blob: e32e7e8ce69cd0aeb4bb6d92ab3487f51e56b033 [file] [log] [blame]
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// 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 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'context_collection_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(OptionalConstDriverResolutionTest);
});
}
@reflectiveTest
class OptionalConstDriverResolutionTest extends PubPackageResolutionTest {
Map<String, LibraryElement> libraries = {};
LibraryElement get libraryA => libraries['package:test/a.dart']!;
test_instantiateToBounds_notPrefixed_named() async {
var creation = await _resolveImplicitConst('B.named()');
assertInstanceCreation(
creation,
libraryA.getType('B')!,
'B<num>',
constructorName: 'named',
expectedConstructorMember: true,
expectedSubstitution: {'T': 'num'},
);
}
test_instantiateToBounds_notPrefixed_unnamed() async {
var creation = await _resolveImplicitConst('B()');
assertInstanceCreation(
creation,
libraryA.getType('B')!,
'B<num>',
expectedConstructorMember: true,
expectedSubstitution: {'T': 'num'},
);
}
test_instantiateToBounds_prefixed_named() async {
var creation = await _resolveImplicitConst('p.B.named()', prefix: 'p');
assertInstanceCreation(
creation,
libraryA.getType('B')!,
'B<num>',
constructorName: 'named',
expectedConstructorMember: true,
expectedSubstitution: {'T': 'num'},
expectedPrefix: _importOfA().prefix,
);
}
test_instantiateToBounds_prefixed_unnamed() async {
var creation = await _resolveImplicitConst('p.B()', prefix: 'p');
assertInstanceCreation(
creation,
libraryA.getType('B')!,
'B<num>',
expectedConstructorMember: true,
expectedSubstitution: {'T': 'num'},
expectedPrefix: _importOfA().prefix,
);
}
test_notPrefixed_named() async {
var creation = await _resolveImplicitConst('A.named()');
assertInstanceCreation(
creation,
libraryA.getType('A')!,
'A',
constructorName: 'named',
);
}
test_notPrefixed_unnamed() async {
var creation = await _resolveImplicitConst('A()');
assertInstanceCreation(
creation,
libraryA.getType('A')!,
'A',
);
}
test_prefixed_named() async {
var creation = await _resolveImplicitConst('p.A.named()', prefix: 'p');
// Note, that we don't resynthesize the import prefix.
assertInstanceCreation(
creation,
libraryA.getType('A')!,
'A',
constructorName: 'named',
expectedPrefix: _importOfA().prefix,
);
}
test_prefixed_unnamed() async {
var creation = await _resolveImplicitConst('p.A()', prefix: 'p');
// Note, that we don't resynthesize the import prefix.
assertInstanceCreation(
creation,
libraryA.getType('A')!,
'A',
expectedPrefix: _importOfA().prefix,
);
}
test_prefixed_unnamed_generic() async {
newFile('$testPackageLibPath/a.dart', content: r'''
class C<T> {
const C();
}
''');
await assertNoErrorsInCode(r'''
import 'a.dart' as p;
const x = p.C<int>();
''');
_fillLibraries();
var element_C = libraryA.getType('C');
var element_p = findElement.prefix('p');
var creation = findNode.instanceCreation('p.C<int>()');
assertType(creation, 'C<int>');
var constructorName = creation.constructorName;
var typeName = constructorName.type;
assertType(typeName, 'C<int>');
var pC = typeName.name as PrefixedIdentifier;
assertElement(pC, element_C);
// TODO(scheglov) enforce
// assertTypeNull(pC);
var ref_p = pC.prefix;
assertElement(ref_p, element_p);
assertTypeNull(ref_p);
var ref_C = pC.identifier;
assertElement(ref_C, element_C);
assertTypeNull(ref_C);
assertType(typeName.typeArguments!.arguments[0], 'int');
}
void _fillLibraries([LibraryElement? library]) {
library ??= result.unit!.declaredElement!.library;
var uriStr = library.source.uri.toString();
if (!libraries.containsKey(uriStr)) {
libraries[uriStr] = library;
library.importedLibraries.forEach(_fillLibraries);
}
}
ImportElement _importOfA() {
var importOfB = findElement.import('package:test/b.dart');
return importOfB.importedLibrary!.imports[0];
}
Future<InstanceCreationExpression> _resolveImplicitConst(String expr,
{String? prefix}) async {
newFile('$testPackageLibPath/a.dart', content: '''
class A {
const A();
const A.named();
}
class B<T extends num> {
const B();
const B.named();
}
''');
if (prefix != null) {
newFile('$testPackageLibPath/b.dart', content: '''
import 'a.dart' as $prefix;
const a = $expr;
''');
} else {
newFile('$testPackageLibPath/b.dart', content: '''
import 'a.dart';
const a = $expr;
''');
}
await resolveTestCode(r'''
import 'b.dart';
var v = a;
''');
_fillLibraries();
var vg = findNode.simple('a;').staticElement as PropertyAccessorElement;
var v = vg.variable as ConstVariableElement;
var creation = v.constantInitializer as InstanceCreationExpression;
return creation;
}
}