blob: 5dcf969fa4c5aa33c78ec481958b906c3d92939a [file] [log] [blame]
// Copyright (c) 2014, 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/constant/value.dart';
import 'package:analyzer/dart/element/element2.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/utilities/extensions/element.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../../generated/type_system_base.dart';
import '../../summary/elements_base.dart';
import '../resolution/context_collection_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ElementAnnotationImplTest);
defineReflectiveTests(FieldElementImplTest);
defineReflectiveTests(FunctionTypeImplTest);
defineReflectiveTests(MaybeAugmentedInstanceElementMixinTest);
defineReflectiveTests(TypeParameterTypeImplTest);
});
}
@reflectiveTest
class ElementAnnotationImplTest extends PubPackageResolutionTest {
test_computeConstantValue() async {
newFile('$testPackageLibPath/a.dart', r'''
class A {
final String f;
const A(this.f);
}
void f(@A('x') int p) {}
''');
await resolveTestCode(r'''
import 'a.dart';
main() {
f(3);
}
''');
var argument = findNode.integerLiteral('3');
var parameter = argument.correspondingParameter!;
ElementAnnotation annotation = parameter.metadata[0];
DartObject value = annotation.computeConstantValue()!;
expect(value.getField('f')!.toStringValue(), 'x');
}
}
@reflectiveTest
class FieldElementImplTest extends PubPackageResolutionTest {
test_isEnumConstant() async {
await resolveTestCode(r'''
enum B {B1, B2, B3}
''');
var B = findElement2.enum_('B');
var b2Element = B.getField2('B2')!;
expect(b2Element.isEnumConstant, isTrue);
var valuesElement = B.getField2('values')!;
expect(valuesElement.isEnumConstant, isFalse);
}
}
@reflectiveTest
class FunctionTypeImplTest extends AbstractTypeSystemTest {
void assertType(DartType type, String expected) {
var typeStr = type.getDisplayString();
expect(typeStr, expected);
}
void test_getNamedParameterTypes_namedParameters() {
var type = functionTypeNone(
typeParameters: [],
formalParameters: [
requiredParameter(name: 'a', type: intNone),
namedParameter(name: 'b', type: doubleNone),
namedParameter(name: 'c', type: stringNone),
],
returnType: voidNone,
);
Map<String, DartType> types = type.namedParameterTypes;
expect(types, hasLength(2));
expect(types['b'], doubleNone);
expect(types['c'], stringNone);
}
void test_getNamedParameterTypes_noNamedParameters() {
var type = functionTypeNone(
typeParameters: [],
formalParameters: [
requiredParameter(type: intNone),
requiredParameter(type: doubleNone),
positionalParameter(type: stringNone),
],
returnType: voidNone,
);
Map<String, DartType> types = type.namedParameterTypes;
expect(types, hasLength(0));
}
void test_getNamedParameterTypes_noParameters() {
var type = functionTypeNone(
typeParameters: [],
formalParameters: [],
returnType: voidNone,
);
Map<String, DartType> types = type.namedParameterTypes;
expect(types, hasLength(0));
}
void test_getNormalParameterTypes_noNormalParameters() {
var type = functionTypeNone(
typeParameters: [],
formalParameters: [
positionalParameter(type: intNone),
positionalParameter(type: doubleNone),
],
returnType: voidNone,
);
List<DartType> types = type.normalParameterTypes;
expect(types, hasLength(0));
}
void test_getNormalParameterTypes_noParameters() {
var type = functionTypeNone(
typeParameters: [],
formalParameters: [],
returnType: voidNone,
);
List<DartType> types = type.normalParameterTypes;
expect(types, hasLength(0));
}
void test_getNormalParameterTypes_normalParameters() {
var type = functionTypeNone(
typeParameters: [],
formalParameters: [
requiredParameter(type: intNone),
requiredParameter(type: doubleNone),
positionalParameter(type: stringNone),
],
returnType: voidNone,
);
List<DartType> types = type.normalParameterTypes;
expect(types, hasLength(2));
expect(types[0], intNone);
expect(types[1], doubleNone);
}
void test_getOptionalParameterTypes_noOptionalParameters() {
var type = functionTypeNone(
typeParameters: [],
formalParameters: [
requiredParameter(name: 'a', type: intNone),
namedParameter(name: 'b', type: doubleNone),
],
returnType: voidNone,
);
List<DartType> types = type.optionalParameterTypes;
expect(types, hasLength(0));
}
void test_getOptionalParameterTypes_noParameters() {
var type = functionTypeNone(
typeParameters: [],
formalParameters: [],
returnType: voidNone,
);
List<DartType> types = type.optionalParameterTypes;
expect(types, hasLength(0));
}
void test_getOptionalParameterTypes_optionalParameters() {
var type = functionTypeNone(
typeParameters: [],
formalParameters: [
requiredParameter(type: intNone),
positionalParameter(type: doubleNone),
positionalParameter(type: stringNone),
],
returnType: voidNone,
);
List<DartType> types = type.optionalParameterTypes;
expect(types, hasLength(2));
expect(types[0], doubleNone);
expect(types[1], stringNone);
}
}
@reflectiveTest
class MaybeAugmentedInstanceElementMixinTest extends ElementsBaseTest {
@override
bool get keepLinkingLibraries => true;
test_lookUpGetter_declared() async {
var library = await buildLibrary('''
class A {
int get g {}
}
''');
var elementA = library.getClass2('A')!;
var getter = elementA.getGetter2('g');
expect(elementA.lookUpGetter2(name: 'g', library: library), same(getter));
}
@FailingTest() // TODO(scheglov): implement augmentation
test_lookUpGetter_fromAugmentation() async {
newFile('$testPackageLibPath/a.dart', '''
part of 'test.dart';
augment class A {
int get g {}
}
''');
var library = await buildLibrary('''
part 'a.dart';
class A {}
''');
var elementA = library.getClass2('A')!;
var getter = elementA.getGetter2('g')!;
expect(elementA.lookUpGetter2(name: 'g', library: library), same(getter));
}
test_lookUpGetter_inherited() async {
var library = await buildLibrary('''
class A {
int get g {}
}
class B extends A {}
''');
var classA = library.getClass2('A')!;
var getter = classA.getGetter2('g');
var classB = library.getClass2('B')!;
expect(classB.lookUpGetter2(name: 'g', library: library), same(getter));
}
test_lookUpGetter_inherited_fromAugmentation() async {
newFile('$testPackageLibPath/a.dart', '''
part of 'test.dart';
augment class A {
int get g {}
}
''');
var library = await buildLibrary('''
part 'a.dart';
class A {}
class B extends A {}
''');
var classA = library.getClass2('A')!;
var getter = classA.getGetter2('g');
var classB = library.getClass2('B')!;
expect(classB.lookUpGetter2(name: 'g', library: library), same(getter));
}
test_lookUpGetter_inherited_fromMixin() async {
var library = await buildLibrary('''
mixin A {
int get g {}
}
class B with A {}
''');
var mixinA = library.getMixin2('A')!;
var getter = mixinA.getGetter2('g');
var classB = library.getClass2('B')!;
expect(classB.lookUpGetter2(name: 'g', library: library), same(getter));
}
test_lookUpGetter_undeclared() async {
var library = await buildLibrary('''
class A {}
''');
var classA = library.getClass2('A')!;
expect(classA.lookUpGetter2(name: 'g', library: library), isNull);
}
test_lookUpGetter_undeclared_recursive() async {
var library = await buildLibrary('''
class A extends B {}
class B extends A {}
''');
var classA = library.getClass2('A')!;
expect(classA.lookUpGetter2(name: 'g', library: library), isNull);
}
test_lookUpMethod_declared() async {
var library = await buildLibrary('''
class A {
int m() {}
}
''');
var classA = library.getClass2('A')!;
var method = classA.getMethod2('m')!;
expect(classA.lookUpMethod2(name: 'm', library: library), same(method));
}
@FailingTest() // TODO(scheglov): implement augmentation
test_lookUpMethod_fromAugmentation() async {
newFile('$testPackageLibPath/a.dart', '''
part of 'test.dart';
augment class A {
int m() {}
}
''');
var library = await buildLibrary('''
part 'a.dart';
class A {}
''');
var classA = library.getClass2('A')!;
var method = classA.getMethod2('m')!;
expect(classA.lookUpMethod2(name: 'm', library: library), same(method));
}
test_lookUpMethod_inherited() async {
var library = await buildLibrary('''
class A {
int m() {}
}
class B extends A {}
''');
var classA = library.getClass2('A')!;
var method = classA.getMethod2('m');
var classB = library.getClass2('B')!;
expect(classB.lookUpMethod2(name: 'm', library: library), same(method));
}
test_lookUpMethod_inherited_fromAugmentation() async {
newFile('$testPackageLibPath/a.dart', '''
part of 'test.dart';
augment class A {
int m() {}
}
''');
var library = await buildLibrary('''
part 'a.dart';
class A {}
class B extends A {}
''');
var classA = library.getClass2('A')!;
var method = classA.getMethod2('m');
var classB = library.getClass2('B')!;
expect(classB.lookUpMethod2(name: 'm', library: library), same(method));
}
test_lookUpMethod_inherited_fromMixin() async {
var library = await buildLibrary('''
mixin A {
int m() {}
}
class B with A {}
''');
var mixinA = library.getMixin2('A')!;
var method = mixinA.getMethod2('m');
var classB = library.getClass2('B')!;
expect(classB.lookUpMethod2(name: 'm', library: library), same(method));
}
test_lookUpMethod_undeclared() async {
var library = await buildLibrary('''
class A {}
''');
var classA = library.getClass2('A')!;
expect(classA.lookUpMethod2(name: 'm', library: library), isNull);
}
test_lookUpMethod_undeclared_recursive() async {
var library = await buildLibrary('''
class A extends B {}
class B extends A {}
''');
var classA = library.getClass2('A')!;
expect(classA.lookUpMethod2(name: 'm', library: library), isNull);
}
test_lookUpSetter_declared() async {
var library = await buildLibrary('''
class A {
set s(x) {}
}
''');
var classA = library.getClass2('A')!;
var setter = classA.getSetter2('s')!;
expect(classA.lookUpSetter2(name: 's', library: library), same(setter));
}
@FailingTest() // TODO(scheglov): implement augmentation
test_lookUpSetter_fromAugmentation() async {
newFile('$testPackageLibPath/a.dart', '''
part of 'test.dart';
augment class A {
set s(x) {}
}
''');
var library = await buildLibrary('''
part 'a.dart';
class A {}
''');
var classA = library.getClass2('A')!;
var setter = classA.getSetter2('s')!;
expect(classA.lookUpSetter2(name: 's', library: library), same(setter));
}
test_lookUpSetter_inherited() async {
var library = await buildLibrary('''
class A {
set s(x) {}
}
class B extends A {}
''');
var classA = library.getClass2('A')!;
var setter = classA.getSetter2('s')!;
var classB = library.getClass2('B')!;
expect(classB.lookUpSetter2(name: 's', library: library), same(setter));
}
@FailingTest() // TODO(scheglov): implement augmentation
test_lookUpSetter_inherited_fromAugmentation() async {
newFile('$testPackageLibPath/a.dart', '''
part of 'test.dart';
augment class A {
set s(x) {}
}
''');
var library = await buildLibrary('''
part 'a.dart';
class A {}
class B extends A {}
''');
var classA = library.getClass2('A')!;
var setter = classA.getSetter2('s')!;
var classB = library.getClass2('B')!;
expect(classB.lookUpSetter2(name: 's', library: library), same(setter));
}
test_lookUpSetter_inherited_fromMixin() async {
var library = await buildLibrary('''
mixin A {
set s(x) {}
}
class B with A {}
''');
var mixinA = library.getMixin2('A')!;
var setter = mixinA.getSetter2('s')!;
var classB = library.getClass2('B')!;
expect(classB.lookUpSetter2(name: 's', library: library), same(setter));
}
test_lookUpSetter_undeclared() async {
var library = await buildLibrary('''
class A {}
''');
var classA = library.getClass2('A')!;
expect(classA.lookUpSetter2(name: 's', library: library), isNull);
}
test_lookUpSetter_undeclared_recursive() async {
var library = await buildLibrary('''
class A extends B {}
class B extends A {}
''');
var classA = library.getClass2('A')!;
expect(classA.lookUpSetter2(name: 's', library: library), isNull);
}
}
@reflectiveTest
class TypeParameterTypeImplTest extends AbstractTypeSystemTest {
void test_asInstanceOf_hasBound_element() {
var T = typeParameter('T', bound: listNone(intNone));
_assert_asInstanceOf(
typeParameterTypeNone(T),
typeProvider.iterableElement2,
'Iterable<int>',
);
}
void test_asInstanceOf_hasBound_element_noMatch() {
var T = typeParameter('T', bound: numNone);
_assert_asInstanceOf(
typeParameterTypeNone(T),
typeProvider.iterableElement2,
null,
);
}
void test_asInstanceOf_hasBound_promoted() {
var T = typeParameter('T');
_assert_asInstanceOf(
typeParameterTypeNone(T, promotedBound: listNone(intNone)),
typeProvider.iterableElement2,
'Iterable<int>',
);
}
void test_asInstanceOf_hasBound_promoted_noMatch() {
var T = typeParameter('T');
_assert_asInstanceOf(
typeParameterTypeNone(T, promotedBound: numNone),
typeProvider.iterableElement2,
null,
);
}
void test_asInstanceOf_noBound() {
var T = typeParameter('T');
_assert_asInstanceOf(
typeParameterTypeNone(T),
typeProvider.iterableElement2,
null,
);
}
void test_creation() {
var element = typeParameter('E');
expect(typeParameterTypeNone(element), isNotNull);
}
void test_getElement() {
var element = typeParameter('E');
TypeParameterTypeImpl type = typeParameterTypeNone(element);
expect(type.element3, element);
}
void _assert_asInstanceOf(
TypeImpl type,
ClassElement2 element,
String? expected,
) {
var result = type.asInstanceOf2(element);
expect(result?.getDisplayString(), expected);
}
}