| 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/correction/namespace.dart'; |
| 10 import 'package:analysis_server/src/services/index/index.dart'; | 10 import 'package:analysis_server/src/services/index/index.dart'; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 if (unitElement == null) { | 32 if (unitElement == null) { |
| 33 return; | 33 return; |
| 34 } | 34 } |
| 35 // about to index | 35 // about to index |
| 36 bool mayIndex = store.aboutToIndexDart(context, unitElement); | 36 bool mayIndex = store.aboutToIndexDart(context, unitElement); |
| 37 if (!mayIndex) { | 37 if (!mayIndex) { |
| 38 return; | 38 return; |
| 39 } | 39 } |
| 40 // do index | 40 // do index |
| 41 unit.accept(new _IndexContributor(store)); | 41 unit.accept(new _IndexContributor(store)); |
| 42 unit.accept(new _AngularDartIndexContributor(store)); | |
| 43 store.doneIndex(); | 42 store.doneIndex(); |
| 44 } | 43 } |
| 45 | 44 |
| 46 | 45 |
| 47 /** | 46 /** |
| 48 * Adds data to [store] based on the resolved HTML [unit]. | 47 * Adds data to [store] based on the resolved HTML [unit]. |
| 49 */ | 48 */ |
| 50 void indexHtmlUnit(IndexStore store, AnalysisContext context, ht.HtmlUnit unit) | 49 void indexHtmlUnit(IndexStore store, AnalysisContext context, ht.HtmlUnit unit) |
| 51 { | 50 { |
| 52 // check unit | 51 // check unit |
| 53 if (unit == null) { | 52 if (unit == null) { |
| 54 return; | 53 return; |
| 55 } | 54 } |
| 56 // prepare unit element | 55 // prepare unit element |
| 57 HtmlElement unitElement = unit.element; | 56 HtmlElement unitElement = unit.element; |
| 58 if (unitElement == null) { | 57 if (unitElement == null) { |
| 59 return; | 58 return; |
| 60 } | 59 } |
| 61 // about to index | 60 // about to index |
| 62 bool mayIndex = store.aboutToIndexHtml(context, unitElement); | 61 bool mayIndex = store.aboutToIndexHtml(context, unitElement); |
| 63 if (!mayIndex) { | 62 if (!mayIndex) { |
| 64 return; | 63 return; |
| 65 } | 64 } |
| 66 // do index | 65 // do index |
| 67 unit.accept(new _AngularHtmlIndexContributor(store)); | |
| 68 store.doneIndex(); | 66 store.doneIndex(); |
| 69 } | 67 } |
| 70 | 68 |
| 71 | 69 |
| 72 /** | 70 /** |
| 73 * Visits resolved [CompilationUnit] and adds Angular specific relationships | |
| 74 * into [IndexStore]. | |
| 75 */ | |
| 76 class _AngularDartIndexContributor extends GeneralizingAstVisitor<Object> { | |
| 77 final IndexStore _store; | |
| 78 | |
| 79 _AngularDartIndexContributor(this._store); | |
| 80 | |
| 81 @override | |
| 82 Object visitClassDeclaration(ClassDeclaration node) { | |
| 83 ClassElement classElement = node.element; | |
| 84 if (classElement != null) { | |
| 85 List<ToolkitObjectElement> toolkitObjects = classElement.toolkitObjects; | |
| 86 for (ToolkitObjectElement object in toolkitObjects) { | |
| 87 if (object is AngularComponentElement) { | |
| 88 _indexComponent(object); | |
| 89 } | |
| 90 if (object is AngularDecoratorElement) { | |
| 91 AngularDecoratorElement directive = object; | |
| 92 _indexDirective(directive); | |
| 93 } | |
| 94 } | |
| 95 } | |
| 96 // stop visiting | |
| 97 return null; | |
| 98 } | |
| 99 | |
| 100 @override | |
| 101 Object visitCompilationUnitMember(CompilationUnitMember node) => null; | |
| 102 | |
| 103 void _indexComponent(AngularComponentElement component) { | |
| 104 _indexProperties(component.properties); | |
| 105 } | |
| 106 | |
| 107 void _indexDirective(AngularDecoratorElement directive) { | |
| 108 _indexProperties(directive.properties); | |
| 109 } | |
| 110 | |
| 111 /** | |
| 112 * Index [FieldElement] references from [AngularPropertyElement]s. | |
| 113 */ | |
| 114 void _indexProperties(List<AngularPropertyElement> properties) { | |
| 115 for (AngularPropertyElement property in properties) { | |
| 116 FieldElement field = property.field; | |
| 117 if (field != null) { | |
| 118 int offset = property.fieldNameOffset; | |
| 119 if (offset == -1) { | |
| 120 continue; | |
| 121 } | |
| 122 int length = field.name.length; | |
| 123 Location location = new Location(property, offset, length); | |
| 124 // getter reference | |
| 125 if (property.propertyKind.callsGetter()) { | |
| 126 PropertyAccessorElement getter = field.getter; | |
| 127 if (getter != null) { | |
| 128 _store.recordRelationship( | |
| 129 getter, | |
| 130 IndexConstants.IS_REFERENCED_BY, | |
| 131 location); | |
| 132 } | |
| 133 } | |
| 134 // setter reference | |
| 135 if (property.propertyKind.callsSetter()) { | |
| 136 PropertyAccessorElement setter = field.setter; | |
| 137 if (setter != null) { | |
| 138 _store.recordRelationship( | |
| 139 setter, | |
| 140 IndexConstants.IS_REFERENCED_BY, | |
| 141 location); | |
| 142 } | |
| 143 } | |
| 144 } | |
| 145 } | |
| 146 } | |
| 147 } | |
| 148 | |
| 149 | |
| 150 /** | |
| 151 * Visits resolved [HtmlUnit] and adds relationships into [IndexStore]. | |
| 152 */ | |
| 153 class _AngularHtmlIndexContributor extends _ExpressionVisitor { | |
| 154 /** | |
| 155 * The [IndexStore] to record relations into. | |
| 156 */ | |
| 157 final IndexStore _store; | |
| 158 | |
| 159 /** | |
| 160 * The index contributor used to index Dart [Expression]s. | |
| 161 */ | |
| 162 _IndexContributor _indexContributor; | |
| 163 | |
| 164 HtmlElement _htmlUnitElement; | |
| 165 | |
| 166 /** | |
| 167 * Initialize a newly created Angular HTML index contributor. | |
| 168 * | |
| 169 * [store] - the [IndexStore] to record relations into. | |
| 170 */ | |
| 171 _AngularHtmlIndexContributor(this._store) { | |
| 172 _indexContributor = | |
| 173 new _AngularHtmlIndexContributor_forEmbeddedDart(_store, this); | |
| 174 } | |
| 175 | |
| 176 @override | |
| 177 void visitExpression(Expression expression) { | |
| 178 // Formatter | |
| 179 if (expression is SimpleIdentifier) { | |
| 180 Element element = expression.bestElement; | |
| 181 if (element is AngularElement) { | |
| 182 _store.recordRelationship( | |
| 183 element, | |
| 184 IndexConstants.ANGULAR_REFERENCE, | |
| 185 _createLocationForIdentifier(expression)); | |
| 186 return; | |
| 187 } | |
| 188 } | |
| 189 // index as a normal Dart expression | |
| 190 expression.accept(_indexContributor); | |
| 191 } | |
| 192 | |
| 193 @override | |
| 194 Object visitHtmlUnit(ht.HtmlUnit node) { | |
| 195 _htmlUnitElement = node.element; | |
| 196 CompilationUnitElement dartUnitElement = | |
| 197 _htmlUnitElement.angularCompilationUnit; | |
| 198 _indexContributor.enterScope(dartUnitElement); | |
| 199 return super.visitHtmlUnit(node); | |
| 200 } | |
| 201 | |
| 202 @override | |
| 203 Object visitXmlAttributeNode(ht.XmlAttributeNode node) { | |
| 204 Element element = node.element; | |
| 205 if (element != null) { | |
| 206 ht.Token nameToken = node.nameToken; | |
| 207 Location location = _createLocationForToken(nameToken); | |
| 208 _store.recordRelationship( | |
| 209 element, | |
| 210 IndexConstants.ANGULAR_REFERENCE, | |
| 211 location); | |
| 212 } | |
| 213 return super.visitXmlAttributeNode(node); | |
| 214 } | |
| 215 | |
| 216 @override | |
| 217 Object visitXmlTagNode(ht.XmlTagNode node) { | |
| 218 Element element = node.element; | |
| 219 if (element != null) { | |
| 220 // tag | |
| 221 { | |
| 222 ht.Token tagToken = node.tagToken; | |
| 223 Location location = _createLocationForToken(tagToken); | |
| 224 _store.recordRelationship( | |
| 225 element, | |
| 226 IndexConstants.ANGULAR_REFERENCE, | |
| 227 location); | |
| 228 } | |
| 229 // maybe add closing tag range | |
| 230 ht.Token closingTag = node.closingTag; | |
| 231 if (closingTag != null) { | |
| 232 Location location = _createLocationForToken(closingTag); | |
| 233 _store.recordRelationship( | |
| 234 element, | |
| 235 IndexConstants.ANGULAR_CLOSING_TAG_REFERENCE, | |
| 236 location); | |
| 237 } | |
| 238 } | |
| 239 return super.visitXmlTagNode(node); | |
| 240 } | |
| 241 | |
| 242 Location _createLocationForIdentifier(SimpleIdentifier identifier) => | |
| 243 new Location(_htmlUnitElement, identifier.offset, identifier.length); | |
| 244 | |
| 245 Location _createLocationForToken(ht.Token token) => | |
| 246 new Location(_htmlUnitElement, token.offset, token.length); | |
| 247 } | |
| 248 | |
| 249 | |
| 250 class _AngularHtmlIndexContributor_forEmbeddedDart extends _IndexContributor { | |
| 251 final _AngularHtmlIndexContributor angularContributor; | |
| 252 | |
| 253 _AngularHtmlIndexContributor_forEmbeddedDart(IndexStore store, | |
| 254 this.angularContributor) | |
| 255 : super(store); | |
| 256 | |
| 257 @override | |
| 258 Element peekElement() => angularContributor._htmlUnitElement; | |
| 259 | |
| 260 @override | |
| 261 void recordRelationship(Element element, Relationship relationship, | |
| 262 Location location) { | |
| 263 AngularElement angularElement = | |
| 264 AngularHtmlUnitResolver.getAngularElement(element); | |
| 265 if (angularElement != null) { | |
| 266 element = angularElement; | |
| 267 relationship = IndexConstants.ANGULAR_REFERENCE; | |
| 268 } | |
| 269 super.recordRelationship(element, relationship, location); | |
| 270 } | |
| 271 } | |
| 272 | |
| 273 | |
| 274 /** | |
| 275 * Recursively visits an [HtmlUnit] and every embedded [Expression]. | |
| 276 */ | |
| 277 abstract class _ExpressionVisitor extends ht.RecursiveXmlVisitor<Object> { | |
| 278 /** | |
| 279 * Visits the given [Expression]s embedded into tag or attribute. | |
| 280 * | |
| 281 * [expression] - the [Expression] to visit, not `null` | |
| 282 */ | |
| 283 void visitExpression(Expression expression); | |
| 284 | |
| 285 @override | |
| 286 Object visitXmlAttributeNode(ht.XmlAttributeNode node) { | |
| 287 _visitExpressions(node.expressions); | |
| 288 return super.visitXmlAttributeNode(node); | |
| 289 } | |
| 290 | |
| 291 @override | |
| 292 Object visitXmlTagNode(ht.XmlTagNode node) { | |
| 293 _visitExpressions(node.expressions); | |
| 294 return super.visitXmlTagNode(node); | |
| 295 } | |
| 296 | |
| 297 /** | |
| 298 * Visits [Expression]s of the given [XmlExpression]s. | |
| 299 */ | |
| 300 void _visitExpressions(List<ht.XmlExpression> expressions) { | |
| 301 for (ht.XmlExpression xmlExpression in expressions) { | |
| 302 if (xmlExpression is AngularXmlExpression) { | |
| 303 AngularXmlExpression angularXmlExpression = xmlExpression; | |
| 304 List<Expression> dartExpressions = | |
| 305 angularXmlExpression.expression.expressions; | |
| 306 for (Expression dartExpression in dartExpressions) { | |
| 307 visitExpression(dartExpression); | |
| 308 } | |
| 309 } | |
| 310 if (xmlExpression is ht.RawXmlExpression) { | |
| 311 ht.RawXmlExpression rawXmlExpression = xmlExpression; | |
| 312 visitExpression(rawXmlExpression.expression); | |
| 313 } | |
| 314 } | |
| 315 } | |
| 316 } | |
| 317 | |
| 318 | |
| 319 /** | |
| 320 * Visits a resolved AST and adds relationships into [IndexStore]. | 71 * Visits a resolved AST and adds relationships into [IndexStore]. |
| 321 */ | 72 */ |
| 322 class _IndexContributor extends GeneralizingAstVisitor<Object> { | 73 class _IndexContributor extends GeneralizingAstVisitor<Object> { |
| 323 final IndexStore _store; | 74 final IndexStore _store; |
| 324 | 75 |
| 325 LibraryElement _libraryElement; | 76 LibraryElement _libraryElement; |
| 326 | 77 |
| 327 Map<ImportElement, Set<Element>> _importElementsMap = {}; | 78 Map<ImportElement, Set<Element>> _importElementsMap = {}; |
| 328 | 79 |
| 329 /** | 80 /** |
| (...skipping 732 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1062 } | 813 } |
| 1063 | 814 |
| 1064 /** | 815 /** |
| 1065 * @return `true` if given "node" is part of [PrefixedIdentifier] "prefix.node
". | 816 * @return `true` if given "node" is part of [PrefixedIdentifier] "prefix.node
". |
| 1066 */ | 817 */ |
| 1067 static bool _isIdentifierInPrefixedIdentifier(SimpleIdentifier node) { | 818 static bool _isIdentifierInPrefixedIdentifier(SimpleIdentifier node) { |
| 1068 AstNode parent = node.parent; | 819 AstNode parent = node.parent; |
| 1069 return parent is PrefixedIdentifier && parent.identifier == node; | 820 return parent is PrefixedIdentifier && parent.identifier == node; |
| 1070 } | 821 } |
| 1071 } | 822 } |
| OLD | NEW |