Chromium Code Reviews| 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 | 7 |
| 8 import 'dart:io'; | 8 import 'dart:io'; |
| 9 | 9 |
| 10 import 'package:analyzer_experimental/analyzer.dart'; | 10 import 'package:analyzer_experimental/analyzer.dart'; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 44 final message; | 44 final message; |
| 45 | 45 |
| 46 /// Creates a new FormatterException with an optional error [message]. | 46 /// Creates a new FormatterException with an optional error [message]. |
| 47 const FormatterException([this.message = '']); | 47 const FormatterException([this.message = '']); |
| 48 | 48 |
| 49 FormatterException.forError(List<AnalysisError> errors) : | 49 FormatterException.forError(List<AnalysisError> errors) : |
| 50 // TODO(pquitslund): add descriptive message based on errors | 50 // TODO(pquitslund): add descriptive message based on errors |
| 51 message = 'an analysis error occured during format'; | 51 message = 'an analysis error occured during format'; |
| 52 | 52 |
| 53 String toString() => 'FormatterException: $message'; | 53 String toString() => 'FormatterException: $message'; |
| 54 | |
| 55 } | 54 } |
| 56 | 55 |
| 57 /// Specifies the kind of code snippet to format. | 56 /// Specifies the kind of code snippet to format. |
| 58 class CodeKind { | 57 class CodeKind { |
| 59 | 58 |
| 60 final index; | 59 final index; |
| 61 | 60 |
| 62 const CodeKind(this.index); | 61 const CodeKind(this.index); |
| 63 | 62 |
| 64 /// A compilation unit snippet. | 63 /// A compilation unit snippet. |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 80 String format(CodeKind kind, String source, {int offset, int end, | 79 String format(CodeKind kind, String source, {int offset, int end, |
| 81 int indentationLevel:0}); | 80 int indentationLevel:0}); |
| 82 | 81 |
| 83 } | 82 } |
| 84 | 83 |
| 85 class CodeFormatterImpl implements CodeFormatter, AnalysisErrorListener { | 84 class CodeFormatterImpl implements CodeFormatter, AnalysisErrorListener { |
| 86 | 85 |
| 87 final FormatterOptions options; | 86 final FormatterOptions options; |
| 88 final errors = <AnalysisError>[]; | 87 final errors = <AnalysisError>[]; |
| 89 | 88 |
| 89 LineInfo lineInfo; | |
| 90 | |
| 90 CodeFormatterImpl(this.options); | 91 CodeFormatterImpl(this.options); |
| 91 | 92 |
| 92 String format(CodeKind kind, String source, {int offset, int end, | 93 String format(CodeKind kind, String source, {int offset, int end, |
| 93 int indentationLevel:0}) { | 94 int indentationLevel:0}) { |
| 94 | 95 |
| 95 var start = tokenize(source); | 96 var start = tokenize(source); |
| 96 checkForErrors(); | 97 checkForErrors(); |
| 97 | 98 |
| 98 var node = parse(kind, start); | 99 var node = parse(kind, start); |
| 99 checkForErrors(); | 100 checkForErrors(); |
| 100 | 101 |
| 101 var formatter = new SourceVisitor(options); | 102 var formatter = new SourceVisitor(options, lineInfo); |
| 102 node.accept(formatter); | 103 node.accept(formatter); |
| 103 | 104 |
| 104 return formatter.writer.toString(); | 105 return formatter.writer.toString(); |
| 105 } | 106 } |
| 106 | 107 |
| 107 ASTNode parse(CodeKind kind, Token start) { | 108 ASTNode parse(CodeKind kind, Token start) { |
| 108 | 109 |
| 109 var parser = new Parser(null, this); | 110 var parser = new Parser(null, this); |
| 110 | 111 |
| 111 switch (kind) { | 112 switch (kind) { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 123 throw new FormatterException.forError(errors); | 124 throw new FormatterException.forError(errors); |
| 124 } | 125 } |
| 125 } | 126 } |
| 126 | 127 |
| 127 void onError(AnalysisError error) { | 128 void onError(AnalysisError error) { |
| 128 errors.add(error); | 129 errors.add(error); |
| 129 } | 130 } |
| 130 | 131 |
| 131 Token tokenize(String source) { | 132 Token tokenize(String source) { |
| 132 var scanner = new StringScanner(null, source, this); | 133 var scanner = new StringScanner(null, source, this); |
| 133 return scanner.tokenize(); | 134 var token = scanner.tokenize(); |
| 135 lineInfo = new LineInfo(scanner.lineStarts); | |
| 136 return token; | |
| 134 } | 137 } |
| 135 | 138 |
| 136 } | 139 } |
| 137 | 140 |
| 138 | 141 |
| 139 | 142 |
| 140 /// An AST visitor that drives formatting heuristics. | 143 /// An AST visitor that drives formatting heuristics. |
| 141 class SourceVisitor implements ASTVisitor { | 144 class SourceVisitor implements ASTVisitor { |
| 142 | 145 |
| 143 /// The writer to which the source is to be written. | 146 /// The writer to which the source is to be written. |
| 144 SourceWriter writer; | 147 SourceWriter writer; |
| 145 | 148 |
| 149 LineInfo lineInfo; | |
| 150 | |
| 146 /// Initialize a newly created visitor to write source code representing | 151 /// Initialize a newly created visitor to write source code representing |
| 147 /// the visited nodes to the given [writer]. | 152 /// the visited nodes to the given [writer]. |
| 148 SourceVisitor(FormatterOptions options) : | 153 SourceVisitor(FormatterOptions options, this.lineInfo) : |
| 149 writer = new SourceWriter(indentCount: options.initialIndentationLevel, | 154 writer = new SourceWriter(indentCount: options.initialIndentationLevel, |
| 150 lineSeparator: options.lineSeparator); | 155 lineSeparator: options.lineSeparator); |
| 151 | 156 |
| 152 visitAdjacentStrings(AdjacentStrings node) { | 157 visitAdjacentStrings(AdjacentStrings node) { |
| 153 visitList(node.strings, ' '); | 158 visitList(node.strings, ' '); |
| 154 } | 159 } |
| 155 | 160 |
| 156 visitAnnotation(Annotation node) { | 161 visitAnnotation(Annotation node) { |
| 157 writer.print('@'); | 162 writer.print('@'); |
| 158 visit(node.name); | 163 visit(node.name); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 286 | 291 |
| 287 visitCommentReference(CommentReference node) => null; | 292 visitCommentReference(CommentReference node) => null; |
| 288 | 293 |
| 289 visitCompilationUnit(CompilationUnit node) { | 294 visitCompilationUnit(CompilationUnit node) { |
| 290 var scriptTag = node.scriptTag; | 295 var scriptTag = node.scriptTag; |
| 291 var directives = node.directives; | 296 var directives = node.directives; |
| 292 visit(scriptTag); | 297 visit(scriptTag); |
| 293 var prefix = scriptTag == null ? '' : ' '; | 298 var prefix = scriptTag == null ? '' : ' '; |
| 294 visitPrefixedList(prefix, directives, ' '); | 299 visitPrefixedList(prefix, directives, ' '); |
| 295 prefix = scriptTag == null && directives.isEmpty ? '' : ' '; | 300 prefix = scriptTag == null && directives.isEmpty ? '' : ' '; |
| 296 visitPrefixedList(prefix, node.declarations, ' '); | 301 visitPrefixedListWithBlanks(prefix, node.declarations); |
| 302 | |
| 303 //TODO(pquitslund): move this? | |
| 304 writer.newline(); | |
| 297 } | 305 } |
| 298 | 306 |
| 299 visitConditionalExpression(ConditionalExpression node) { | 307 visitConditionalExpression(ConditionalExpression node) { |
| 300 visit(node.condition); | 308 visit(node.condition); |
| 301 writer.print(' ? '); | 309 writer.print(' ? '); |
| 302 visit(node.thenExpression); | 310 visit(node.thenExpression); |
| 303 writer.print(' : '); | 311 writer.print(' : '); |
| 304 visit(node.elseExpression); | 312 visit(node.elseExpression); |
| 305 } | 313 } |
| 306 | 314 |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 639 } | 647 } |
| 640 visit(node.methodName); | 648 visit(node.methodName); |
| 641 visit(node.argumentList); | 649 visit(node.argumentList); |
| 642 } | 650 } |
| 643 | 651 |
| 644 visitNamedExpression(NamedExpression node) { | 652 visitNamedExpression(NamedExpression node) { |
| 645 visit(node.name); | 653 visit(node.name); |
| 646 visitPrefixed(' ', node.expression); | 654 visitPrefixed(' ', node.expression); |
| 647 } | 655 } |
| 648 | 656 |
| 657 visitNativeClause(NativeClause node) { | |
| 658 writer.print("native "); | |
| 659 visit(node.name); | |
| 660 } | |
| 661 | |
| 649 visitNativeFunctionBody(NativeFunctionBody node) { | 662 visitNativeFunctionBody(NativeFunctionBody node) { |
| 650 writer.print('native '); | 663 writer.print('native '); |
| 651 visit(node.stringLiteral); | 664 visit(node.stringLiteral); |
| 652 writer.print(';'); | 665 writer.print(';'); |
| 653 } | 666 } |
| 654 | 667 |
| 655 visitNullLiteral(NullLiteral node) { | 668 visitNullLiteral(NullLiteral node) { |
| 656 writer.print('null'); | 669 writer.print('null'); |
| 657 } | 670 } |
| 658 | 671 |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 935 for (var i = 0; i < size; i++) { | 948 for (var i = 0; i < size; i++) { |
| 936 if (i > 0) { | 949 if (i > 0) { |
| 937 writer.print(separator); | 950 writer.print(separator); |
| 938 } | 951 } |
| 939 nodes[i].accept(this); | 952 nodes[i].accept(this); |
| 940 } | 953 } |
| 941 } | 954 } |
| 942 } | 955 } |
| 943 } | 956 } |
| 944 | 957 |
| 958 /// Print a list of [nodes], preserving blanklines between nodes. | |
|
Brian Wilkerson
2013/07/17 21:25:09
nit: "blanklines" --> "blank lines"
pquitslund
2013/07/17 21:44:13
Fixed!
| |
| 959 visitPrefixedListWithBlanks(String prefix, | |
| 960 NodeList<ASTNode> nodes) { | |
| 961 if (nodes != null) { | |
| 962 var size = nodes.length; | |
| 963 if (size > 0) { | |
| 964 writer.print(prefix); | |
| 965 for (var i = 0; i < size; i++) { | |
| 966 if (i > 0) { | |
| 967 // Emit blanks lines | |
| 968 var lastLine = | |
| 969 lineInfo.getLocation(nodes[i-1].endToken.offset).lineNumber; | |
| 970 var currentLine = | |
| 971 lineInfo.getLocation(nodes[i].beginToken.offset).lineNumber; | |
| 972 var blanks = currentLine - lastLine; | |
| 973 for (var i = 0; i < blanks; i++) { | |
| 974 writer.newline(); | |
| 975 } | |
| 976 } | |
| 977 nodes[i].accept(this); | |
| 978 } | |
| 979 } | |
| 980 } | |
| 981 } | |
| 982 | |
| 945 } | 983 } |
| OLD | NEW |