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

Unified Diff: pkg/analysis_services/lib/src/correction/assist.dart

Issue 438453002: Port and test more assists. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 5 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
Index: pkg/analysis_services/lib/src/correction/assist.dart
diff --git a/pkg/analysis_services/lib/src/correction/assist.dart b/pkg/analysis_services/lib/src/correction/assist.dart
index a2ac69e6598711f7cd139989577f2a15699ff199..ef1d76fcf23e6636bbeede367708c7454fa5fede 100644
--- a/pkg/analysis_services/lib/src/correction/assist.dart
+++ b/pkg/analysis_services/lib/src/correction/assist.dart
@@ -9,6 +9,7 @@ library services.src.correction.assist;
import 'package:analysis_services/correction/assist.dart';
import 'package:analysis_services/correction/change.dart';
+import 'package:analysis_services/search/hierarchy.dart';
import 'package:analysis_services/search/search_engine.dart';
import 'package:analysis_services/src/correction/name_suggestion.dart';
import 'package:analysis_services/src/correction/source_buffer.dart';
@@ -46,8 +47,6 @@ class AssistProcessor {
int selectionEnd;
CorrectionUtils utils;
AstNode node;
- AstNode coveredNode;
-
AssistProcessor(this.searchEngine, this.source, this.file, this.unit,
this.selectionOffset, this.selectionLength) {
@@ -65,8 +64,7 @@ class AssistProcessor {
List<Assist> compute() {
utils = new CorrectionUtils(unit);
- node = new NodeLocator.con1(selectionOffset).searchWithin(unit);
- coveredNode = new NodeLocator.con2(
+ node = new NodeLocator.con2(
selectionOffset,
selectionEnd).searchWithin(unit);
// try to add proposals
@@ -94,6 +92,31 @@ class AssistProcessor {
return assists;
}
+ FunctionBody getEnclosingFunctionBody() {
+ {
+ FunctionExpression function =
+ node.getAncestor((node) => node is FunctionExpression);
+ if (function != null) {
+ return function.body;
+ }
+ }
+ {
+ FunctionDeclaration function =
+ node.getAncestor((node) => node is FunctionDeclaration);
+ if (function != null) {
+ return function.functionExpression.body;
+ }
+ }
+ {
+ MethodDeclaration method =
+ node.getAncestor((node) => node is MethodDeclaration);
+ if (method != null) {
+ return method.body;
+ }
+ }
+ return null;
+ }
+
void _addAssist(AssistKind kind, List args, {String assistFile}) {
if (assistFile == null) {
assistFile = file;
@@ -229,256 +252,255 @@ class AssistProcessor {
}
void _addProposal_convertToBlockFunctionBody() {
- // TODO(scheglov) implement
-// FunctionBody body = enclosingFunctionBody;
-// // prepare expression body
-// if (body is! ExpressionFunctionBody) {
-// return;
-// }
-// Expression returnValue = (body as ExpressionFunctionBody).expression;
-// // prepare prefix
-// String prefix;
-// {
-// AstNode bodyParent = body.parent;
-// prefix = utils.getNodePrefix(bodyParent);
-// }
-// // add change
-// String eol = utils.endOfLine;
-// String indent = utils.getIndent(1);
-// String newBodySource =
-// "{${eol}${prefix}${indent}return ${_getSource(returnValue)};${eol}${prefix}}";
-// _addReplaceEdit(rangeNode(body), newBodySource);
-// // add proposal
-// _addAssist(AssistKind.CONVERT_INTO_BLOCK_BODY, []);
+ FunctionBody body = getEnclosingFunctionBody();
+ // prepare expression body
+ if (body is! ExpressionFunctionBody) {
+ _coverageMarker();
+ return;
+ }
+ Expression returnValue = (body as ExpressionFunctionBody).expression;
+ // prepare prefix
+ String prefix;
+ {
+ AstNode bodyParent = body.parent;
Brian Wilkerson 2014/07/31 13:24:58 You know I don't like nested blocks in general, bu
scheglov 2014/07/31 16:09:03 Done.
+ prefix = utils.getNodePrefix(bodyParent);
+ }
+ // add change
+ String indent = utils.getIndent(1);
+ String returnSource = 'return ' + _getSource(returnValue);
+ String newBodySource = "{$eol$prefix${indent}$returnSource;$eol$prefix}";
+ _addReplaceEdit(rangeNode(body), newBodySource);
+ // add proposal
+ _addAssist(AssistKind.CONVERT_INTO_BLOCK_BODY, []);
}
void _addProposal_convertToExpressionFunctionBody() {
- // TODO(scheglov) implement
-// // prepare current body
-// FunctionBody body = enclosingFunctionBody;
-// if (body is! BlockFunctionBody) {
-// return;
-// }
-// // prepare return statement
-// List<Statement> statements = (body as BlockFunctionBody).block.statements;
-// if (statements.length != 1) {
-// return;
-// }
-// if (statements[0] is! ReturnStatement) {
-// return;
-// }
-// ReturnStatement returnStatement = statements[0] as ReturnStatement;
-// // prepare returned expression
-// Expression returnExpression = returnStatement.expression;
-// if (returnExpression == null) {
-// return;
-// }
-// // add change
-// String newBodySource = "=> ${_getSource(returnExpression)}";
-// if (body.parent is! FunctionExpression ||
-// body.parent.parent is FunctionDeclaration) {
-// newBodySource += ";";
-// }
-// _addReplaceEdit(rangeNode(body), newBodySource);
-// // add proposal
-// _addAssist(
-// AssistKind.CONVERT_INTO_EXPRESSION_BODY,
-// []);
+ // prepare current body
+ FunctionBody body = getEnclosingFunctionBody();
+ if (body is! BlockFunctionBody) {
+ _coverageMarker();
+ return;
+ }
+ // prepare return statement
+ List<Statement> statements = (body as BlockFunctionBody).block.statements;
+ if (statements.length != 1) {
+ _coverageMarker();
+ return;
+ }
+ if (statements[0] is! ReturnStatement) {
+ _coverageMarker();
+ return;
+ }
+ ReturnStatement returnStatement = statements[0] as ReturnStatement;
+ // prepare returned expression
+ Expression returnExpression = returnStatement.expression;
+ if (returnExpression == null) {
+ _coverageMarker();
+ return;
+ }
+ // add change
+ String newBodySource = "=> ${_getSource(returnExpression)}";
+ if (body.parent is! FunctionExpression ||
+ body.parent.parent is FunctionDeclaration) {
+ newBodySource += ";";
+ }
+ _addReplaceEdit(rangeNode(body), newBodySource);
+ // add proposal
+ _addAssist(AssistKind.CONVERT_INTO_EXPRESSION_BODY, []);
}
/**
* Converts "!isEmpty" -> "isNotEmpty" if possible.
*/
void _addProposal_convertToIsNotEmpty() {
- // TODO(scheglov) implement
-// // prepare "expr.isEmpty"
-// AstNode isEmptyAccess = null;
-// SimpleIdentifier isEmptyIdentifier = null;
-// if (node is SimpleIdentifier) {
-// SimpleIdentifier identifier = node as SimpleIdentifier;
-// AstNode parent = identifier.parent;
-// // normal case (but rare)
-// if (parent is PropertyAccess) {
-// PropertyAccess propertyAccess = parent;
-// isEmptyIdentifier = propertyAccess.propertyName;
-// isEmptyAccess = propertyAccess;
-// }
-// // usual case
-// if (parent is PrefixedIdentifier) {
-// PrefixedIdentifier prefixedIdentifier = parent;
-// isEmptyIdentifier = prefixedIdentifier.identifier;
-// isEmptyAccess = prefixedIdentifier;
-// }
-// }
-// if (isEmptyIdentifier == null) {
-// return;
-// }
-// // should be "isEmpty"
-// Element propertyElement = isEmptyIdentifier.bestElement;
-// if (propertyElement == null || "isEmpty" != propertyElement.name) {
-// return;
-// }
-// // should have "isNotEmpty"
-// Element propertyTarget = propertyElement.enclosingElement;
-// if (propertyTarget == null ||
-// CorrectionUtils.getChildren2(propertyTarget, "isNotEmpty").isEmpty) {
-// return;
-// }
-// // should be in PrefixExpression
-// if (isEmptyAccess.parent is! PrefixExpression) {
-// return;
-// }
-// PrefixExpression prefixExpression =
-// isEmptyAccess.parent as PrefixExpression;
-// // should be !
-// if (prefixExpression.operator.type != TokenType.BANG) {
-// return;
-// }
-// // do replace
-// _addRemoveEdit(
-// rangeStartStart(prefixExpression, prefixExpression.operand));
-// _addReplaceEdit(
-// rangeNode(isEmptyIdentifier),
-// "isNotEmpty");
-// // add proposal
-// _addAssist(AssistKind.CONVERT_INTO_IS_NOT_EMPTY, []);
+ // prepare "expr.isEmpty"
+ AstNode isEmptyAccess = null;
+ SimpleIdentifier isEmptyIdentifier = null;
+ if (node is SimpleIdentifier) {
+ SimpleIdentifier identifier = node as SimpleIdentifier;
+ AstNode parent = identifier.parent;
+ // normal case (but rare)
+ if (parent is PropertyAccess) {
+ isEmptyIdentifier = parent.propertyName;
+ isEmptyAccess = parent;
+ }
+ // usual case
+ if (parent is PrefixedIdentifier) {
+ isEmptyIdentifier = parent.identifier;
+ isEmptyAccess = parent;
+ }
+ }
+ if (isEmptyIdentifier == null) {
+ _coverageMarker();
+ return;
+ }
+ // should be "isEmpty"
+ Element propertyElement = isEmptyIdentifier.bestElement;
+ if (propertyElement == null || "isEmpty" != propertyElement.name) {
+ _coverageMarker();
+ return;
+ }
+ // should have "isNotEmpty"
+ Element propertyTarget = propertyElement.enclosingElement;
+ if (propertyTarget == null ||
+ getChildren(propertyTarget, "isNotEmpty").isEmpty) {
+ _coverageMarker();
+ return;
+ }
+ // should be in PrefixExpression
+ if (isEmptyAccess.parent is! PrefixExpression) {
+ _coverageMarker();
+ return;
+ }
+ PrefixExpression prefixExpression =
+ isEmptyAccess.parent as PrefixExpression;
+ // should be !
+ if (prefixExpression.operator.type != TokenType.BANG) {
+ return;
+ }
+ // do replace
+ _addRemoveEdit(rangeStartStart(prefixExpression, prefixExpression.operand));
+ _addReplaceEdit(rangeNode(isEmptyIdentifier), "isNotEmpty");
+ // add proposal
+ _addAssist(AssistKind.CONVERT_INTO_IS_NOT_EMPTY, []);
}
void _addProposal_convertToIsNot_onIs() {
- // TODO(scheglov) implement
-// // may be child of "is"
-// AstNode node = this.node;
-// while (node != null && node is! IsExpression) {
-// node = node.parent;
-// }
-// // prepare "is"
-// if (node is! IsExpression) {
-// return;
-// }
-// IsExpression isExpression = node as IsExpression;
-// if (isExpression.notOperator != null) {
-// return;
-// }
-// // prepare enclosing ()
-// AstNode parent = isExpression.parent;
-// if (parent is! ParenthesizedExpression) {
-// return;
-// }
-// ParenthesizedExpression parExpression = parent as ParenthesizedExpression;
-// // prepare enclosing !()
-// AstNode parent2 = parent.parent;
-// if (parent2 is! PrefixExpression) {
-// return;
-// }
-// PrefixExpression prefExpression = parent2 as PrefixExpression;
-// if (prefExpression.operator.type != TokenType.BANG) {
-// return;
-// }
-// // strip !()
-// if (CorrectionUtils.getParentPrecedence(prefExpression) >=
-// TokenType.IS.precedence) {
-// _addRemoveEdit(rangeToken(prefExpression.operator));
-// } else {
-// _addRemoveEdit(
-// rangeStartEnd(
-// prefExpression,
-// parExpression.leftParenthesis));
-// _addRemoveEdit(
-// rangeStartEnd(
-// parExpression.rightParenthesis,
-// prefExpression));
-// }
-// _addInsertEdit(isExpression.isOperator.end, "!");
-// // add proposal
-// _addAssist(AssistKind.CONVERT_INTO_IS_NOT, []);
+ // may be child of "is"
+ AstNode node = this.node;
+ while (node != null && node is! IsExpression) {
+ node = node.parent;
+ }
+ // prepare "is"
+ if (node is! IsExpression) {
+ _coverageMarker();
+ return;
+ }
+ IsExpression isExpression = node as IsExpression;
+ if (isExpression.notOperator != null) {
+ _coverageMarker();
+ return;
+ }
+ // prepare enclosing ()
+ AstNode parent = isExpression.parent;
+ if (parent is! ParenthesizedExpression) {
+ _coverageMarker();
+ return;
+ }
+ ParenthesizedExpression parExpression = parent as ParenthesizedExpression;
+ // prepare enclosing !()
+ AstNode parent2 = parent.parent;
+ if (parent2 is! PrefixExpression) {
+ _coverageMarker();
+ return;
+ }
+ PrefixExpression prefExpression = parent2 as PrefixExpression;
+ if (prefExpression.operator.type != TokenType.BANG) {
+ _coverageMarker();
+ return;
+ }
+ // strip !()
+ if (getExpressionParentPrecedence(prefExpression) >=
+ TokenType.IS.precedence) {
+ _addRemoveEdit(rangeToken(prefExpression.operator));
+ } else {
+ _addRemoveEdit(
+ rangeStartEnd(prefExpression, parExpression.leftParenthesis));
+ _addRemoveEdit(
+ rangeStartEnd(parExpression.rightParenthesis, prefExpression));
+ }
+ _addInsertEdit(isExpression.isOperator.end, "!");
+ // add proposal
+ _addAssist(AssistKind.CONVERT_INTO_IS_NOT, []);
}
void _addProposal_convertToIsNot_onNot() {
- // TODO(scheglov) implement
-// // may be () in prefix expression
-// if (node is ParenthesizedExpression && node.parent is PrefixExpression) {
-// node = node.parent;
-// }
-// // prepare !()
-// if (node is! PrefixExpression) {
-// return;
-// }
-// PrefixExpression prefExpression = node as PrefixExpression;
-// // should be ! operator
-// if (prefExpression.operator.type != TokenType.BANG) {
-// return;
-// }
-// // prepare !()
-// Expression operand = prefExpression.operand;
-// if (operand is! ParenthesizedExpression) {
-// return;
-// }
-// ParenthesizedExpression parExpression = operand as ParenthesizedExpression;
-// operand = parExpression.expression;
-// // prepare "is"
-// if (operand is! IsExpression) {
-// return;
-// }
-// IsExpression isExpression = operand as IsExpression;
-// if (isExpression.notOperator != null) {
-// return;
-// }
-// // strip !()
-// if (getExpressionParentPrecedence(prefExpression) >=
-// TokenType.IS.precedence) {
-// _addRemoveEdit(rangeToken(prefExpression.operator));
-// } else {
-// _addRemoveEdit(
-// rangeStartEnd(
-// prefExpression,
-// parExpression.leftParenthesis));
-// _addRemoveEdit(
-// rangeStartEnd(
-// parExpression.rightParenthesis,
-// prefExpression));
-// }
-// _addInsertEdit(isExpression.isOperator.end, "!");
-// // add proposal
-// _addAssist(AssistKind.CONVERT_INTO_IS_NOT, []);
+ // may be () in prefix expression
+ if (node is ParenthesizedExpression && node.parent is PrefixExpression) {
+ node = node.parent;
+ }
+ // prepare !()
+ if (node is! PrefixExpression) {
+ _coverageMarker();
+ return;
+ }
+ PrefixExpression prefExpression = node as PrefixExpression;
+ // should be ! operator
+ if (prefExpression.operator.type != TokenType.BANG) {
+ _coverageMarker();
+ return;
+ }
+ // prepare !()
+ Expression operand = prefExpression.operand;
+ if (operand is! ParenthesizedExpression) {
+ _coverageMarker();
+ return;
+ }
+ ParenthesizedExpression parExpression = operand as ParenthesizedExpression;
+ operand = parExpression.expression;
+ // prepare "is"
+ if (operand is! IsExpression) {
+ _coverageMarker();
+ return;
+ }
+ IsExpression isExpression = operand as IsExpression;
+ if (isExpression.notOperator != null) {
+ _coverageMarker();
+ return;
+ }
+ // strip !()
+ if (getExpressionParentPrecedence(prefExpression) >=
+ TokenType.IS.precedence) {
+ _addRemoveEdit(rangeToken(prefExpression.operator));
+ } else {
+ _addRemoveEdit(
+ rangeStartEnd(prefExpression, parExpression.leftParenthesis));
+ _addRemoveEdit(
+ rangeStartEnd(parExpression.rightParenthesis, prefExpression));
+ }
+ _addInsertEdit(isExpression.isOperator.end, "!");
+ // add proposal
+ _addAssist(AssistKind.CONVERT_INTO_IS_NOT, []);
}
void _addProposal_exchangeOperands() {
- // TODO(scheglov) implement
-// // check that user invokes quick assist on binary expression
-// if (node is! BinaryExpression) {
-// return;
-// }
-// BinaryExpression binaryExpression = node as BinaryExpression;
-// // prepare operator position
-// int offset =
-// _isOperatorSelected(binaryExpression, _selectionOffset, _selectionLength);
-// if (offset == -1) {
-// return;
-// }
-// // add edits
-// {
-// Expression leftOperand = binaryExpression.leftOperand;
-// Expression rightOperand = binaryExpression.rightOperand;
-// // find "wide" enclosing binary expression with same operator
-// while (binaryExpression.parent is BinaryExpression) {
-// BinaryExpression newBinaryExpression =
-// binaryExpression.parent as BinaryExpression;
-// if (newBinaryExpression.operator.type !=
-// binaryExpression.operator.type) {
-// break;
-// }
-// binaryExpression = newBinaryExpression;
-// }
-// // exchange parts of "wide" expression parts
-// SourceRange leftRange =
-// rangeStartEnd(binaryExpression, leftOperand);
-// SourceRange rightRange =
-// rangeStartEnd(rightOperand, binaryExpression);
-// _addReplaceEdit(leftRange, _getSource2(rightRange));
-// _addReplaceEdit(rightRange, _getSource2(leftRange));
-// }
-// // add proposal
-// _addAssist(AssistKind.EXCHANGE_OPERANDS, []);
+ // check that user invokes quick assist on binary expression
+ if (node is! BinaryExpression) {
+ _coverageMarker();
+ return;
+ }
+ BinaryExpression binaryExpression = node as BinaryExpression;
+ // prepare operator position
+ if (!_isOperatorSelected(
+ binaryExpression,
+ selectionOffset,
+ selectionLength)) {
+ _coverageMarker();
+ return;
+ }
+ // add edits
+ {
+ Expression leftOperand = binaryExpression.leftOperand;
+ Expression rightOperand = binaryExpression.rightOperand;
+ // find "wide" enclosing binary expression with same operator
+ while (binaryExpression.parent is BinaryExpression) {
+ BinaryExpression newBinaryExpression =
+ binaryExpression.parent as BinaryExpression;
+ if (newBinaryExpression.operator.type !=
+ binaryExpression.operator.type) {
+ _coverageMarker();
+ break;
+ }
+ binaryExpression = newBinaryExpression;
+ }
+ // exchange parts of "wide" expression parts
+ SourceRange leftRange = rangeStartEnd(binaryExpression, leftOperand);
+ SourceRange rightRange = rangeStartEnd(rightOperand, binaryExpression);
+ _addReplaceEdit(leftRange, _getSource2(rightRange));
+ _addReplaceEdit(rightRange, _getSource2(leftRange));
+ }
+ // add proposal
+ _addAssist(AssistKind.EXCHANGE_OPERANDS, []);
}
void _addProposal_extractClassIntoPart() {
@@ -541,22 +563,20 @@ class AssistProcessor {
// // prepare whole import namespace
// ImportElement importElement = importDirective.element;
// Map<String, Element> namespace =
-// CorrectionUtils.getImportNamespace(importElement);
+// getImportNamespace(importElement);
// // prepare names of referenced elements (from this import)
// Set<String> referencedNames = new Set();
-// // TODO(scheglov)
-//// SearchEngine searchEngine = _assistContext.searchEngine;
-//// for (Element element in namespace.values) {
-//// List<SearchMatch> references =
-//// searchEngine.searchReferences(element, null, null);
-//// for (SearchMatch match in references) {
-//// LibraryElement library = match.element.library;
-//// if (_unitLibraryElement == library) {
-//// referencedNames.add(element.displayName);
-//// break;
-//// }
-//// }
-//// }
+// for (Element element in namespace.values) {
+// List<SearchMatch> references =
+// searchEngine.searchReferences(element, null, null);
+// for (SearchMatch match in references) {
+// LibraryElement library = match.element.library;
+// if (unitLibraryElement == library) {
+// referencedNames.add(element.displayName);
+// break;
+// }
+// }
+// }
// // ignore if unused
// if (referencedNames.isEmpty) {
// return;
@@ -591,9 +611,10 @@ class AssistProcessor {
// _addReplaceEdit(rangeNode(elseStatement), thenSource);
// // add proposal
// _addAssist(AssistKind.INVERT_IF_STATEMENT, []);
-// }
-//
-// void _addProposal_joinIfStatementInner() {
+ }
+
+ void _addProposal_joinIfStatementInner() {
+ // TODO(scheglov) implement
// // climb up condition to the (supposedly) "if" statement
// AstNode node = this.node;
// while (node is Expression) {
@@ -620,7 +641,6 @@ class AssistProcessor {
// }
// // prepare environment
// String prefix = utils.getNodePrefix(targetIfStatement);
-// String eol = utils.endOfLine;
// // merge conditions
// String condition;
// {
@@ -684,7 +704,6 @@ class AssistProcessor {
// }
// // prepare environment
// String prefix = utils.getNodePrefix(outerIfStatement);
-// String eol = utils.endOfLine;
// // merge conditions
// String condition;
// {
@@ -720,296 +739,292 @@ class AssistProcessor {
}
void _addProposal_joinVariableDeclaration_onAssignment() {
- // TODO(scheglov) implement
-// // check that node is LHS in assignment
-// if (node is SimpleIdentifier &&
-// node.parent is AssignmentExpression &&
-// identical((node.parent as AssignmentExpression).leftHandSide, node) &&
-// node.parent.parent is ExpressionStatement) {
-// } else {
-// return;
-// }
-// AssignmentExpression assignExpression =
-// node.parent as AssignmentExpression;
-// // check that binary expression is assignment
-// if (assignExpression.operator.type != TokenType.EQ) {
-// return;
-// }
-// // prepare "declaration" statement
-// Element element = (node as SimpleIdentifier).staticElement;
-// if (element == null) {
-// return;
-// }
-// int declOffset = element.nameOffset;
-// AstNode declNode = new NodeLocator.con1(declOffset).searchWithin(_unit);
-// if (declNode != null &&
-// declNode.parent is VariableDeclaration &&
-// identical((declNode.parent as VariableDeclaration).name, declNode) &&
-// declNode.parent.parent is VariableDeclarationList &&
-// declNode.parent.parent.parent is VariableDeclarationStatement) {
-// } else {
-// return;
-// }
-// VariableDeclaration decl = declNode.parent as VariableDeclaration;
-// VariableDeclarationStatement declStatement =
-// decl.parent.parent as VariableDeclarationStatement;
-// // may be has initializer
-// if (decl.initializer != null) {
-// return;
-// }
-// // check that "declaration" statement declared only one variable
-// if (declStatement.variables.variables.length != 1) {
-// return;
-// }
-//
-// // check that "declaration" and "assignment" statements are part of same Block
-// ExpressionStatement assignStatement =
-// node.parent.parent as ExpressionStatement;
-// if (assignStatement.parent is Block &&
-// identical(assignStatement.parent, declStatement.parent)) {
-// } else {
-// return;
-// }
-// Block block = assignStatement.parent as Block;
-// // check that "declaration" and "assignment" statements are adjacent
-// List<Statement> statements = block.statements;
-// if (statements.indexOf(assignStatement) ==
-// statements.indexOf(declStatement) + 1) {
-// } else {
-// return;
-// }
-// // add edits
-// {
-// int assignOffset = assignExpression.operator.offset;
-// _addReplaceEdit(
-// rangeEndStart(declNode, assignOffset),
-// " ");
-// }
-// // add proposal
-// _addAssist(AssistKind.JOIN_VARIABLE_DECLARATION, []);
+ // check that node is LHS in assignment
+ if (node is SimpleIdentifier &&
+ node.parent is AssignmentExpression &&
+ identical((node.parent as AssignmentExpression).leftHandSide, node) &&
+ node.parent.parent is ExpressionStatement) {
+ } else {
+ _coverageMarker();
+ return;
+ }
+ AssignmentExpression assignExpression = node.parent as AssignmentExpression;
+ // check that binary expression is assignment
+ if (assignExpression.operator.type != TokenType.EQ) {
+ _coverageMarker();
+ return;
+ }
+ // prepare "declaration" statement
+ Element element = (node as SimpleIdentifier).staticElement;
+ if (element == null) {
+ _coverageMarker();
+ return;
+ }
+ int declOffset = element.nameOffset;
+ AstNode declNode = new NodeLocator.con1(declOffset).searchWithin(unit);
+ if (declNode != null &&
+ declNode.parent is VariableDeclaration &&
+ identical((declNode.parent as VariableDeclaration).name, declNode) &&
+ declNode.parent.parent is VariableDeclarationList &&
+ declNode.parent.parent.parent is VariableDeclarationStatement) {
+ } else {
+ _coverageMarker();
+ return;
+ }
+ VariableDeclaration decl = declNode.parent as VariableDeclaration;
+ VariableDeclarationStatement declStatement =
+ decl.parent.parent as VariableDeclarationStatement;
+ // may be has initializer
+ if (decl.initializer != null) {
+ _coverageMarker();
+ return;
+ }
+ // check that "declaration" statement declared only one variable
+ if (declStatement.variables.variables.length != 1) {
+ _coverageMarker();
+ return;
+ }
+ // check that the "declaration" and "assignment" statements are
+ // parts of the same Block
+ ExpressionStatement assignStatement =
+ node.parent.parent as ExpressionStatement;
+ if (assignStatement.parent is Block &&
+ assignStatement.parent == declStatement.parent) {
+ } else {
+ _coverageMarker();
+ return;
+ }
+ Block block = assignStatement.parent as Block;
+ // check that "declaration" and "assignment" statements are adjacent
+ List<Statement> statements = block.statements;
+ if (statements.indexOf(assignStatement) ==
+ statements.indexOf(declStatement) + 1) {
+ } else {
+ _coverageMarker();
+ return;
+ }
+ // add edits
+ {
+ int assignOffset = assignExpression.operator.offset;
+ _addReplaceEdit(rangeEndStart(declNode, assignOffset), " ");
+ }
+ // add proposal
+ _addAssist(AssistKind.JOIN_VARIABLE_DECLARATION, []);
}
void _addProposal_joinVariableDeclaration_onDeclaration() {
- // TODO(scheglov) implement
-// // prepare enclosing VariableDeclarationList
-// VariableDeclarationList declList =
-// node.getAncestor((node) => node is VariableDeclarationList);
-// if (declList != null && declList.variables.length == 1) {
-// } else {
-// return;
-// }
-// VariableDeclaration decl = declList.variables[0];
-// // already initialized
-// if (decl.initializer != null) {
-// return;
-// }
-// // prepare VariableDeclarationStatement in Block
-// if (declList.parent is VariableDeclarationStatement &&
-// declList.parent.parent is Block) {
-// } else {
-// return;
-// }
-// VariableDeclarationStatement declStatement =
-// declList.parent as VariableDeclarationStatement;
-// Block block = declStatement.parent as Block;
-// List<Statement> statements = block.statements;
-// // prepare assignment
-// AssignmentExpression assignExpression;
-// {
-// // declaration should not be last Statement
-// int declIndex = statements.indexOf(declStatement);
-// if (declIndex < statements.length - 1) {
-// } else {
-// return;
-// }
-// // next Statement should be assignment
-// Statement assignStatement = statements[declIndex + 1];
-// if (assignStatement is ExpressionStatement) {
-// } else {
-// return;
-// }
-// ExpressionStatement expressionStatement =
-// assignStatement as ExpressionStatement;
-// // expression should be assignment
-// if (expressionStatement.expression is AssignmentExpression) {
-// } else {
-// return;
-// }
-// assignExpression = expressionStatement.expression as AssignmentExpression;
-// }
-// // check that pure assignment
-// if (assignExpression.operator.type != TokenType.EQ) {
-// return;
-// }
-// // add edits
-// {
-// int assignOffset = assignExpression.operator.offset;
-// _addReplaceEdit(
-// rangeEndStart(decl.name, assignOffset),
-// " ");
-// }
-// // add proposal
-// _addAssist(AssistKind.JOIN_VARIABLE_DECLARATION, []);
+ // prepare enclosing VariableDeclarationList
+ VariableDeclarationList declList =
+ node.getAncestor((node) => node is VariableDeclarationList);
+ if (declList != null && declList.variables.length == 1) {
+ } else {
+ _coverageMarker();
+ return;
+ }
+ VariableDeclaration decl = declList.variables[0];
+ // already initialized
+ if (decl.initializer != null) {
+ _coverageMarker();
+ return;
+ }
+ // prepare VariableDeclarationStatement in Block
+ if (declList.parent is VariableDeclarationStatement &&
+ declList.parent.parent is Block) {
+ } else {
+ _coverageMarker();
+ return;
+ }
+ VariableDeclarationStatement declStatement =
+ declList.parent as VariableDeclarationStatement;
+ Block block = declStatement.parent as Block;
+ List<Statement> statements = block.statements;
+ // prepare assignment
+ AssignmentExpression assignExpression;
+ {
+ // declaration should not be last Statement
+ int declIndex = statements.indexOf(declStatement);
+ if (declIndex < statements.length - 1) {
+ } else {
+ _coverageMarker();
+ return;
+ }
+ // next Statement should be assignment
+ Statement assignStatement = statements[declIndex + 1];
+ if (assignStatement is ExpressionStatement) {
+ } else {
+ _coverageMarker();
+ return;
+ }
+ ExpressionStatement expressionStatement =
+ assignStatement as ExpressionStatement;
+ // expression should be assignment
+ if (expressionStatement.expression is AssignmentExpression) {
+ } else {
+ _coverageMarker();
+ return;
+ }
+ assignExpression = expressionStatement.expression as AssignmentExpression;
+ }
+ // check that pure assignment
+ if (assignExpression.operator.type != TokenType.EQ) {
+ _coverageMarker();
+ return;
+ }
+ // add edits
+ {
+ int assignOffset = assignExpression.operator.offset;
+ _addReplaceEdit(rangeEndStart(decl.name, assignOffset), " ");
+ }
+ // add proposal
+ _addAssist(AssistKind.JOIN_VARIABLE_DECLARATION, []);
}
void _addProposal_removeTypeAnnotation() {
- // TODO(scheglov) implement
-// AstNode typeStart = null;
-// AstNode typeEnd = null;
-// // try top-level variable
-// {
-// TopLevelVariableDeclaration declaration =
-// node.getAncestor((node) => node is TopLevelVariableDeclaration);
-// if (declaration != null) {
-// TypeName typeNode = declaration.variables.type;
-// if (typeNode != null) {
-// VariableDeclaration field = declaration.variables.variables[0];
-// typeStart = declaration;
-// typeEnd = field;
-// }
-// }
-// }
-// // try class field
-// {
-// FieldDeclaration fieldDeclaration =
-// node.getAncestor((node) => node is FieldDeclaration);
-// if (fieldDeclaration != null) {
-// TypeName typeNode = fieldDeclaration.fields.type;
-// if (typeNode != null) {
-// VariableDeclaration field = fieldDeclaration.fields.variables[0];
-// typeStart = fieldDeclaration;
-// typeEnd = field;
-// }
-// }
-// }
-// // try local variable
-// {
-// VariableDeclarationStatement statement =
-// node.getAncestor((node) => node is VariableDeclarationStatement);
-// if (statement != null) {
-// TypeName typeNode = statement.variables.type;
-// if (typeNode != null) {
-// VariableDeclaration variable = statement.variables.variables[0];
-// typeStart = typeNode;
-// typeEnd = variable;
-// }
-// }
-// }
-// // add edit
-// if (typeStart != null && typeEnd != null) {
-// SourceRange typeRange =
-// rangeStartStart(typeStart, typeEnd);
-// _addReplaceEdit(typeRange, "var ");
-// }
-// // add proposal
-// _addAssist(AssistKind.REMOVE_TYPE_ANNOTATION, []);
+ AstNode typeStart = null;
+ AstNode typeEnd = null;
+ // try top-level variable
+ {
+ TopLevelVariableDeclaration declaration =
+ node.getAncestor((node) => node is TopLevelVariableDeclaration);
+ if (declaration != null) {
+ TypeName typeNode = declaration.variables.type;
+ if (typeNode != null) {
+ VariableDeclaration field = declaration.variables.variables[0];
+ typeStart = declaration;
+ typeEnd = field;
+ }
+ }
+ }
+ // try class field
+ {
+ FieldDeclaration fieldDeclaration =
+ node.getAncestor((node) => node is FieldDeclaration);
+ if (fieldDeclaration != null) {
+ TypeName typeNode = fieldDeclaration.fields.type;
+ if (typeNode != null) {
+ VariableDeclaration field = fieldDeclaration.fields.variables[0];
+ typeStart = fieldDeclaration;
+ typeEnd = field;
+ }
+ }
+ }
+ // try local variable
+ {
+ VariableDeclarationStatement statement =
+ node.getAncestor((node) => node is VariableDeclarationStatement);
+ if (statement != null) {
+ TypeName typeNode = statement.variables.type;
+ if (typeNode != null) {
+ VariableDeclaration variable = statement.variables.variables[0];
+ typeStart = typeNode;
+ typeEnd = variable;
+ }
+ }
+ }
+ // add edit
+ if (typeStart != null && typeEnd != null) {
+ SourceRange typeRange = rangeStartStart(typeStart, typeEnd);
+ _addReplaceEdit(typeRange, "var ");
+ }
+ // add proposal
+ _addAssist(AssistKind.REMOVE_TYPE_ANNOTATION, []);
}
void _addProposal_replaceConditionalWithIfElse() {
- // TODO(scheglov) implement
-// ConditionalExpression conditional = null;
-// // may be on Statement with Conditional
-// Statement statement = node.getAncestor((node) => node is Statement);
-// if (statement == null) {
-// return;
-// }
-// // variable declaration
-// bool inVariable = false;
-// if (statement is VariableDeclarationStatement) {
-// VariableDeclarationStatement variableStatement = statement;
-// for (VariableDeclaration variable in
-// variableStatement.variables.variables) {
-// if (variable.initializer is ConditionalExpression) {
-// conditional = variable.initializer as ConditionalExpression;
-// inVariable = true;
-// break;
-// }
-// }
-// }
-// // assignment
-// bool inAssignment = false;
-// if (statement is ExpressionStatement) {
-// ExpressionStatement exprStmt = statement;
-// if (exprStmt.expression is AssignmentExpression) {
-// AssignmentExpression assignment =
-// exprStmt.expression as AssignmentExpression;
-// if (assignment.operator.type == TokenType.EQ &&
-// assignment.rightHandSide is ConditionalExpression) {
-// conditional = assignment.rightHandSide as ConditionalExpression;
-// inAssignment = true;
-// }
-// }
-// }
-// // return
-// bool inReturn = false;
-// if (statement is ReturnStatement) {
-// ReturnStatement returnStatement = statement;
-// if (returnStatement.expression is ConditionalExpression) {
-// conditional = returnStatement.expression as ConditionalExpression;
-// inReturn = true;
-// }
-// }
-// // prepare environment
-// String eol = utils.endOfLine;
-// String indent = utils.getIndent(1);
-// String prefix = utils.getNodePrefix(statement);
-// // Type v = Conditional;
-// if (inVariable) {
-// VariableDeclaration variable = conditional.parent as VariableDeclaration;
-// _addRemoveEdit(
-// rangeEndEnd(variable.name, conditional));
-// // TODO(scheglov)
-//// _addReplaceEdit(
-//// rangeEndLength(statement, 0),
-//// MessageFormat.format(
-//// "{3}{4}if ({0}) '{'{3}{4}{5}{6} = {1};{3}{4}'} else {'{3}{4}{5}{6} = {2};{3}{4}'}'",
-//// [
-//// _getSource(conditional.condition),
-//// _getSource(conditional.thenExpression),
-//// _getSource(conditional.elseExpression),
-//// eol,
-//// prefix,
-//// indent,
-//// variable.name]));
-// }
-// // v = Conditional;
-// if (inAssignment) {
-// AssignmentExpression assignment =
-// conditional.parent as AssignmentExpression;
-// Expression leftSide = assignment.leftHandSide;
-// // TODO(scheglov)
-//// _addReplaceEdit(
-//// rangeNode(statement),
-//// MessageFormat.format(
-//// "if ({0}) '{'{3}{4}{5}{6} = {1};{3}{4}'} else {'{3}{4}{5}{6} = {2};{3}{4}'}'",
-//// [
-//// _getSource(conditional.condition),
-//// _getSource(conditional.thenExpression),
-//// _getSource(conditional.elseExpression),
-//// eol,
-//// prefix,
-//// indent,
-//// _getSource(leftSide)]));
-// }
-// // return Conditional;
-// if (inReturn) {
-// // TODO(scheglov)
-//// _addReplaceEdit(
-//// rangeNode(statement),
-//// MessageFormat.format(
-//// "if ({0}) '{'{3}{4}{5}return {1};{3}{4}'} else {'{3}{4}{5}return {2};{3}{4}'}'",
-//// [
-//// _getSource(conditional.condition),
-//// _getSource(conditional.thenExpression),
-//// _getSource(conditional.elseExpression),
-//// eol,
-//// prefix,
-//// indent]));
-// }
-// // add proposal
-// _addAssist(
-// AssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE,
-// []);
+ ConditionalExpression conditional = null;
+ // may be on Statement with Conditional
+ Statement statement = node.getAncestor((node) => node is Statement);
+ if (statement == null) {
+ _coverageMarker();
+ return;
+ }
+ // variable declaration
+ bool inVariable = false;
+ if (statement is VariableDeclarationStatement) {
+ VariableDeclarationStatement variableStatement = statement;
+ for (VariableDeclaration variable in
+ variableStatement.variables.variables) {
+ if (variable.initializer is ConditionalExpression) {
+ conditional = variable.initializer as ConditionalExpression;
+ inVariable = true;
+ break;
+ }
+ }
+ }
+ // assignment
+ bool inAssignment = false;
+ if (statement is ExpressionStatement) {
+ ExpressionStatement exprStmt = statement;
+ if (exprStmt.expression is AssignmentExpression) {
+ AssignmentExpression assignment =
+ exprStmt.expression as AssignmentExpression;
+ if (assignment.operator.type == TokenType.EQ &&
+ assignment.rightHandSide is ConditionalExpression) {
+ conditional = assignment.rightHandSide as ConditionalExpression;
+ inAssignment = true;
+ }
+ }
+ }
+ // return
+ bool inReturn = false;
+ if (statement is ReturnStatement) {
+ ReturnStatement returnStatement = statement;
+ if (returnStatement.expression is ConditionalExpression) {
+ conditional = returnStatement.expression as ConditionalExpression;
+ inReturn = true;
+ }
+ }
+ // prepare environment
+ String indent = utils.getIndent(1);
+ String prefix = utils.getNodePrefix(statement);
+ // Type v = Conditional;
+ if (inVariable) {
+ VariableDeclaration variable = conditional.parent as VariableDeclaration;
+ _addRemoveEdit(rangeEndEnd(variable.name, conditional));
+ String conditionSrc = _getSource(conditional.condition);
+ String thenSrc = _getSource(conditional.thenExpression);
+ String elseSrc = _getSource(conditional.elseExpression);
+ String name = variable.name.name;
+ String src = eol;
+ src += prefix + 'if ($conditionSrc) {' + eol;
+ src += prefix + indent + '$name = $thenSrc;' + eol;
+ src += prefix + '} else {' + eol;
+ src += prefix + indent + '$name = $elseSrc;' + eol;
+ src += prefix + '}';
+ _addReplaceEdit(rangeEndLength(statement, 0), src);
+ }
+ // v = Conditional;
+ if (inAssignment) {
+ AssignmentExpression assignment =
+ conditional.parent as AssignmentExpression;
+ Expression leftSide = assignment.leftHandSide;
+ String conditionSrc = _getSource(conditional.condition);
+ String thenSrc = _getSource(conditional.thenExpression);
+ String elseSrc = _getSource(conditional.elseExpression);
+ String name = _getSource(leftSide);
+ String src = '';
+ src += 'if ($conditionSrc) {' + eol;
+ src += prefix + indent + '$name = $thenSrc;' + eol;
+ src += prefix + '} else {' + eol;
+ src += prefix + indent + '$name = $elseSrc;' + eol;
+ src += prefix + '}';
+ _addReplaceEdit(rangeNode(statement), src);
+ }
+ // return Conditional;
+ if (inReturn) {
+ String conditionSrc = _getSource(conditional.condition);
+ String thenSrc = _getSource(conditional.thenExpression);
+ String elseSrc = _getSource(conditional.elseExpression);
+ String src = '';
+ src += 'if ($conditionSrc) {' + eol;
+ src += prefix + indent + 'return $thenSrc;' + eol;
+ src += prefix + '} else {' + eol;
+ src += prefix + indent + 'return $elseSrc;' + eol;
+ src += prefix + '}';
+ _addReplaceEdit(rangeNode(statement), src);
+ }
+ // add proposal
+ _addAssist(AssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE, []);
}
void _addProposal_replaceIfElseWithConditional() {
@@ -1109,7 +1124,6 @@ class AssistProcessor {
// }
// // prepare environment
// String prefix = utils.getNodePrefix(ifStatement);
-// String eol = utils.endOfLine;
// String indent = utils.getIndent(1);
// // prepare "rightCondition"
// String rightConditionSource;
@@ -1210,7 +1224,6 @@ class AssistProcessor {
// rangeEndStart(variable.name, statement.semicolon));
// // TODO(scheglov)
//// // add assignment statement
-//// String eol = _utils.endOfLine;
//// String indent = _utils.getNodePrefix(statement);
//// String assignSource =
//// MessageFormat.format(
@@ -1253,7 +1266,6 @@ class AssistProcessor {
// Statement lastStatement = selectedStatements[selectedStatements.length - 1];
// SourceRange statementsRange = utils.getLinesRange(selectedStatements);
// // prepare environment
-// String eol = utils.endOfLine;
// String indentOld = utils.getNodePrefix(firstStatement);
// String indentNew = "${indentOld}${utils.getIndent(1)}";
// // "block"
@@ -1522,16 +1534,6 @@ class AssistProcessor {
}
/**
- * This method does nothing, but we invoke it in places where Dart VM
- * coverage agent fails to provide coverage information - such as almost
- * all "return" statements.
- *
- * https://code.google.com/p/dart/issues/detail?id=19912
- */
- void _coverageMarker() {
- }
-
- /**
* Returns an existing or just added [LinkedPositionGroup] with [groupId].
*/
LinkedPositionGroup _getLinkedPosition(String groupId) {
@@ -1576,4 +1578,41 @@ class AssistProcessor {
});
});
}
+
+ /**
+ * This method does nothing, but we invoke it in places where Dart VM
+ * coverage agent fails to provide coverage information - such as almost
+ * all "return" statements.
+ *
+ * https://code.google.com/p/dart/issues/detail?id=19912
+ */
+ static void _coverageMarker() {
+ }
+
+ /**
+ * Returns `true` if the selection covers an operator of the given
+ * [BinaryExpression].
+ */
+ static bool _isOperatorSelected(BinaryExpression binaryExpression, int offset,
+ int length) {
+ AstNode left = binaryExpression.leftOperand;
+ AstNode right = binaryExpression.rightOperand;
+ // between the nodes
+ if (offset >= left.endToken.end && offset + length <= right.offset) {
+ _coverageMarker();
+ return true;
+ }
+ // or exactly select the node (but not with infix expressions)
+ if (offset == left.offset && offset + length == right.endToken.end) {
+ if (left is BinaryExpression || right is BinaryExpression) {
+ _coverageMarker();
+ return false;
+ }
+ _coverageMarker();
+ return true;
+ }
+ // invalid selection (part of node, etc)
+ _coverageMarker();
+ return false;
+ }
}
« no previous file with comments | « pkg/analysis_services/lib/correction/assist.dart ('k') | pkg/analysis_services/lib/src/correction/source_range.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698