| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library formatter_impl; | 5 library formatter_impl; |
| 6 | 6 |
| 7 import 'dart:math'; | 7 import 'dart:math'; |
| 8 | 8 |
| 9 import 'package:analyzer_experimental/analyzer.dart'; | 9 import 'package:analyzer_experimental/analyzer.dart'; |
| 10 import 'package:analyzer_experimental/src/generated/parser.dart'; | 10 import 'package:analyzer_experimental/src/generated/parser.dart'; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 /// Source selection state information. | 86 /// Source selection state information. |
| 87 class Selection { | 87 class Selection { |
| 88 | 88 |
| 89 /// The offset of the source selection. | 89 /// The offset of the source selection. |
| 90 final int offset; | 90 final int offset; |
| 91 | 91 |
| 92 /// The length of the selection. | 92 /// The length of the selection. |
| 93 final int length; | 93 final int length; |
| 94 | 94 |
| 95 Selection(this.offset, this.length); | 95 Selection(this.offset, this.length); |
| 96 |
| 97 String toString() => 'Selection (offset: $offset, length: $length)'; |
| 96 } | 98 } |
| 97 | 99 |
| 98 /// Formatted source. | 100 /// Formatted source. |
| 99 class FormattedSource { | 101 class FormattedSource { |
| 100 | 102 |
| 101 /// Selection state or null if unspecified. | 103 /// Selection state or null if unspecified. |
| 102 final Selection selection; | 104 final Selection selection; |
| 103 | 105 |
| 104 /// Formatted source string. | 106 /// Formatted source string. |
| 105 final String source; | 107 final String source; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 121 | 123 |
| 122 FormattedSource format(CodeKind kind, String source, {int offset, int end, | 124 FormattedSource format(CodeKind kind, String source, {int offset, int end, |
| 123 int indentationLevel: 0, Selection selection: null}) { | 125 int indentationLevel: 0, Selection selection: null}) { |
| 124 | 126 |
| 125 var startToken = tokenize(source); | 127 var startToken = tokenize(source); |
| 126 checkForErrors(); | 128 checkForErrors(); |
| 127 | 129 |
| 128 var node = parse(kind, startToken); | 130 var node = parse(kind, startToken); |
| 129 checkForErrors(); | 131 checkForErrors(); |
| 130 | 132 |
| 131 var formatter = new SourceVisitor(options, lineInfo); | 133 var formatter = new SourceVisitor(options, lineInfo, selection); |
| 132 node.accept(formatter); | 134 node.accept(formatter); |
| 133 | 135 |
| 134 var formattedSource = formatter.writer.toString(); | 136 var formattedSource = formatter.writer.toString(); |
| 135 | 137 |
| 136 checkTokenStreams(startToken, tokenize(formattedSource)); | 138 checkTokenStreams(startToken, tokenize(formattedSource)); |
| 137 | 139 |
| 138 return new FormattedSource(formattedSource); | 140 return new FormattedSource(formattedSource, formatter.selection); |
| 139 } | 141 } |
| 140 | 142 |
| 141 checkTokenStreams(Token t1, Token t2) => | 143 checkTokenStreams(Token t1, Token t2) => |
| 142 new TokenStreamComparator(lineInfo, t1, t2).verifyEquals(); | 144 new TokenStreamComparator(lineInfo, t1, t2).verifyEquals(); |
| 143 | 145 |
| 144 ASTNode parse(CodeKind kind, Token start) { | 146 ASTNode parse(CodeKind kind, Token start) { |
| 145 | 147 |
| 146 var parser = new Parser(null, this); | 148 var parser = new Parser(null, this); |
| 147 | 149 |
| 148 switch (kind) { | 150 switch (kind) { |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 LineInfo lineInfo; | 304 LineInfo lineInfo; |
| 303 | 305 |
| 304 /// Cached previous token for calculating preceding whitespace. | 306 /// Cached previous token for calculating preceding whitespace. |
| 305 Token previousToken; | 307 Token previousToken; |
| 306 | 308 |
| 307 /// A flag to indicate that a newline should be emitted before the next token. | 309 /// A flag to indicate that a newline should be emitted before the next token. |
| 308 bool needsNewline = false; | 310 bool needsNewline = false; |
| 309 | 311 |
| 310 /// Used for matching EOL comments | 312 /// Used for matching EOL comments |
| 311 final twoSlashes = new RegExp(r'//[^/]'); | 313 final twoSlashes = new RegExp(r'//[^/]'); |
| 314 |
| 315 /// Original pre-format selection information (may be null). |
| 316 final Selection preSelection; |
| 317 |
| 318 /// Post format selection information. |
| 319 Selection selection; |
| 312 | 320 |
| 313 /// Initialize a newly created visitor to write source code representing | 321 /// Initialize a newly created visitor to write source code representing |
| 314 /// the visited nodes to the given [writer]. | 322 /// the visited nodes to the given [writer]. |
| 315 SourceVisitor(FormatterOptions options, this.lineInfo) : | 323 SourceVisitor(FormatterOptions options, this.lineInfo, this.preSelection) : |
| 316 writer = new SourceWriter(indentCount: options.initialIndentationLevel, | 324 writer = new SourceWriter(indentCount: options.initialIndentationLevel, |
| 317 lineSeparator: options.lineSeparator); | 325 lineSeparator: options.lineSeparator); |
| 318 | 326 |
| 319 visitAdjacentStrings(AdjacentStrings node) { | 327 visitAdjacentStrings(AdjacentStrings node) { |
| 320 visitNodes(node.strings, separatedBy: space); | 328 visitNodes(node.strings, separatedBy: space); |
| 321 } | 329 } |
| 322 | 330 |
| 323 visitAnnotation(Annotation node) { | 331 visitAnnotation(Annotation node) { |
| 324 token(node.atSign); | 332 token(node.atSign); |
| 325 visit(node.name); | 333 visit(node.name); |
| (...skipping 876 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1202 if (needsNewline) { | 1210 if (needsNewline) { |
| 1203 minNewlines = max(1, minNewlines); | 1211 minNewlines = max(1, minNewlines); |
| 1204 } | 1212 } |
| 1205 var emitted = emitPrecedingCommentsAndNewlines(token, min: minNewlines); | 1213 var emitted = emitPrecedingCommentsAndNewlines(token, min: minNewlines); |
| 1206 if (emitted > 0) { | 1214 if (emitted > 0) { |
| 1207 needsNewline = false; | 1215 needsNewline = false; |
| 1208 } | 1216 } |
| 1209 if (precededBy != null) { | 1217 if (precededBy != null) { |
| 1210 precededBy(); | 1218 precededBy(); |
| 1211 } | 1219 } |
| 1220 checkForSelectionUpdate(token); |
| 1212 append(token.lexeme); | 1221 append(token.lexeme); |
| 1213 if (followedBy != null) { | 1222 if (followedBy != null) { |
| 1214 followedBy(); | 1223 followedBy(); |
| 1215 } | 1224 } |
| 1216 previousToken = token; | 1225 previousToken = token; |
| 1217 } | 1226 } |
| 1218 } | 1227 } |
| 1228 |
| 1229 checkForSelectionUpdate(Token token) { |
| 1230 // Cache the first token on or AFTER the selection offset |
| 1231 if (preSelection != null && selection == null) { |
| 1232 // Check for overshots |
| 1233 var overshot = token.offset - preSelection.offset; |
| 1234 if (overshot >= 0) { |
| 1235 //TODO(pquitslund): update length (may need truncating) |
| 1236 selection = new Selection(writer.toString().length - overshot, |
| 1237 preSelection.length); |
| 1238 } |
| 1239 } |
| 1240 } |
| 1219 | 1241 |
| 1220 commaSeperator() { | 1242 commaSeperator() { |
| 1221 comma(); | 1243 comma(); |
| 1222 space(); | 1244 space(); |
| 1223 } | 1245 } |
| 1224 | 1246 |
| 1225 comma() { | 1247 comma() { |
| 1226 append(','); | 1248 append(','); |
| 1227 } | 1249 } |
| 1228 | 1250 |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1385 var lastLine = | 1407 var lastLine = |
| 1386 lineInfo.getLocation(lastOffset).lineNumber; | 1408 lineInfo.getLocation(lastOffset).lineNumber; |
| 1387 var currentLine = | 1409 var currentLine = |
| 1388 lineInfo.getLocation(currentOffset).lineNumber; | 1410 lineInfo.getLocation(currentOffset).lineNumber; |
| 1389 return currentLine - lastLine; | 1411 return currentLine - lastLine; |
| 1390 } | 1412 } |
| 1391 | 1413 |
| 1392 String toString() => writer.toString(); | 1414 String toString() => writer.toString(); |
| 1393 | 1415 |
| 1394 } | 1416 } |
| OLD | NEW |