| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import 'package:analyzer/dart/ast/ast.dart'; | 5 import 'package:analyzer/dart/ast/ast.dart'; |
| 6 import 'package:analyzer/dart/ast/token.dart'; | 6 import 'package:analyzer/dart/ast/token.dart'; |
| 7 import 'package:analyzer/dart/ast/visitor.dart'; | 7 import 'package:analyzer/dart/ast/visitor.dart'; |
| 8 import 'package:analyzer/dart/element/element.dart'; | 8 import 'package:analyzer/dart/element/element.dart'; |
| 9 import 'package:analyzer/dart/element/type.dart'; | |
| 10 import 'package:analyzer/src/generated/utilities_dart.dart'; | 9 import 'package:analyzer/src/generated/utilities_dart.dart'; |
| 11 import 'package:analyzer/src/summary/format.dart'; | 10 import 'package:analyzer/src/summary/format.dart'; |
| 12 import 'package:analyzer/src/summary/idl.dart'; | 11 import 'package:analyzer/src/summary/idl.dart'; |
| 13 | 12 |
| 14 /** | 13 /** |
| 15 * Object that gathers information about the whole package index and then uses | 14 * Object that gathers information about the whole package index and then uses |
| 16 * it to assemble a new [PackageIndexBuilder]. Call [index] on each compilation | 15 * it to assemble a new [PackageIndexBuilder]. Call [index] on each compilation |
| 17 * unit to be indexed, then call [assemble] to retrieve the complete index for | 16 * unit to be indexed, then call [assemble] to retrieve the complete index for |
| 18 * the package. | 17 * the package. |
| 19 */ | 18 */ |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 | 198 |
| 200 /** | 199 /** |
| 201 * Visits a resolved AST and adds relationships into [_UnitIndexAssembler]. | 200 * Visits a resolved AST and adds relationships into [_UnitIndexAssembler]. |
| 202 */ | 201 */ |
| 203 class _IndexContributor extends GeneralizingAstVisitor { | 202 class _IndexContributor extends GeneralizingAstVisitor { |
| 204 final _UnitIndexAssembler assembler; | 203 final _UnitIndexAssembler assembler; |
| 205 | 204 |
| 206 _IndexContributor(this.assembler); | 205 _IndexContributor(this.assembler); |
| 207 | 206 |
| 208 /** | 207 /** |
| 209 * Record information about a [ClassDeclaration] or [ClassTypeAlias] with | |
| 210 * the given [nameNode]. Nodes [superNode], [withClause] and | |
| 211 * [implementsClause] can be `null`. | |
| 212 */ | |
| 213 void recordClassClauses(SimpleIdentifier nameNode, TypeName superNode, | |
| 214 WithClause withClause, ImplementsClause implementsClause) { | |
| 215 if (superNode != null) { | |
| 216 recordSuperType(superNode, IndexRelationKind.IS_EXTENDED_BY); | |
| 217 } else { | |
| 218 ClassElement element = nameNode.staticElement; | |
| 219 InterfaceType superType = element.supertype; | |
| 220 if (superType != null) { | |
| 221 ClassElement objectElement = superType.element; | |
| 222 recordRelationOffset(objectElement, IndexRelationKind.IS_EXTENDED_BY, | |
| 223 nameNode.offset, 0); | |
| 224 } | |
| 225 } | |
| 226 if (withClause != null) { | |
| 227 for (TypeName mixinNode in withClause.mixinTypes) { | |
| 228 recordSuperType(mixinNode, IndexRelationKind.IS_MIXED_IN_BY); | |
| 229 } | |
| 230 } | |
| 231 if (implementsClause != null) { | |
| 232 for (TypeName interfaceNode in implementsClause.interfaces) { | |
| 233 recordSuperType(interfaceNode, IndexRelationKind.IS_IMPLEMENTED_BY); | |
| 234 } | |
| 235 } | |
| 236 } | |
| 237 | |
| 238 /** | |
| 239 * Record reference to the given operator [Element] and name. | 208 * Record reference to the given operator [Element] and name. |
| 240 */ | 209 */ |
| 241 void recordOperatorReference(Token operator, Element element) { | 210 void recordOperatorReference(Token operator, Element element) { |
| 242 recordRelationToken(element, IndexRelationKind.IS_INVOKED_BY, operator); | 211 recordRelationToken(element, IndexRelationKind.IS_INVOKED_BY, operator); |
| 243 // TODO(scheglov) do we need this? | 212 // TODO(scheglov) do we need this? |
| 244 // // prepare location | 213 // // prepare location |
| 245 // LocationImpl location = _createLocationForToken(operator, element != null)
; | 214 // LocationImpl location = _createLocationForToken(operator, element != null)
; |
| 246 // // record name reference | 215 // // record name reference |
| 247 // { | 216 // { |
| 248 // String name = operator.lexeme; | 217 // String name = operator.lexeme; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 * of the given [token]. | 272 * of the given [token]. |
| 304 */ | 273 */ |
| 305 void recordRelationToken( | 274 void recordRelationToken( |
| 306 Element element, IndexRelationKind kind, Token token) { | 275 Element element, IndexRelationKind kind, Token token) { |
| 307 if (element != null && token != null) { | 276 if (element != null && token != null) { |
| 308 recordRelationOffset(element, kind, token.offset, token.length); | 277 recordRelationOffset(element, kind, token.offset, token.length); |
| 309 } | 278 } |
| 310 } | 279 } |
| 311 | 280 |
| 312 /** | 281 /** |
| 313 * Records a relation between [superNode] and its [Element]. | 282 * Record a relation between a super [typeName] and its [Element]. |
| 314 */ | 283 */ |
| 315 void recordSuperType(TypeName superNode, IndexRelationKind kind) { | 284 void recordSuperType(TypeName typeName, IndexRelationKind kind) { |
| 316 if (superNode != null) { | 285 Identifier name = typeName?.name; |
| 317 Identifier superName = superNode.name; | 286 if (name != null) { |
| 318 if (superName != null) { | 287 recordRelation(name.staticElement, kind, name); |
| 319 Element superElement = superName.staticElement; | 288 typeName.typeArguments?.accept(this); |
| 320 recordRelation(superElement, kind, superName); | |
| 321 } | |
| 322 } | 289 } |
| 323 } | 290 } |
| 324 | 291 |
| 325 /** | 292 /** |
| 326 * Record the top-level [element] definition. | 293 * Record the top-level [element] definition. |
| 327 */ | 294 */ |
| 328 void recordTopLevelElementDefinition(Element element) { | 295 void recordTopLevelElementDefinition(Element element) { |
| 329 // TODO(scheglov) do we need this? | 296 // TODO(scheglov) do we need this? |
| 330 // if (element?.enclosingElement is CompilationUnitElement) { | 297 // if (element?.enclosingElement is CompilationUnitElement) { |
| 331 // IndexableElement indexable = new IndexableElement(element); | 298 // IndexableElement indexable = new IndexableElement(element); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 351 @override | 318 @override |
| 352 visitBinaryExpression(BinaryExpression node) { | 319 visitBinaryExpression(BinaryExpression node) { |
| 353 recordOperatorReference(node.operator, node.bestElement); | 320 recordOperatorReference(node.operator, node.bestElement); |
| 354 super.visitBinaryExpression(node); | 321 super.visitBinaryExpression(node); |
| 355 } | 322 } |
| 356 | 323 |
| 357 @override | 324 @override |
| 358 visitClassDeclaration(ClassDeclaration node) { | 325 visitClassDeclaration(ClassDeclaration node) { |
| 359 ClassElement element = node.element; | 326 ClassElement element = node.element; |
| 360 recordTopLevelElementDefinition(element); | 327 recordTopLevelElementDefinition(element); |
| 361 recordClassClauses(node.name, node.extendsClause?.superclass, | 328 if (node.extendsClause == null) { |
| 362 node.withClause, node.implementsClause); | 329 ClassElement objectElement = element.supertype?.element; |
| 330 recordRelationOffset( |
| 331 objectElement, IndexRelationKind.IS_EXTENDED_BY, node.name.offset, 0); |
| 332 } |
| 363 super.visitClassDeclaration(node); | 333 super.visitClassDeclaration(node); |
| 364 } | 334 } |
| 365 | 335 |
| 366 @override | 336 @override |
| 367 visitClassTypeAlias(ClassTypeAlias node) { | 337 visitClassTypeAlias(ClassTypeAlias node) { |
| 368 ClassElement element = node.element; | 338 ClassElement element = node.element; |
| 369 recordTopLevelElementDefinition(element); | 339 recordTopLevelElementDefinition(element); |
| 370 recordClassClauses( | |
| 371 node.name, node.superclass, node.withClause, node.implementsClause); | |
| 372 super.visitClassTypeAlias(node); | 340 super.visitClassTypeAlias(node); |
| 373 } | 341 } |
| 374 | 342 |
| 375 @override | 343 @override |
| 376 visitConstructorFieldInitializer(ConstructorFieldInitializer node) { | 344 visitConstructorFieldInitializer(ConstructorFieldInitializer node) { |
| 377 SimpleIdentifier fieldName = node.fieldName; | 345 SimpleIdentifier fieldName = node.fieldName; |
| 378 if (fieldName != null) { | 346 if (fieldName != null) { |
| 379 Element element = fieldName.staticElement; | 347 Element element = fieldName.staticElement; |
| 380 recordRelation(element, IndexRelationKind.IS_REFERENCED_BY, fieldName); | 348 recordRelation(element, IndexRelationKind.IS_REFERENCED_BY, fieldName); |
| 381 } | 349 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 } | 383 } |
| 416 | 384 |
| 417 @override | 385 @override |
| 418 visitExportDirective(ExportDirective node) { | 386 visitExportDirective(ExportDirective node) { |
| 419 ExportElement element = node.element; | 387 ExportElement element = node.element; |
| 420 recordUriReference(element?.exportedLibrary, node); | 388 recordUriReference(element?.exportedLibrary, node); |
| 421 super.visitExportDirective(node); | 389 super.visitExportDirective(node); |
| 422 } | 390 } |
| 423 | 391 |
| 424 @override | 392 @override |
| 393 visitExtendsClause(ExtendsClause node) { |
| 394 recordSuperType(node.superclass, IndexRelationKind.IS_EXTENDED_BY); |
| 395 } |
| 396 |
| 397 @override |
| 425 visitFunctionDeclaration(FunctionDeclaration node) { | 398 visitFunctionDeclaration(FunctionDeclaration node) { |
| 426 Element element = node.element; | 399 Element element = node.element; |
| 427 recordTopLevelElementDefinition(element); | 400 recordTopLevelElementDefinition(element); |
| 428 super.visitFunctionDeclaration(node); | 401 super.visitFunctionDeclaration(node); |
| 429 } | 402 } |
| 430 | 403 |
| 431 @override | 404 @override |
| 432 visitFunctionTypeAlias(FunctionTypeAlias node) { | 405 visitFunctionTypeAlias(FunctionTypeAlias node) { |
| 433 Element element = node.element; | 406 Element element = node.element; |
| 434 recordTopLevelElementDefinition(element); | 407 recordTopLevelElementDefinition(element); |
| 435 super.visitFunctionTypeAlias(node); | 408 super.visitFunctionTypeAlias(node); |
| 436 } | 409 } |
| 437 | 410 |
| 438 @override | 411 @override |
| 412 visitImplementsClause(ImplementsClause node) { |
| 413 for (TypeName typeName in node.interfaces) { |
| 414 recordSuperType(typeName, IndexRelationKind.IS_IMPLEMENTED_BY); |
| 415 } |
| 416 } |
| 417 |
| 418 @override |
| 439 visitImportDirective(ImportDirective node) { | 419 visitImportDirective(ImportDirective node) { |
| 440 ImportElement element = node.element; | 420 ImportElement element = node.element; |
| 441 recordUriReference(element?.importedLibrary, node); | 421 recordUriReference(element?.importedLibrary, node); |
| 442 super.visitImportDirective(node); | 422 super.visitImportDirective(node); |
| 443 } | 423 } |
| 444 | 424 |
| 445 @override | 425 @override |
| 446 visitIndexExpression(IndexExpression node) { | 426 visitIndexExpression(IndexExpression node) { |
| 447 MethodElement element = node.bestElement; | 427 MethodElement element = node.bestElement; |
| 448 if (element is MethodElement) { | 428 if (element is MethodElement) { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 // if (location == null) { | 497 // if (location == null) { |
| 518 // return; | 498 // return; |
| 519 // } | 499 // } |
| 520 // name in declaration | 500 // name in declaration |
| 521 if (node.inDeclarationContext()) { | 501 if (node.inDeclarationContext()) { |
| 522 // TODO(scheglov) do we need this? | 502 // TODO(scheglov) do we need this? |
| 523 // recordRelationshipIndexable( | 503 // recordRelationshipIndexable( |
| 524 // indexableName, IndexConstants.NAME_IS_DEFINED_BY, location); | 504 // indexableName, IndexConstants.NAME_IS_DEFINED_BY, location); |
| 525 return; | 505 return; |
| 526 } | 506 } |
| 527 // name in an extends/with/implements clause | |
| 528 if (_isInExtendsWithImplementsClause(node)) { | |
| 529 return; | |
| 530 } | |
| 531 Element element = node.bestElement; | 507 Element element = node.bestElement; |
| 532 // this.field parameter | 508 // this.field parameter |
| 533 if (element is FieldFormalParameterElement) { | 509 if (element is FieldFormalParameterElement) { |
| 534 recordRelation(element.field, IndexRelationKind.IS_REFERENCED_BY, node); | 510 recordRelation(element.field, IndexRelationKind.IS_REFERENCED_BY, node); |
| 535 return; | 511 return; |
| 536 } | 512 } |
| 537 // record specific relations | 513 // record specific relations |
| 538 // TODO(scheglov) consider removing the conditions | 514 // TODO(scheglov) consider removing the conditions |
| 539 if (element is ClassElement || | 515 if (element is ClassElement || |
| 540 element is FunctionElement || | 516 element is FunctionElement || |
| (...skipping 19 matching lines...) Expand all Loading... |
| 560 element, IndexRelationKind.IS_REFERENCED_BY, offset, length); | 536 element, IndexRelationKind.IS_REFERENCED_BY, offset, length); |
| 561 } else { | 537 } else { |
| 562 int offset = node.superKeyword.end; | 538 int offset = node.superKeyword.end; |
| 563 recordRelationOffset( | 539 recordRelationOffset( |
| 564 element, IndexRelationKind.IS_REFERENCED_BY, offset, 0); | 540 element, IndexRelationKind.IS_REFERENCED_BY, offset, 0); |
| 565 } | 541 } |
| 566 super.visitSuperConstructorInvocation(node); | 542 super.visitSuperConstructorInvocation(node); |
| 567 } | 543 } |
| 568 | 544 |
| 569 @override | 545 @override |
| 546 visitTypeName(TypeName node) { |
| 547 AstNode parent = node.parent; |
| 548 if (parent is ClassTypeAlias && parent.superclass == node) { |
| 549 recordSuperType(node, IndexRelationKind.IS_EXTENDED_BY); |
| 550 } else { |
| 551 super.visitTypeName(node); |
| 552 } |
| 553 } |
| 554 |
| 555 @override |
| 570 visitVariableDeclaration(VariableDeclaration node) { | 556 visitVariableDeclaration(VariableDeclaration node) { |
| 571 VariableElement element = node.element; | 557 VariableElement element = node.element; |
| 572 recordTopLevelElementDefinition(element); | 558 recordTopLevelElementDefinition(element); |
| 573 // TODO(scheglov) do we need this? | 559 // TODO(scheglov) do we need this? |
| 574 // // record declaration | 560 // // record declaration |
| 575 // { | 561 // { |
| 576 // SimpleIdentifier name = node.name; | 562 // SimpleIdentifier name = node.name; |
| 577 // LocationImpl location = _createLocationForNode(name); | 563 // LocationImpl location = _createLocationForNode(name); |
| 578 // location = _getLocationWithExpressionType(location, node.initializer); | 564 // location = _getLocationWithExpressionType(location, node.initializer); |
| 579 // recordRelationshipElement( | 565 // recordRelationshipElement( |
| 580 // element, IndexConstants.NAME_IS_DEFINED_BY, location); | 566 // element, IndexConstants.NAME_IS_DEFINED_BY, location); |
| 581 // } | 567 // } |
| 582 super.visitVariableDeclaration(node); | 568 super.visitVariableDeclaration(node); |
| 583 } | 569 } |
| 584 | 570 |
| 585 static bool _isInExtendsWithImplementsClause(SimpleIdentifier node) { | 571 @override |
| 586 TypeName typeName; | 572 visitWithClause(WithClause node) { |
| 587 AstNode parent = node?.parent; | 573 for (TypeName typeName in node.mixinTypes) { |
| 588 AstNode parent2 = parent?.parent; | 574 recordSuperType(typeName, IndexRelationKind.IS_MIXED_IN_BY); |
| 589 if (parent is TypeName && parent.name == node) { | |
| 590 typeName = parent; | |
| 591 } else if (parent is PrefixedIdentifier && | |
| 592 parent.identifier == node && | |
| 593 parent2 is TypeName && | |
| 594 parent2.name == node) { | |
| 595 typeName = parent2; | |
| 596 } else { | |
| 597 return false; | |
| 598 } | 575 } |
| 599 AstNode clause = typeName.parent; | |
| 600 return clause is ExtendsClause || | |
| 601 clause is WithClause || | |
| 602 clause is ImplementsClause; | |
| 603 } | 576 } |
| 604 } | 577 } |
| 605 | 578 |
| 606 /** | 579 /** |
| 607 * Information about a single relation. Any [_RelationInfo] is always part | 580 * Information about a single relation. Any [_RelationInfo] is always part |
| 608 * of a [_UnitIndexAssembler], so [offset] and [length] should be understood | 581 * of a [_UnitIndexAssembler], so [offset] and [length] should be understood |
| 609 * within the context of the compilation unit pointed to by the | 582 * within the context of the compilation unit pointed to by the |
| 610 * [_UnitIndexAssembler]. | 583 * [_UnitIndexAssembler]. |
| 611 */ | 584 */ |
| 612 class _RelationInfo { | 585 class _RelationInfo { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 650 }); | 623 }); |
| 651 return new UnitIndexBuilder( | 624 return new UnitIndexBuilder( |
| 652 elements: relations.map((r) => r.elementInfo.id).toList(), | 625 elements: relations.map((r) => r.elementInfo.id).toList(), |
| 653 kinds: relations.map((r) => r.kind).toList(), | 626 kinds: relations.map((r) => r.kind).toList(), |
| 654 locationOffsets: relations.map((r) => r.offset).toList(), | 627 locationOffsets: relations.map((r) => r.offset).toList(), |
| 655 locationLengths: relations.map((r) => r.length).toList(), | 628 locationLengths: relations.map((r) => r.length).toList(), |
| 656 libraryUri: pkg._getUriId(unitElement.library.source.uri), | 629 libraryUri: pkg._getUriId(unitElement.library.source.uri), |
| 657 unitUri: pkg._getUriId(unitElement.source.uri)); | 630 unitUri: pkg._getUriId(unitElement.source.uri)); |
| 658 } | 631 } |
| 659 } | 632 } |
| OLD | NEW |