Index: dart_style/lib/src/call_chain_visitor.dart |
diff --git a/dart_style/lib/src/call_chain_visitor.dart b/dart_style/lib/src/call_chain_visitor.dart |
deleted file mode 100644 |
index 36faccaab5a9289b25f471e7a1f5adcd0efa1832..0000000000000000000000000000000000000000 |
--- a/dart_style/lib/src/call_chain_visitor.dart |
+++ /dev/null |
@@ -1,247 +0,0 @@ |
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-library dart_style.src.call_chain_visitor; |
- |
-import 'package:analyzer/analyzer.dart'; |
- |
-import 'argument_list_visitor.dart'; |
-import 'rule/argument.dart'; |
-import 'source_visitor.dart'; |
- |
-/// Helper class for [SourceVisitor] that handles visiting and writing a |
-/// chained series of method invocations, property accesses, and/or prefix |
-/// expressions. In other words, anything using the "." operator. |
-class CallChainVisitor { |
- final SourceVisitor _visitor; |
- |
- /// The initial target of the call chain. |
- /// |
- /// This may be any expression except [MethodInvocation], [PropertyAccess] or |
- /// [PrefixedIdentifier]. |
- final Expression _target; |
- |
- /// The list of dotted names ([PropertyAccess] and [PrefixedIdentifier] at |
- /// the start of the call chain. |
- /// |
- /// This will be empty if the [_target] is not a [SimpleIdentifier]. |
- final List<Expression> _properties; |
- |
- /// The mixed method calls and property accesses in the call chain in the |
- /// order that they appear in the source. |
- final List<Expression> _calls; |
- |
- /// Whether or not a [Rule] is currently active for the call chain. |
- bool _ruleEnabled = false; |
- |
- /// Whether or not the span wrapping the call chain is currently active. |
- bool _spanEnded = false; |
- |
- /// Creates a new call chain visitor for [visitor] starting with [node]. |
- /// |
- /// The [node] is the outermost expression containing the chained "." |
- /// operators and must be a [MethodInvocation], [PropertyAccess] or |
- /// [PrefixedIdentifier]. |
- factory CallChainVisitor(SourceVisitor visitor, Expression node) { |
- var target; |
- |
- // Recursively walk the chain of calls and turn the tree into a list. |
- var calls = []; |
- flatten(expression) { |
- target = expression; |
- |
- if (expression is MethodInvocation && expression.target != null) { |
- flatten(expression.target); |
- calls.add(expression); |
- } else if (expression is PropertyAccess && expression.target != null) { |
- flatten(expression.target); |
- calls.add(expression); |
- } else if (expression is PrefixedIdentifier) { |
- flatten(expression.prefix); |
- calls.add(expression); |
- } |
- } |
- |
- flatten(node); |
- |
- // An expression that starts with a series of dotted names gets treated a |
- // little specially. We don't force leading properties to split with the |
- // rest of the chain. Allows code like: |
- // |
- // address.street.number |
- // .toString() |
- // .length; |
- var properties = []; |
- if (target is SimpleIdentifier) { |
- properties = |
- calls.takeWhile((call) => call is! MethodInvocation).toList(); |
- } |
- |
- calls.removeRange(0, properties.length); |
- |
- return new CallChainVisitor._(visitor, target, properties, calls); |
- } |
- |
- CallChainVisitor._( |
- this._visitor, this._target, this._properties, this._calls); |
- |
- /// Builds chunks for the call chain. |
- /// |
- /// If [unnest] is `false` than this will not close the expression nesting |
- /// created for the call chain and the caller must end it. Used by cascades |
- /// to force a cascade after a method chain to be more deeply nested than |
- /// the methods. |
- void visit({bool unnest}) { |
- if (unnest == null) unnest = true; |
- |
- _visitor.builder.nestExpression(); |
- |
- // Try to keep the entire method invocation one line. |
- _visitor.builder.startSpan(); |
- |
- _visitor.visit(_target); |
- |
- // Leading properties split like positional arguments: either not at all, |
- // before one ".", or before all of them. |
- if (_properties.length == 1) { |
- _visitor.soloZeroSplit(); |
- _writeCall(_properties.single); |
- } else if (_properties.length > 1) { |
- var argRule = new MultiplePositionalRule(null, 0, 0); |
- _visitor.builder.startRule(argRule); |
- |
- for (var property in _properties) { |
- argRule.beforeArgument(_visitor.zeroSplit()); |
- _writeCall(property); |
- } |
- |
- _visitor.builder.endRule(); |
- } |
- |
- // The remaining chain of calls generally split atomically (either all or |
- // none), except that block arguments may split a chain into two parts. |
- for (var call in _calls) { |
- _enableRule(); |
- _visitor.zeroSplit(); |
- _writeCall(call); |
- } |
- |
- _disableRule(); |
- _endSpan(); |
- |
- if (unnest) _visitor.builder.unnest(); |
- } |
- |
- /// Writes [call], which must be one of the supported expression types. |
- void _writeCall(Expression call) { |
- if (call is MethodInvocation) { |
- _writeInvocation(call); |
- } else if (call is PropertyAccess) { |
- _writePropertyAccess(call); |
- } else if (call is PrefixedIdentifier) { |
- _writePrefixedIdentifier(call); |
- } else { |
- // Unexpected type. |
- assert(false); |
- } |
- } |
- |
- void _writeInvocation(MethodInvocation invocation) { |
- _visitor.token(invocation.operator); |
- _visitor.token(invocation.methodName.token); |
- |
- // If a method's argument list includes any block arguments, there's a |
- // good chance it will split. Treat the chains before and after that as |
- // separate unrelated method chains. |
- // |
- // This is kind of a hack since it treats methods before and after a |
- // collection literal argument differently even when the collection |
- // doesn't split, but it works out OK in practice. |
- // |
- // Doing something more precise would require setting up a bunch of complex |
- // constraints between various rules. You'd basically have to say "if the |
- // block argument splits then allow the chain after it to split |
- // independently, otherwise force it to follow the previous chain". |
- var args = new ArgumentListVisitor(_visitor, invocation.argumentList); |
- |
- // Stop the rule after the last call, but before its arguments. This |
- // allows unsplit chains where the last argument list wraps, like: |
- // |
- // foo().bar().baz( |
- // argument, list); |
- // |
- // Also stop the rule to split the argument list at any call with |
- // block arguments. This makes for nicer chains of higher-order method |
- // calls, like: |
- // |
- // items.map((element) { |
- // ... |
- // }).where((element) { |
- // ... |
- // }); |
- if (invocation == _calls.last || args.hasBlockArguments) _disableRule(); |
- |
- if (args.nestMethodArguments) _visitor.builder.startBlockArgumentNesting(); |
- |
- // For a single method call on an identifier, stop the span before the |
- // arguments to make it easier to keep the call name with the target. In |
- // other words, prefer: |
- // |
- // target.method( |
- // argument, list); |
- // |
- // Over: |
- // |
- // target |
- // .method(argument, list); |
- // |
- // Alternatively, the way to think of this is try to avoid splitting on the |
- // "." when calling a single method on a single name. This is especially |
- // important because the identifier is often a library prefix, and splitting |
- // there looks really odd. |
- if (_properties.isEmpty && |
- _calls.length == 1 && |
- _target is SimpleIdentifier) { |
- _endSpan(); |
- } |
- |
- _visitor.visit(invocation.argumentList); |
- |
- 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; |
- |
- _visitor.builder.endRule(); |
- _ruleEnabled = false; |
- } |
- |
- /// Creates a new method chain [Rule] if one is not already active. |
- void _enableRule() { |
- if (_ruleEnabled) return; |
- |
- _visitor.builder.startRule(); |
- _ruleEnabled = true; |
- } |
- |
- /// Ends the span wrapping the call chain if it hasn't ended already. |
- void _endSpan() { |
- if (_spanEnded) return; |
- |
- _visitor.builder.endSpan(); |
- _spanEnded = true; |
- } |
-} |