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

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

Issue 414273002: New 'use similar' fixes. (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/fix.dart
diff --git a/pkg/analysis_services/lib/src/correction/fix.dart b/pkg/analysis_services/lib/src/correction/fix.dart
index ddf5d35dd7faad4ccfe84d71d557268262b54469..9d463ed0d12e0f9b858202ad1cf90b36c9f0f71b 100644
--- a/pkg/analysis_services/lib/src/correction/fix.dart
+++ b/pkg/analysis_services/lib/src/correction/fix.dart
@@ -9,7 +9,9 @@ library services.src.correction.fix;
import 'package:analysis_services/correction/change.dart';
import 'package:analysis_services/correction/fix.dart';
+import 'package:analysis_services/search/hierarchy.dart';
import 'package:analysis_services/search/search_engine.dart';
+import 'package:analysis_services/src/correction/levenshtein.dart';
import 'package:analysis_services/src/correction/name_suggestion.dart';
import 'package:analysis_services/src/correction/source_buffer.dart';
import 'package:analysis_services/src/correction/source_range.dart' as rf;
@@ -26,6 +28,12 @@ import 'package:analyzer/src/generated/utilities_dart.dart';
/**
+ * A predicate is a one-argument function that returns a boolean value.
+ */
+typedef bool Predicate<E>(E argument);
+
+
+/**
* The computer for Dart fixes.
*/
class FixProcessor {
@@ -1018,40 +1026,34 @@ class FixProcessor {
}
void _addFix_undefinedClass_useSimilar() {
- // TODO(scheglov) implement
-// if (_mayBeTypeIdentifier(node)) {
-// String name = (node as SimpleIdentifier).name;
-// QuickFixProcessorImpl_ClosestElementFinder finder =
-// new QuickFixProcessorImpl_ClosestElementFinder(
-// name,
-// new Predicate_QuickFixProcessorImpl_addFix_undefinedClass_useSimilar());
-// // find closest element
-// {
-// // elements of this library
-// _unitLibraryElement.accept(
-// new RecursiveElementVisitor_QuickFixProcessorImpl_addFix_undefinedClass_useSimilar(
-// finder));
-// // elements from imports
-// for (ImportElement importElement in _unitLibraryElement.imports) {
-// if (importElement.prefix == null) {
-// Map<String, Element> namespace =
-// CorrectionUtils.getImportNamespace(importElement);
-// finder._update2(namespace.values);
-// }
-// }
-// }
-// // if we have close enough element, suggest to use it
-// if (finder != null && finder._distance < 5) {
-// String closestName = finder._element.name;
-// _addReplaceEdit(SourceRangeFactory.rangeNode(node), closestName);
-// // add proposal
-// if (closestName != null) {
-// _addFix(
-// FixKind.CHANGE_TO,
-// [closestName]);
-// }
-// }
-// }
+ if (_mayBeTypeIdentifier(node)) {
+ String name = (node as SimpleIdentifier).name;
+ _ClosestElementFinder finder =
+ new _ClosestElementFinder(name, (Element element) => element is ClassElement);
+ // find closest element
+ {
+ // elements of this library
+ for (CompilationUnitElement unit in unitLibraryElement.units) {
+ finder._updateList(unit.types);
+ }
+ // elements from imports
+ for (ImportElement importElement in unitLibraryElement.imports) {
+ if (importElement.prefix == null) {
+ Map<String, Element> namespace = getImportNamespace(importElement);
+ finder._updateList(namespace.values);
+ }
+ }
+ }
+ // if we have close enough element, suggest to use it
+ if (finder != null && finder._distance < 5) {
+ String closestName = finder._element.name;
+ _addReplaceEdit(rf.rangeNode(node), closestName);
+ // add proposal
+ if (closestName != null) {
+ _addFix(FixKind.CHANGE_TO, [closestName]);
+ }
+ }
+ }
}
void _addFix_undefinedFunction_create() {
@@ -1100,33 +1102,31 @@ class FixProcessor {
}
void _addFix_undefinedFunction_useSimilar() {
Paul Berry 2014/07/25 18:10:36 Any way we could share code between this function
- // TODO(scheglov) implement
-// if (node is SimpleIdentifier) {
-// String name = (node as SimpleIdentifier).name;
-// QuickFixProcessorImpl_ClosestElementFinder finder =
-// new QuickFixProcessorImpl_ClosestElementFinder(
-// name,
-// new Predicate_QuickFixProcessorImpl_addFix_undefinedFunction_useSimilar());
-// // this library
-// _unitLibraryElement.accept(
-// new RecursiveElementVisitor_QuickFixProcessorImpl_addFix_undefinedFunction_useSimilar(
-// finder));
-// // imports
-// for (ImportElement importElement in _unitLibraryElement.imports) {
-// if (importElement.prefix == null) {
-// Map<String, Element> namespace =
-// CorrectionUtils.getImportNamespace(importElement);
-// finder._update2(namespace.values);
-// }
-// }
-// // if we have close enough element, suggest to use it
-// String closestName = null;
-// if (finder != null && finder._distance < 5) {
-// closestName = finder._element.name;
-// _addReplaceEdit(SourceRangeFactory.rangeNode(node), closestName);
-// _addFix(FixKind.CHANGE_TO, [closestName]);
-// }
-// }
+ if (node is SimpleIdentifier) {
+ String name = (node as SimpleIdentifier).name;
+ _ClosestElementFinder finder =
+ new _ClosestElementFinder(
+ name,
+ (Element element) => element is FunctionElement);
+ // this library
+ for (CompilationUnitElement unit in unitLibraryElement.units) {
+ finder._updateList(unit.functions);
+ }
+ // imports
+ for (ImportElement importElement in unitLibraryElement.imports) {
+ if (importElement.prefix == null) {
+ Map<String, Element> namespace = getImportNamespace(importElement);
+ finder._updateList(namespace.values);
+ }
+ }
+ // if we have close enough element, suggest to use it
+ String closestName = null;
+ if (finder != null && finder._distance < 5) {
+ closestName = finder._element.name;
+ _addReplaceEdit(rf.rangeNode(node), closestName);
+ _addFix(FixKind.CHANGE_TO, [closestName]);
+ }
+ }
}
void _addFix_undefinedMethod_create() {
@@ -1243,38 +1243,37 @@ class FixProcessor {
}
void _addFix_undefinedMethod_useSimilar() {
- // TODO(scheglov) implement
-// if (node is SimpleIdentifier && node.parent is MethodInvocation) {
-// MethodInvocation invocation = node.parent as MethodInvocation;
-// String name = (node as SimpleIdentifier).name;
-// QuickFixProcessorImpl_ClosestElementFinder finder =
-// new QuickFixProcessorImpl_ClosestElementFinder(
-// name,
-// new Predicate_QuickFixProcessorImpl_addFix_undefinedMethod_useSimilar());
-// // unqualified invocation
-// Expression target = invocation.realTarget;
-// if (target == null) {
-// ClassDeclaration clazz =
-// invocation.getAncestor((node) => node is ClassDeclaration);
-// if (clazz != null) {
-// ClassElement classElement = clazz.element;
-// _updateFinderWithClassMembers(finder, classElement);
-// }
-// } else {
-// DartType type = target.bestType;
-// if (type is InterfaceType) {
-// ClassElement classElement = type.element;
-// _updateFinderWithClassMembers(finder, classElement);
-// }
-// }
-// // if we have close enough element, suggest to use it
-// String closestName = null;
-// if (finder != null && finder._distance < 5) {
-// closestName = finder._element.name;
-// _addReplaceEdit(SourceRangeFactory.rangeNode(node), closestName);
-// _addFix(FixKind.CHANGE_TO, [closestName]);
-// }
-// }
+ if (node is SimpleIdentifier && node.parent is MethodInvocation) {
+ MethodInvocation invocation = node.parent as MethodInvocation;
+ String name = (node as SimpleIdentifier).name;
+ _ClosestElementFinder finder =
+ new _ClosestElementFinder(name, (Element element) {
+ return element is MethodElement && !element.isOperator;
+ });
+ // unqualified invocation
+ Expression target = invocation.realTarget;
+ if (target == null) {
+ ClassDeclaration clazz =
+ invocation.getAncestor((node) => node is ClassDeclaration);
+ if (clazz != null) {
+ ClassElement classElement = clazz.element;
+ _updateFinderWithClassMembers(finder, classElement);
+ }
+ } else {
+ DartType type = target.bestType;
+ if (type is InterfaceType) {
+ ClassElement classElement = type.element;
+ _updateFinderWithClassMembers(finder, classElement);
+ }
+ }
+ // if we have close enough element, suggest to use it
+ String closestName = null;
+ if (finder != null && finder._distance < 5) {
+ closestName = finder._element.name;
+ _addReplaceEdit(rf.rangeNode(node), closestName);
+ _addFix(FixKind.CHANGE_TO, [closestName]);
+ }
+ }
}
void _addFix_useEffectiveIntegerDivision() {
@@ -1860,6 +1859,14 @@ class FixProcessor {
}
}
+ void _updateFinderWithClassMembers(_ClosestElementFinder finder,
+ ClassElement clazz) {
+ if (clazz != null) {
+ List<Element> members = getMembers(clazz);
+ finder._updateList(members);
+ }
+ }
+
static void _addSuperTypeProposals(SourceBuilder sb,
Set<DartType> alreadyAdded, DartType type) {
if (type != null &&
@@ -1908,6 +1915,34 @@ class FixProcessor {
}
}
+/**
+ * Helper for finding [Element] with name closest to the given.
+ */
+class _ClosestElementFinder {
+ final String _targetName;
+ final Predicate<Element> _predicate;
+
+ Element _element = null;
+ int _distance = 1 << 10;
+
+ _ClosestElementFinder(this._targetName, this._predicate);
+
+ void _update(Element element) {
+ if (_predicate(element)) {
+ int memberDistance = getLevenshteinDistance(element.name, _targetName);
Paul Berry 2014/07/25 18:10:36 Levenshtein distance is O(n*m) to compute in the w
scheglov 2014/07/25 18:53:29 https://codereview.chromium.org/417263003
+ if (memberDistance < _distance) {
+ _element = element;
+ _distance = memberDistance;
+ }
+ }
+ }
+
+ void _updateList(Iterable<Element> elements) {
+ for (Element element in elements) {
+ _update(element);
+ }
+ }
+}
/**
* Describes the location for a newly created [ConstructorDeclaration].
« no previous file with comments | « pkg/analysis_services/lib/search/hierarchy.dart ('k') | pkg/analysis_services/lib/src/correction/levenshtein.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698