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

Unified Diff: dart_style/lib/src/argument_list_visitor.dart

Issue 1400473008: Roll Observatory packages and add a roll script (Closed) Base URL: git@github.com:dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « dart_style/lib/src/._formatter_options.dart ('k') | dart_style/lib/src/call_chain_visitor.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: dart_style/lib/src/argument_list_visitor.dart
diff --git a/dart_style/lib/src/argument_list_visitor.dart b/dart_style/lib/src/argument_list_visitor.dart
deleted file mode 100644
index c45b73724827255098d99f0f86c7a0c6a4045d40..0000000000000000000000000000000000000000
--- a/dart_style/lib/src/argument_list_visitor.dart
+++ /dev/null
@@ -1,419 +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.argument_list_visitor;
-
-import 'package:analyzer/analyzer.dart';
-
-import 'chunk.dart';
-import 'rule/argument.dart';
-import 'rule/rule.dart';
-import 'source_visitor.dart';
-
-/// Helper class for [SourceVisitor] that handles visiting and writing an
-/// [ArgumentList], including all of the special code needed to handle function
-/// and collection arguments.
-class ArgumentListVisitor {
- final SourceVisitor _visitor;
-
- final ArgumentList _node;
-
- /// The normal arguments preceding any block function arguments.
- final ArgumentSublist _arguments;
-
- /// The contiguous list of block function arguments, if any.
- ///
- /// Otherwise, this is `null`.
- final List<Expression> _functions;
-
- /// If there are block function arguments, this is the arguments after them.
- ///
- /// Otherwise, this is `null`.
- final ArgumentSublist _argumentsAfterFunctions;
-
- /// Returns `true` if there is only a single positional argument.
- bool get _isSingle =>
- _node.arguments.length == 1 && _node.arguments.single is! NamedExpression;
-
- /// Whether this argument list has any collection or block function arguments.
- bool get hasBlockArguments =>
- _arguments._collections.isNotEmpty || _functions != null;
-
- /// Whether this argument list should force the containing method chain to
- /// add a level of block nesting.
- bool get nestMethodArguments {
- // If there are block arguments, we don't want the method to force them to
- // the right.
- if (hasBlockArguments) return false;
-
- // Corner case: If there is just a single argument, don't bump the nesting.
- // This lets us avoid spurious indentation in cases like:
- //
- // object.method(function(() {
- // body;
- // }));
- return _node.arguments.length > 1;
- }
-
- factory ArgumentListVisitor(SourceVisitor visitor, ArgumentList node) {
- // Look for a single contiguous range of block function arguments.
- var functionsStart;
- var functionsEnd;
-
- for (var i = 0; i < node.arguments.length; i++) {
- var argument = node.arguments[i];
- if (_isBlockFunction(argument)) {
- if (functionsStart == null) functionsStart = i;
-
- // The functions must be one contiguous section.
- if (functionsEnd != null && functionsEnd != i) {
- functionsStart = null;
- functionsEnd = null;
- break;
- }
-
- functionsEnd = i + 1;
- }
- }
-
- if (functionsStart == null) {
- // No functions, so there is just a single argument list.
- return new ArgumentListVisitor._(visitor, node,
- new ArgumentSublist(node.arguments, node.arguments), null, null);
- }
-
- // Split the arguments into two independent argument lists with the
- // functions in the middle.
- var argumentsBefore = node.arguments.take(functionsStart).toList();
- var functions = node.arguments.sublist(functionsStart, functionsEnd);
- var argumentsAfter = node.arguments.skip(functionsEnd).toList();
-
- return new ArgumentListVisitor._(
- visitor,
- node,
- new ArgumentSublist(node.arguments, argumentsBefore),
- functions,
- new ArgumentSublist(node.arguments, argumentsAfter));
- }
-
- ArgumentListVisitor._(this._visitor, this._node, this._arguments,
- this._functions, this._argumentsAfterFunctions);
-
- /// Builds chunks for the call chain.
- void visit() {
- // If there is just one positional argument, it tends to look weird to
- // split before it, so try not to.
- if (_isSingle) _visitor.builder.startSpan();
-
- // Nest around the parentheses in case there are comments before or after
- // them.
- _visitor.builder.nestExpression();
- _visitor.builder.startSpan();
- _visitor.token(_node.leftParenthesis);
-
- _arguments.visit(_visitor);
-
- _visitor.builder.endSpan();
-
- if (_functions != null) {
- // TODO(rnystrom): It might look better to treat the parameter list of the
- // first function as if it were an argument in the preceding argument list
- // instead of just having this little solo split here. That would try to
- // keep the parameter list with other arguments when possible, and, I
- // think, generally look nicer.
- if (_functions.first == _node.arguments.first) {
- _visitor.soloZeroSplit();
- } else {
- _visitor.soloSplit();
- }
-
- for (var argument in _functions) {
- if (argument != _functions.first) _visitor.space();
-
- _visitor.visit(argument);
-
- // Write the trailing comma.
- if (argument != _node.arguments.last) {
- _visitor.token(argument.endToken.next);
- }
- }
-
- _visitor.builder.startSpan();
- _argumentsAfterFunctions.visit(_visitor);
- _visitor.builder.endSpan();
- }
-
- _visitor.token(_node.rightParenthesis);
-
- _visitor.builder.unnest();
-
- if (_isSingle) _visitor.builder.endSpan();
- }
-
- /// Returns `true` if [expression] is a [FunctionExpression] with a block
- /// body.
- static bool _isBlockFunction(Expression expression) {
- if (expression is NamedExpression) {
- expression = (expression as NamedExpression).expression;
- }
-
- // Allow functions wrapped in dotted method calls like "a.b.c(() { ... })".
- if (expression is MethodInvocation) {
- if (!_isValidWrappingTarget(expression.target)) return false;
- if (expression.argumentList.arguments.length != 1) return false;
-
- return _isBlockFunction(expression.argumentList.arguments.single);
- }
-
- // Curly body functions are.
- if (expression is! FunctionExpression) return false;
- var function = expression as FunctionExpression;
- return function.body is BlockFunctionBody;
- }
-
- /// Returns `true` if [expression] is a valid method invocation target for
- /// an invocation that wraps a function literal argument.
- static bool _isValidWrappingTarget(Expression expression) {
- // Allow bare function calls.
- if (expression == null) return true;
-
- // Allow property accesses.
- while (expression is PropertyAccess) {
- expression = (expression as PropertyAccess).target;
- }
-
- if (expression is PrefixedIdentifier) return true;
- if (expression is SimpleIdentifier) return true;
-
- return false;
- }
-}
-
-/// A range of arguments from a complete argument list.
-///
-/// One of these typically covers all of the arguments in an invocation. But,
-/// when an argument list has block functions in the middle, the arguments
-/// before and after the functions are treated as separate independent lists.
-/// In that case, there will be two of these.
-class ArgumentSublist {
- /// The full argument list from the AST.
- final List<Expression> _allArguments;
-
- /// The positional arguments, in order.
- final List<Expression> _positional;
-
- /// The named arguments, in order.
- final List<Expression> _named;
-
- /// The arguments that are collection literals that get special formatting.
- final Set<Expression> _collections;
-
- /// The number of leading collections.
- ///
- /// If all arguments are collections, this counts them.
- final int _leadingCollections;
-
- /// The number of trailing collections.
- ///
- /// If all arguments are collections, this is zero.
- final int _trailingCollections;
-
- /// The rule used to split the bodies of all of the collection arguments.
- Rule get _collectionRule {
- // Lazy initialize.
- if (_collectionRuleField == null && _collections.isNotEmpty) {
- _collectionRuleField = new SimpleRule(cost: Cost.splitCollections);
- }
-
- return _collectionRuleField;
- }
-
- Rule _collectionRuleField;
-
- bool get _hasMultipleArguments => _positional.length + _named.length > 1;
-
- factory ArgumentSublist(
- List<Expression> allArguments, List<Expression> arguments) {
- // Assumes named arguments follow all positional ones.
- var positional =
- arguments.takeWhile((arg) => arg is! NamedExpression).toList();
- var named = arguments.skip(positional.length).toList();
-
- var collections = arguments.where(_isCollectionArgument).toSet();
-
- // Count the leading arguments that are collection literals.
- var leadingCollections = 0;
- for (var argument in arguments) {
- if (!collections.contains(argument)) break;
- leadingCollections++;
- }
-
- // Count the trailing arguments that are collection literals.
- var trailingCollections = 0;
- if (leadingCollections != arguments.length) {
- for (var argument in arguments.reversed) {
- if (!collections.contains(argument)) break;
- trailingCollections++;
- }
- }
-
- // If only some of the named arguments are collections, treat none of them
- // specially. Avoids cases like:
- //
- // function(
- // a: arg,
- // b: [
- // ...
- // ]);
- if (trailingCollections < named.length) trailingCollections = 0;
-
- // Collections must all be a prefix or suffix of the argument list (and not
- // both).
- if (leadingCollections != collections.length) leadingCollections = 0;
- if (trailingCollections != collections.length) trailingCollections = 0;
-
- // Ignore any collections in the middle of the argument list.
- if (leadingCollections == 0 && trailingCollections == 0) {
- collections.clear();
- }
-
- return new ArgumentSublist._(allArguments, positional, named, collections,
- leadingCollections, trailingCollections);
- }
-
- ArgumentSublist._(this._allArguments, this._positional, this._named,
- this._collections, this._leadingCollections, this._trailingCollections);
-
- void visit(SourceVisitor visitor) {
- var rule = _visitPositional(visitor);
- _visitNamed(visitor, rule);
- }
-
- /// Writes the positional arguments, if any.
- PositionalRule _visitPositional(SourceVisitor visitor) {
- if (_positional.isEmpty) return null;
-
- // Allow splitting after "(".
- var rule;
- if (_positional.length == 1) {
- rule = new SinglePositionalRule(_collectionRule,
- splitsOnInnerRules: _allArguments.length > 1 &&
- !_isCollectionArgument(_positional.first));
- } else {
- // Only count the positional bodies in the positional rule.
- var leadingPositional = _leadingCollections;
- if (_leadingCollections == _positional.length + _named.length) {
- leadingPositional -= _named.length;
- }
-
- var trailingPositional = _trailingCollections - _named.length;
- rule = new MultiplePositionalRule(
- _collectionRule, leadingPositional, trailingPositional);
- }
-
- visitor.builder.startRule(rule);
-
- var chunk;
- if (_isFirstArgument(_positional.first)) {
- chunk = visitor.zeroSplit();
- } else {
- chunk = visitor.split();
- }
- rule.beforeArgument(chunk);
-
- // Try to not split the arguments.
- visitor.builder.startSpan(Cost.positionalArguments);
-
- for (var argument in _positional) {
- _visitArgument(visitor, rule, argument);
-
- // Positional arguments split independently.
- if (argument != _positional.last) {
- rule.beforeArgument(visitor.split());
- }
- }
-
- visitor.builder.endSpan();
- visitor.builder.endRule();
-
- return rule;
- }
-
- /// Writes the named arguments, if any.
- void _visitNamed(SourceVisitor visitor, PositionalRule rule) {
- if (_named.isEmpty) return;
-
- var positionalRule = rule;
- var namedRule = new NamedRule(_collectionRule);
- visitor.builder.startRule(namedRule);
-
- // Let the positional args force the named ones to split.
- if (positionalRule != null) {
- positionalRule.setNamedArgsRule(namedRule);
- }
-
- // Split before the first named argument.
- namedRule.beforeArguments(
- visitor.builder.split(space: !_isFirstArgument(_named.first)));
-
- for (var argument in _named) {
- _visitArgument(visitor, namedRule, argument);
-
- // Write the split.
- if (argument != _named.last) visitor.split();
- }
-
- visitor.builder.endRule();
- }
-
- void _visitArgument(
- SourceVisitor visitor, ArgumentRule rule, Expression argument) {
- // If we're about to write a collection argument, handle it specially.
- if (_collections.contains(argument)) {
- if (rule != null) rule.beforeCollection();
-
- // Tell it to use the rule we've already created.
- visitor.setNextLiteralBodyRule(_collectionRule);
- } else if (_hasMultipleArguments) {
- // Corner case: If there is just a single argument, don't bump the
- // nesting. This lets us avoid spurious indentation in cases like:
- //
- // function(function(() {
- // body;
- // }));
- visitor.builder.startBlockArgumentNesting();
- }
-
- visitor.visit(argument);
-
- if (_collections.contains(argument)) {
- if (rule != null) rule.afterCollection();
- } else if (_hasMultipleArguments) {
- visitor.builder.endBlockArgumentNesting();
- }
-
- // Write the trailing comma.
- if (!_isLastArgument(argument)) {
- visitor.token(argument.endToken.next);
- }
- }
-
- bool _isFirstArgument(Expression argument) => argument == _allArguments.first;
-
- bool _isLastArgument(Expression argument) => argument == _allArguments.last;
-
- /// Returns true if [expression] denotes a collection literal argument.
- ///
- /// Similar to block functions, collection arguments can get special
- /// indentation to make them look more statement-like.
- static bool _isCollectionArgument(Expression expression) {
- if (expression is NamedExpression) {
- expression = (expression as NamedExpression).expression;
- }
-
- // TODO(rnystrom): Should we step into parenthesized expressions?
-
- return expression is ListLiteral || expression is MapLiteral;
- }
-}
« no previous file with comments | « dart_style/lib/src/._formatter_options.dart ('k') | dart_style/lib/src/call_chain_visitor.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698