Permalink
Browse files

Handle index expressions in the middle of call chains.

R=pquitslund@google.com

Review URL: https://chromiumcodereview.appspot.com//1355203002 .
  • Loading branch information...
munificent committed Sep 21, 2015
1 parent c25dc29 commit 619dfbf1f73fe55b0ea071c67a9cea9f0f951609
View
@@ -4,6 +4,7 @@
* Consider a rule live if it constrains a rule in the overflow line (#407).
* Allow splitting in prefix expressions (#410).
* Don't collapse states that differ by unbound rule constraints (#424).
+* Handle index expressions in the middle of call chains.
# 0.2.0
View
@@ -44,10 +44,6 @@ void runFormatter(String source, int pageWidth, {bool isCompilationUnit}) {
result = formatter.formatStatement(source);
}
- if (debug.useAnsiColors) {
- result = result.replaceAll(" ", debug.gray(debug.unicodeMidDot));
- }
-
drawRuler("before", pageWidth);
print(source);
drawRuler("after", pageWidth);
@@ -51,14 +51,25 @@ class CallChainVisitor {
flatten(expression) {
target = expression;
- if (expression is MethodInvocation && expression.target != null) {
- flatten(expression.target);
+ // Treat index expressions where the target is a valid call in a method
+ // chain as being part of the call. Handles cases like:
+ //
+ // receiver
+ // .property
+ // .property[0]
+ // .property
+ // .property;
+ var call = expression;
+ while (call is IndexExpression) call = call.target;
+
+ if (call is MethodInvocation && call.target != null) {
+ flatten(call.target);
calls.add(expression);
- } else if (expression is PropertyAccess && expression.target != null) {
- flatten(expression.target);
+ } else if (call is PropertyAccess && call.target != null) {
+ flatten(call.target);
calls.add(expression);
- } else if (expression is PrefixedIdentifier) {
- flatten(expression.prefix);
+ } else if (call is PrefixedIdentifier) {
+ flatten(call.prefix);
calls.add(expression);
}
}
@@ -135,12 +146,19 @@ class CallChainVisitor {
/// Writes [call], which must be one of the supported expression types.
void _writeCall(Expression call) {
- if (call is MethodInvocation) {
+ if (call is IndexExpression) {
+ _visitor.builder.nestExpression();
+ _writeCall(call.target);
+ _visitor.finishIndexExpression(call);
+ _visitor.builder.unnest();
+ } else if (call is MethodInvocation) {
_writeInvocation(call);
} else if (call is PropertyAccess) {
- _writePropertyAccess(call);
+ _visitor.token(call.operator);
+ _visitor.visit(call.propertyName);
} else if (call is PrefixedIdentifier) {
- _writePrefixedIdentifier(call);
+ _visitor.token(call.period);
+ _visitor.visit(call.identifier);
} else {
// Unexpected type.
assert(false);
@@ -211,16 +229,6 @@ class CallChainVisitor {
if (args.nestMethodArguments) _visitor.builder.endBlockArgumentNesting();
}
- void _writePropertyAccess(PropertyAccess property) {
- _visitor.token(property.operator);
- _visitor.visit(property.propertyName);
- }
-
- void _writePrefixedIdentifier(PrefixedIdentifier prefix) {
- _visitor.token(prefix.period);
- _visitor.visit(prefix.identifier);
- }
-
/// If a [Rule] for the method chain is currently active, ends it.
void _disableRule() {
if (_ruleEnabled == false) return;
@@ -1012,8 +1012,18 @@ class SourceVisitor implements AstVisitor {
visit(node.target);
}
+ finishIndexExpression(node);
+
+ builder.unnest();
+ }
+
+ /// Visit the index part of [node], excluding the target.
+ ///
+ /// Called by [CallChainVisitor] to handle index expressions in the middle of
+ /// call chains.
+ void finishIndexExpression(IndexExpression node) {
if (node.target is IndexExpression) {
- // Corner case: On a chain of [] accesses, allow splitting between them.
+ // Edge case: On a chain of [] accesses, allow splitting between them.
// Produces nicer output in cases like:
//
// someJson['property']['property']['property']['property']...
@@ -1026,7 +1036,6 @@ class SourceVisitor implements AstVisitor {
visit(node.index);
token(node.rightBracket);
builder.endSpan();
- builder.unnest();
}
visitInstanceCreationExpression(InstanceCreationExpression node) {
@@ -246,4 +246,16 @@ final ListResultDescriptor<AnalysisError> HINTS =
build(body);
return irBuilder.makeConstructorDefinition(const [], const []);
});
- }
+ }
+>>> (indent 4)
+ Element expectedElement = (declarations[0] as TopLevelVariableDeclaration)
+ .variables
+ .variables[0]
+ .name
+ .staticElement;
+<<<
+ Element expectedElement = (declarations[0] as TopLevelVariableDeclaration)
+ .variables
+ .variables[0]
+ .name
+ .staticElement;
@@ -159,4 +159,34 @@ object
?.method()
.method()
?.method()
- .method();
+ .method();
+>>> index in property chain
+someReceiverObject.property1.property2
+ .property3[0]
+ .property4
+ .property5
+ .property6;
+<<<
+someReceiverObject
+ .property1
+ .property2
+ .property3[0]
+ .property4
+ .property5
+ .property6;
+>>> chained indexes
+someReceiverObject.property1.property2
+ .property3[argument]
+ [argument][argument]
+ .property4
+ .property5
+ .property6;
+<<<
+someReceiverObject
+ .property1
+ .property2
+ .property3[argument][argument]
+ [argument]
+ .property4
+ .property5
+ .property6;

0 comments on commit 619dfbf

Please sign in to comment.