Capture the prefix for references in the search index, take 2

Change-Id: I600dd7c064ce9779251d043305becd4a8203bbc5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/271802
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Brian Wilkerson 2022-12-02 18:00:59 +00:00 committed by Commit Queue
parent 46bffdabb1
commit edb66fe3bb
5 changed files with 342 additions and 57 deletions

View file

@ -207,6 +207,9 @@ class _ElementInfo {
/// The kind of the element.
final IndexSyntheticElementKind kind;
/// The prefixes used to reference the element.
final Set<String> importPrefixes = {};
/// The unique id of the element. It is set after indexing of the whole
/// package is done and we are assembling the full package index.
late int id;
@ -291,6 +294,11 @@ class _IndexAssembler {
nameRelations.add(_NameRelationInfo(nameId, kind, offset, isQualified));
}
void addPrefixForElement(PrefixElement prefixElement, Element element) {
_ElementInfo elementInfo = _getElementInfo(element);
elementInfo.importPrefixes.add(prefixElement.name);
}
void addSubtype(String name, List<String> members, List<String> supertypes) {
for (var supertype in supertypes) {
subtypes.add(
@ -352,6 +360,9 @@ class _IndexAssembler {
nullStringId: nullString.id,
unitLibraryUris: unitLibraryUris.map((s) => s.id).toList(),
unitUnitUris: unitUnitUris.map((s) => s.id).toList(),
elementImportPrefixes: elementInfoList
.map((e) => e.importPrefixes.toList().join(','))
.toList(),
elementKinds: elementInfoList.map((e) => e.kind).toList(),
elementUnits: elementInfoList.map((e) => e.unitId).toList(),
elementNameUnitMemberIds:
@ -575,6 +586,10 @@ class _IndexContributor extends GeneralizingAstVisitor {
void visitClassTypeAlias(ClassTypeAlias node) {
_addSubtypeForClassTypeAlis(node);
recordIsAncestorOf(node.declaredElement!);
var superclassName = node.superclass.name;
if (superclassName is PrefixedIdentifier) {
visitPrefixedIdentifier(superclassName);
}
super.visitClassTypeAlias(node);
}
@ -706,6 +721,10 @@ class _IndexContributor extends GeneralizingAstVisitor {
@override
void visitExtendsClause(ExtendsClause node) {
recordSuperType(node.superclass, IndexRelationKind.IS_EXTENDED_BY);
var superclassName = node.superclass.name;
if (superclassName is PrefixedIdentifier) {
visitPrefixedIdentifier(superclassName);
}
}
@override
@ -725,6 +744,10 @@ class _IndexContributor extends GeneralizingAstVisitor {
void visitImplementsClause(ImplementsClause node) {
for (NamedType namedType in node.interfaces) {
recordSuperType(namedType, IndexRelationKind.IS_IMPLEMENTED_BY);
var supertypeName = namedType.name;
if (supertypeName is PrefixedIdentifier) {
visitPrefixedIdentifier(supertypeName);
}
}
}
@ -809,6 +832,26 @@ class _IndexContributor extends GeneralizingAstVisitor {
super.visitPostfixExpression(node);
}
@override
void visitPrefixedIdentifier(PrefixedIdentifier node) {
var prefixElement = node.prefix.staticElement;
var element = node.staticElement;
if (element != null &&
prefixElement is PrefixElement &&
element is! MultiplyDefinedElementImpl &&
element is! DynamicElementImpl &&
element is! NeverElementImpl) {
// TODO(brianwilkerson) The last two conditions are here because the
// elements for `dynamic` and `Never` are singletons and hence don't have
// a parent element for which we can find an `_ElementInfo`. This means
// that any reference to either type via a prefix can't be stored in the
// index. The solution is to make those elements be normal (not unique)
// elements.
assembler.addPrefixForElement(prefixElement, element);
}
super.visitPrefixedIdentifier(node);
}
@override
void visitPrefixExpression(PrefixExpression node) {
recordOperatorReference(node.operator, node.staticElement);
@ -902,6 +945,10 @@ class _IndexContributor extends GeneralizingAstVisitor {
void visitWithClause(WithClause node) {
for (NamedType namedType in node.mixinTypes) {
recordSuperType(namedType, IndexRelationKind.IS_MIXED_IN_BY);
var supertypeName = namedType.name;
if (supertypeName is PrefixedIdentifier) {
visitPrefixedIdentifier(supertypeName);
}
}
}

View file

@ -902,6 +902,7 @@ abstract class _AnalysisDriverUnitErrorMixin
class AnalysisDriverUnitIndexBuilder extends Object
with _AnalysisDriverUnitIndexMixin
implements idl.AnalysisDriverUnitIndex {
List<String>? _elementImportPrefixes;
List<idl.IndexSyntheticElementKind>? _elementKinds;
List<int>? _elementNameClassMemberIds;
List<int>? _elementNameParameterIds;
@ -923,6 +924,16 @@ class AnalysisDriverUnitIndexBuilder extends Object
List<int>? _usedNameOffsets;
List<int>? _usedNames;
@override
List<String> get elementImportPrefixes =>
_elementImportPrefixes ??= <String>[];
/// Each item of this list corresponds to a unique referenced element. It is
/// a list of the prefixes associated with references to the element.
set elementImportPrefixes(List<String> value) {
this._elementImportPrefixes = value;
}
@override
List<idl.IndexSyntheticElementKind> get elementKinds =>
_elementKinds ??= <idl.IndexSyntheticElementKind>[];
@ -1136,7 +1147,8 @@ class AnalysisDriverUnitIndexBuilder extends Object
}
AnalysisDriverUnitIndexBuilder(
{List<idl.IndexSyntheticElementKind>? elementKinds,
{List<String>? elementImportPrefixes,
List<idl.IndexSyntheticElementKind>? elementKinds,
List<int>? elementNameClassMemberIds,
List<int>? elementNameParameterIds,
List<int>? elementNameUnitMemberIds,
@ -1156,7 +1168,8 @@ class AnalysisDriverUnitIndexBuilder extends Object
List<idl.IndexRelationKind>? usedNameKinds,
List<int>? usedNameOffsets,
List<int>? usedNames})
: _elementKinds = elementKinds,
: _elementImportPrefixes = elementImportPrefixes,
_elementKinds = elementKinds,
_elementNameClassMemberIds = elementNameClassMemberIds,
_elementNameParameterIds = elementNameParameterIds,
_elementNameUnitMemberIds = elementNameUnitMemberIds,
@ -1356,6 +1369,15 @@ class AnalysisDriverUnitIndexBuilder extends Object
x.collectApiSignature(signatureSink);
}
}
var elementImportPrefixes = this._elementImportPrefixes;
if (elementImportPrefixes == null) {
signatureSink.addInt(0);
} else {
signatureSink.addInt(elementImportPrefixes.length);
for (var x in elementImportPrefixes) {
signatureSink.addString(x);
}
}
}
typed_data.Uint8List toBuffer() {
@ -1364,6 +1386,7 @@ class AnalysisDriverUnitIndexBuilder extends Object
}
fb.Offset finish(fb.Builder fbBuilder) {
fb.Offset? offset_elementImportPrefixes;
fb.Offset? offset_elementKinds;
fb.Offset? offset_elementNameClassMemberIds;
fb.Offset? offset_elementNameParameterIds;
@ -1383,6 +1406,11 @@ class AnalysisDriverUnitIndexBuilder extends Object
fb.Offset? offset_usedNameKinds;
fb.Offset? offset_usedNameOffsets;
fb.Offset? offset_usedNames;
var elementImportPrefixes = _elementImportPrefixes;
if (!(elementImportPrefixes == null || elementImportPrefixes.isEmpty)) {
offset_elementImportPrefixes = fbBuilder.writeList(
elementImportPrefixes.map((b) => fbBuilder.writeString(b)).toList());
}
var elementKinds = _elementKinds;
if (!(elementKinds == null || elementKinds.isEmpty)) {
offset_elementKinds =
@ -1474,6 +1502,9 @@ class AnalysisDriverUnitIndexBuilder extends Object
offset_usedNames = fbBuilder.writeListUint32(usedNames);
}
fbBuilder.startTable();
if (offset_elementImportPrefixes != null) {
fbBuilder.addOffset(20, offset_elementImportPrefixes);
}
if (offset_elementKinds != null) {
fbBuilder.addOffset(4, offset_elementKinds);
}
@ -1558,6 +1589,7 @@ class _AnalysisDriverUnitIndexImpl extends Object
_AnalysisDriverUnitIndexImpl(this._bc, this._bcOffset);
List<String>? _elementImportPrefixes;
List<idl.IndexSyntheticElementKind>? _elementKinds;
List<int>? _elementNameClassMemberIds;
List<int>? _elementNameParameterIds;
@ -1579,6 +1611,13 @@ class _AnalysisDriverUnitIndexImpl extends Object
List<int>? _usedNameOffsets;
List<int>? _usedNames;
@override
List<String> get elementImportPrefixes {
return _elementImportPrefixes ??=
const fb.ListReader<String>(fb.StringReader())
.vTableGet(_bc, _bcOffset, 20, const <String>[]);
}
@override
List<idl.IndexSyntheticElementKind> get elementKinds {
return _elementKinds ??= const fb.ListReader<idl.IndexSyntheticElementKind>(
@ -1709,6 +1748,10 @@ abstract class _AnalysisDriverUnitIndexMixin
@override
Map<String, Object> toJson() {
Map<String, Object> result = <String, Object>{};
var local_elementImportPrefixes = elementImportPrefixes;
if (local_elementImportPrefixes.isNotEmpty) {
result["elementImportPrefixes"] = local_elementImportPrefixes;
}
var local_elementKinds = elementKinds;
if (local_elementKinds.isNotEmpty) {
result["elementKinds"] = local_elementKinds
@ -1801,6 +1844,7 @@ abstract class _AnalysisDriverUnitIndexMixin
@override
Map<String, Object?> toMap() => {
"elementImportPrefixes": elementImportPrefixes,
"elementKinds": elementKinds,
"elementNameClassMemberIds": elementNameClassMemberIds,
"elementNameParameterIds": elementNameParameterIds,

View file

@ -212,6 +212,10 @@ table AnalysisDriverUnitError {
/// Information about a resolved unit.
table AnalysisDriverUnitIndex {
/// Each item of this list corresponds to a unique referenced element. It is
/// a list of the prefixes associated with references to the element.
elementImportPrefixes:[string] (id: 20);
/// Each item of this list corresponds to a unique referenced element. It is
/// the kind of the synthetic element.
elementKinds:[IndexSyntheticElementKind] (id: 4);

View file

@ -147,6 +147,11 @@ abstract class AnalysisDriverUnitIndex extends base.SummaryClass {
factory AnalysisDriverUnitIndex.fromBuffer(List<int> buffer) =>
generated.readAnalysisDriverUnitIndex(buffer);
/// Each item of this list corresponds to a unique referenced element. It is
/// a list of the prefixes associated with references to the element.
@Id(20)
List<String> get elementImportPrefixes;
/// Each item of this list corresponds to a unique referenced element. It is
/// the kind of the synthetic element.
@Id(4)

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:convert';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/analysis/index.dart';
@ -126,7 +124,9 @@ import 'lib.dart' as p;
class B extends p.A {} // 2
''');
ClassElement elementA = importFindLib().class_('A');
assertThat(elementA).isExtendedAt('A {} // 2', true);
assertThat(elementA)
..isExtendedAt('A {} // 2', true)
..hasPrefixes('p');
}
test_isExtendedBy_ClassDeclaration_Object() async {
@ -174,7 +174,8 @@ class C = p.A with B;
ClassElement elementA = importFindLib().class_('A');
assertThat(elementA)
..isExtendedAt('A with', true)
..isReferencedAt('A with', true);
..isReferencedAt('A with', true)
..hasPrefixes('p');
}
test_isImplementedBy_ClassDeclaration() async {
@ -199,7 +200,8 @@ class B implements p.A {} // 2
ClassElement elementA = importFindLib().class_('A');
assertThat(elementA)
..isImplementedAt('A {} // 2', true)
..isReferencedAt('A {} // 2', true);
..isReferencedAt('A {} // 2', true)
..hasPrefixes('p');
}
test_isImplementedBy_ClassDeclaration_TypeAliasElement() async {
@ -258,7 +260,7 @@ foo() {}
await _indexTestUnit('''
import 'lib.dart';
import 'lib.dart' as pref;
main() {
void f() {
pref.foo(); // q
foo(); // nq
}''');
@ -271,7 +273,7 @@ main() {
test_isInvokedBy_FunctionElement_synthetic_loadLibrary() async {
await _indexTestUnit('''
import 'dart:math' deferred as math;
main() {
void f() {
math.loadLibrary(); // 1
math.loadLibrary(); // 2
}
@ -286,7 +288,7 @@ main() {
await _indexTestUnit('''
class A {
foo() {}
main() {
void m() {
this.foo(); // q
foo(); // nq
}
@ -323,7 +325,7 @@ extension E on int {
void foo() {}
}
main() {
void f() {
0.foo();
}
''');
@ -337,7 +339,7 @@ extension E on int {
static void foo() {}
}
main() {
void f() {
E.foo();
}
''');
@ -355,7 +357,7 @@ extension on double {
void foo() {} // double
}
main() {
void f() {
0.foo(); // int ref
(1.2).foo(); // double ref
}
@ -375,7 +377,7 @@ main() {
class A {
foo() {}
}
main() {
void f() {
var a = new A();
a.foo();
}
@ -389,7 +391,7 @@ main() {
class A {
operator +(other) => this;
}
main(A a) {
void f(A a) {
print(a + 1);
a += 2;
++a;
@ -410,7 +412,7 @@ class A {
operator [](i) => null;
operator []=(i, v) {}
}
main(A a) {
void f(A a) {
print(a[0]);
a[1] = 42;
}
@ -426,7 +428,7 @@ main(A a) {
class A {
A operator ~() => this;
}
main(A a) {
void f(A a) {
print(~a);
}
''');
@ -518,7 +520,9 @@ import 'lib.dart' as p;
class B extends Object with p.A {} // 2
''');
ClassElement elementA = importFindLib().class_('A');
assertThat(elementA).isMixedInAt('A {} // 2', true);
assertThat(elementA)
..isMixedInAt('A {} // 2', true)
..hasPrefixes('p');
}
test_isMixedInBy_ClassDeclaration_mixin() async {
@ -566,7 +570,7 @@ enum E with M { // 2
await _indexTestUnit('''
class A {
var field;
main() {
void m() {
this.field(); // q
field(); // nq
}
@ -581,7 +585,7 @@ class A {
await _indexTestUnit('''
class A {
get ggg => null;
main() {
void m() {
this.ggg(); // q
ggg(); // nq
}
@ -597,7 +601,7 @@ class A {
class A {
static var field;
}
main(A p) {
void f(A p) {
A v;
new A(); // 2
A.field = 1;
@ -617,7 +621,7 @@ main(A p) {
await _indexTestUnit('''
enum MyEnum {a}
main(MyEnum p) {
void f(MyEnum p) {
MyEnum v;
MyEnum.a;
}
@ -642,7 +646,7 @@ extension E on A<int> {}
test_isReferencedBy_ClassElement_implicitNew() async {
await _indexTestUnit('''
class A {}
main() {
void f() {
A(); // invalid code, but still a reference
}''');
ClassElement element = findElement.class_('A');
@ -697,18 +701,20 @@ class A {}
''');
await _indexTestUnit('''
import 'lib.dart' as p;
main() {
void f() {
p.A(); // invalid code, but still a reference
}''');
Element element = importFindLib().class_('A');
assertThat(element).isReferencedAt('A();', true);
assertThat(element)
..isReferencedAt('A();', true)
..hasPrefixes('p');
}
test_isReferencedBy_ClassElement_invocationTypeArgument() async {
await _indexTestUnit('''
class A {}
void f<T>() {}
main() {
void g() {
f<A>();
}
''');
@ -720,7 +726,7 @@ main() {
await _indexTestUnit('''
class A {}
class B = Object with A;
main(B p) {
void f(B p) {
B v;
}
''');
@ -730,6 +736,36 @@ main(B p) {
..isReferencedAt('B v;', false);
}
test_isReferencedBy_commentReference() async {
newFile('$testPackageLibPath/lib.dart', '''
class A {}
''');
await _indexTestUnit('''
import 'lib.dart';
/// An [A].
void f(A a) {}
''');
var element = findElement.function('f').parameters[0].type.element!;
assertThat(element).isReferencedAt('A]', false, length: 1);
}
test_isReferencedBy_commentReference_withPrefix() async {
newFile('$testPackageLibPath/lib.dart', '''
class A {}
''');
await _indexTestUnit('''
import 'lib.dart' as p;
/// A [p.A].
void f(p.A a) {}
''');
var element = findElement.function('f').parameters[0].type.element!;
assertThat(element)
..isReferencedAt('A]', true, length: 1)
..hasPrefixes('p');
}
test_isReferencedBy_CompilationUnitElement_export() async {
newFile('$testPackageLibPath/lib.dart', '''
library lib;
@ -806,7 +842,7 @@ void f() {
class A {
A.named() {}
}
main() {
void f() {
new A.named();
}
''');
@ -918,7 +954,7 @@ class A implements B {
}
class B = A with M;
class C = B with M;
main() {
void f() {
new B(); // B1
new B.named(); // B2
new C(); // C1
@ -940,7 +976,7 @@ main() {
class M {}
class A = B with M;
class B = A with M;
main() {
void f() {
new A();
new B();
}
@ -1032,13 +1068,71 @@ dynamic f() {
expect(index.usedElementOffsets, isEmpty);
}
test_isReferencedBy_enumConstant() async {
newFile('$testPackageLibPath/lib.dart', '''
enum E {
c;
}
''');
await _indexTestUnit('''
import 'lib.dart';
void f(E e) {
f(E.c);
}
''');
var element = findElement.function('f').parameters[0].type.element!;
assertThat(element)
..isReferencedAt('E.', false, length: 1)
..hasPrefixes('');
}
test_isReferencedBy_enumConstant_withMultiplePrefixes() async {
newFile('$testPackageLibPath/lib.dart', '''
enum E {
c;
}
''');
await _indexTestUnit('''
import 'lib.dart' as p;
import 'lib.dart' as q;
void f(p.E e) {
f(q.E.c);
}
''');
var element = findElement.function('f').parameters[0].type.element!;
assertThat(element)
..isReferencedAt('E.', true, length: 1)
..hasPrefixes('p,q');
}
test_isReferencedBy_enumConstant_withPrefix() async {
newFile('$testPackageLibPath/lib.dart', '''
enum E {
c;
}
''');
await _indexTestUnit('''
import 'lib.dart' as p;
void f(p.E e) {
f(p.E.c);
}
''');
var element = findElement.function('f').parameters[0].type.element!;
assertThat(element)
..isReferencedAt('E.', true, length: 1)
..hasPrefixes('p');
}
test_isReferencedBy_ExtensionElement() async {
await _indexTestUnit('''
extension E on int {
void foo() {}
}
main() {
void f() {
E(0).foo();
}
''');
@ -1056,7 +1150,7 @@ class A {
print(field); // nq
}
}
main(A a) {
void f(A a) {
a.field = 3; // q
print(a.field); // q
new A(field: 4);
@ -1073,7 +1167,7 @@ main(A a) {
// m()
assertThat(setter).isReferencedAt('field = 2; // nq', false, length: 5);
assertThat(getter).isReferencedAt('field); // nq', false, length: 5);
// main()
// f()
assertThat(setter).isReferencedAt('field = 3; // q', true, length: 5);
assertThat(getter).isReferencedAt('field); // q', true, length: 5);
}
@ -1184,7 +1278,7 @@ void f(E e) {
enum MyEnum {
A, B, C
}
main() {
void f() {
print(MyEnum.values);
print(MyEnum.A.index);
print(MyEnum.A);
@ -1237,7 +1331,7 @@ enum E {
test_isReferencedBy_FunctionElement() async {
await _indexTestUnit('''
foo() {}
main() {
void f() {
print(foo);
print(foo());
}
@ -1254,7 +1348,7 @@ bar() {}
''');
await _indexTestUnit('''
import "foo.dart";
main() {
void f() {
bar();
}
''');
@ -1270,13 +1364,32 @@ main() {
test_isReferencedBy_FunctionTypeAliasElement() async {
await _indexTestUnit('''
typedef A();
main(A p) {
void f(A p) {
}
''');
Element element = findElement.typeAlias('A');
assertThat(element).isReferencedAt('A p) {', false);
}
test_isReferencedBy_getter_withPrefix() async {
newFile('$testPackageLibPath/lib.dart', '''
class A {
static int get f => 0;
}
''');
await _indexTestUnit('''
import 'lib.dart' as p;
int f() => p.A.f;
class B extends p.A {}
''');
var element = findElement.class_('B').supertype!.element;
assertThat(element)
..isReferencedAt('A.', true, length: 1)
..hasPrefixes('p');
}
/// There was a bug in the AST structure, when single [Comment] was cloned and
/// assigned to both [FieldDeclaration] and [VariableDeclaration].
///
@ -1296,7 +1409,7 @@ var myVariable = null;
await _indexTestUnit('''
class A {
method() {}
main() {
void m() {
print(this.method); // q
print(method); // nq
}
@ -1327,6 +1440,25 @@ void f(E e) {
..isReferencedAt('foo; // q2', true);
}
test_isReferencedBy_methodInvocation_withPrefix() async {
newFile('$testPackageLibPath/lib.dart', '''
class A {
static void m() {}
}
''');
await _indexTestUnit('''
import 'lib.dart' as p;
void f() => p.A.m();
class B extends p.A {}
''');
var element = findElement.class_('B').supertype!.element;
assertThat(element)
..isReferencedAt('A.', true, length: 1)
..hasPrefixes('p');
}
test_isReferencedBy_MultiplyDefinedElement() async {
newFile('$testPackageLibPath/a1.dart', 'class A {}');
newFile('$testPackageLibPath/a2.dart', 'class A {}');
@ -1347,7 +1479,7 @@ Never f() {
test_isReferencedBy_ParameterElement() async {
await _indexTestUnit('''
foo({var p}) {}
main() {
void f() {
foo(p: 1);
}
''');
@ -1359,7 +1491,7 @@ main() {
await _indexTestUnit('''
typedef F = void Function({int? p});
void main(F f) {
void g(F f) {
f(p: 0);
}
''');
@ -1371,7 +1503,7 @@ void main(F f) {
await _indexTestUnit('''
typedef F<T> = void Function({T? test});
main(F<int> f) {
void g(F<int> f) {
f.call(test: 0);
}
''');
@ -1389,7 +1521,7 @@ void foo<T>({T? a}) {}
import 'a.dart';
import 'b.dart';
void main() {
void f() {
foo(a: 0);
}
""");
@ -1428,7 +1560,7 @@ class A<T> {
A({T? test});
}
main() {
void f() {
A(test: 0);
}
''');
@ -1442,7 +1574,7 @@ class A<T> {
void foo({T? test}) {}
}
main(A<int> a) {
void f(A<int> a) {
a.foo(test: 0);
}
''');
@ -1479,7 +1611,7 @@ void() {
foo([p]) {
p; // 1
}
main() {
void f() {
foo(1); // 2
}
''');
@ -1508,7 +1640,7 @@ extension E on int {
void set foo(int _) {}
}
main() {
void f() {
0.foo;
0.foo = 0;
}
@ -1526,7 +1658,7 @@ extension E on int {
static void set foo(int _) {}
}
main() {
void f() {
0.foo;
0.foo = 0;
}
@ -1549,7 +1681,7 @@ extension on double {
void set foo(int _) {} // double setter
}
main() {
void f() {
0.foo; // int getter ref
0.foo = 0; // int setter ref
(1.2).foo; // double getter ref
@ -1572,11 +1704,47 @@ main() {
.isReferencedAt('foo = 0; // double setter ref', true);
}
test_isReferencedBy_setter_withPrefix() async {
newFile('$testPackageLibPath/lib.dart', '''
class A {
static int f = 0;
}
''');
await _indexTestUnit('''
import 'lib.dart' as p;
void f(int i) => p.A.f = i;
class B extends p.A {}
''');
var element = findElement.class_('B').supertype!.element;
assertThat(element)
..isReferencedAt('A.', true, length: 1)
..hasPrefixes('p');
}
test_isReferencedBy_simpleIdentifier_withPrefix() async {
newFile('$testPackageLibPath/lib.dart', '''
class A {}
''');
await _indexTestUnit('''
import 'lib.dart' as p;
var t = p.A;
class B extends p.A {}
''');
var element = findElement.class_('B').supertype!.element;
assertThat(element)
..isReferencedAt('A;', true, length: 1)
..hasPrefixes('p');
}
test_isReferencedBy_synthetic_leastUpperBound() async {
await _indexTestUnit('''
int f1({int p}) => 1;
int f2({int p}) => 2;
main(bool b) {
void g(bool b) {
var f = b ? f1 : f2;
f(p: 0);
}''');
@ -1592,7 +1760,7 @@ var V;
await _indexTestUnit('''
import 'lib.dart' show V; // imp
import 'lib.dart' as pref;
main() {
void f() {
pref.V = 5; // q
print(pref.V); // q
V = 5; // nq
@ -1832,7 +2000,7 @@ library aaa.bbb.ccc;
class C {
var bbb;
}
main(p) {
void f(p) {
p.bbb = 1;
}
''');
@ -1846,7 +2014,7 @@ main(p) {
class C {
var x;
}
main(C c) {
void f(C c) {
c.x; // 1
c.x = 1;
c.x += 2;
@ -1862,7 +2030,7 @@ main(C c) {
test_usedName_qualified_unresolved() async {
await _indexTestUnit('''
main(p) {
void f(p) {
p.x;
p.x = 1;
p.x += 2;
@ -1897,7 +2065,7 @@ class C {
test_usedName_unqualified_unresolved() async {
await _indexTestUnit('''
main() {
void f() {
x;
x = 1;
x += 2;
@ -1919,6 +2087,12 @@ class _ElementIndexAssert {
_ElementIndexAssert(this.test, this.element, this.relations);
void hasPrefixes(String expectedPrefixes) {
var id = test._findElementId(element);
var actualPrefixes = test.index.elementImportPrefixes[id];
expect(actualPrefixes, expectedPrefixes);
}
void hasRelationCount(int expectedCount) {
expect(relations, hasLength(expectedCount));
}
@ -2077,9 +2251,20 @@ mixin _IndexMixin on PubPackageResolutionTest {
}
void _failWithIndexDump(String msg) {
String packageIndexJsonString =
JsonEncoder.withIndent(' ').convert(index.toJson());
fail('$msg in\n$packageIndexJsonString');
var buffer = StringBuffer();
for (int i = 0; i < index.usedElementOffsets.length; i++) {
buffer.write(' id = ');
buffer.write(index.usedElements[i]);
buffer.write(' kind = ');
buffer.write(index.usedElementKinds[i]);
buffer.write(' offset = ');
buffer.write(index.usedElementOffsets[i]);
buffer.write(' length = ');
buffer.write(index.usedElementLengths[i]);
buffer.write(' isQualified = ');
buffer.writeln(index.usedElementIsQualifiedFlags[i]);
}
fail('$msg in\n${buffer.toString()}');
}
/// Return the [element] identifier in [index] or fail.