Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: pkg/analyzer_experimental/lib/src/services/formatter_impl.dart

Issue 25350003: Flow control structure formatting (a la the Style Guide). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/analyzer_experimental/test/services/formatter_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 /// Verify that these two token streams are equal. 188 /// Verify that these two token streams are equal.
189 verifyEquals() { 189 verifyEquals() {
190 while (!isEOF(token1)) { 190 while (!isEOF(token1)) {
191 checkPrecedingComments(); 191 checkPrecedingComments();
192 if (!checkTokens()) { 192 if (!checkTokens()) {
193 throwNotEqualException(token1, token2); 193 throwNotEqualException(token1, token2);
194 } 194 }
195 advance(); 195 advance();
196 196
197 } 197 }
198 if (!isEOF(token2)) { 198 // TODO(pquitslund): consider a better way to notice trailing synthetics
199 if (!isEOF(token2) &&
200 !(isCLOSE_CURLY_BRACKET(token2) && isEOF(token2.next))) {
199 throw new FormatterException( 201 throw new FormatterException(
200 'Expected "EOF" but got "${token2}".'); 202 'Expected "EOF" but got "${token2}".');
201 } 203 }
202 } 204 }
203 205
204 checkPrecedingComments() { 206 checkPrecedingComments() {
205 var comment1 = token1.precedingComments; 207 var comment1 = token1.precedingComments;
206 var comment2 = token2.precedingComments; 208 var comment2 = token2.precedingComments;
207 while (comment1 != null) { 209 while (comment1 != null) {
208 if (comment2 == null) { 210 if (comment2 == null) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 return true; 256 return true;
255 } 257 }
256 } 258 }
257 // '>' '>' => '>>' 259 // '>' '>' => '>>'
258 if (isGT(token1) && isGT(token1.next)) { 260 if (isGT(token1) && isGT(token1.next)) {
259 if (isGT_GT(token2)) { 261 if (isGT_GT(token2)) {
260 token1 = token1.next; 262 token1 = token1.next;
261 return true; 263 return true;
262 } 264 }
263 } 265 }
266 // Advance past synthetic { } tokens
267 if (isOPEN_CURLY_BRACKET(token2) || isCLOSE_CURLY_BRACKET(token2)) {
268 token2 = token2.next;
269 return checkTokens();
270 }
264 271
265 return false; 272 return false;
266 } 273 }
267 274
268 } 275 }
269 276
270 // Cached parser for testing token types. 277 // Cached parser for testing token types.
271 final tokenTester = new Parser(null,null); 278 final tokenTester = new Parser(null,null);
272 279
273 /// Test if this token is an EOF token. 280 /// Test if this token is an EOF token.
274 bool isEOF(Token token) => tokenIs(token, TokenType.EOF); 281 bool isEOF(Token token) => tokenIs(token, TokenType.EOF);
275 282
276 /// Test for token type. 283 /// Test for token type.
277 bool tokenIs(Token token, TokenType type) => 284 bool tokenIs(Token token, TokenType type) =>
278 token != null && tokenTester.matches4(token, type); 285 token != null && tokenTester.matches4(token, type);
279 286
280 /// Test if this token is a GT token. 287 /// Test if this token is a GT token.
281 bool isGT(Token token) => tokenIs(token, TokenType.GT); 288 bool isGT(Token token) => tokenIs(token, TokenType.GT);
282 289
283 /// Test if this token is a GT_GT token. 290 /// Test if this token is a GT_GT token.
284 bool isGT_GT(Token token) => tokenIs(token, TokenType.GT_GT); 291 bool isGT_GT(Token token) => tokenIs(token, TokenType.GT_GT);
285 292
286 /// Test if this token is an INDEX token. 293 /// Test if this token is an INDEX token.
287 bool isINDEX(Token token) => tokenIs(token, TokenType.INDEX); 294 bool isINDEX(Token token) => tokenIs(token, TokenType.INDEX);
288 295
296 /// Test if this token is a OPEN_CURLY_BRACKET token.
297 bool isOPEN_CURLY_BRACKET(Token token) =>
298 tokenIs(token, TokenType.OPEN_CURLY_BRACKET);
299
300 /// Test if this token is a CLOSE_CURLY_BRACKET token.
301 bool isCLOSE_CURLY_BRACKET(Token token) =>
302 tokenIs(token, TokenType.CLOSE_CURLY_BRACKET);
303
289 /// Test if this token is a OPEN_SQUARE_BRACKET token. 304 /// Test if this token is a OPEN_SQUARE_BRACKET token.
290 bool isOPEN_SQ_BRACKET(Token token) => 305 bool isOPEN_SQ_BRACKET(Token token) =>
291 tokenIs(token, TokenType.OPEN_SQUARE_BRACKET); 306 tokenIs(token, TokenType.OPEN_SQUARE_BRACKET);
292 307
293 /// Test if this token is a CLOSE_SQUARE_BRACKET token. 308 /// Test if this token is a CLOSE_SQUARE_BRACKET token.
294 bool isCLOSE_SQUARE_BRACKET(Token token) => 309 bool isCLOSE_SQUARE_BRACKET(Token token) =>
295 tokenIs(token, TokenType.CLOSE_SQUARE_BRACKET); 310 tokenIs(token, TokenType.CLOSE_SQUARE_BRACKET);
296 311
312
297 /// An AST visitor that drives formatting heuristics. 313 /// An AST visitor that drives formatting heuristics.
298 class SourceVisitor implements ASTVisitor { 314 class SourceVisitor implements ASTVisitor {
315
316 static final OPEN_CURLY = syntheticToken(TokenType.OPEN_CURLY_BRACKET, '{');
317 static final CLOSE_CURLY = syntheticToken(TokenType.CLOSE_CURLY_BRACKET, '}');
318
319 static const SYNTH_OFFSET = -13;
320
321 static StringToken syntheticToken(TokenType type, String value) =>
322 new StringToken(type, value, SYNTH_OFFSET);
323
324 static bool isSynthetic(Token token) => token.offset == SYNTH_OFFSET;
299 325
300 /// The writer to which the source is to be written. 326 /// The writer to which the source is to be written.
301 final SourceWriter writer; 327 final SourceWriter writer;
302 328
303 /// Cached line info for calculating blank lines. 329 /// Cached line info for calculating blank lines.
304 LineInfo lineInfo; 330 LineInfo lineInfo;
305 331
306 /// Cached previous token for calculating preceding whitespace. 332 /// Cached previous token for calculating preceding whitespace.
307 Token previousToken; 333 Token previousToken;
308 334
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 visitNode(node.returnType, followedBy: space); 749 visitNode(node.returnType, followedBy: space);
724 visit(node.identifier); 750 visit(node.identifier);
725 visit(node.parameters); 751 visit(node.parameters);
726 } 752 }
727 753
728 visitHideCombinator(HideCombinator node) { 754 visitHideCombinator(HideCombinator node) {
729 token(node.keyword); 755 token(node.keyword);
730 space(); 756 space();
731 visitNodes(node.hiddenNames, separatedBy: commaSeperator); 757 visitNodes(node.hiddenNames, separatedBy: commaSeperator);
732 } 758 }
733 759
734 visitIfStatement(IfStatement node) { 760 visitIfStatement(IfStatement node) {
761 var hasElse = node.elseStatement != null;
735 token(node.ifKeyword); 762 token(node.ifKeyword);
736 space(); 763 space();
737 token(node.leftParenthesis); 764 token(node.leftParenthesis);
738 visit(node.condition); 765 visit(node.condition);
739 token(node.rightParenthesis); 766 token(node.rightParenthesis);
740 space(); 767 space();
741 visit(node.thenStatement); 768 if (hasElse) {
742 //visitPrefixed(' else ', node.elseStatement); 769 printAsBlock(node.thenStatement);
743 if (node.elseStatement != null) {
744 space(); 770 space();
745 token(node.elseKeyword); 771 token(node.elseKeyword);
746 space(); 772 space();
747 visit(node.elseStatement); 773 printAsBlock(node.elseStatement);
774 } else {
775 visit(node.thenStatement);
748 } 776 }
749 } 777 }
750 778
751 visitImplementsClause(ImplementsClause node) { 779 visitImplementsClause(ImplementsClause node) {
752 token(node.keyword); 780 token(node.keyword);
753 space(); 781 space();
754 visitNodes(node.interfaces, separatedBy: commaSeperator); 782 visitNodes(node.interfaces, separatedBy: commaSeperator);
755 } 783 }
756 784
757 visitImportDirective(ImportDirective node) { 785 visitImportDirective(ImportDirective node) {
758 token(node.keyword); 786 token(node.keyword);
759 space(); 787 space();
760 visit(node.uri); 788 visit(node.uri);
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after
1268 1296
1269 /// Indent. 1297 /// Indent.
1270 indent() { 1298 indent() {
1271 writer.indent(); 1299 writer.indent();
1272 } 1300 }
1273 1301
1274 /// Unindent 1302 /// Unindent
1275 unindent() { 1303 unindent() {
1276 writer.unindent(); 1304 writer.unindent();
1277 } 1305 }
1278 1306
1279 1307 /// Print this statement as if it were a block (e.g., surrounded by braces).
1308 printAsBlock(Statement statement) {
1309 if (statement is! Block) {
1310 token(OPEN_CURLY);
1311 indent();
1312 newlines();
1313 visit(statement);
1314 newlines();
1315 unindent();
1316 token(CLOSE_CURLY);
1317 } else {
1318 visit(statement);
1319 }
1320 }
1321
1280 /// Emit any detected comments and newlines or a minimum as specified 1322 /// Emit any detected comments and newlines or a minimum as specified
1281 /// by [min]. 1323 /// by [min].
1282 int emitPrecedingCommentsAndNewlines(Token token, {min: 0}) { 1324 int emitPrecedingCommentsAndNewlines(Token token, {min: 0}) {
1283 1325
1284 var comment = token.precedingComments; 1326 var comment = token.precedingComments;
1285 var currentToken = comment != null ? comment : token; 1327 var currentToken = comment != null ? comment : token;
1286 1328
1287 //Handle EOLs before newlines 1329 //Handle EOLs before newlines
1288 if (isAtEOL(comment)) { 1330 if (isAtEOL(comment)) {
1289 emitComment(comment, previousToken); 1331 emitComment(comment, previousToken);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1354 /// Count newlines preceeding this [node]. 1396 /// Count newlines preceeding this [node].
1355 int countPrecedingNewlines(ASTNode node) => 1397 int countPrecedingNewlines(ASTNode node) =>
1356 countNewlinesBetween(node.beginToken.previous, node.beginToken); 1398 countNewlinesBetween(node.beginToken.previous, node.beginToken);
1357 1399
1358 /// Count newlines succeeding this [node]. 1400 /// Count newlines succeeding this [node].
1359 int countSucceedingNewlines(ASTNode node) => node == null ? 0 : 1401 int countSucceedingNewlines(ASTNode node) => node == null ? 0 :
1360 countNewlinesBetween(node.endToken, node.endToken.next); 1402 countNewlinesBetween(node.endToken, node.endToken.next);
1361 1403
1362 /// Count the blanks between these two tokens. 1404 /// Count the blanks between these two tokens.
1363 int countNewlinesBetween(Token last, Token current) { 1405 int countNewlinesBetween(Token last, Token current) {
1364 if (last == null || current == null) { 1406 if (last == null || current == null || isSynthetic(last)) {
1365 return 0; 1407 return 0;
1366 } 1408 }
1367 1409
1368 return linesBetween(last.end - 1, current.offset); 1410 return linesBetween(last.end - 1, current.offset);
1369 } 1411 }
1370 1412
1371 /// Calculate the newlines that should separate these comments. 1413 /// Calculate the newlines that should separate these comments.
1372 int calculateNewlinesBetweenComments(Token last, Token current) { 1414 int calculateNewlinesBetweenComments(Token last, Token current) {
1373 // Insist on a newline after doc comments or single line comments 1415 // Insist on a newline after doc comments or single line comments
1374 // (NOTE that EOL comments have already been processed). 1416 // (NOTE that EOL comments have already been processed).
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1407 var lastLine = 1449 var lastLine =
1408 lineInfo.getLocation(lastOffset).lineNumber; 1450 lineInfo.getLocation(lastOffset).lineNumber;
1409 var currentLine = 1451 var currentLine =
1410 lineInfo.getLocation(currentOffset).lineNumber; 1452 lineInfo.getLocation(currentOffset).lineNumber;
1411 return currentLine - lastLine; 1453 return currentLine - lastLine;
1412 } 1454 }
1413 1455
1414 String toString() => writer.toString(); 1456 String toString() => writer.toString();
1415 1457
1416 } 1458 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer_experimental/test/services/formatter_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698