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

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) && !isCLOSE_CURLY_BRACKET(token2)) {
Brian Wilkerson 2013/09/30 22:19:34 Do you need to check that the token following the
pquitslund 2013/09/30 22:41:56 Done.
199 throw new FormatterException( 200 throw new FormatterException(
200 'Expected "EOF" but got "${token2}".'); 201 'Expected "EOF" but got "${token2}".');
201 } 202 }
202 } 203 }
203 204
204 checkPrecedingComments() { 205 checkPrecedingComments() {
205 var comment1 = token1.precedingComments; 206 var comment1 = token1.precedingComments;
206 var comment2 = token2.precedingComments; 207 var comment2 = token2.precedingComments;
207 while (comment1 != null) { 208 while (comment1 != null) {
208 if (comment2 == null) { 209 if (comment2 == null) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 return true; 255 return true;
255 } 256 }
256 } 257 }
257 // '>' '>' => '>>' 258 // '>' '>' => '>>'
258 if (isGT(token1) && isGT(token1.next)) { 259 if (isGT(token1) && isGT(token1.next)) {
259 if (isGT_GT(token2)) { 260 if (isGT_GT(token2)) {
260 token1 = token1.next; 261 token1 = token1.next;
261 return true; 262 return true;
262 } 263 }
263 } 264 }
265 // Advance past synthetic { } tokens
266 if (isOPEN_CURLY_BRACKET(token2) || isCLOSE_CURLY_BRACKET(token2)) {
267 token2 = token2.next;
268 return checkTokens();
269 }
264 270
265 return false; 271 return false;
266 } 272 }
267 273
268 } 274 }
269 275
270 // Cached parser for testing token types. 276 // Cached parser for testing token types.
271 final tokenTester = new Parser(null,null); 277 final tokenTester = new Parser(null,null);
272 278
273 /// Test if this token is an EOF token. 279 /// Test if this token is an EOF token.
274 bool isEOF(Token token) => tokenIs(token, TokenType.EOF); 280 bool isEOF(Token token) => tokenIs(token, TokenType.EOF);
275 281
276 /// Test for token type. 282 /// Test for token type.
277 bool tokenIs(Token token, TokenType type) => 283 bool tokenIs(Token token, TokenType type) =>
278 token != null && tokenTester.matches4(token, type); 284 token != null && tokenTester.matches4(token, type);
279 285
280 /// Test if this token is a GT token. 286 /// Test if this token is a GT token.
281 bool isGT(Token token) => tokenIs(token, TokenType.GT); 287 bool isGT(Token token) => tokenIs(token, TokenType.GT);
282 288
283 /// Test if this token is a GT_GT token. 289 /// Test if this token is a GT_GT token.
284 bool isGT_GT(Token token) => tokenIs(token, TokenType.GT_GT); 290 bool isGT_GT(Token token) => tokenIs(token, TokenType.GT_GT);
285 291
286 /// Test if this token is an INDEX token. 292 /// Test if this token is an INDEX token.
287 bool isINDEX(Token token) => tokenIs(token, TokenType.INDEX); 293 bool isINDEX(Token token) => tokenIs(token, TokenType.INDEX);
288 294
295 /// Test if this token is a OPEN_CURLY_BRACKET token.
296 bool isOPEN_CURLY_BRACKET(Token token) =>
297 tokenIs(token, TokenType.OPEN_CURLY_BRACKET);
298
299 /// Test if this token is a CLOSE_CURLY_BRACKET token.
300 bool isCLOSE_CURLY_BRACKET(Token token) =>
301 tokenIs(token, TokenType.CLOSE_CURLY_BRACKET);
302
289 /// Test if this token is a OPEN_SQUARE_BRACKET token. 303 /// Test if this token is a OPEN_SQUARE_BRACKET token.
290 bool isOPEN_SQ_BRACKET(Token token) => 304 bool isOPEN_SQ_BRACKET(Token token) =>
291 tokenIs(token, TokenType.OPEN_SQUARE_BRACKET); 305 tokenIs(token, TokenType.OPEN_SQUARE_BRACKET);
292 306
293 /// Test if this token is a CLOSE_SQUARE_BRACKET token. 307 /// Test if this token is a CLOSE_SQUARE_BRACKET token.
294 bool isCLOSE_SQUARE_BRACKET(Token token) => 308 bool isCLOSE_SQUARE_BRACKET(Token token) =>
295 tokenIs(token, TokenType.CLOSE_SQUARE_BRACKET); 309 tokenIs(token, TokenType.CLOSE_SQUARE_BRACKET);
296 310
297 /// An AST visitor that drives formatting heuristics. 311 /// An AST visitor that drives formatting heuristics.
298 class SourceVisitor implements ASTVisitor { 312 class SourceVisitor implements ASTVisitor {
313
314 static final OPEN_CURLY = syntheticToken(TokenType.OPEN_CURLY_BRACKET, '{');
315 static final CLOSE_CURLY = syntheticToken(TokenType.CLOSE_CURLY_BRACKET, '}');
316
317 static const SYNTH_OFFSET = -13;
318
319 static StringToken syntheticToken(TokenType type, String value) =>
320 new StringToken(type, value, SYNTH_OFFSET);
321
322 static bool isSynthetic(Token token) => token.offset == SYNTH_OFFSET;
Brian Wilkerson 2013/09/30 22:19:34 It's a little unfortunate that you have a helper m
pquitslund 2013/09/30 22:41:56 Totally. As per our conversation, we'd have to ad
299 323
300 /// The writer to which the source is to be written. 324 /// The writer to which the source is to be written.
301 final SourceWriter writer; 325 final SourceWriter writer;
302 326
303 /// Cached line info for calculating blank lines. 327 /// Cached line info for calculating blank lines.
304 LineInfo lineInfo; 328 LineInfo lineInfo;
305 329
306 /// Cached previous token for calculating preceding whitespace. 330 /// Cached previous token for calculating preceding whitespace.
307 Token previousToken; 331 Token previousToken;
308 332
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 visitNode(node.returnType, followedBy: space); 747 visitNode(node.returnType, followedBy: space);
724 visit(node.identifier); 748 visit(node.identifier);
725 visit(node.parameters); 749 visit(node.parameters);
726 } 750 }
727 751
728 visitHideCombinator(HideCombinator node) { 752 visitHideCombinator(HideCombinator node) {
729 token(node.keyword); 753 token(node.keyword);
730 space(); 754 space();
731 visitNodes(node.hiddenNames, separatedBy: commaSeperator); 755 visitNodes(node.hiddenNames, separatedBy: commaSeperator);
732 } 756 }
733 757
734 visitIfStatement(IfStatement node) { 758 visitIfStatement(IfStatement node) {
759 var hasElse = node.elseStatement != null;
735 token(node.ifKeyword); 760 token(node.ifKeyword);
736 space(); 761 space();
737 token(node.leftParenthesis); 762 token(node.leftParenthesis);
738 visit(node.condition); 763 visit(node.condition);
739 token(node.rightParenthesis); 764 token(node.rightParenthesis);
740 space(); 765 space();
741 visit(node.thenStatement); 766 if (hasElse) {
742 //visitPrefixed(' else ', node.elseStatement); 767 printAsBlock(node.thenStatement);
743 if (node.elseStatement != null) {
744 space(); 768 space();
745 token(node.elseKeyword); 769 token(node.elseKeyword);
746 space(); 770 space();
747 visit(node.elseStatement); 771 printAsBlock(node.elseStatement);
772 } else {
773 visit(node.thenStatement);
748 } 774 }
749 } 775 }
750 776
751 visitImplementsClause(ImplementsClause node) { 777 visitImplementsClause(ImplementsClause node) {
752 token(node.keyword); 778 token(node.keyword);
753 space(); 779 space();
754 visitNodes(node.interfaces, separatedBy: commaSeperator); 780 visitNodes(node.interfaces, separatedBy: commaSeperator);
755 } 781 }
756 782
757 visitImportDirective(ImportDirective node) { 783 visitImportDirective(ImportDirective node) {
758 token(node.keyword); 784 token(node.keyword);
759 space(); 785 space();
760 visit(node.uri); 786 visit(node.uri);
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after
1268 1294
1269 /// Indent. 1295 /// Indent.
1270 indent() { 1296 indent() {
1271 writer.indent(); 1297 writer.indent();
1272 } 1298 }
1273 1299
1274 /// Unindent 1300 /// Unindent
1275 unindent() { 1301 unindent() {
1276 writer.unindent(); 1302 writer.unindent();
1277 } 1303 }
1278 1304
1279 1305 /// Print this statement as if it were a block (e.g., surrounded by braces).
1306 printAsBlock(Statement statement) {
1307 if (statement is! Block) {
1308 token(OPEN_CURLY);
1309 indent();
1310 newlines();
1311 visit(statement);
1312 newlines();
1313 unindent();
1314 token(CLOSE_CURLY);
1315 } else {
1316 visit(statement);
1317 }
1318 }
1319
1280 /// Emit any detected comments and newlines or a minimum as specified 1320 /// Emit any detected comments and newlines or a minimum as specified
1281 /// by [min]. 1321 /// by [min].
1282 int emitPrecedingCommentsAndNewlines(Token token, {min: 0}) { 1322 int emitPrecedingCommentsAndNewlines(Token token, {min: 0}) {
1283 1323
1284 var comment = token.precedingComments; 1324 var comment = token.precedingComments;
1285 var currentToken = comment != null ? comment : token; 1325 var currentToken = comment != null ? comment : token;
1286 1326
1287 //Handle EOLs before newlines 1327 //Handle EOLs before newlines
1288 if (isAtEOL(comment)) { 1328 if (isAtEOL(comment)) {
1289 emitComment(comment, previousToken); 1329 emitComment(comment, previousToken);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1354 /// Count newlines preceeding this [node]. 1394 /// Count newlines preceeding this [node].
1355 int countPrecedingNewlines(ASTNode node) => 1395 int countPrecedingNewlines(ASTNode node) =>
1356 countNewlinesBetween(node.beginToken.previous, node.beginToken); 1396 countNewlinesBetween(node.beginToken.previous, node.beginToken);
1357 1397
1358 /// Count newlines succeeding this [node]. 1398 /// Count newlines succeeding this [node].
1359 int countSucceedingNewlines(ASTNode node) => node == null ? 0 : 1399 int countSucceedingNewlines(ASTNode node) => node == null ? 0 :
1360 countNewlinesBetween(node.endToken, node.endToken.next); 1400 countNewlinesBetween(node.endToken, node.endToken.next);
1361 1401
1362 /// Count the blanks between these two tokens. 1402 /// Count the blanks between these two tokens.
1363 int countNewlinesBetween(Token last, Token current) { 1403 int countNewlinesBetween(Token last, Token current) {
1364 if (last == null || current == null) { 1404 if (last == null || current == null || isSynthetic(last)) {
1365 return 0; 1405 return 0;
1366 } 1406 }
1367 1407
1368 return linesBetween(last.end - 1, current.offset); 1408 return linesBetween(last.end - 1, current.offset);
1369 } 1409 }
1370 1410
1371 /// Calculate the newlines that should separate these comments. 1411 /// Calculate the newlines that should separate these comments.
1372 int calculateNewlinesBetweenComments(Token last, Token current) { 1412 int calculateNewlinesBetweenComments(Token last, Token current) {
1373 // Insist on a newline after doc comments or single line comments 1413 // Insist on a newline after doc comments or single line comments
1374 // (NOTE that EOL comments have already been processed). 1414 // (NOTE that EOL comments have already been processed).
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1407 var lastLine = 1447 var lastLine =
1408 lineInfo.getLocation(lastOffset).lineNumber; 1448 lineInfo.getLocation(lastOffset).lineNumber;
1409 var currentLine = 1449 var currentLine =
1410 lineInfo.getLocation(currentOffset).lineNumber; 1450 lineInfo.getLocation(currentOffset).lineNumber;
1411 return currentLine - lastLine; 1451 return currentLine - lastLine;
1412 } 1452 }
1413 1453
1414 String toString() => writer.toString(); 1454 String toString() => writer.toString();
1415 1455
1416 } 1456 }
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