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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 // This code was auto-generated, is not intended to be edited, and is subject to 5 // This code was auto-generated, is not intended to be edited, and is subject to
6 // significant change. Please see the README file for more information. 6 // significant change. Please see the README file for more information.
7 7
8 library services.src.correction.fix; 8 library services.src.correction.fix;
9 9
10 import 'package:analysis_services/correction/change.dart'; 10 import 'package:analysis_services/correction/change.dart';
11 import 'package:analysis_services/correction/fix.dart'; 11 import 'package:analysis_services/correction/fix.dart';
12 import 'package:analysis_services/search/hierarchy.dart';
12 import 'package:analysis_services/search/search_engine.dart'; 13 import 'package:analysis_services/search/search_engine.dart';
14 import 'package:analysis_services/src/correction/levenshtein.dart';
13 import 'package:analysis_services/src/correction/name_suggestion.dart'; 15 import 'package:analysis_services/src/correction/name_suggestion.dart';
14 import 'package:analysis_services/src/correction/source_buffer.dart'; 16 import 'package:analysis_services/src/correction/source_buffer.dart';
15 import 'package:analysis_services/src/correction/source_range.dart' as rf; 17 import 'package:analysis_services/src/correction/source_range.dart' as rf;
16 import 'package:analysis_services/src/correction/strings.dart'; 18 import 'package:analysis_services/src/correction/strings.dart';
17 import 'package:analysis_services/src/correction/util.dart'; 19 import 'package:analysis_services/src/correction/util.dart';
18 import 'package:analyzer/src/generated/ast.dart'; 20 import 'package:analyzer/src/generated/ast.dart';
19 import 'package:analyzer/src/generated/element.dart'; 21 import 'package:analyzer/src/generated/element.dart';
20 import 'package:analyzer/src/generated/error.dart'; 22 import 'package:analyzer/src/generated/error.dart';
21 import 'package:analyzer/src/generated/java_core.dart'; 23 import 'package:analyzer/src/generated/java_core.dart';
22 import 'package:analyzer/src/generated/parser.dart'; 24 import 'package:analyzer/src/generated/parser.dart';
23 import 'package:analyzer/src/generated/scanner.dart'; 25 import 'package:analyzer/src/generated/scanner.dart';
24 import 'package:analyzer/src/generated/source.dart'; 26 import 'package:analyzer/src/generated/source.dart';
25 import 'package:analyzer/src/generated/utilities_dart.dart'; 27 import 'package:analyzer/src/generated/utilities_dart.dart';
26 28
27 29
28 /** 30 /**
31 * A predicate is a one-argument function that returns a boolean value.
32 */
33 typedef bool Predicate<E>(E argument);
34
35
36 /**
29 * The computer for Dart fixes. 37 * The computer for Dart fixes.
30 */ 38 */
31 class FixProcessor { 39 class FixProcessor {
32 final SearchEngine searchEngine; 40 final SearchEngine searchEngine;
33 final Source source; 41 final Source source;
34 final String file; 42 final String file;
35 final CompilationUnit unit; 43 final CompilationUnit unit;
36 final AnalysisError error; 44 final AnalysisError error;
37 CompilationUnitElement unitElement; 45 CompilationUnitElement unitElement;
38 LibraryElement unitLibraryElement; 46 LibraryElement unitLibraryElement;
(...skipping 972 matching lines...) Expand 10 before | Expand all | Expand 10 after
1011 1019
1012 void _addFix_replaceWithConstInstanceCreation() { 1020 void _addFix_replaceWithConstInstanceCreation() {
1013 if (coveredNode is InstanceCreationExpression) { 1021 if (coveredNode is InstanceCreationExpression) {
1014 var instanceCreation = coveredNode as InstanceCreationExpression; 1022 var instanceCreation = coveredNode as InstanceCreationExpression;
1015 _addReplaceEdit(rf.rangeToken(instanceCreation.keyword), "const"); 1023 _addReplaceEdit(rf.rangeToken(instanceCreation.keyword), "const");
1016 _addFix(FixKind.USE_CONST, []); 1024 _addFix(FixKind.USE_CONST, []);
1017 } 1025 }
1018 } 1026 }
1019 1027
1020 void _addFix_undefinedClass_useSimilar() { 1028 void _addFix_undefinedClass_useSimilar() {
1021 // TODO(scheglov) implement 1029 if (_mayBeTypeIdentifier(node)) {
1022 // if (_mayBeTypeIdentifier(node)) { 1030 String name = (node as SimpleIdentifier).name;
1023 // String name = (node as SimpleIdentifier).name; 1031 _ClosestElementFinder finder =
1024 // QuickFixProcessorImpl_ClosestElementFinder finder = 1032 new _ClosestElementFinder(name, (Element element) => element is ClassE lement);
1025 // new QuickFixProcessorImpl_ClosestElementFinder( 1033 // find closest element
1026 // name, 1034 {
1027 // new Predicate_QuickFixProcessorImpl_addFix_undefinedClass_useSim ilar()); 1035 // elements of this library
1028 // // find closest element 1036 for (CompilationUnitElement unit in unitLibraryElement.units) {
1029 // { 1037 finder._updateList(unit.types);
1030 // // elements of this library 1038 }
1031 // _unitLibraryElement.accept( 1039 // elements from imports
1032 // new RecursiveElementVisitor_QuickFixProcessorImpl_addFix_undefined Class_useSimilar( 1040 for (ImportElement importElement in unitLibraryElement.imports) {
1033 // finder)); 1041 if (importElement.prefix == null) {
1034 // // elements from imports 1042 Map<String, Element> namespace = getImportNamespace(importElement);
1035 // for (ImportElement importElement in _unitLibraryElement.imports) { 1043 finder._updateList(namespace.values);
1036 // if (importElement.prefix == null) { 1044 }
1037 // Map<String, Element> namespace = 1045 }
1038 // CorrectionUtils.getImportNamespace(importElement); 1046 }
1039 // finder._update2(namespace.values); 1047 // if we have close enough element, suggest to use it
1040 // } 1048 if (finder != null && finder._distance < 5) {
1041 // } 1049 String closestName = finder._element.name;
1042 // } 1050 _addReplaceEdit(rf.rangeNode(node), closestName);
1043 // // if we have close enough element, suggest to use it 1051 // add proposal
1044 // if (finder != null && finder._distance < 5) { 1052 if (closestName != null) {
1045 // String closestName = finder._element.name; 1053 _addFix(FixKind.CHANGE_TO, [closestName]);
1046 // _addReplaceEdit(SourceRangeFactory.rangeNode(node), closestName); 1054 }
1047 // // add proposal 1055 }
1048 // if (closestName != null) { 1056 }
1049 // _addFix(
1050 // FixKind.CHANGE_TO,
1051 // [closestName]);
1052 // }
1053 // }
1054 // }
1055 } 1057 }
1056 1058
1057 void _addFix_undefinedFunction_create() { 1059 void _addFix_undefinedFunction_create() {
1058 // should be the name of the invocation 1060 // should be the name of the invocation
1059 if (node is SimpleIdentifier && node.parent is MethodInvocation) { 1061 if (node is SimpleIdentifier && node.parent is MethodInvocation) {
1060 } else { 1062 } else {
1061 return; 1063 return;
1062 } 1064 }
1063 String name = (node as SimpleIdentifier).name; 1065 String name = (node as SimpleIdentifier).name;
1064 MethodInvocation invocation = node.parent as MethodInvocation; 1066 MethodInvocation invocation = node.parent as MethodInvocation;
(...skipping 27 matching lines...) Expand all
1092 _addFix_undefinedMethod_create_parameters(sb, invocation.argumentList); 1094 _addFix_undefinedMethod_create_parameters(sb, invocation.argumentList);
1093 sb.append(") {${eol}}"); 1095 sb.append(") {${eol}}");
1094 } 1096 }
1095 // insert source 1097 // insert source
1096 _insertBuilder(sb); 1098 _insertBuilder(sb);
1097 _addLinkedPosition3('NAME', sb, rf.rangeNode(node)); 1099 _addLinkedPosition3('NAME', sb, rf.rangeNode(node));
1098 // add proposal 1100 // add proposal
1099 _addFix(FixKind.CREATE_FUNCTION, [name]); 1101 _addFix(FixKind.CREATE_FUNCTION, [name]);
1100 } 1102 }
1101 1103
1102 void _addFix_undefinedFunction_useSimilar() { 1104 void _addFix_undefinedFunction_useSimilar() {
Paul Berry 2014/07/25 18:10:36 Any way we could share code between this function
1103 // TODO(scheglov) implement 1105 if (node is SimpleIdentifier) {
1104 // if (node is SimpleIdentifier) { 1106 String name = (node as SimpleIdentifier).name;
1105 // String name = (node as SimpleIdentifier).name; 1107 _ClosestElementFinder finder =
1106 // QuickFixProcessorImpl_ClosestElementFinder finder = 1108 new _ClosestElementFinder(
1107 // new QuickFixProcessorImpl_ClosestElementFinder( 1109 name,
1108 // name, 1110 (Element element) => element is FunctionElement);
1109 // new Predicate_QuickFixProcessorImpl_addFix_undefinedFunction_use Similar()); 1111 // this library
1110 // // this library 1112 for (CompilationUnitElement unit in unitLibraryElement.units) {
1111 // _unitLibraryElement.accept( 1113 finder._updateList(unit.functions);
1112 // new RecursiveElementVisitor_QuickFixProcessorImpl_addFix_undefinedFu nction_useSimilar( 1114 }
1113 // finder)); 1115 // imports
1114 // // imports 1116 for (ImportElement importElement in unitLibraryElement.imports) {
1115 // for (ImportElement importElement in _unitLibraryElement.imports) { 1117 if (importElement.prefix == null) {
1116 // if (importElement.prefix == null) { 1118 Map<String, Element> namespace = getImportNamespace(importElement);
1117 // Map<String, Element> namespace = 1119 finder._updateList(namespace.values);
1118 // CorrectionUtils.getImportNamespace(importElement); 1120 }
1119 // finder._update2(namespace.values); 1121 }
1120 // } 1122 // if we have close enough element, suggest to use it
1121 // } 1123 String closestName = null;
1122 // // if we have close enough element, suggest to use it 1124 if (finder != null && finder._distance < 5) {
1123 // String closestName = null; 1125 closestName = finder._element.name;
1124 // if (finder != null && finder._distance < 5) { 1126 _addReplaceEdit(rf.rangeNode(node), closestName);
1125 // closestName = finder._element.name; 1127 _addFix(FixKind.CHANGE_TO, [closestName]);
1126 // _addReplaceEdit(SourceRangeFactory.rangeNode(node), closestName); 1128 }
1127 // _addFix(FixKind.CHANGE_TO, [closestName]); 1129 }
1128 // }
1129 // }
1130 } 1130 }
1131 1131
1132 void _addFix_undefinedMethod_create() { 1132 void _addFix_undefinedMethod_create() {
1133 if (node is SimpleIdentifier && node.parent is MethodInvocation) { 1133 if (node is SimpleIdentifier && node.parent is MethodInvocation) {
1134 String name = (node as SimpleIdentifier).name; 1134 String name = (node as SimpleIdentifier).name;
1135 MethodInvocation invocation = node.parent as MethodInvocation; 1135 MethodInvocation invocation = node.parent as MethodInvocation;
1136 // prepare environment 1136 // prepare environment
1137 Source targetSource; 1137 Source targetSource;
1138 String prefix; 1138 String prefix;
1139 int insertOffset; 1139 int insertOffset;
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1236 excluded.add(favorite); 1236 excluded.add(favorite);
1237 sb.startPosition("ARG${i}"); 1237 sb.startPosition("ARG${i}");
1238 sb.append(favorite); 1238 sb.append(favorite);
1239 sb.addProposals(suggestions); 1239 sb.addProposals(suggestions);
1240 sb.endPosition(); 1240 sb.endPosition();
1241 } 1241 }
1242 } 1242 }
1243 } 1243 }
1244 1244
1245 void _addFix_undefinedMethod_useSimilar() { 1245 void _addFix_undefinedMethod_useSimilar() {
1246 // TODO(scheglov) implement 1246 if (node is SimpleIdentifier && node.parent is MethodInvocation) {
1247 // if (node is SimpleIdentifier && node.parent is MethodInvocation) { 1247 MethodInvocation invocation = node.parent as MethodInvocation;
1248 // MethodInvocation invocation = node.parent as MethodInvocation; 1248 String name = (node as SimpleIdentifier).name;
1249 // String name = (node as SimpleIdentifier).name; 1249 _ClosestElementFinder finder =
1250 // QuickFixProcessorImpl_ClosestElementFinder finder = 1250 new _ClosestElementFinder(name, (Element element) {
1251 // new QuickFixProcessorImpl_ClosestElementFinder( 1251 return element is MethodElement && !element.isOperator;
1252 // name, 1252 });
1253 // new Predicate_QuickFixProcessorImpl_addFix_undefinedMethod_useSi milar()); 1253 // unqualified invocation
1254 // // unqualified invocation 1254 Expression target = invocation.realTarget;
1255 // Expression target = invocation.realTarget; 1255 if (target == null) {
1256 // if (target == null) { 1256 ClassDeclaration clazz =
1257 // ClassDeclaration clazz = 1257 invocation.getAncestor((node) => node is ClassDeclaration);
1258 // invocation.getAncestor((node) => node is ClassDeclaration); 1258 if (clazz != null) {
1259 // if (clazz != null) { 1259 ClassElement classElement = clazz.element;
1260 // ClassElement classElement = clazz.element; 1260 _updateFinderWithClassMembers(finder, classElement);
1261 // _updateFinderWithClassMembers(finder, classElement); 1261 }
1262 // } 1262 } else {
1263 // } else { 1263 DartType type = target.bestType;
1264 // DartType type = target.bestType; 1264 if (type is InterfaceType) {
1265 // if (type is InterfaceType) { 1265 ClassElement classElement = type.element;
1266 // ClassElement classElement = type.element; 1266 _updateFinderWithClassMembers(finder, classElement);
1267 // _updateFinderWithClassMembers(finder, classElement); 1267 }
1268 // } 1268 }
1269 // } 1269 // if we have close enough element, suggest to use it
1270 // // if we have close enough element, suggest to use it 1270 String closestName = null;
1271 // String closestName = null; 1271 if (finder != null && finder._distance < 5) {
1272 // if (finder != null && finder._distance < 5) { 1272 closestName = finder._element.name;
1273 // closestName = finder._element.name; 1273 _addReplaceEdit(rf.rangeNode(node), closestName);
1274 // _addReplaceEdit(SourceRangeFactory.rangeNode(node), closestName); 1274 _addFix(FixKind.CHANGE_TO, [closestName]);
1275 // _addFix(FixKind.CHANGE_TO, [closestName]); 1275 }
1276 // } 1276 }
1277 // }
1278 } 1277 }
1279 1278
1280 void _addFix_useEffectiveIntegerDivision() { 1279 void _addFix_useEffectiveIntegerDivision() {
1281 for (AstNode n = node; n != null; n = n.parent) { 1280 for (AstNode n = node; n != null; n = n.parent) {
1282 if (n is MethodInvocation && 1281 if (n is MethodInvocation &&
1283 n.offset == errorOffset && 1282 n.offset == errorOffset &&
1284 n.length == errorLength) { 1283 n.length == errorLength) {
1285 MethodInvocation invocation = n as MethodInvocation; 1284 MethodInvocation invocation = n as MethodInvocation;
1286 Expression target = invocation.target; 1285 Expression target = invocation.target;
1287 while (target is ParenthesizedExpression) { 1286 while (target is ParenthesizedExpression) {
(...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after
1853 expr.parent as ParenthesizedExpression; 1852 expr.parent as ParenthesizedExpression;
1854 if (getExpressionParentPrecedence(parenthesized) > exprPrecedence) { 1853 if (getExpressionParentPrecedence(parenthesized) > exprPrecedence) {
1855 break; 1854 break;
1856 } 1855 }
1857 _addRemoveEdit(rf.rangeToken(parenthesized.leftParenthesis)); 1856 _addRemoveEdit(rf.rangeToken(parenthesized.leftParenthesis));
1858 _addRemoveEdit(rf.rangeToken(parenthesized.rightParenthesis)); 1857 _addRemoveEdit(rf.rangeToken(parenthesized.rightParenthesis));
1859 expr = parenthesized; 1858 expr = parenthesized;
1860 } 1859 }
1861 } 1860 }
1862 1861
1862 void _updateFinderWithClassMembers(_ClosestElementFinder finder,
1863 ClassElement clazz) {
1864 if (clazz != null) {
1865 List<Element> members = getMembers(clazz);
1866 finder._updateList(members);
1867 }
1868 }
1869
1863 static void _addSuperTypeProposals(SourceBuilder sb, 1870 static void _addSuperTypeProposals(SourceBuilder sb,
1864 Set<DartType> alreadyAdded, DartType type) { 1871 Set<DartType> alreadyAdded, DartType type) {
1865 if (type != null && 1872 if (type != null &&
1866 !alreadyAdded.contains(type) && 1873 !alreadyAdded.contains(type) &&
1867 type.element is ClassElement) { 1874 type.element is ClassElement) {
1868 alreadyAdded.add(type); 1875 alreadyAdded.add(type);
1869 ClassElement element = type.element as ClassElement; 1876 ClassElement element = type.element as ClassElement;
1870 sb.addProposal(element.name); 1877 sb.addProposal(element.name);
1871 _addSuperTypeProposals(sb, alreadyAdded, element.supertype); 1878 _addSuperTypeProposals(sb, alreadyAdded, element.supertype);
1872 for (InterfaceType interfaceType in element.interfaces) { 1879 for (InterfaceType interfaceType in element.interfaces) {
(...skipping 28 matching lines...) Expand all
1901 return parent.realTarget == node; 1908 return parent.realTarget == node;
1902 } 1909 }
1903 if (parent is PrefixedIdentifier) { 1910 if (parent is PrefixedIdentifier) {
1904 return parent.prefix == node; 1911 return parent.prefix == node;
1905 } 1912 }
1906 } 1913 }
1907 return false; 1914 return false;
1908 } 1915 }
1909 } 1916 }
1910 1917
1918 /**
1919 * Helper for finding [Element] with name closest to the given.
1920 */
1921 class _ClosestElementFinder {
1922 final String _targetName;
1923 final Predicate<Element> _predicate;
1924
1925 Element _element = null;
1926 int _distance = 1 << 10;
1927
1928 _ClosestElementFinder(this._targetName, this._predicate);
1929
1930 void _update(Element element) {
1931 if (_predicate(element)) {
1932 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
1933 if (memberDistance < _distance) {
1934 _element = element;
1935 _distance = memberDistance;
1936 }
1937 }
1938 }
1939
1940 void _updateList(Iterable<Element> elements) {
1941 for (Element element in elements) {
1942 _update(element);
1943 }
1944 }
1945 }
1911 1946
1912 /** 1947 /**
1913 * Describes the location for a newly created [ConstructorDeclaration]. 1948 * Describes the location for a newly created [ConstructorDeclaration].
1914 */ 1949 */
1915 class _ConstructorLocation { 1950 class _ConstructorLocation {
1916 final String _prefix; 1951 final String _prefix;
1917 final int _offset; 1952 final int _offset;
1918 final String _suffix; 1953 final String _suffix;
1919 1954
1920 _ConstructorLocation(this._prefix, this._offset, this._suffix); 1955 _ConstructorLocation(this._prefix, this._offset, this._suffix);
1921 } 1956 }
OLDNEW
« 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