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

Side by Side Diff: pkg/analysis_server/lib/src/services/index/index_contributor.dart

Issue 481173002: When user renames 'prefix' in 'prefix.Class' she actually wants to rename ImportElement. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Tweak for test - reference ambiguous prefix name. Created 6 years, 4 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 library services.src.index.index_contributor; 5 library services.src.index.index_contributor;
6 6
7 import 'dart:collection' show Queue; 7 import 'dart:collection' show Queue;
8 8
9 import 'package:analysis_server/src/services/correction/namespace.dart';
9 import 'package:analysis_server/src/services/index/index.dart'; 10 import 'package:analysis_server/src/services/index/index.dart';
10 import 'package:analysis_server/src/services/index/index_store.dart'; 11 import 'package:analysis_server/src/services/index/index_store.dart';
11 import 'package:analyzer/src/generated/ast.dart'; 12 import 'package:analyzer/src/generated/ast.dart';
12 import 'package:analyzer/src/generated/element.dart'; 13 import 'package:analyzer/src/generated/element.dart';
13 import 'package:analyzer/src/generated/engine.dart'; 14 import 'package:analyzer/src/generated/engine.dart';
14 import 'package:analyzer/src/generated/html.dart' as ht; 15 import 'package:analyzer/src/generated/html.dart' as ht;
15 import 'package:analyzer/src/generated/java_core.dart';
16 import 'package:analyzer/src/generated/java_engine.dart'; 16 import 'package:analyzer/src/generated/java_engine.dart';
17 import 'package:analyzer/src/generated/resolver.dart';
18 import 'package:analyzer/src/generated/scanner.dart'; 17 import 'package:analyzer/src/generated/scanner.dart';
19 import 'package:analyzer/src/generated/source.dart'; 18 import 'package:analyzer/src/generated/source.dart';
20 19
21 20
22 /** 21 /**
23 * Adds data to [store] based on the resolved Dart [unit]. 22 * Adds data to [store] based on the resolved Dart [unit].
24 */ 23 */
25 void indexDartUnit(IndexStore store, AnalysisContext context, 24 void indexDartUnit(IndexStore store, AnalysisContext context,
26 CompilationUnit unit) { 25 CompilationUnit unit) {
27 // check unit 26 // check unit
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 if (xmlExpression is ht.RawXmlExpression) { 311 if (xmlExpression is ht.RawXmlExpression) {
313 ht.RawXmlExpression rawXmlExpression = xmlExpression; 312 ht.RawXmlExpression rawXmlExpression = xmlExpression;
314 visitExpression(rawXmlExpression.expression); 313 visitExpression(rawXmlExpression.expression);
315 } 314 }
316 } 315 }
317 } 316 }
318 } 317 }
319 318
320 319
321 /** 320 /**
322 * Information about [ImportElement] and place where it is referenced using
323 * [PrefixElement].
324 */
325 class _ImportElementInfo {
326 ImportElement _element;
327
328 int _periodEnd = 0;
329 }
330
331
332 /**
333 * Visits a resolved AST and adds relationships into [IndexStore]. 321 * Visits a resolved AST and adds relationships into [IndexStore].
334 */ 322 */
335 class _IndexContributor extends GeneralizingAstVisitor<Object> { 323 class _IndexContributor extends GeneralizingAstVisitor<Object> {
336 final IndexStore _store; 324 final IndexStore _store;
337 325
338 LibraryElement _libraryElement; 326 LibraryElement _libraryElement;
339 327
340 Map<ImportElement, Set<Element>> _importElementsMap = {}; 328 Map<ImportElement, Set<Element>> _importElementsMap = {};
341 329
342 /** 330 /**
(...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after
911 Relationship relationship = IndexConstants.DEFINES; 899 Relationship relationship = IndexConstants.DEFINES;
912 recordRelationship(_libraryElement, relationship, location); 900 recordRelationship(_libraryElement, relationship, location);
913 recordRelationship(UniverseElement.INSTANCE, relationship, location); 901 recordRelationship(UniverseElement.INSTANCE, relationship, location);
914 } 902 }
915 903
916 /** 904 /**
917 * Records [ImportElement] that declares given prefix and imports library with element used 905 * Records [ImportElement] that declares given prefix and imports library with element used
918 * with given prefix node. 906 * with given prefix node.
919 */ 907 */
920 void _recordImportElementReferenceWithPrefix(SimpleIdentifier prefixNode) { 908 void _recordImportElementReferenceWithPrefix(SimpleIdentifier prefixNode) {
921 _ImportElementInfo info = getImportElementInfo(prefixNode); 909 ImportElementInfo info = internal_getImportElementInfo(prefixNode);
922 if (info != null) { 910 if (info != null) {
923 int offset = prefixNode.offset; 911 int offset = prefixNode.offset;
924 int length = info._periodEnd - offset; 912 int length = info.periodEnd - offset;
925 Location location = _createLocationForOffset(offset, length); 913 Location location = _createLocationForOffset(offset, length);
926 recordRelationship( 914 recordRelationship(
927 info._element, 915 info.element,
928 IndexConstants.IS_REFERENCED_BY, 916 IndexConstants.IS_REFERENCED_BY,
929 location); 917 location);
930 } 918 }
931 } 919 }
932 920
933 /** 921 /**
934 * Records [ImportElement] reference if given [SimpleIdentifier] references so me 922 * Records [ImportElement] reference if given [SimpleIdentifier] references so me
935 * top-level element and not qualified with import prefix. 923 * top-level element and not qualified with import prefix.
936 */ 924 */
937 void _recordImportElementReferenceWithoutPrefix(SimpleIdentifier node) { 925 void _recordImportElementReferenceWithoutPrefix(SimpleIdentifier node) {
938 if (_isIdentifierInImportCombinator(node)) { 926 if (_isIdentifierInImportCombinator(node)) {
939 return; 927 return;
940 } 928 }
941 if (_isIdentifierInPrefixedIdentifier(node)) { 929 if (_isIdentifierInPrefixedIdentifier(node)) {
942 return; 930 return;
943 } 931 }
944 Element element = node.staticElement; 932 Element element = node.staticElement;
945 ImportElement importElement = 933 ImportElement importElement =
946 _internalGetImportElement(_libraryElement, null, element, _importElement sMap); 934 internal_getImportElement(_libraryElement, null, element, _importElement sMap);
947 if (importElement != null) { 935 if (importElement != null) {
948 Location location = _createLocationForOffset(node.offset, 0); 936 Location location = _createLocationForOffset(node.offset, 0);
949 recordRelationship( 937 recordRelationship(
950 importElement, 938 importElement,
951 IndexConstants.IS_REFERENCED_BY, 939 IndexConstants.IS_REFERENCED_BY,
952 location); 940 location);
953 } 941 }
954 } 942 }
955 943
956 /** 944 /**
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1016 static Location createLocation(Element element) { 1004 static Location createLocation(Element element) {
1017 if (element != null) { 1005 if (element != null) {
1018 int offset = element.nameOffset; 1006 int offset = element.nameOffset;
1019 int length = element.displayName.length; 1007 int length = element.displayName.length;
1020 return new Location(element, offset, length); 1008 return new Location(element, offset, length);
1021 } 1009 }
1022 return null; 1010 return null;
1023 } 1011 }
1024 1012
1025 /** 1013 /**
1026 * @return the [ImportElement] that is referenced by this node with [PrefixEle ment],
1027 * may be `null`.
1028 */
1029 static ImportElement getImportElement(SimpleIdentifier prefixNode) {
1030 _ImportElementInfo info = getImportElementInfo(prefixNode);
1031 return info != null ? info._element : null;
1032 }
1033
1034 /**
1035 * @return the [ImportElementInfo] with [ImportElement] that is referenced by this
1036 * node with [PrefixElement], may be `null`.
1037 */
1038 static _ImportElementInfo getImportElementInfo(SimpleIdentifier prefixNode) {
1039 _ImportElementInfo info = new _ImportElementInfo();
1040 // prepare environment
1041 AstNode parent = prefixNode.parent;
1042 CompilationUnit unit =
1043 prefixNode.getAncestor((node) => node is CompilationUnit);
1044 LibraryElement libraryElement = unit.element.library;
1045 // prepare used element
1046 Element usedElement = null;
1047 if (parent is PrefixedIdentifier) {
1048 PrefixedIdentifier prefixed = parent;
1049 if (prefixed.prefix == prefixNode) {
1050 usedElement = prefixed.staticElement;
1051 info._periodEnd = prefixed.period.end;
1052 }
1053 }
1054 if (parent is MethodInvocation) {
1055 MethodInvocation invocation = parent;
1056 if (invocation.target == prefixNode) {
1057 usedElement = invocation.methodName.staticElement;
1058 info._periodEnd = invocation.period.end;
1059 }
1060 }
1061 // we need used Element
1062 if (usedElement == null) {
1063 return null;
1064 }
1065 // find ImportElement
1066 String prefix = prefixNode.name;
1067 Map<ImportElement, Set<Element>> importElementsMap = {};
1068 info._element = _internalGetImportElement(
1069 libraryElement,
1070 prefix,
1071 usedElement,
1072 importElementsMap);
1073 if (info._element == null) {
1074 return null;
1075 }
1076 return info;
1077 }
1078
1079 /**
1080 * If the given expression has resolved type, returns the new location with th is type. 1014 * If the given expression has resolved type, returns the new location with th is type.
1081 * 1015 *
1082 * [location] - the base location 1016 * [location] - the base location
1083 * [expression] - the expression assigned at the given location 1017 * [expression] - the expression assigned at the given location
1084 */ 1018 */
1085 static Location _getLocationWithExpressionType(Location location, 1019 static Location _getLocationWithExpressionType(Location location,
1086 Expression expression) { 1020 Expression expression) {
1087 if (expression != null) { 1021 if (expression != null) {
1088 return new LocationWithData<DartType>(location, expression.bestType); 1022 return new LocationWithData<DartType>(location, expression.bestType);
1089 } 1023 }
1090 return location; 1024 return location;
1091 } 1025 }
1092 1026
1093 /** 1027 /**
1094 * @return the [ImportElement] that declares given [PrefixElement] and imports library
1095 * with given "usedElement".
1096 */
1097 static ImportElement _internalGetImportElement(LibraryElement libraryElement,
1098 String prefix, Element usedElement, Map<ImportElement,
1099 Set<Element>> importElementsMap) {
1100 // validate Element
1101 if (usedElement == null) {
1102 return null;
1103 }
1104 if (usedElement.enclosingElement is! CompilationUnitElement) {
1105 return null;
1106 }
1107 LibraryElement usedLibrary = usedElement.library;
1108 // find ImportElement that imports used library with used prefix
1109 List<ImportElement> candidates = null;
1110 for (ImportElement importElement in libraryElement.imports) {
1111 // required library
1112 if (importElement.importedLibrary != usedLibrary) {
1113 continue;
1114 }
1115 // required prefix
1116 PrefixElement prefixElement = importElement.prefix;
1117 if (prefix == null) {
1118 if (prefixElement != null) {
1119 continue;
1120 }
1121 } else {
1122 if (prefixElement == null) {
1123 continue;
1124 }
1125 if (prefix != prefixElement.name) {
1126 continue;
1127 }
1128 }
1129 // no combinators => only possible candidate
1130 if (importElement.combinators.length == 0) {
1131 return importElement;
1132 }
1133 // OK, we have candidate
1134 if (candidates == null) {
1135 candidates = [];
1136 }
1137 candidates.add(importElement);
1138 }
1139 // no candidates, probably element is defined in this library
1140 if (candidates == null) {
1141 return null;
1142 }
1143 // one candidate
1144 if (candidates.length == 1) {
1145 return candidates[0];
1146 }
1147 // ensure that each ImportElement has set of elements
1148 for (ImportElement importElement in candidates) {
1149 if (importElementsMap.containsKey(importElement)) {
1150 continue;
1151 }
1152 Namespace namespace =
1153 new NamespaceBuilder().createImportNamespaceForDirective(importElement );
1154 Set<Element> elements = new Set.from(namespace.definedNames.values);
1155 importElementsMap[importElement] = elements;
1156 }
1157 // use import namespace to choose correct one
1158 for (MapEntry<ImportElement, Set<Element>> entry in getMapEntrySet(
1159 importElementsMap)) {
1160 if (entry.getValue().contains(usedElement)) {
1161 return entry.getKey();
1162 }
1163 }
1164 // not found
1165 return null;
1166 }
1167
1168 /**
1169 * @return `true` if given "node" is part of an import [Combinator]. 1028 * @return `true` if given "node" is part of an import [Combinator].
1170 */ 1029 */
1171 static bool _isIdentifierInImportCombinator(SimpleIdentifier node) { 1030 static bool _isIdentifierInImportCombinator(SimpleIdentifier node) {
1172 AstNode parent = node.parent; 1031 AstNode parent = node.parent;
1173 return parent is Combinator; 1032 return parent is Combinator;
1174 } 1033 }
1175 1034
1176 /** 1035 /**
1177 * @return `true` if given "node" is part of [PrefixedIdentifier] "prefix.node ". 1036 * @return `true` if given "node" is part of [PrefixedIdentifier] "prefix.node ".
1178 */ 1037 */
1179 static bool _isIdentifierInPrefixedIdentifier(SimpleIdentifier node) { 1038 static bool _isIdentifierInPrefixedIdentifier(SimpleIdentifier node) {
1180 AstNode parent = node.parent; 1039 AstNode parent = node.parent;
1181 return parent is PrefixedIdentifier && parent.identifier == node; 1040 return parent is PrefixedIdentifier && parent.identifier == node;
1182 } 1041 }
1183 } 1042 }
OLDNEW
« no previous file with comments | « pkg/analysis_server/lib/src/services/correction/util.dart ('k') | pkg/analysis_server/test/edit/refactoring_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698