OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 /** | |
6 * Tools to help implement refactoring like transformations to Dart code. | |
7 * | |
8 * [TextEditTransaction] supports making a series of changes to a text buffer. | |
9 * [guessIndent] helps to guess the appropriate indentiation for the new code. | |
10 */ | |
11 library refactor; | |
12 | |
13 const $CR = 13; | |
14 const $LF = 10; | |
15 const $TAB = 9; | |
16 const $SPACE = 32; | |
17 | |
18 /** | |
19 * Editable text transaction. Applies a series of edits using original location | |
20 * information, and composes them into the edited string. | |
21 */ | |
22 class TextEditTransaction { | |
23 final String original; | |
24 final _edits = <_TextEdit>[]; | |
25 | |
26 TextEditTransaction(this.original); | |
27 | |
28 bool get hasEdits => _edits.length > 0; | |
29 | |
30 /** | |
31 * Edit the original text, replacing text on the range [begin] and [end] | |
32 * with the [replace] text. | |
33 */ | |
34 void edit(int begin, int end, String replace) { | |
35 _edits.add(new _TextEdit(begin, end, replace)); | |
36 } | |
37 | |
38 /** | |
39 * Applies all pending [edit]s and returns the rewritten string. | |
40 * If no edits were made, returns the [original] string. | |
41 * Throws [UnsupportedError] if the edits were overlapping. | |
42 */ | |
43 String commit() { | |
44 if (_edits.length == 0) return original; | |
45 | |
46 // Sort edits by start location. | |
47 _edits.sort((x, y) => x.begin - y.begin); | |
48 | |
49 var result = new StringBuffer(); | |
50 int consumed = 0; | |
51 for (var edit in _edits) { | |
52 if (consumed > edit.begin) { | |
53 throw new UnsupportedError('overlapping edits: insert at offset ' | |
54 '${edit.begin} but have consumed $consumed input characters.'); | |
55 } | |
56 | |
57 // Add characters from the original string between this edit and the last | |
58 // one, if any. | |
59 var betweenEdits = original.substring(consumed, edit.begin); | |
60 result.add(betweenEdits); | |
61 consumed += betweenEdits.length; | |
62 | |
63 // Add the replaced characters | |
64 result.add(edit.replace); | |
65 consumed += edit.length; | |
Siggi Cherem (dart-lang)
2013/02/13 19:28:54
alternatively, get rid of line 61 and write:
c
Jennifer Messerly
2013/02/14 00:38:09
Done.
| |
66 } | |
67 | |
68 // Add any text from the end of the original string that was not replaced. | |
69 result.add(original.substring(consumed)); | |
70 return result.toString(); | |
71 } | |
72 } | |
73 | |
74 class _TextEdit { | |
75 final int begin; | |
76 final int end; | |
77 final String replace; | |
78 | |
79 _TextEdit(this.begin, this.end, this.replace); | |
80 | |
81 int get length => end - begin; | |
82 } | |
83 | |
84 /** | |
85 * Finds and returns all whitespace characters at the start of the current line. | |
86 */ | |
87 String guessIndent(String code, int charOffset) { | |
Siggi Cherem (dart-lang)
2013/02/13 19:28:54
neat! =)
Jennifer Messerly
2013/02/14 00:38:09
Done.
| |
88 // Find the beginning of the line | |
89 int lineStart = 0; | |
90 for (int i = charOffset - 1; i >= 0; i--) { | |
91 var c = code.charCodeAt(i); | |
92 if (c == $LF || c == $CR) { | |
93 lineStart = i + 1; | |
94 break; | |
95 } | |
96 } | |
97 | |
98 // Grab all the whitespace | |
99 int whitespaceEnd = code.length; | |
100 for (int i = lineStart; i < code.length; i++) { | |
101 var c = code.charCodeAt(i); | |
102 if (c != $SPACE && c != $TAB) { | |
103 whitespaceEnd = i; | |
104 break; | |
105 } | |
106 } | |
107 | |
108 return code.substring(lineStart, whitespaceEnd); | |
109 } | |
OLD | NEW |