Chromium Code Reviews| Index: pkg/analysis_server/lib/src/services/correction/assist_internal.dart |
| diff --git a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart |
| index 525a198d0775746ccd58a30bee4c5079c91d9c15..45c8abaf7bc1efd48d2c43dc26ba18c700eb05a5 100644 |
| --- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart |
| +++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart |
| @@ -81,6 +81,7 @@ class AssistProcessor { |
| _addProposal_assignToLocalVariable(); |
| _addProposal_convertToBlockFunctionBody(); |
| _addProposal_convertToExpressionFunctionBody(); |
| + _addProposal_convertToForIndexLoop(); |
| _addProposal_convertToIsNot_onIs(); |
| _addProposal_convertToIsNot_onNot(); |
| _addProposal_convertToIsNotEmpty(); |
| @@ -215,6 +216,44 @@ class AssistProcessor { |
| _addAssist(AssistKind.ADD_TYPE_ANNOTATION, []); |
| } |
| + void _addProposal_addTypeAnnotation_SimpleFormalParameter() { |
| + AstNode node = this.node; |
| + // should be the name of a simple parameter |
| + if (node is! SimpleIdentifier || node.parent is! SimpleFormalParameter) { |
| + _coverageMarker(); |
| + return; |
| + } |
| + SimpleIdentifier name = node; |
| + SimpleFormalParameter parameter = node.parent; |
| + // the parameter should not have a type |
| + if (parameter.type != null) { |
| + _coverageMarker(); |
| + return; |
| + } |
| + // prepare propagated type |
| + DartType type = name.propagatedType; |
| + // TODO(scheglov) If the parameter is in a method declaration, and if the |
| + // method overrides a method that has a type for the corresponding |
| + // parameter, it would be nice to copy down the type from the overridden |
| + // method. |
| + if (type is! InterfaceType) { |
| + _coverageMarker(); |
| + return; |
| + } |
| + // prepare type source |
| + String typeSource; |
| + { |
| + _configureTargetLocation(node); |
| + Set<LibraryElement> librariesToImport = new Set<LibraryElement>(); |
| + typeSource = utils.getTypeSource(type, librariesToImport); |
| + addLibraryImports(change, unitLibraryElement, librariesToImport); |
| + } |
| + // add edit |
| + _addInsertEdit(name.offset, '$typeSource '); |
| + // add proposal |
| + _addAssist(AssistKind.ADD_TYPE_ANNOTATION, []); |
| + } |
| + |
| void _addProposal_addTypeAnnotation_VariableDeclaration() { |
| AstNode node = this.node; |
| // check if "var v = 42;^" |
| @@ -270,44 +309,6 @@ class AssistProcessor { |
| _addAssist(AssistKind.ADD_TYPE_ANNOTATION, []); |
| } |
| - void _addProposal_addTypeAnnotation_SimpleFormalParameter() { |
| - AstNode node = this.node; |
| - // should be the name of a simple parameter |
| - if (node is! SimpleIdentifier || node.parent is! SimpleFormalParameter) { |
| - _coverageMarker(); |
| - return; |
| - } |
| - SimpleIdentifier name = node; |
| - SimpleFormalParameter parameter = node.parent; |
| - // the parameter should not have a type |
| - if (parameter.type != null) { |
| - _coverageMarker(); |
| - return; |
| - } |
| - // prepare propagated type |
| - DartType type = name.propagatedType; |
| - // TODO(scheglov) If the parameter is in a method declaration, and if the |
| - // method overrides a method that has a type for the corresponding |
| - // parameter, it would be nice to copy down the type from the overridden |
| - // method. |
| - if (type is! InterfaceType) { |
| - _coverageMarker(); |
| - return; |
| - } |
| - // prepare type source |
| - String typeSource; |
| - { |
| - _configureTargetLocation(node); |
| - Set<LibraryElement> librariesToImport = new Set<LibraryElement>(); |
| - typeSource = utils.getTypeSource(type, librariesToImport); |
| - addLibraryImports(change, unitLibraryElement, librariesToImport); |
| - } |
| - // add edit |
| - _addInsertEdit(name.offset, '$typeSource '); |
| - // add proposal |
| - _addAssist(AssistKind.ADD_TYPE_ANNOTATION, []); |
| - } |
| - |
| void _addProposal_assignToLocalVariable() { |
| // prepare enclosing ExpressionStatement |
| Statement statement = node.getAncestor((node) => node is Statement); |
| @@ -424,6 +425,81 @@ class AssistProcessor { |
| _addAssist(AssistKind.CONVERT_INTO_EXPRESSION_BODY, []); |
| } |
| + void _addProposal_convertToForIndexLoop() { |
| + // find enclosing ForEachStatement |
| + ForEachStatement forEachStatement = |
| + node.getAncestor((n) => n is ForEachStatement); |
| + if (forEachStatement == null) { |
| + _coverageMarker(); |
| + return; |
| + } |
| + if (selectionOffset < forEachStatement.offset || |
| + forEachStatement.rightParenthesis.end < selectionOffset) { |
| + _coverageMarker(); |
| + return; |
| + } |
| + // loop should declare variable |
| + DeclaredIdentifier loopVariable = forEachStatement.loopVariable; |
| + if (loopVariable == null) { |
| + _coverageMarker(); |
| + return; |
| + } |
| + // iterable should be VariableElement |
| + String listName; |
| + Expression iterable = forEachStatement.iterable; |
| + if (iterable is SimpleIdentifier && |
| + iterable.staticElement is VariableElement) { |
| + listName = iterable.name; |
| + } else { |
| + _coverageMarker(); |
| + return; |
| + } |
| + // iterable should be List |
| + { |
| + DartType iterableType = iterable.bestType; |
| + InterfaceType listType = context.typeProvider.listType; |
| + if (iterableType is InterfaceType && |
| + iterableType.element == listType.element) {} else { |
|
Brian Wilkerson
2015/03/16 13:54:45
This is ugly. Consider inverting the condition.
|
| + _coverageMarker(); |
| + return; |
| + } |
| + } |
| + // body should be Block |
| + if (forEachStatement.body is! Block) { |
| + _coverageMarker(); |
| + return; |
| + } |
| + Block body = forEachStatement.body; |
| + // prepare a name for the index variable |
| + String indexName; |
| + { |
| + Set<String> conflicts = |
| + utils.findPossibleLocalVariableConflicts(forEachStatement.offset); |
| + if (!conflicts.contains('i')) { |
| + indexName = 'i'; |
| + } else if (!conflicts.contains('j')) { |
| + indexName = 'j'; |
| + } else if (!conflicts.contains('k')) { |
| + indexName = 'k'; |
| + } else { |
| + _coverageMarker(); |
| + return; |
| + } |
| + } |
| + // prepare environment |
| + String prefix = utils.getNodePrefix(forEachStatement); |
| + String indent = utils.getIndent(1); |
| + int firstBlockLine = utils.getLineContentEnd(body.leftBracket.end); |
| + // add change |
| + _addReplaceEdit( |
| + rangeStartEnd(forEachStatement, forEachStatement.rightParenthesis), |
| + 'for (int $indexName = 0; $indexName < $listName.length; $indexName++)'); |
| + _addInsertEdit(firstBlockLine, |
| + '$prefix$indent$loopVariable = $listName[$indexName];$eol'); |
| + // add proposal |
| + _addAssist(AssistKind.CONVERT_INTO_FOR_INDEX, []); |
| + } |
| + |
| void _addProposal_convertToIsNot_onIs() { |
| // may be child of "is" |
| AstNode node = this.node; |