Version 2.14.0-271.0.dev
Merge commit 'b1db8a3c6525a83b660652e5835dfd5facfb88b7' into 'dev'
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 52d52dc..e6eb121 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -456,6 +456,7 @@
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR,
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_EXTENSION,
+ CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION,
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD,
CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_POSITION,
diff --git a/pkg/analyzer/lib/src/dart/resolver/exit_detector.dart b/pkg/analyzer/lib/src/dart/resolver/exit_detector.dart
index a09335c..adb9ff5 100644
--- a/pkg/analyzer/lib/src/dart/resolver/exit_detector.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/exit_detector.dart
@@ -551,6 +551,9 @@
}
@override
+ bool visitTypeLiteral(TypeLiteral node) => _nodeExits(node.typeName);
+
+ @override
bool visitTypeName(TypeName node) => false;
@override
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
index 96cc743..802fa11 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
@@ -4,10 +4,13 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/ast_factory.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/resolver/resolution_result.dart';
import 'package:analyzer/src/error/codes.dart';
@@ -22,25 +25,54 @@
/// The resolver driving this participant.
final ResolverVisitor _resolver;
- FunctionReferenceResolver(this._resolver);
+ final bool _isNonNullableByDefault;
+
+ /// The type representing the type 'type'.
+ final InterfaceType _typeType;
+
+ FunctionReferenceResolver(this._resolver, this._isNonNullableByDefault)
+ : _typeType = _resolver.typeProvider.typeType;
ErrorReporter get _errorReporter => _resolver.errorReporter;
+ NullabilitySuffix get _nullabilitySuffixForTypeNames =>
+ _isNonNullableByDefault ? NullabilitySuffix.none : NullabilitySuffix.star;
+
void resolve(FunctionReferenceImpl node) {
var function = node.function;
node.typeArguments?.accept(_resolver);
if (function is SimpleIdentifierImpl) {
var element = _resolver.nameScope.lookup(function.name).getter;
- if (element is ExecutableElement) {
+
+ // Classes and type aliases are checked first so as to include a
+ // PropertyAccess parent check, which does not need to be done for
+ // functions.
+ if (element is ClassElement || element is TypeAliasElement) {
+ // A type-instantiated constructor tearoff like `C<int>.name` or
+ // `prefix.C<int>.name` is initially represented as a [PropertyAccess]
+ // with a [FunctionReference] target.
+ if (node.parent is PropertyAccess) {
+ _resolveConstructorReference(node);
+ return;
+ } else if (element is ClassElement) {
+ function.staticElement = element;
+ _resolveDirectTypeLiteral(node, function, element);
+ return;
+ } else if (element is TypeAliasElement) {
+ function.staticElement = element;
+ _resolveTypeAlias(node: node, element: element, typeAlias: function);
+ return;
+ }
+ } else if (element is ExecutableElement) {
function.staticElement = element;
- _resolve(node: node, rawType: element.type);
+ _resolve(node: node, name: element.name, rawType: element.type);
return;
} else if (element is VariableElement) {
var functionType = element.type;
if (functionType is FunctionType) {
function.accept(_resolver);
- _resolve(node: node, rawType: functionType);
+ _resolve(node: node, name: element.name ?? '', rawType: functionType);
return;
}
}
@@ -52,32 +84,7 @@
var prefixElement =
_resolver.nameScope.lookup(function.prefix.name).getter;
if (prefixElement is PrefixElement) {
- var nameNode = function.identifier;
- var name = nameNode.name;
- _resolveReceiverPrefix(node, prefixElement, nameNode, name);
- return;
- }
-
- if (prefixElement is ClassElement) {
- // TODO(srawlins): Rewrite `node` as a [TypeLiteral], then resolve the
- // [TypeLiteral] instead of `function`.
- function.accept(_resolver);
- node.staticType = DynamicTypeImpl.instance;
- return;
- } else if (prefixElement is TypeAliasElement) {
- var aliasedType = prefixElement.aliasedType;
- if (aliasedType is InterfaceType) {
- // TODO(srawlins): Rewrite `node` as a [TypeLiteral], then resolve
- // the [TypeLiteral] instead of `function`.
- function.accept(_resolver);
- node.staticType = DynamicTypeImpl.instance;
- return;
- }
- } else if (prefixElement is ExtensionElement) {
- // TODO(srawlins): Rewrite `node` as a [TypeLiteral], then resolve the
- // [TypeLiteral] instead of `function`.
- function.accept(_resolver);
- node.staticType = DynamicTypeImpl.instance;
+ _resolveReceiverPrefix(node, prefixElement, function);
return;
}
@@ -103,23 +110,61 @@
methodElement = resolveTypeProperty(prefixType).getter;
}
if (methodElement is MethodElement) {
- _resolveFunctionReferenceMethod(node: node, function: function);
+ _resolveFunctionReferenceMethod(
+ node: node, function: function, element: methodElement);
return;
}
- // TODO(srawlins): Check for [ConstructorElement] and rewrite to
- // [ConstructorReference] before resolving.
+ // TODO(srawlins): Need to report cases where [methodElement] is not
+ // generic. The 'test_instanceGetter_explicitReceiver' test case needs to
+ // be updated to handle this.
+
function.accept(_resolver);
node.staticType = DynamicTypeImpl.instance;
return;
}
- if (function is PropertyAccess) {
+ if (function is PropertyAccessImpl) {
function.accept(_resolver);
- DartType functionType = function.typeOrThrow;
+ var target = function.target;
+ DartType targetType;
+ if (target is SuperExpressionImpl) {
+ targetType = target.typeOrThrow;
+ } else if (target is ThisExpressionImpl) {
+ targetType = target.typeOrThrow;
+ } else if (target is SimpleIdentifierImpl) {
+ var targetElement = _resolver.nameScope.lookup(target.name).getter;
+ if (targetElement is VariableElement) {
+ targetType = targetElement.type;
+ } else if (targetElement is PropertyAccessorElement) {
+ targetType = targetElement.returnType;
+ } else {
+ // TODO(srawlins): Can we get here?
+ node.staticType = DynamicTypeImpl.instance;
+ return;
+ }
+ } else {
+ // TODO(srawlins): Can we get here? PrefixedIdentifier?
+ node.staticType = DynamicTypeImpl.instance;
+ return;
+ }
+ var propertyElement = _resolver.typePropertyResolver
+ .resolve(
+ receiver: function.realTarget,
+ receiverType: targetType,
+ name: function.propertyName.name,
+ propertyErrorEntity: function.propertyName,
+ nameErrorEntity: function,
+ )
+ .getter;
- if (functionType is FunctionType) {
- _resolve(node: node, rawType: function.staticType as FunctionType);
+ var functionType = function.typeOrThrow;
+ if (functionType is FunctionType && propertyElement != null) {
+ _resolve(
+ node: node,
+ name: propertyElement.name,
+ rawType: functionType,
+ );
return;
}
@@ -133,45 +178,70 @@
node.staticType = DynamicTypeImpl.instance;
}
+ List<DartType> _checkTypeArguments(
+ TypeArgumentList typeArgumentList,
+ String name,
+ List<TypeParameterElement> typeParameters,
+ CompileTimeErrorCode errorCode,
+ ) {
+ if (typeArgumentList.arguments.length != typeParameters.length) {
+ _errorReporter.reportErrorForNode(
+ errorCode,
+ typeArgumentList,
+ [name, typeParameters.length, typeArgumentList.arguments.length],
+ );
+ return List.filled(typeParameters.length, DynamicTypeImpl.instance);
+ } else {
+ return typeArgumentList.arguments
+ .map((typeAnnotation) => typeAnnotation.typeOrThrow)
+ .toList();
+ }
+ }
+
/// Resolves [node]'s static type, as an instantiated function type, and type
/// argument types, using [rawType] as the uninstantiated function type.
void _resolve({
required FunctionReferenceImpl node,
+ required String name,
required FunctionType rawType,
}) {
- // `node.typeArguments`, coming from the parser, is never null.
- var typeArgumentList = node.typeArguments!;
- var typeParameters = rawType.typeFormals;
-
- List<DartType> typeArguments;
- if (typeArgumentList.arguments.length != typeParameters.length) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
- typeArgumentList,
- [
- rawType,
- typeParameters.length,
- typeArgumentList.arguments.length,
- ],
- );
- typeArguments = List.filled(
- typeParameters.length,
- DynamicTypeImpl.instance,
- );
- } else {
- typeArguments = typeArgumentList.arguments
- .map((typeArgument) => typeArgument.typeOrThrow)
- .toList();
- }
+ var typeArguments = _checkTypeArguments(
+ // `node.typeArguments`, coming from the parser, is never null.
+ node.typeArguments!, name, rawType.typeFormals,
+ CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION,
+ );
var invokeType = rawType.instantiate(typeArguments);
node.typeArgumentTypes = typeArguments;
node.staticType = invokeType;
}
+ void _resolveConstructorReference(FunctionReferenceImpl node) {
+ // TODO(srawlins): Rewrite and resolve [node] as a constructor reference.
+ node.function.accept(_resolver);
+ node.staticType = DynamicTypeImpl.instance;
+ }
+
+ /// Resolves [node] as a [TypeLiteral] referencing an interface type directly
+ /// (not through a type alias).
+ void _resolveDirectTypeLiteral(
+ FunctionReferenceImpl node, Identifier name, ClassElement element) {
+ var typeArguments = _checkTypeArguments(
+ // `node.typeArguments`, coming from the parser, is never null.
+ node.typeArguments!, name.name, element.typeParameters,
+ CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
+ );
+ var type = element.instantiate(
+ typeArguments: typeArguments,
+ nullabilitySuffix: _nullabilitySuffixForTypeNames,
+ );
+ _resolveTypeLiteral(node: node, instantiatedType: type, name: name);
+ }
+
void _resolveFunctionReferenceMethod({
required FunctionReferenceImpl node,
required PrefixedIdentifier function,
+ required MethodElement element,
}) {
function.accept(_resolver);
var receiver = function.prefix;
@@ -196,10 +266,7 @@
if (target != null) {
// TODO(srawlins): Set static type on `nameNode`?
- _resolve(
- node: node,
- rawType: function.staticType as FunctionType,
- );
+ _resolve(node: node, name: name, rawType: element.type);
return;
}
@@ -210,15 +277,15 @@
void _resolveReceiverPrefix(
FunctionReferenceImpl node,
- PrefixElement prefix,
- SimpleIdentifierImpl nameNode,
- String name,
+ PrefixElement prefixElement,
+ PrefixedIdentifier prefix,
) {
// TODO(srawlins): Handle `loadLibrary`, as in `p.loadLibrary<int>;`.
- var element = prefix.scope.lookup(name).getter;
+ var nameNode = prefix.identifier;
+ var name = nameNode.name;
+ var element = prefixElement.scope.lookup(name).getter;
element = _resolver.toLegacyElement(element);
- nameNode.staticElement = element;
if (element is MultiplyDefinedElement) {
MultiplyDefinedElement multiply = element;
@@ -227,18 +294,68 @@
// TODO(srawlins): Add a resolution test for this case.
}
- if (element is ExecutableElement) {
- var function = node.function;
- function.accept(_resolver);
- return _resolve(
- node: node, rawType: function.typeOrThrow as FunctionType);
+ // Classes and type aliases are checked first so as to include a
+ // PropertyAccess parent check, which does not need to be done for
+ // functions.
+ if (element is ClassElement || element is TypeAliasElement) {
+ // A type-instantiated constructor tearoff like `prefix.C<int>.name` is
+ // initially represented as a [PropertyAccess] with a
+ // [FunctionReference] 'target'.
+ if (node.parent is PropertyAccess) {
+ _resolveConstructorReference(node);
+ return;
+ } else if (element is ClassElement) {
+ node.function.accept(_resolver);
+ _resolveDirectTypeLiteral(node, prefix, element);
+ return;
+ } else if (element is TypeAliasElement) {
+ prefix.accept(_resolver);
+ (nameNode as SimpleIdentifierImpl).staticElement = element;
+ _resolveTypeAlias(node: node, element: element, typeAlias: prefix);
+ return;
+ }
+ } else if (element is ExecutableElement) {
+ node.function.accept(_resolver);
+ _resolve(
+ node: node,
+ name: element.name,
+ rawType: node.function.typeOrThrow as FunctionType,
+ );
+ return;
}
- // TODO(srawlins): Handle prefixed constructor references and type literals.
-
// TODO(srawlins): Report undefined prefixed identifier.
node.function.accept(_resolver);
node.staticType = DynamicTypeImpl.instance;
}
+
+ void _resolveTypeAlias({
+ required FunctionReferenceImpl node,
+ required TypeAliasElement element,
+ required Identifier typeAlias,
+ }) {
+ var typeArguments = _checkTypeArguments(
+ // `node.typeArguments`, coming from the parser, is never null.
+ node.typeArguments!, element.name, element.typeParameters,
+ CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
+ );
+ var type = element.instantiate(
+ typeArguments: typeArguments,
+ nullabilitySuffix: _nullabilitySuffixForTypeNames);
+ _resolveTypeLiteral(node: node, instantiatedType: type, name: typeAlias);
+ }
+
+ void _resolveTypeLiteral({
+ required FunctionReferenceImpl node,
+ required DartType instantiatedType,
+ required Identifier name,
+ }) {
+ var typeName = astFactory.typeName(name, node.typeArguments);
+ typeName.type = instantiatedType;
+ typeName.name.staticType = instantiatedType;
+ var typeLiteral = astFactory.typeLiteral(typeName: typeName);
+ typeLiteral.staticType = _typeType;
+ NodeReplacer.replace(node, typeLiteral);
+ }
}
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index d383272..a5fdaf2 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -14735,6 +14735,22 @@
/**
* Parameters:
+ * 0: the name of the function being referenced
+ * 1: the number of type parameters that were declared
+ * 2: the number of type arguments provided
+ */
+ static const CompileTimeErrorCode WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION =
+ CompileTimeErrorCode(
+ 'WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION',
+ "The function '{0}' is declared with {1} type parameters, "
+ "but {2} type arguments were given.",
+ correction:
+ "Try adjusting the number of type arguments to match the number "
+ "of type parameters.",
+ hasPublishedDocs: true);
+
+ /**
+ * Parameters:
* 0: the name of the method being referenced (<i>G</i>)
* 1: the number of type parameters that were declared
* 2: the number of type arguments provided
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index a089bf5..112f2e7 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -371,7 +371,8 @@
migratableAstInfoProvider: _migratableAstInfoProvider);
inferenceContext = InferenceContext._(this);
typeAnalyzer = StaticTypeAnalyzer(this, migrationResolutionHooks);
- _functionReferenceResolver = FunctionReferenceResolver(this);
+ _functionReferenceResolver =
+ FunctionReferenceResolver(this, _isNonNullableByDefault);
}
/// Return the element representing the function containing the current node,
diff --git a/pkg/analyzer/lib/src/test_utilities/find_node.dart b/pkg/analyzer/lib/src/test_utilities/find_node.dart
index 260f431..1a71750 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_node.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_node.dart
@@ -362,6 +362,10 @@
return _node(search, (n) => n is TypedLiteral);
}
+ TypeLiteral typeLiteral(String search) {
+ return _node(search, (n) => n is TypeLiteral);
+ }
+
TypeName typeName(String search) {
return _node(search, (n) => n is TypeName);
}
diff --git a/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart b/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
index 7e56db3..b8af67e 100644
--- a/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
+++ b/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
@@ -1039,8 +1039,7 @@
}
@reflectiveTest
-class InheritanceManager3WithNullSafetyTest extends _InheritanceManager3Base
- with WithNullSafetyMixin {
+class InheritanceManager3WithNullSafetyTest extends _InheritanceManager3Base {
test_getInheritedMap_topMerge_method() async {
newFile('$testPackageLibPath/a.dart', content: r'''
// @dart = 2.6
diff --git a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
index b545267..27ec665 100644
--- a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
@@ -424,6 +424,11 @@
bool get typeToStringWithNullability => true;
}
+mixin WithoutConstructorTearoffsMixin on PubPackageResolutionTest {
+ @override
+ String? get testPackageLanguageVersion => '2.13';
+}
+
mixin WithoutNullSafetyMixin on PubPackageResolutionTest {
@override
String? get testPackageLanguageVersion => '2.9';
diff --git a/pkg/analyzer/test/src/dart/resolution/extension_method_test.dart b/pkg/analyzer/test/src/dart/resolution/extension_method_test.dart
index 1f7f618..902e2e7 100644
--- a/pkg/analyzer/test/src/dart/resolution/extension_method_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/extension_method_test.dart
@@ -14,21 +14,61 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ExtensionMethodsDeclarationTest);
- defineReflectiveTests(ExtensionMethodsDeclarationWithNullSafetyTest);
+ defineReflectiveTests(ExtensionMethodsDeclarationWithoutNullSafetyTest);
defineReflectiveTests(ExtensionMethodsExtendedTypeTest);
- defineReflectiveTests(ExtensionMethodsExtendedTypeWithNullSafetyTest);
+ defineReflectiveTests(ExtensionMethodsExtendedTypeWithoutNullSafetyTest);
defineReflectiveTests(ExtensionMethodsExternalReferenceTest);
- defineReflectiveTests(ExtensionMethodsExternalReferenceWithNullSafetyTest);
+ defineReflectiveTests(
+ ExtensionMethodsExternalReferenceWithoutNullSafetyTest);
defineReflectiveTests(ExtensionMethodsInternalReferenceTest);
- defineReflectiveTests(ExtensionMethodsInternalReferenceWithNullSafetyTest);
+ defineReflectiveTests(
+ ExtensionMethodsInternalReferenceWithoutNullSafetyTest);
});
}
/// Tests that show that extension declarations and the members inside them are
/// resolved correctly.
@reflectiveTest
-class ExtensionMethodsDeclarationTest extends PubPackageResolutionTest
- with WithoutNullSafetyMixin {
+class ExtensionMethodsDeclarationTest extends PubPackageResolutionTest {
+ test_this_type_interface() async {
+ await assertNoErrorsInCode('''
+extension E on int {
+ void foo() {
+ this;
+ }
+}
+''');
+ assertType(findNode.this_('this;'), 'int');
+ }
+
+ test_this_type_typeParameter() async {
+ await assertNoErrorsInCode('''
+extension E<T> on T {
+ void foo() {
+ this;
+ }
+}
+''');
+ assertType(findNode.this_('this;'), 'T');
+ }
+
+ test_this_type_typeParameter_withBound() async {
+ await assertNoErrorsInCode('''
+extension E<T extends Object> on T {
+ void foo() {
+ this;
+ }
+}
+''');
+ assertType(findNode.this_('this;'), 'T');
+ }
+}
+
+/// Tests that show that extension declarations and the members inside them are
+/// resolved correctly.
+@reflectiveTest
+class ExtensionMethodsDeclarationWithoutNullSafetyTest
+ extends PubPackageResolutionTest with WithoutNullSafetyMixin {
@override
List<MockSdkLibrary> get additionalMockSdkLibraries => [
MockSdkLibrary([
@@ -314,50 +354,11 @@
}
}
-/// Tests that show that extension declarations and the members inside them are
-/// resolved correctly.
-@reflectiveTest
-class ExtensionMethodsDeclarationWithNullSafetyTest
- extends PubPackageResolutionTest {
- test_this_type_interface() async {
- await assertNoErrorsInCode('''
-extension E on int {
- void foo() {
- this;
- }
-}
-''');
- assertType(findNode.this_('this;'), 'int');
- }
-
- test_this_type_typeParameter() async {
- await assertNoErrorsInCode('''
-extension E<T> on T {
- void foo() {
- this;
- }
-}
-''');
- assertType(findNode.this_('this;'), 'T');
- }
-
- test_this_type_typeParameter_withBound() async {
- await assertNoErrorsInCode('''
-extension E<T extends Object> on T {
- void foo() {
- this;
- }
-}
-''');
- assertType(findNode.this_('this;'), 'T');
- }
-}
-
-/// Tests that show that extension declarations support all of the possible
-/// types in the `on` clause.
@reflectiveTest
class ExtensionMethodsExtendedTypeTest extends PubPackageResolutionTest
- with WithoutNullSafetyMixin {
+ with ExtensionMethodsExtendedTypeTestCases {}
+
+mixin ExtensionMethodsExtendedTypeTestCases on PubPackageResolutionTest {
test_named_generic() async {
await assertNoErrorsInCode('''
class C<T> {}
@@ -477,15 +478,287 @@
}
}
+/// Tests that show that extension declarations support all of the possible
+/// types in the `on` clause.
@reflectiveTest
-class ExtensionMethodsExtendedTypeWithNullSafetyTest
- extends ExtensionMethodsExtendedTypeTest with WithNullSafetyMixin {}
+class ExtensionMethodsExtendedTypeWithoutNullSafetyTest
+ extends PubPackageResolutionTest
+ with ExtensionMethodsExtendedTypeTestCases, WithoutNullSafetyMixin {}
-/// Tests that extension members can be correctly resolved when referenced
-/// by code external to the extension declaration.
@reflectiveTest
class ExtensionMethodsExternalReferenceTest extends PubPackageResolutionTest
- with WithoutNullSafetyMixin {
+ with ExtensionMethodsExternalReferenceTestCases {
+ test_instance_getter_fromInstance_Never() async {
+ await assertNoErrorsInCode('''
+extension E on Never {
+ int get foo => 0;
+}
+
+f(Never a) {
+ a.foo;
+}
+''');
+ var access = findNode.prefixed('a.foo');
+ assertElementNull(access);
+ assertType(access, 'Never');
+ }
+
+ test_instance_getter_fromInstance_nullable() async {
+ await assertNoErrorsInCode('''
+extension E on int? {
+ int get foo => 0;
+}
+
+f(int? a) {
+ a.foo;
+}
+''');
+ var access = findNode.prefixed('a.foo');
+ assertElement(access, findElement.getter('foo', of: 'E'));
+ assertType(access, 'int');
+ }
+
+ test_instance_getter_fromInstance_nullAware() async {
+ await assertNoErrorsInCode('''
+extension E on int {
+ int get foo => 0;
+}
+
+f(int? a) {
+ a?.foo;
+}
+''');
+ var identifier = findNode.simple('foo;');
+ assertElement(identifier, findElement.getter('foo', of: 'E'));
+ assertType(identifier, 'int');
+ }
+
+ test_instance_method_fromInstance_Never() async {
+ await assertErrorsInCode('''
+extension E on Never {
+ void foo() {}
+}
+
+f(Never a) {
+ a.foo();
+}
+''', [
+ error(HintCode.RECEIVER_OF_TYPE_NEVER, 57, 1),
+ error(HintCode.DEAD_CODE, 62, 3),
+ ]);
+ assertMethodInvocation2(
+ findNode.methodInvocation('a.foo()'),
+ element: null,
+ typeArgumentTypes: [],
+ invokeType: 'dynamic',
+ type: 'Never',
+ );
+ }
+
+ test_instance_method_fromInstance_nullable() async {
+ await assertNoErrorsInCode('''
+extension E on int? {
+ void foo() {}
+}
+
+f(int? a) {
+ a.foo();
+}
+''');
+ var invocation = findNode.methodInvocation('a.foo()');
+ assertElement(invocation, findElement.method('foo', of: 'E'));
+ assertInvokeType(invocation, 'void Function()');
+ }
+
+ test_instance_method_fromInstance_nullable_nullLiteral() async {
+ await assertNoErrorsInCode('''
+extension E on int? {
+ void foo() {}
+}
+
+f(int? a) {
+ null.foo();
+}
+''');
+ var invocation = findNode.methodInvocation('null.foo()');
+ assertElement(invocation, findElement.method('foo', of: 'E'));
+ assertInvokeType(invocation, 'void Function()');
+ }
+
+ test_instance_method_fromInstance_nullAware() async {
+ await assertNoErrorsInCode('''
+extension E on int {
+ void foo() {}
+}
+
+f(int? a) {
+ a?.foo();
+}
+''');
+ var invocation = findNode.methodInvocation('a?.foo()');
+ assertElement(invocation, findElement.method('foo', of: 'E'));
+ assertInvokeType(invocation, 'void Function()');
+ }
+
+ test_instance_method_fromInstance_nullLiteral() async {
+ await assertNoErrorsInCode('''
+extension E<T> on T {
+ void foo() {}
+}
+
+f() {
+ null.foo();
+}
+''');
+ var invocation = findNode.methodInvocation('null.foo()');
+ assertMember(
+ invocation,
+ findElement.method('foo', of: 'E'),
+ {'T': 'Null'},
+ );
+ assertInvokeType(invocation, 'void Function()');
+ }
+
+ test_instance_operator_binary_fromInstance_nullable() async {
+ await assertNoErrorsInCode('''
+class A {}
+
+extension E on A? {
+ int operator +(int _) => 0;
+}
+
+f(A? a) {
+ a + 1;
+}
+''');
+ var binary = findNode.binary('a + 1');
+ assertElement(binary, findElement.method('+'));
+ assertType(binary, 'int');
+ }
+
+ test_instance_operator_index_fromInstance_nullable() async {
+ await assertNoErrorsInCode('''
+extension E on int? {
+ int operator [](int index) => 0;
+}
+
+f(int? a) {
+ a[0];
+}
+''');
+ var index = findNode.index('a[0]');
+ assertElement(index, findElement.method('[]'));
+ }
+
+ test_instance_operator_index_fromInstance_nullAware() async {
+ await assertNoErrorsInCode('''
+extension E on int {
+ int operator [](int index) => 0;
+}
+
+f(int? a) {
+ a?[0];
+}
+''');
+ var index = findNode.index('a?[0]');
+ assertElement(index, findElement.method('[]'));
+ }
+
+ test_instance_operator_postfixInc_fromInstance_nullable() async {
+ await assertNoErrorsInCode('''
+class A {}
+
+extension E on A? {
+ A? operator +(int _) => this;
+}
+
+f(A? a) {
+ a++;
+}
+''');
+ var expression = findNode.postfix('a++');
+ assertElement(expression, findElement.method('+'));
+ assertType(expression, 'A?');
+ }
+
+ test_instance_operator_prefixInc_fromInstance_nullable() async {
+ await assertNoErrorsInCode('''
+class A {}
+
+extension E on A? {
+ A? operator +(int _) => this;
+}
+
+f(A? a) {
+ ++a;
+}
+''');
+ var expression = findNode.prefix('++a');
+ assertElement(expression, findElement.method('+'));
+ assertType(expression, 'A?');
+ }
+
+ test_instance_operator_unaryMinus_fromInstance_nullable() async {
+ await assertNoErrorsInCode('''
+class A {}
+
+extension E on A? {
+ A? operator -() => this;
+}
+
+f(A? a) {
+ -a;
+}
+''');
+ var expression = findNode.prefix('-a');
+ assertElement(expression, findElement.method('unary-'));
+ assertType(expression, 'A?');
+ }
+
+ test_instance_setter_fromInstance_nullable() async {
+ await assertNoErrorsInCode('''
+extension E on int? {
+ set foo(int _) {}
+}
+
+f(int? a) {
+ a.foo = 1;
+}
+''');
+ assertAssignment(
+ findNode.assignment('foo = 1'),
+ readElement: null,
+ readType: null,
+ writeElement: findElement.setter('foo'),
+ writeType: 'int',
+ operatorElement: null,
+ type: 'int',
+ );
+ }
+
+ test_instance_setter_fromInstance_nullAware() async {
+ await assertNoErrorsInCode('''
+extension E on int {
+ set foo(int _) {}
+}
+
+f(int? a) {
+ a?.foo = 1;
+}
+''');
+ assertAssignment(
+ findNode.assignment('foo = 1'),
+ readElement: null,
+ readType: null,
+ writeElement: findElement.setter('foo'),
+ writeType: 'int',
+ operatorElement: null,
+ type: 'int?',
+ );
+ }
+}
+
+mixin ExtensionMethodsExternalReferenceTestCases on PubPackageResolutionTest {
/// Corresponds to: extension_member_resolution_t07
test_dynamicInvocation() async {
await assertNoErrorsInCode(r'''
@@ -1474,284 +1747,18 @@
}
}
-@reflectiveTest
-class ExtensionMethodsExternalReferenceWithNullSafetyTest
- extends ExtensionMethodsExternalReferenceTest with WithNullSafetyMixin {
- test_instance_getter_fromInstance_Never() async {
- await assertNoErrorsInCode('''
-extension E on Never {
- int get foo => 0;
-}
-
-f(Never a) {
- a.foo;
-}
-''');
- var access = findNode.prefixed('a.foo');
- assertElementNull(access);
- assertType(access, 'Never');
- }
-
- test_instance_getter_fromInstance_nullable() async {
- await assertNoErrorsInCode('''
-extension E on int? {
- int get foo => 0;
-}
-
-f(int? a) {
- a.foo;
-}
-''');
- var access = findNode.prefixed('a.foo');
- assertElement(access, findElement.getter('foo', of: 'E'));
- assertType(access, 'int');
- }
-
- test_instance_getter_fromInstance_nullAware() async {
- await assertNoErrorsInCode('''
-extension E on int {
- int get foo => 0;
-}
-
-f(int? a) {
- a?.foo;
-}
-''');
- var identifier = findNode.simple('foo;');
- assertElement(identifier, findElement.getter('foo', of: 'E'));
- assertType(identifier, 'int');
- }
-
- test_instance_method_fromInstance_Never() async {
- await assertErrorsInCode('''
-extension E on Never {
- void foo() {}
-}
-
-f(Never a) {
- a.foo();
-}
-''', [
- error(HintCode.RECEIVER_OF_TYPE_NEVER, 57, 1),
- error(HintCode.DEAD_CODE, 62, 3),
- ]);
- assertMethodInvocation2(
- findNode.methodInvocation('a.foo()'),
- element: null,
- typeArgumentTypes: [],
- invokeType: 'dynamic',
- type: 'Never',
- );
- }
-
- test_instance_method_fromInstance_nullable() async {
- await assertNoErrorsInCode('''
-extension E on int? {
- void foo() {}
-}
-
-f(int? a) {
- a.foo();
-}
-''');
- var invocation = findNode.methodInvocation('a.foo()');
- assertElement(invocation, findElement.method('foo', of: 'E'));
- assertInvokeType(invocation, 'void Function()');
- }
-
- test_instance_method_fromInstance_nullable_nullLiteral() async {
- await assertNoErrorsInCode('''
-extension E on int? {
- void foo() {}
-}
-
-f(int? a) {
- null.foo();
-}
-''');
- var invocation = findNode.methodInvocation('null.foo()');
- assertElement(invocation, findElement.method('foo', of: 'E'));
- assertInvokeType(invocation, 'void Function()');
- }
-
- test_instance_method_fromInstance_nullAware() async {
- await assertNoErrorsInCode('''
-extension E on int {
- void foo() {}
-}
-
-f(int? a) {
- a?.foo();
-}
-''');
- var invocation = findNode.methodInvocation('a?.foo()');
- assertElement(invocation, findElement.method('foo', of: 'E'));
- assertInvokeType(invocation, 'void Function()');
- }
-
- test_instance_method_fromInstance_nullLiteral() async {
- await assertNoErrorsInCode('''
-extension E<T> on T {
- void foo() {}
-}
-
-f() {
- null.foo();
-}
-''');
- var invocation = findNode.methodInvocation('null.foo()');
- assertMember(
- invocation,
- findElement.method('foo', of: 'E'),
- {'T': 'Null'},
- );
- assertInvokeType(invocation, 'void Function()');
- }
-
- test_instance_operator_binary_fromInstance_nullable() async {
- await assertNoErrorsInCode('''
-class A {}
-
-extension E on A? {
- int operator +(int _) => 0;
-}
-
-f(A? a) {
- a + 1;
-}
-''');
- var binary = findNode.binary('a + 1');
- assertElement(binary, findElement.method('+'));
- assertType(binary, 'int');
- }
-
- test_instance_operator_index_fromInstance_nullable() async {
- await assertNoErrorsInCode('''
-extension E on int? {
- int operator [](int index) => 0;
-}
-
-f(int? a) {
- a[0];
-}
-''');
- var index = findNode.index('a[0]');
- assertElement(index, findElement.method('[]'));
- }
-
- test_instance_operator_index_fromInstance_nullAware() async {
- await assertNoErrorsInCode('''
-extension E on int {
- int operator [](int index) => 0;
-}
-
-f(int? a) {
- a?[0];
-}
-''');
- var index = findNode.index('a?[0]');
- assertElement(index, findElement.method('[]'));
- }
-
- test_instance_operator_postfixInc_fromInstance_nullable() async {
- await assertNoErrorsInCode('''
-class A {}
-
-extension E on A? {
- A? operator +(int _) => this;
-}
-
-f(A? a) {
- a++;
-}
-''');
- var expression = findNode.postfix('a++');
- assertElement(expression, findElement.method('+'));
- assertType(expression, 'A?');
- }
-
- test_instance_operator_prefixInc_fromInstance_nullable() async {
- await assertNoErrorsInCode('''
-class A {}
-
-extension E on A? {
- A? operator +(int _) => this;
-}
-
-f(A? a) {
- ++a;
-}
-''');
- var expression = findNode.prefix('++a');
- assertElement(expression, findElement.method('+'));
- assertType(expression, 'A?');
- }
-
- test_instance_operator_unaryMinus_fromInstance_nullable() async {
- await assertNoErrorsInCode('''
-class A {}
-
-extension E on A? {
- A? operator -() => this;
-}
-
-f(A? a) {
- -a;
-}
-''');
- var expression = findNode.prefix('-a');
- assertElement(expression, findElement.method('unary-'));
- assertType(expression, 'A?');
- }
-
- test_instance_setter_fromInstance_nullable() async {
- await assertNoErrorsInCode('''
-extension E on int? {
- set foo(int _) {}
-}
-
-f(int? a) {
- a.foo = 1;
-}
-''');
- assertAssignment(
- findNode.assignment('foo = 1'),
- readElement: null,
- readType: null,
- writeElement: findElement.setter('foo'),
- writeType: 'int',
- operatorElement: null,
- type: 'int',
- );
- }
-
- test_instance_setter_fromInstance_nullAware() async {
- await assertNoErrorsInCode('''
-extension E on int {
- set foo(int _) {}
-}
-
-f(int? a) {
- a?.foo = 1;
-}
-''');
- assertAssignment(
- findNode.assignment('foo = 1'),
- readElement: null,
- readType: null,
- writeElement: findElement.setter('foo'),
- writeType: 'int',
- operatorElement: null,
- type: 'int?',
- );
- }
-}
-
/// Tests that extension members can be correctly resolved when referenced
-/// by code internal to (within) the extension declaration.
+/// by code external to the extension declaration.
+@reflectiveTest
+class ExtensionMethodsExternalReferenceWithoutNullSafetyTest
+ extends PubPackageResolutionTest
+ with ExtensionMethodsExternalReferenceTestCases, WithoutNullSafetyMixin {}
+
@reflectiveTest
class ExtensionMethodsInternalReferenceTest extends PubPackageResolutionTest
- with WithoutNullSafetyMixin {
+ with ExtensionMethodsInternalReferenceTestCases {}
+
+mixin ExtensionMethodsInternalReferenceTestCases on PubPackageResolutionTest {
test_instance_call() async {
await assertNoErrorsInCode('''
class C {}
@@ -2350,6 +2357,9 @@
}
}
+/// Tests that extension members can be correctly resolved when referenced
+/// by code internal to (within) the extension declaration.
@reflectiveTest
-class ExtensionMethodsInternalReferenceWithNullSafetyTest
- extends ExtensionMethodsInternalReferenceTest with WithNullSafetyMixin {}
+class ExtensionMethodsInternalReferenceWithoutNullSafetyTest
+ extends PubPackageResolutionTest
+ with ExtensionMethodsInternalReferenceTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/extension_override_test.dart b/pkg/analyzer/test/src/dart/resolution/extension_override_test.dart
index eea3223..946f223 100644
--- a/pkg/analyzer/test/src/dart/resolution/extension_override_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/extension_override_test.dart
@@ -14,13 +14,106 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ExtensionOverrideTest);
- defineReflectiveTests(ExtensionOverrideWithNullSafetyTest);
+ defineReflectiveTests(ExtensionOverrideWithoutNullSafetyTest);
});
}
@reflectiveTest
class ExtensionOverrideTest extends PubPackageResolutionTest
- with WithoutNullSafetyMixin {
+ with ExtensionOverrideTestCases {
+ test_indexExpression_read_nullAware() async {
+ await assertNoErrorsInCode('''
+extension E on int {
+ int operator [](int index) => 0;
+}
+
+void f(int? a) {
+ E(a)?[0];
+}
+''');
+
+ assertIndexExpression(
+ findNode.index('[0]'),
+ readElement: findElement.method('[]', of: 'E'),
+ writeElement: null,
+ type: 'int?',
+ );
+ }
+
+ test_indexExpression_write_nullAware() async {
+ await assertNoErrorsInCode('''
+extension E on int {
+ operator []=(int index, int value) {}
+}
+
+void f(int? a) {
+ E(a)?[0] = 1;
+}
+''');
+
+ assertAssignment(
+ findNode.assignment('[0] ='),
+ readElement: null,
+ readType: null,
+ writeElement: findElement.method('[]=', of: 'E'),
+ writeType: 'int',
+ operatorElement: null,
+ type: 'int?',
+ );
+ }
+
+ test_methodInvocation_nullAware() async {
+ await assertNoErrorsInCode('''
+extension E on int {
+ int foo() => 0;
+}
+
+void f(int? a) {
+ E(a)?.foo();
+}
+''');
+
+ assertMethodInvocation2(
+ findNode.methodInvocation('foo();'),
+ element: findElement.method('foo'),
+ typeArgumentTypes: [],
+ invokeType: 'int Function()',
+ type: 'int?',
+ );
+ }
+
+ test_propertyAccess_getter_nullAware() async {
+ await assertNoErrorsInCode('''
+extension E on int {
+ int get foo => 0;
+}
+
+void f(int? a) {
+ E(a)?.foo;
+}
+''');
+
+ assertPropertyAccess2(
+ findNode.propertyAccess('?.foo'),
+ element: findElement.getter('foo'),
+ type: 'int?',
+ );
+ }
+
+ test_propertyAccess_setter_nullAware() async {
+ await assertNoErrorsInCode('''
+extension E on int {
+ set foo(int _) {}
+}
+
+void f(int? a) {
+ E(a)?.foo = 0;
+}
+''');
+ }
+}
+
+mixin ExtensionOverrideTestCases on PubPackageResolutionTest {
late ExtensionElement extension;
late ExtensionOverride extensionOverride;
@@ -720,96 +813,5 @@
}
@reflectiveTest
-class ExtensionOverrideWithNullSafetyTest extends ExtensionOverrideTest
- with WithNullSafetyMixin {
- test_indexExpression_read_nullAware() async {
- await assertNoErrorsInCode('''
-extension E on int {
- int operator [](int index) => 0;
-}
-
-void f(int? a) {
- E(a)?[0];
-}
-''');
-
- assertIndexExpression(
- findNode.index('[0]'),
- readElement: findElement.method('[]', of: 'E'),
- writeElement: null,
- type: 'int?',
- );
- }
-
- test_indexExpression_write_nullAware() async {
- await assertNoErrorsInCode('''
-extension E on int {
- operator []=(int index, int value) {}
-}
-
-void f(int? a) {
- E(a)?[0] = 1;
-}
-''');
-
- assertAssignment(
- findNode.assignment('[0] ='),
- readElement: null,
- readType: null,
- writeElement: findElement.method('[]=', of: 'E'),
- writeType: 'int',
- operatorElement: null,
- type: 'int?',
- );
- }
-
- test_methodInvocation_nullAware() async {
- await assertNoErrorsInCode('''
-extension E on int {
- int foo() => 0;
-}
-
-void f(int? a) {
- E(a)?.foo();
-}
-''');
-
- assertMethodInvocation2(
- findNode.methodInvocation('foo();'),
- element: findElement.method('foo'),
- typeArgumentTypes: [],
- invokeType: 'int Function()',
- type: 'int?',
- );
- }
-
- test_propertyAccess_getter_nullAware() async {
- await assertNoErrorsInCode('''
-extension E on int {
- int get foo => 0;
-}
-
-void f(int? a) {
- E(a)?.foo;
-}
-''');
-
- assertPropertyAccess2(
- findNode.propertyAccess('?.foo'),
- element: findElement.getter('foo'),
- type: 'int?',
- );
- }
-
- test_propertyAccess_setter_nullAware() async {
- await assertNoErrorsInCode('''
-extension E on int {
- set foo(int _) {}
-}
-
-void f(int? a) {
- E(a)?.foo = 0;
-}
-''');
- }
-}
+class ExtensionOverrideWithoutNullSafetyTest extends PubPackageResolutionTest
+ with ExtensionOverrideTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
index 4dba4a4..19e9a10 100644
--- a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
@@ -15,6 +15,36 @@
@reflectiveTest
class FunctionReferenceResolutionTest extends PubPackageResolutionTest {
+ test_explicitReceiver_unknown() async {
+ await assertErrorsInCode('''
+bar() {
+ a.foo<int>;
+}
+''', [
+ error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 10, 1),
+ ]);
+
+ var reference = findNode.functionReference('foo<int>;');
+ assertType(reference, 'dynamic');
+ }
+
+ test_instanceGetter_explicitReceiver() async {
+ // This test is here to assert that the resolver does not throw, but in the
+ // future, an error should be reported here as well.
+ await assertNoErrorsInCode('''
+class A {
+ int foo = 0;
+}
+
+bar(A a) {
+ a.foo<int>;
+}
+''');
+
+ var reference = findNode.functionReference('foo<int>;');
+ assertType(reference, 'dynamic');
+ }
+
test_instanceMethod() async {
await assertNoErrorsInCode('''
class A {
@@ -26,9 +56,9 @@
}
''');
- var identifier = findNode.functionReference('foo<int>;');
- assertElement(identifier, findElement.method('foo'));
- assertType(identifier, 'void Function(int)');
+ var reference = findNode.functionReference('foo<int>;');
+ assertFunctionReference(
+ reference, findElement.method('foo'), 'void Function(int)');
}
test_instanceMethod_explicitReceiver_field() async {
@@ -46,9 +76,9 @@
}
''');
- var identifier = findNode.functionReference('foo<int>;');
- assertElement(identifier, findElement.method('foo'));
- assertType(identifier, 'void Function(int)');
+ var reference = findNode.functionReference('foo<int>;');
+ assertFunctionReference(
+ reference, findElement.method('foo'), 'void Function(int)');
}
test_instanceMethod_explicitReceiver_super() async {
@@ -63,9 +93,37 @@
}
''');
- var identifier = findNode.functionReference('foo<int>;');
- assertElement(identifier, findElement.method('foo'));
- assertType(identifier, 'void Function(int)');
+ var reference = findNode.functionReference('foo<int>;');
+ assertFunctionReference(
+ reference, findElement.method('foo'), 'void Function(int)');
+ }
+
+ test_instanceMethod_explicitReceiver_super_noMethod() async {
+ await assertErrorsInCode('''
+class A {
+ bar() {
+ super.foo<int>;
+ }
+}
+''', [
+ error(CompileTimeErrorCode.UNDEFINED_SUPER_GETTER, 30, 3),
+ ]);
+
+ var reference = findNode.functionReference('foo<int>;');
+ assertType(reference, 'dynamic');
+ }
+
+ test_instanceMethod_explicitReceiver_super_noSuper() async {
+ await assertErrorsInCode('''
+bar() {
+ super.foo<int>;
+}
+''', [
+ error(CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT, 10, 5),
+ ]);
+
+ var reference = findNode.functionReference('foo<int>;');
+ assertType(reference, 'dynamic');
}
test_instanceMethod_explicitReceiver_this() async {
@@ -79,9 +137,9 @@
}
''');
- var identifier = findNode.functionReference('foo<int>;');
- assertElement(identifier, findElement.method('foo'));
- assertType(identifier, 'void Function(int)');
+ var reference = findNode.functionReference('foo<int>;');
+ assertFunctionReference(
+ reference, findElement.method('foo'), 'void Function(int)');
}
test_instanceMethod_explicitReceiver_variable() async {
@@ -97,9 +155,9 @@
}
''');
- var identifier = findNode.functionReference('foo<int>;');
- assertElement(identifier, findElement.method('foo'));
- assertType(identifier, 'void Function(int)');
+ var reference = findNode.functionReference('foo<int>;');
+ assertFunctionReference(
+ reference, findElement.method('foo'), 'void Function(int)');
}
test_localFunction() async {
@@ -111,9 +169,9 @@
}
''');
- var identifier = findNode.functionReference('foo<int>;');
- assertElement(identifier, findElement.localFunction('foo'));
- assertType(identifier, 'void Function(int)');
+ var reference = findNode.functionReference('foo<int>;');
+ assertFunctionReference(
+ reference, findElement.localFunction('foo'), 'void Function(int)');
}
test_localVariable() async {
@@ -123,9 +181,9 @@
}
''');
- var identifier = findNode.functionReference('foo<int>;');
- assertElement(identifier, findElement.parameter('foo'));
- assertType(identifier, 'void Function(int)');
+ var reference = findNode.functionReference('foo<int>;');
+ assertFunctionReference(
+ reference, findElement.parameter('foo'), 'void Function(int)');
}
test_nonGenericFunction() async {
@@ -138,12 +196,13 @@
}
}
''', [
- error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 44, 5),
+ error(
+ CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 44, 5),
]);
- var identifier = findNode.functionReference('foo<int>;');
- assertElement(identifier, findElement.method('foo'));
- assertType(identifier, 'void Function()');
+ var reference = findNode.functionReference('foo<int>;');
+ assertFunctionReference(
+ reference, findElement.method('foo'), 'void Function()');
}
test_staticMethod() async {
@@ -157,9 +216,9 @@
}
''');
- var identifier = findNode.functionReference('foo<int>;');
- assertElement(identifier, findElement.method('foo'));
- assertType(identifier, 'void Function(int)');
+ var reference = findNode.functionReference('foo<int>;');
+ assertFunctionReference(
+ reference, findElement.method('foo'), 'void Function(int)');
}
@FailingTest(reason: 'Unresolved TODO in FunctionReferenceResolver')
@@ -174,9 +233,9 @@
}
''');
- var identifier = findNode.functionReference('foo<int>;');
- assertElement(identifier, findElement.method('foo'));
- assertType(identifier, 'void Function(int)');
+ var reference = findNode.functionReference('foo<int>;');
+ assertElement(reference, findElement.method('foo'));
+ assertType(reference, 'void Function(int)');
}
@FailingTest(reason: 'Unresolved TODO in FunctionReferenceResolver')
@@ -194,9 +253,9 @@
}
''');
- var identifier = findNode.functionReference('foo<int>;');
- assertElement(identifier, findElement.method('foo'));
- assertType(identifier, 'void Function(int)');
+ var reference = findNode.functionReference('foo<int>;');
+ assertElement(reference, findElement.method('foo'));
+ assertType(reference, 'void Function(int)');
}
test_tooFewTypeArguments() async {
@@ -209,12 +268,13 @@
}
}
''', [
- error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 58, 5),
+ error(
+ CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 58, 5),
]);
- var identifier = findNode.functionReference('foo<int>;');
- assertElement(identifier, findElement.method('foo'));
- assertType(identifier, 'void Function(dynamic, dynamic)');
+ var reference = findNode.functionReference('foo<int>;');
+ assertFunctionReference(reference, findElement.method('foo'),
+ 'void Function(dynamic, dynamic)');
}
test_tooManyTypeArguments() async {
@@ -227,12 +287,13 @@
}
}
''', [
- error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 50, 10),
+ error(
+ CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 50, 10),
]);
- var identifier = findNode.functionReference('foo<int, int>;');
- assertElement(identifier, findElement.method('foo'));
- assertType(identifier, 'void Function(dynamic)');
+ var reference = findNode.functionReference('foo<int, int>;');
+ assertFunctionReference(
+ reference, findElement.method('foo'), 'void Function(dynamic)');
}
test_topLevelFunction() async {
@@ -244,9 +305,9 @@
}
''');
- var identifier = findNode.functionReference('foo<int>;');
- assertElement(identifier, findElement.topFunction('foo'));
- assertType(identifier, 'void Function(int)');
+ var reference = findNode.functionReference('foo<int>;');
+ assertFunctionReference(
+ reference, findElement.topFunction('foo'), 'void Function(int)');
}
test_topLevelFunction_importPrefix() async {
@@ -261,10 +322,12 @@
}
''');
- var identifier = findNode.functionReference('foo<int>;');
- assertElement(identifier,
- findElement.importFind('package:test/a.dart').topFunction('foo'));
- assertType(identifier, 'void Function(int)');
+ var reference = findNode.functionReference('foo<int>;');
+ assertFunctionReference(
+ reference,
+ findElement.importFind('package:test/a.dart').topFunction('foo'),
+ 'void Function(int)',
+ );
}
test_unknownIdentifier() async {
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index 2d2415b..65d329f 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -340,6 +340,12 @@
assertType(node, type);
}
+ void assertFunctionReference(
+ FunctionReference node, Element expectedElement, String expectedType) {
+ assertElement(node, expectedElement);
+ assertType(node, expectedType);
+ }
+
void assertHasTestErrors() {
expect(result.errors, isNotEmpty);
}
@@ -798,6 +804,14 @@
expect(actual, NullabilitySuffix.star);
}
+ void assertTypeLiteral(
+ TypeLiteral node, Element? expectedElement, String expectedType,
+ {Element? expectedPrefix}) {
+ assertType(node, 'Type');
+ assertTypeName(node.typeName, expectedElement, expectedType,
+ expectedPrefix: expectedPrefix);
+ }
+
void assertTypeName(
TypeName node, Element? expectedElement, String expectedType,
{Element? expectedPrefix}) {
diff --git a/pkg/analyzer/test/src/dart/resolution/test_all.dart b/pkg/analyzer/test/src/dart/resolution/test_all.dart
index 5b1355f..5f1c71d 100644
--- a/pkg/analyzer/test/src/dart/resolution/test_all.dart
+++ b/pkg/analyzer/test/src/dart/resolution/test_all.dart
@@ -60,6 +60,7 @@
import 'top_type_inference_test.dart' as top_type_inference;
import 'try_statement_test.dart' as try_statement;
import 'type_inference/test_all.dart' as type_inference;
+import 'type_literal_test.dart' as type_literal;
import 'type_name_test.dart' as type_name;
import 'yield_statement_test.dart' as yield_statement;
@@ -117,8 +118,9 @@
top_level_variable.main();
top_type_inference.main();
try_statement.main();
- type_name.main();
type_inference.main();
+ type_literal.main();
+ type_name.main();
yield_statement.main();
}, name: 'resolution');
}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_literal_test.dart
new file mode 100644
index 0000000..5391331
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/type_literal_test.dart
@@ -0,0 +1,193 @@
+// Copyright (c) 2021, 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/src/dart/error/syntactic_errors.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(TypeLiteralResolutionTest);
+ defineReflectiveTests(TypeLiteralResolutionWithoutConstructorTearoffsTest);
+ });
+}
+
+@reflectiveTest
+class TypeLiteralResolutionTest extends PubPackageResolutionTest {
+ test_class() async {
+ await assertNoErrorsInCode('''
+class C<T> {}
+var t = C<int>;
+''');
+
+ var typeLiteral = findNode.typeLiteral('C<int>;');
+ assertTypeLiteral(typeLiteral, findElement.class_('C'), 'C<int>');
+ }
+
+ test_class_importPrefix() async {
+ newFile('$testPackageLibPath/a.dart', content: '''
+class C<T> {}
+''');
+ await assertNoErrorsInCode('''
+import 'a.dart' as a;
+var t = a.C<int>;
+''');
+
+ var typeLiteral = findNode.typeLiteral('C<int>;');
+ assertTypeLiteral(
+ typeLiteral,
+ findElement.importFind('package:test/a.dart').class_('C'),
+ 'C<int>',
+ expectedPrefix: findElement.import('package:test/a.dart').prefix,
+ );
+ }
+
+ test_class_tooFewTypeArgs() async {
+ await assertErrorsInCode('''
+class C<T, U> {}
+var t = C<int>;
+''', [
+ error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 26, 5),
+ ]);
+
+ var typeLiteral = findNode.typeLiteral('C<int>;');
+ assertTypeLiteral(
+ typeLiteral, findElement.class_('C'), 'C<dynamic, dynamic>');
+ }
+
+ test_class_tooManyTypeArgs() async {
+ await assertErrorsInCode('''
+class C<T> {}
+var t = C<int, int>;
+''', [
+ error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 23, 10),
+ ]);
+
+ var typeLiteral = findNode.typeLiteral('C<int, int>;');
+ assertTypeLiteral(typeLiteral, findElement.class_('C'), 'C<dynamic>');
+ }
+
+ test_classAlias() async {
+ await assertNoErrorsInCode('''
+class C<T> {}
+typedef CA<T> = C<T>;
+var t = CA<int>;
+''');
+
+ var typeLiteral = findNode.typeLiteral('CA<int>;');
+ assertTypeLiteral(typeLiteral, findElement.typeAlias('CA'), 'C<int>');
+ }
+
+ test_classAlias_differentTypeArgCount() async {
+ await assertNoErrorsInCode('''
+class C<T, U> {}
+typedef CA<T> = C<T, int>;
+var t = CA<String>;
+''');
+
+ var typeLiteral = findNode.typeLiteral('CA<String>;');
+ assertTypeLiteral(
+ typeLiteral, findElement.typeAlias('CA'), 'C<String, int>');
+ }
+
+ test_classAlias_functionTypeArg() async {
+ await assertNoErrorsInCode('''
+class C<T> {}
+typedef CA<T> = C<T>;
+var t = CA<void Function()>;
+''');
+
+ var typeLiteral = findNode.typeLiteral('CA<void Function()>;');
+ assertTypeLiteral(
+ typeLiteral, findElement.typeAlias('CA'), 'C<void Function()>');
+ }
+
+ test_classAlias_importPrefix() async {
+ newFile('$testPackageLibPath/a.dart', content: '''
+class C<T> {}
+typedef CA<T> = C<T>;
+''');
+ await assertNoErrorsInCode('''
+import 'a.dart' as a;
+var t = a.CA<int>;
+''');
+
+ var typeLiteral = findNode.typeLiteral('CA<int>;');
+ assertTypeLiteral(
+ typeLiteral,
+ findElement.importFind('package:test/a.dart').typeAlias('CA'),
+ 'C<int>',
+ expectedPrefix: findElement.import('package:test/a.dart').prefix,
+ );
+ }
+
+ test_functionAlias() async {
+ await assertNoErrorsInCode('''
+typedef Fn<T> = void Function(T);
+var t = Fn<int>;
+''');
+
+ var typeLiteral = findNode.typeLiteral('Fn<int>;');
+ assertTypeLiteral(
+ typeLiteral, findElement.typeAlias('Fn'), 'void Function(int)');
+ }
+
+ test_mixin() async {
+ await assertNoErrorsInCode('''
+mixin M<T> {}
+var t = M<int>;
+''');
+
+ var typeLiteral = findNode.typeLiteral('M<int>;');
+ assertTypeLiteral(typeLiteral, findElement.mixin('M'), 'M<int>');
+ }
+
+ test_typeVariableTypeAlias() async {
+ await assertNoErrorsInCode('''
+typedef T<E> = E;
+var t = T<int>;
+''');
+
+ var typeLiteral = findNode.typeLiteral('T<int>;');
+ assertTypeLiteral(typeLiteral, findElement.typeAlias('T'), 'int');
+ }
+
+ test_typeVariableTypeAlias_functionTypeArgument() async {
+ await assertNoErrorsInCode('''
+typedef T<E> = E;
+var t = T<void Function()>;
+''');
+
+ var typeLiteral = findNode.typeLiteral('T<void Function()>;');
+ assertTypeLiteral(
+ typeLiteral, findElement.typeAlias('T'), 'void Function()');
+ }
+}
+
+@reflectiveTest
+class TypeLiteralResolutionWithoutConstructorTearoffsTest
+ extends PubPackageResolutionTest with WithoutConstructorTearoffsMixin {
+ test_class() async {
+ await assertErrorsInCode('''
+class C<T> {}
+var t = C<int>;
+''', [
+ error(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 23, 5),
+ ]);
+ }
+
+ test_class_importPrefix() async {
+ newFile('$testPackageLibPath/a.dart', content: '''
+class C<T> {}
+''');
+ await assertErrorsInCode('''
+import 'a.dart' as a;
+var t = a.C<int>;
+''', [
+ error(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 33, 5),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_test.dart b/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_test.dart
index b610200..ae55d6f 100644
--- a/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_test.dart
@@ -99,7 +99,8 @@
foo<int>;
}
''', [
- error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 36, 5),
+ error(
+ CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 36, 5),
]);
}
@@ -109,7 +110,8 @@
foo<int, int>;
}
''', [
- error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 33, 10),
+ error(
+ CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 33, 10),
]);
}
diff --git a/tests/standalone/io/large_file_read_small_file_test.dart b/tests/standalone/io/large_file_read_small_file_test.dart
index 2f4c276..9a7e97d 100644
--- a/tests/standalone/io/large_file_read_small_file_test.dart
+++ b/tests/standalone/io/large_file_read_small_file_test.dart
@@ -30,6 +30,9 @@
try {
final buffers = [];
for (int i = 0; i < 100 * 1000; ++i) {
+ if (i % 1000 == 0) {
+ print(i);
+ }
// We issue a 1 MB read but get only a small typed data back. We hang on
// to those buffers. If the implementation actually malloc()ed 1 MB then
// we would hang on to 100 GB and this test would OOM.
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index fc091da..f2d93f5 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -73,6 +73,9 @@
io/https_connection_closed_during_handshake_test: SkipByDesign # long_ssl_cert_evaluation needed for long handshake is only supported on mac.
io/https_nonblocking_trust_evaluation_test: SkipByDesign
+[ $system == windows ]
+io/large_file_read_small_file_test: Slow # Test reads small file 1M times
+
[ $builder_tag == swarming && $system == macos ]
io/*: Skip # Issue 30618
diff --git a/tests/standalone_2/io/large_file_read_small_file_test.dart b/tests/standalone_2/io/large_file_read_small_file_test.dart
index 0f62b12..755bc78 100644
--- a/tests/standalone_2/io/large_file_read_small_file_test.dart
+++ b/tests/standalone_2/io/large_file_read_small_file_test.dart
@@ -32,6 +32,9 @@
try {
final buffers = [];
for (int i = 0; i < 100 * 1000; ++i) {
+ if (i % 1000 == 0) {
+ print(i);
+ }
// We issue a 1 MB read but get only a small typed data back. We hang on
// to those buffers. If the implementation actually malloc()ed 1 MB then
// we would hang on to 100 GB and this test would OOM.
diff --git a/tests/standalone_2/standalone_2.status b/tests/standalone_2/standalone_2.status
index d875452..becc448 100644
--- a/tests/standalone_2/standalone_2.status
+++ b/tests/standalone_2/standalone_2.status
@@ -83,6 +83,9 @@
io/https_connection_closed_during_handshake_test: SkipByDesign # long_ssl_cert_evaluation needed for long handshake is only supported on mac.
io/https_nonblocking_trust_evaluation_test: SkipByDesign
+[ $system == windows ]
+io/large_file_read_small_file_test: Slow # Test reads small file 1M times
+
[ $builder_tag == swarming && $system == macos ]
io/*: Skip # Issue 30618
diff --git a/tools/VERSION b/tools/VERSION
index f272f4f..d1e510e 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 14
PATCH 0
-PRERELEASE 270
+PRERELEASE 271
PRERELEASE_PATCH 0
\ No newline at end of file