| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |