| // 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(); |
| |
| PropertyAccessorElement vg = findNode.simple('a;').staticElement; |
| var v = vg.variable as ConstVariableElement; |
| |
| InstanceCreationExpression creation = v.constantInitializer; |
| return creation; |
| } |
| } |