Chromium Code Reviews| 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/src/dart/element/member.dart'; | 9 import 'package:analyzer/src/dart/element/member.dart'; |
| 10 import 'package:analyzer/src/generated/utilities_dart.dart'; | 10 import 'package:analyzer/src/generated/utilities_dart.dart'; |
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 366 if (fieldName != null) { | 366 if (fieldName != null) { |
| 367 Element element = fieldName.staticElement; | 367 Element element = fieldName.staticElement; |
| 368 recordRelation(element, IndexRelationKind.IS_REFERENCED_BY, fieldName); | 368 recordRelation(element, IndexRelationKind.IS_REFERENCED_BY, fieldName); |
| 369 } | 369 } |
| 370 node.expression?.accept(this); | 370 node.expression?.accept(this); |
| 371 } | 371 } |
| 372 | 372 |
| 373 @override | 373 @override |
| 374 visitConstructorName(ConstructorName node) { | 374 visitConstructorName(ConstructorName node) { |
| 375 ConstructorElement element = node.staticElement; | 375 ConstructorElement element = node.staticElement; |
| 376 // in 'class B = A;' actually A constructors are invoked | 376 element = _getActualConstructorElement(element); |
| 377 // TODO(scheglov) add support for multiple levels of redirection | |
| 378 // TODO(scheglov) test for a loop of redirection | |
| 379 if (element != null && | |
| 380 element.isSynthetic && | |
| 381 element.redirectedConstructor != null) { | |
| 382 element = element.redirectedConstructor; | |
| 383 } | |
| 384 // record relation | 377 // record relation |
| 385 if (node.name != null) { | 378 if (node.name != null) { |
| 386 int offset = node.period.offset; | 379 int offset = node.period.offset; |
| 387 int length = node.name.end - offset; | 380 int length = node.name.end - offset; |
| 388 recordRelationOffset( | 381 recordRelationOffset( |
| 389 element, IndexRelationKind.IS_REFERENCED_BY, offset, length); | 382 element, IndexRelationKind.IS_REFERENCED_BY, offset, length); |
| 390 } else { | 383 } else { |
| 391 int offset = node.type.end; | 384 int offset = node.type.end; |
| 392 recordRelationOffset( | 385 recordRelationOffset( |
| 393 element, IndexRelationKind.IS_REFERENCED_BY, offset, 0); | 386 element, IndexRelationKind.IS_REFERENCED_BY, offset, 0); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 542 super.visitTypeName(node); | 535 super.visitTypeName(node); |
| 543 } | 536 } |
| 544 } | 537 } |
| 545 | 538 |
| 546 @override | 539 @override |
| 547 visitWithClause(WithClause node) { | 540 visitWithClause(WithClause node) { |
| 548 for (TypeName typeName in node.mixinTypes) { | 541 for (TypeName typeName in node.mixinTypes) { |
| 549 recordSuperType(typeName, IndexRelationKind.IS_MIXED_IN_BY); | 542 recordSuperType(typeName, IndexRelationKind.IS_MIXED_IN_BY); |
| 550 } | 543 } |
| 551 } | 544 } |
| 545 | |
| 546 /** | |
| 547 * If the given [constructor] is a synthetic constructor created for a | |
| 548 * [ClassTypeAlias], return the actual constructor of a [ClassDeclaration] | |
| 549 * which is invoked. Return `null` if a redirection cycle is detected. | |
| 550 */ | |
| 551 ConstructorElement _getActualConstructorElement( | |
| 552 ConstructorElement constructor) { | |
| 553 Set<ConstructorElement> seenConstructors; | |
| 554 // follow zero or more redirections | |
| 555 while (constructor != null && | |
| 556 constructor.isSynthetic && | |
| 557 constructor.redirectedConstructor != null) { | |
| 558 constructor = constructor.redirectedConstructor; | |
| 559 // fail if a cycle is detected | |
| 560 if (seenConstructors?.add(constructor) == false) { | |
| 561 return null; | |
| 562 } | |
| 563 // done if no another redirection | |
|
Paul Berry
2016/02/29 21:28:01
s/no another redirection/no more redirections/
| |
| 564 if (constructor.redirectedConstructor == false) { | |
|
Brian Wilkerson
2016/02/29 21:27:18
"false"?
Do we need this test anyway? Isn't it go
Paul Berry
2016/02/29 21:28:01
I think you mean `== null`, not `== false`.
But I
scheglov
2016/02/29 22:11:55
Well, yes, it is going to drop out of the while on
| |
| 565 return constructor; | |
| 566 } | |
| 567 // delay the Set creation until we have a potential cycle | |
| 568 seenConstructors ??= new Set<ConstructorElement>(); | |
| 569 } | |
| 570 return constructor; | |
| 571 } | |
| 552 } | 572 } |
| 553 | 573 |
| 554 /** | 574 /** |
| 555 * Information about a single relation. Any [_RelationInfo] is always part | 575 * Information about a single relation. Any [_RelationInfo] is always part |
| 556 * of a [_UnitIndexAssembler], so [offset] and [length] should be understood | 576 * of a [_UnitIndexAssembler], so [offset] and [length] should be understood |
| 557 * within the context of the compilation unit pointed to by the | 577 * within the context of the compilation unit pointed to by the |
| 558 * [_UnitIndexAssembler]. | 578 * [_UnitIndexAssembler]. |
| 559 */ | 579 */ |
| 560 class _RelationInfo { | 580 class _RelationInfo { |
| 561 final _ElementInfo elementInfo; | 581 final _ElementInfo elementInfo; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 614 usedElementKinds: relations.map((r) => r.kind).toList(), | 634 usedElementKinds: relations.map((r) => r.kind).toList(), |
| 615 usedElementOffsets: relations.map((r) => r.offset).toList(), | 635 usedElementOffsets: relations.map((r) => r.offset).toList(), |
| 616 usedElementLengths: relations.map((r) => r.length).toList()); | 636 usedElementLengths: relations.map((r) => r.length).toList()); |
| 617 } | 637 } |
| 618 | 638 |
| 619 void defineName(String name, IndexNameKind kind, int offset) { | 639 void defineName(String name, IndexNameKind kind, int offset) { |
| 620 int nameId = pkg._getStringId(name); | 640 int nameId = pkg._getStringId(name); |
| 621 definedNames.add(new _DefinedNameInfo(nameId, kind, offset)); | 641 definedNames.add(new _DefinedNameInfo(nameId, kind, offset)); |
| 622 } | 642 } |
| 623 } | 643 } |
| OLD | NEW |