Extract and rewrite MethodInvocation resolution.

This is a copy of https://dart-review.googlesource.com/c/sdk/+/78182,
but now in the analyzer branch.

R=brianwilkerson@google.com, paulberry@google.com

Change-Id: I75d17a351ee7a33c164d560009cf3ffd088d956a
Reviewed-on: https://dart-review.googlesource.com/c/80942
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Konstantin Shcheglov 2018-10-22 03:36:30 +00:00 committed by commit-bot@chromium.org
parent 108101149e
commit c44fa48f8f
27 changed files with 2435 additions and 1294 deletions

View file

@ -62,7 +62,6 @@ bool hasFix(ErrorCode errorCode) =>
errorCode == HintCode.UNUSED_CATCH_CLAUSE ||
errorCode == HintCode.UNUSED_CATCH_STACK ||
errorCode == HintCode.UNUSED_IMPORT ||
errorCode == HintCode.UNDEFINED_METHOD ||
errorCode == ParserErrorCode.EXPECTED_TOKEN ||
errorCode == ParserErrorCode.GETTER_WITH_PARAMETERS ||
errorCode == ParserErrorCode.VAR_AS_TYPE_NAME ||

View file

@ -524,8 +524,7 @@ class FixProcessor {
await _addFix_importLibrary_withTopLevelVariable();
await _addFix_importLibrary_withType();
}
if (errorCode == HintCode.UNDEFINED_METHOD ||
errorCode == StaticTypeWarningCode.UNDEFINED_METHOD) {
if (errorCode == StaticTypeWarningCode.UNDEFINED_METHOD) {
await _addFix_createClass();
await _addFix_importLibrary_withFunction();
await _addFix_importLibrary_withType();

View file

@ -314,7 +314,6 @@ const List<ErrorCode> errorCodeValues = const [
HintCode.TYPE_CHECK_IS_NULL,
HintCode.UNDEFINED_GETTER,
HintCode.UNDEFINED_HIDDEN_NAME,
HintCode.UNDEFINED_METHOD,
HintCode.UNDEFINED_OPERATOR,
HintCode.UNDEFINED_SETTER,
HintCode.UNDEFINED_SHOWN_NAME,

View file

@ -557,21 +557,6 @@ class HintCode extends ErrorCode {
"The library '{0}' doesn't export a member with the hidden name '{1}'.",
correction: "Try removing the name from the list of hidden members.");
/**
* This hint is generated anywhere where the
* [StaticTypeWarningCode.UNDEFINED_METHOD] would have been generated, if we
* used propagated information for the warnings.
*
* Parameters:
* 0: the name of the method that is undefined
* 1: the resolved type name that the method lookup is happening on
*/
static const HintCode UNDEFINED_METHOD = const HintCode(
'UNDEFINED_METHOD', "The method '{0}' isn't defined for the class '{1}'.",
correction:
"Try correcting the name to the name of an existing method, or "
"defining a method named '{0}'.");
/**
* This hint is generated anywhere where the
* [StaticTypeWarningCode.UNDEFINED_OPERATOR] would have been generated, if we

View file

@ -0,0 +1,638 @@
// 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/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/resolver.dart';
class MethodInvocationResolver {
static final _nameCall = new Name(null, 'call');
/// The resolver driving this participant.
final ResolverVisitor _resolver;
/// The type representing the type 'dynamic'.
final DynamicTypeImpl _dynamicType = DynamicTypeImpl.instance;
/// The type representing the type 'type'.
final InterfaceType _typeType;
/// The manager for the inheritance mappings.
final InheritanceManager2 _inheritance;
/// The element for the library containing the compilation unit being visited.
final LibraryElement _definingLibrary;
/// The object keeping track of which elements have had their types promoted.
TypePromotionManager _promoteManager;
MethodInvocationResolver(this._resolver)
: _typeType = _resolver.typeProvider.typeType,
_inheritance = _resolver.inheritance,
_definingLibrary = _resolver.definingLibrary,
_promoteManager = _resolver.promoteManager;
/// The scope used to resolve identifiers.
Scope get nameScope => _resolver.nameScope;
void resolve(MethodInvocation node) {
SimpleIdentifier nameNode = node.methodName;
String name = nameNode.name;
//
// Synthetic identifiers have been already reported during parsing.
//
if (nameNode.isSynthetic) {
return;
}
Expression receiver = node.realTarget;
if (receiver == null) {
_resolveReceiverNull(node, nameNode, name);
return;
}
if (receiver is NullLiteral) {
_setDynamicResolution(node);
return;
}
if (receiver is SimpleIdentifier) {
var receiverElement = receiver.staticElement;
if (receiverElement is PrefixElement) {
_resolveReceiverPrefix(node, receiver, receiverElement, nameNode, name);
return;
}
}
if (receiver is SuperExpression) {
_resolveReceiverSuper(node, receiver, nameNode, name);
return;
}
ClassElement typeReference = getTypeReference(receiver);
if (typeReference != null) {
_resolveReceiverTypeLiteral(node, typeReference, nameNode, name);
return;
}
DartType receiverType = receiver.staticType;
receiverType = _resolveTypeParameter(receiverType);
if (receiverType is InterfaceType) {
_resolveReceiverInterfaceType(node, receiverType, nameNode, name);
return;
}
if (receiverType is DynamicTypeImpl) {
_resolveReceiverDynamic(node, name);
return;
}
if (receiverType is FunctionType) {
_resolveReceiverFunctionType(
node, receiver, receiverType, nameNode, name);
return;
}
if (receiverType is VoidType) {
_reportUseOfVoidType(node, receiver);
return;
}
}
/// Given an [argumentList] and the executable [element] that will be invoked
/// using those arguments, compute the list of parameters that correspond to
/// the list of arguments. Return the parameters that correspond to the
/// arguments, or `null` if no correspondence could be computed.
List<ParameterElement> _computeCorrespondingParameters(
ArgumentList argumentList, DartType type) {
if (type is InterfaceType) {
MethodElement callMethod =
type.lookUpMethod(FunctionElement.CALL_METHOD_NAME, _definingLibrary);
if (callMethod != null) {
return _resolveArgumentsToFunction(false, argumentList, callMethod);
}
} else if (type is FunctionType) {
return _resolveArgumentsToParameters(
false, argumentList, type.parameters);
}
return null;
}
DartType _getCalleeType(FunctionType targetType) {
if (targetType.element.kind == ElementKind.GETTER) {
var calleeType = (targetType as FunctionTypeImpl).returnType;
calleeType = _resolveTypeParameter(calleeType);
return calleeType;
}
return targetType;
}
/// Check for a generic type, and apply type arguments.
FunctionType _instantiateFunctionType(
FunctionType invokeType, TypeArgumentList typeArguments, AstNode node) {
var typeFormals = invokeType.typeFormals;
var arguments = typeArguments?.arguments;
if (arguments != null && arguments.length != typeFormals.length) {
_resolver.errorReporter.reportErrorForNode(
StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD,
node,
[invokeType, typeFormals.length, arguments?.length ?? 0]);
arguments = null;
}
if (typeFormals.isNotEmpty) {
if (arguments == null) {
return _resolver.typeSystem.instantiateToBounds(invokeType);
} else {
return invokeType.instantiate(arguments.map((n) => n.type).toList());
}
}
return invokeType;
}
bool _isCoreFunction(DartType type) {
// TODO(scheglov) Can we optimize this?
return type is InterfaceType && type.isDartCoreFunction;
}
ExecutableElement _lookUpClassMember(ClassElement element, String name) {
// TODO(scheglov) Use class hierarchy.
return element.lookUpMethod(name, _definingLibrary);
}
/// Return a signature of a member of a superinterface of [type].
/// It might be abstract.
/// TODO(scheglov) Replace this with class hierarchy.
FunctionType _lookUpInheritedMember(InterfaceType type, Name name) {
for (var mixin in type.mixins.reversed) {
var result = _inheritance.getMember(mixin, name);
if (result != null) return result;
}
{
var result = _inheritance.getMember(type.superclass, name);
if (result != null) return result;
}
for (var interface in type.interfaces) {
var result = _inheritance.getMember(interface, name);
if (result != null) return result;
}
return null;
}
void _reportInvocationOfNonFunction(MethodInvocation node) {
_setDynamicResolution(node, setNameTypeToDynamic: false);
_resolver.errorReporter.reportErrorForNode(
StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION,
node.methodName,
[node.methodName.name],
);
}
void _reportPrefixIdentifierNotFollowedByDot(SimpleIdentifier target) {
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
target,
[target.name],
);
}
void _reportUndefinedFunction(
MethodInvocation node, Identifier ignorableIdentifier) {
_setDynamicResolution(node);
// TODO(scheglov) This is duplication.
if (nameScope.shouldIgnoreUndefined(ignorableIdentifier)) {
return;
}
_resolver.errorReporter.reportErrorForNode(
StaticTypeWarningCode.UNDEFINED_FUNCTION,
node.methodName,
[node.methodName.name],
);
}
void _reportUndefinedMethod(
MethodInvocation node, String name, ClassElement typeReference) {
_setDynamicResolution(node);
_resolver.errorReporter.reportErrorForNode(
StaticTypeWarningCode.UNDEFINED_METHOD,
node.methodName,
[name, typeReference.displayName],
);
}
void _reportUseOfVoidType(MethodInvocation node, AstNode errorNode) {
_setDynamicResolution(node);
_resolver.errorReporter.reportErrorForNode(
StaticWarningCode.USE_OF_VOID_RESULT,
errorNode,
);
}
/// Given an [argumentList] and the [executableElement] that will be invoked
/// using those argument, compute the list of parameters that correspond to the
/// list of arguments. An error will be reported if any of the arguments cannot
/// be matched to a parameter. The flag [reportAsError] should be `true` if a
/// compile-time error should be reported; or `false` if a compile-time warning
/// should be reported. Return the parameters that correspond to the arguments,
/// or `null` if no correspondence could be computed.
List<ParameterElement> _resolveArgumentsToFunction(bool reportAsError,
ArgumentList argumentList, ExecutableElement executableElement) {
if (executableElement == null) {
return null;
}
List<ParameterElement> parameters = executableElement.parameters;
return _resolveArgumentsToParameters(
reportAsError, argumentList, parameters);
}
/// Given an [argumentList] and the [parameters] related to the element that
/// will be invoked using those arguments, compute the list of parameters that
/// correspond to the list of arguments. An error will be reported if any of
/// the arguments cannot be matched to a parameter. The flag [reportAsError]
/// should be `true` if a compile-time error should be reported; or `false` if
/// a compile-time warning should be reported. Return the parameters that
/// correspond to the arguments.
List<ParameterElement> _resolveArgumentsToParameters(bool reportAsError,
ArgumentList argumentList, List<ParameterElement> parameters) {
return ResolverVisitor.resolveArgumentsToParameters(
argumentList, parameters, _resolver.errorReporter.reportErrorForNode,
reportAsError: reportAsError);
}
/// Given that we are accessing a property of the given [classElement] with the
/// given [propertyName], return the element that represents the property.
Element _resolveElement(
ClassElement classElement, SimpleIdentifier propertyName) {
// TODO(scheglov) Replace with class hierarchy.
String name = propertyName.name;
Element element = null;
if (propertyName.inSetterContext()) {
element = classElement.getSetter(name);
}
if (element == null) {
element = classElement.getGetter(name);
}
if (element == null) {
element = classElement.getMethod(name);
}
if (element != null && element.isAccessibleIn(_definingLibrary)) {
return element;
}
return null;
}
void _resolveReceiverDynamic(MethodInvocation node, String name) {
_setDynamicResolution(node);
}
void _resolveReceiverFunctionType(MethodInvocation node, Expression receiver,
FunctionType receiverType, SimpleIdentifier nameNode, String name) {
if (name == FunctionElement.CALL_METHOD_NAME) {
_setResolution(node, receiverType);
// TODO(scheglov) Replace this with using FunctionType directly.
// Here was erase resolution that _setResolution() sets.
nameNode.staticElement = null;
nameNode.staticType = _dynamicType;
return;
}
// We can invoke Object methods on Function.
var type = _inheritance.getMember(
_resolver.typeProvider.objectType,
new Name(null, name),
);
if (type != null) {
nameNode.staticElement = type.element;
return _setResolution(node, type);
}
_reportUndefinedMethod(
node,
name,
_resolver.typeProvider.functionType.element,
);
}
void _resolveReceiverInterfaceType(MethodInvocation node,
InterfaceType receiverType, SimpleIdentifier nameNode, String name) {
if (_isCoreFunction(receiverType) &&
name == FunctionElement.CALL_METHOD_NAME) {
_setDynamicResolution(node);
return;
}
// TODO(scheglov) It is wasteful: get library URI multiple times.
// TODO(scheglov) It is wasteful: create names multiple times.
var targetType = _inheritance.getMember(
receiverType,
new Name(_definingLibrary.source.uri, name),
);
if (targetType != null) {
var calleeType = _getCalleeType(targetType);
// TODO(scheglov) This is bad, we have to create members here.
// Find a way to avoid this.
Element element;
var baseElement = targetType.element;
if (baseElement is MethodElement) {
element = MethodMember.from(baseElement, receiverType);
} else if (baseElement is PropertyAccessorElement) {
element = PropertyAccessorMember.from(baseElement, receiverType);
}
nameNode.staticElement = element;
return _setResolution(node, calleeType);
}
// The interface of the receiver does not have an instance member.
// Try to recover and find a member in the class.
var targetElement = _lookUpClassMember(receiverType.element, name);
if (targetElement != null && targetElement.isStatic) {
nameNode.staticElement = targetElement;
_setDynamicResolution(node);
_resolver.errorReporter.reportErrorForNode(
StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER,
nameNode,
[
name,
targetElement.kind.displayName,
targetElement.enclosingElement.displayName,
],
);
return;
}
_setDynamicResolution(node);
_resolver.errorReporter.reportErrorForNode(
StaticTypeWarningCode.UNDEFINED_METHOD,
nameNode,
[name, receiverType.element.displayName],
);
}
void _resolveReceiverNull(
MethodInvocation node, SimpleIdentifier nameNode, String name) {
var element = nameScope.lookup(nameNode, _definingLibrary);
if (element != null) {
nameNode.staticElement = element;
if (element is MultiplyDefinedElement) {
MultiplyDefinedElement multiply = element;
element = multiply.conflictingElements[0];
}
if (element is ExecutableElement) {
var calleeType = _getCalleeType(element.type);
return _setResolution(node, calleeType);
}
if (element is VariableElement) {
var targetType = _promoteManager.getStaticType(element);
return _setResolution(node, targetType);
}
// TODO(scheglov) This is a questionable distinction.
if (element is PrefixElement) {
_setDynamicResolution(node);
return _reportPrefixIdentifierNotFollowedByDot(nameNode);
}
return _reportInvocationOfNonFunction(node);
}
ClassElement enclosingClass = _resolver.enclosingClass;
if (enclosingClass == null) {
return _reportUndefinedFunction(node, node.methodName);
}
var receiverType = enclosingClass.type;
var targetType = _inheritance.getMember(
receiverType,
new Name(_definingLibrary.source.uri, name),
);
if (targetType != null) {
nameNode.staticElement = targetType.element;
var calleeType = _getCalleeType(targetType);
return _setResolution(node, calleeType);
}
var targetElement = _lookUpClassMember(enclosingClass, name);
if (targetElement != null && targetElement.isStatic) {
nameNode.staticElement = targetElement;
_setDynamicResolution(node);
_resolver.errorReporter.reportErrorForNode(
StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER,
nameNode,
[receiverType.displayName],
);
return;
}
return _reportUndefinedMethod(node, name, enclosingClass);
}
void _resolveReceiverPrefix(MethodInvocation node, SimpleIdentifier receiver,
PrefixElement prefix, SimpleIdentifier nameNode, String name) {
if (node.operator.type == TokenType.QUESTION_PERIOD) {
_reportPrefixIdentifierNotFollowedByDot(receiver);
}
if (name == FunctionElement.LOAD_LIBRARY_NAME) {
var imports = _definingLibrary.getImportsWithPrefix(prefix);
if (imports.length == 1 && imports[0].isDeferred) {
var importedLibrary = imports[0].importedLibrary;
var loadLibraryFunction = importedLibrary?.loadLibraryFunction;
nameNode.staticElement = loadLibraryFunction;
node.staticInvokeType = loadLibraryFunction?.type;
node.staticType = loadLibraryFunction?.returnType;
return;
}
}
// TODO(scheglov) I don't like how we resolve prefixed names.
// But maybe this is the only one solution.
var prefixedName = new PrefixedIdentifierImpl.temp(receiver, nameNode);
var element = nameScope.lookup(prefixedName, _definingLibrary);
nameNode.staticElement = element;
if (element is MultiplyDefinedElement) {
MultiplyDefinedElement multiply = element;
element = multiply.conflictingElements[0];
}
if (element is ExecutableElement) {
var calleeType = _getCalleeType(element.type);
return _setResolution(node, calleeType);
}
_reportUndefinedFunction(node, prefixedName);
}
void _resolveReceiverSuper(MethodInvocation node, SuperExpression receiver,
SimpleIdentifier nameNode, String name) {
if (!_isSuperInValidContext(receiver)) {
return;
}
var receiverType = _resolver.enclosingClass.type;
var targetType = _inheritance.getMember(
receiverType,
new Name(_definingLibrary.source.uri, name),
forSuper: true,
);
// If there is that concrete dispatch target, then we are done.
if (targetType != null) {
nameNode.staticElement = targetType.element;
var calleeType = _getCalleeType(targetType);
_setResolution(node, calleeType);
return;
}
// Otherwise, this is an error.
// But we would like to give the user at least some resolution.
// So, we try to find the interface target.
targetType = _lookUpInheritedMember(
receiverType,
new Name(_definingLibrary.source.uri, name),
);
if (targetType != null) {
nameNode.staticElement = targetType.element;
var calleeType = _getCalleeType(targetType);
_setResolution(node, calleeType);
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE,
nameNode,
[targetType.element.kind.displayName, name]);
return;
}
// Nothing help, there is no target at all.
_setDynamicResolution(node);
_resolver.errorReporter.reportErrorForNode(
StaticTypeWarningCode.UNDEFINED_SUPER_METHOD,
nameNode,
[name, _resolver.enclosingClass.displayName]);
}
void _resolveReceiverTypeLiteral(MethodInvocation node, ClassElement receiver,
SimpleIdentifier nameNode, String name) {
if (node.isCascaded) {
receiver = _typeType.element;
}
var element = _resolveElement(receiver, nameNode);
if (element != null) {
if (element is ExecutableElement) {
nameNode.staticElement = element;
var calleeType = _getCalleeType(element.type);
_setResolution(node, calleeType);
} else {
_reportInvocationOfNonFunction(node);
}
return;
}
_reportUndefinedMethod(node, name, receiver);
}
/// If the given [type] is a type parameter, replace with its bound.
/// Otherwise, return the original type.
DartType _resolveTypeParameter(DartType type) {
if (type is TypeParameterType) {
return type.resolveToBound(_resolver.typeProvider.objectType);
}
return type;
}
void _setDynamicResolution(MethodInvocation node,
{bool setNameTypeToDynamic: true}) {
if (setNameTypeToDynamic) {
node.methodName.staticType = _dynamicType;
}
node.staticInvokeType = _dynamicType;
node.staticType = _dynamicType;
}
void _setResolution(MethodInvocation node, DartType type) {
if (type == _dynamicType || _isCoreFunction(type)) {
_setDynamicResolution(node);
return;
}
// TODO(scheglov) We need this for StaticTypeAnalyzer to run inference.
// But it seems weird. Do we need to know the raw type of a function?!
node.methodName.staticType = type;
if (type is InterfaceType) {
var call = _inheritance.getMember(type, _nameCall);
if (call != null && call.element.kind == ElementKind.METHOD) {
type = call;
}
}
if (type is FunctionType) {
// TODO(scheglov) Extract this when receiver is already FunctionType?
var instantiatedType = _instantiateFunctionType(
type,
node.typeArguments,
node.methodName,
);
node.staticInvokeType = instantiatedType;
node.staticType = instantiatedType.returnType;
// TODO(scheglov) too much magic
node.argumentList.correspondingStaticParameters =
_computeCorrespondingParameters(
node.argumentList,
instantiatedType,
);
return;
}
if (type is VoidType) {
return _reportUseOfVoidType(node, node.methodName);
}
_reportInvocationOfNonFunction(node);
}
/// Checks whether the given [expression] is a reference to a class. If it is
/// then the element representing the class is returned, otherwise `null` is
/// returned.
static ClassElement getTypeReference(Expression expression) {
if (expression is Identifier) {
Element staticElement = expression.staticElement;
if (staticElement is ClassElement) {
return staticElement;
}
}
return null;
}
/// Return `true` if the given 'super' [expression] is used in a valid context.
static bool _isSuperInValidContext(SuperExpression expression) {
for (AstNode node = expression; node != null; node = node.parent) {
if (node is CompilationUnit) {
return false;
} else if (node is ConstructorDeclaration) {
return node.factoryKeyword == null;
} else if (node is ConstructorFieldInitializer) {
return false;
} else if (node is MethodDeclaration) {
return !node.isStatic;
}
}
return false;
}
}

View file

@ -19,6 +19,7 @@ import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/resolver/method_invocation_resolver.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
@ -108,24 +109,21 @@ class ElementResolver extends SimpleAstVisitor<Object> {
*/
InterfaceType _typeType;
/**
* The object keeping track of which elements have had their types promoted.
*/
TypePromotionManager _promoteManager;
/// Whether constant evaluation errors should be reported during resolution.
final bool reportConstEvaluationErrors;
final MethodInvocationResolver _methodInvocationResolver;
/**
* Initialize a newly created visitor to work for the given [_resolver] to
* resolve the nodes in a compilation unit.
*/
ElementResolver(this._resolver, {this.reportConstEvaluationErrors: true})
: _inheritance = _resolver.inheritance,
_definingLibrary = _resolver.definingLibrary {
_definingLibrary = _resolver.definingLibrary,
_methodInvocationResolver = new MethodInvocationResolver(_resolver) {
_dynamicType = _resolver.typeProvider.dynamicType;
_typeType = _resolver.typeProvider.typeType;
_promoteManager = _resolver.promoteManager;
}
/**
@ -537,212 +535,7 @@ class ElementResolver extends SimpleAstVisitor<Object> {
@override
Object visitMethodInvocation(MethodInvocation node) {
SimpleIdentifier methodName = node.methodName;
//
// Synthetic identifiers have been already reported during parsing.
//
if (methodName.isSynthetic) {
return null;
}
//
// We have a method invocation of one of two forms: 'e.m(a1, ..., an)' or
// 'm(a1, ..., an)'. The first step is to figure out which executable is
// being invoked, using both the static and the propagated type information.
//
Expression target = node.realTarget;
if (target is SuperExpression && !_isSuperInValidContext(target)) {
return null;
}
Element staticElement;
if (target == null) {
staticElement = _resolveInvokedElement(methodName);
} else if (methodName.name == FunctionElement.LOAD_LIBRARY_NAME &&
_isDeferredPrefix(target)) {
if (node.operator.type == TokenType.QUESTION_PERIOD) {
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
target,
[(target as SimpleIdentifier).name]);
}
LibraryElement importedLibrary = _getImportedLibrary(target);
FunctionElement loadLibraryFunction =
importedLibrary?.loadLibraryFunction;
methodName.staticElement = loadLibraryFunction;
node.staticInvokeType = loadLibraryFunction?.type;
return null;
} else {
//
// If this method invocation is of the form 'C.m' where 'C' is a class,
// then we don't call resolveInvokedElement(...) which walks up the class
// hierarchy, instead we just look for the member in the type only. This
// does not apply to conditional method invocation (i.e. 'C?.m(...)').
//
bool isConditional = node.operator.type == TokenType.QUESTION_PERIOD;
ClassElement typeReference = getTypeReference(target);
if (typeReference != null) {
if (node.isCascaded) {
typeReference = _typeType.element;
}
staticElement = _resolveElement(typeReference, methodName);
} else {
DartType staticType = _getStaticTypeOrFunctionType(target);
if (staticType is FunctionType &&
methodName.name == FunctionElement.CALL_METHOD_NAME) {
if (target is SimpleIdentifier) {
methodName.staticElement = target.staticElement;
}
methodName.staticType = target.staticType;
node.staticType = staticType;
node.staticInvokeType = staticType;
node.argumentList.correspondingStaticParameters =
_computeCorrespondingParameters(node.argumentList, staticType);
return null;
}
if (target is SuperExpression) {
if (staticType is InterfaceTypeImpl) {
staticElement = staticType.lookUpInheritedMember(
methodName.name, _definingLibrary,
concrete: true, forSuperInvocation: true);
// We were not able to find the concrete dispatch target.
// But we would like to give the user at least some resolution.
// So, we retry without the "concrete" requirement.
if (staticElement == null) {
staticElement = staticType.lookUpInheritedMember(
methodName.name, _definingLibrary,
concrete: false);
if (staticElement != null) {
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE,
methodName,
[staticElement.kind.displayName, methodName.name]);
}
}
}
} else {
staticElement = _resolveInvokedElementWithTarget(
target, staticType, methodName, isConditional);
}
}
}
staticElement = _convertSetterToGetter(staticElement);
//
// Given the elements, determine the type of the function we are invoking
//
DartType staticType = _getInvokeType(staticElement);
methodName.staticType = staticType;
//
// Instantiate generic function or method if needed.
//
DartType staticInvokeType = _instantiateGenericMethod(
staticType, node.typeArguments, node.methodName);
//
// Record the results.
//
methodName.staticElement = staticElement;
node.staticInvokeType = staticInvokeType;
ArgumentList argumentList = node.argumentList;
if (staticInvokeType != null) {
List<ParameterElement> parameters =
_computeCorrespondingParameters(argumentList, staticInvokeType);
argumentList.correspondingStaticParameters = parameters;
}
//
// Then check for error conditions.
//
ErrorCode errorCode = _checkForInvocationError(
target, true, staticElement, staticType, methodName.name);
if (errorCode != null &&
target is SimpleIdentifier &&
target.staticElement is PrefixElement) {
Identifier functionName =
new PrefixedIdentifierImpl.temp(target, methodName);
if (_resolver.nameScope.shouldIgnoreUndefined(functionName)) {
return null;
}
}
if (errorCode == null) {
return null;
}
if (identical(
errorCode, StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION) ||
identical(errorCode,
CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT) ||
identical(errorCode, StaticTypeWarningCode.UNDEFINED_FUNCTION)) {
if (!_resolver.nameScope.shouldIgnoreUndefined(methodName)) {
_resolver.errorReporter
.reportErrorForNode(errorCode, methodName, [methodName.name]);
}
} else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) {
String targetTypeName;
if (target == null) {
ClassElement enclosingClass = _resolver.enclosingClass;
targetTypeName = enclosingClass.displayName;
ErrorCode proxyErrorCode = StaticTypeWarningCode.UNDEFINED_METHOD;
_recordUndefinedNode(_resolver.enclosingClass, proxyErrorCode,
methodName, [methodName.name, targetTypeName]);
} else {
// ignore Function "call"
// (if we are about to create a hint using type propagation,
// then we can use type propagation here as well)
DartType targetType = null;
targetType = _getStaticType(target);
if (targetType != null &&
targetType.isDartCoreFunction &&
methodName.name == FunctionElement.CALL_METHOD_NAME) {
return null;
}
if (!node.isCascaded) {
ClassElement typeReference = getTypeReference(target);
if (typeReference != null) {
ConstructorElement constructor =
typeReference.getNamedConstructor(methodName.name);
if (constructor != null) {
_recordUndefinedNode(
typeReference,
StaticTypeWarningCode.UNDEFINED_METHOD_WITH_CONSTRUCTOR,
methodName,
[methodName.name, typeReference.name]);
return null;
}
}
}
targetTypeName = targetType?.displayName;
ErrorCode proxyErrorCode = StaticTypeWarningCode.UNDEFINED_METHOD;
_recordUndefinedNode(targetType.element, proxyErrorCode, methodName,
[methodName.name, targetTypeName]);
}
} else if (identical(
errorCode, StaticTypeWarningCode.UNDEFINED_SUPER_METHOD)) {
// Generate the type name.
// The error code will never be generated via type propagation
DartType getSuperType(DartType type) {
if (type is InterfaceType) {
InterfaceType superclass = type.superclass;
if (superclass != null) return superclass;
}
return type;
}
DartType targetType = getSuperType(_getStaticType(target));
String targetTypeName = targetType?.name;
_resolver.errorReporter.reportErrorForNode(
StaticTypeWarningCode.UNDEFINED_SUPER_METHOD,
methodName,
[methodName.name, targetTypeName]);
} else if (identical(errorCode, StaticWarningCode.USE_OF_VOID_RESULT)) {
_resolver.errorReporter.reportErrorForNode(
StaticWarningCode.USE_OF_VOID_RESULT, target ?? methodName, []);
}
_methodInvocationResolver.resolve(node);
return null;
}
@ -1121,99 +914,6 @@ class ElementResolver extends SimpleAstVisitor<Object> {
return null;
}
/**
* Given that we have found code to invoke the given [element], return the
* error code that should be reported, or `null` if no error should be
* reported. The [target] is the target of the invocation, or `null` if there
* was no target. The flag [useStaticContext] should be `true` if the
* invocation is in a static constant (does not have access to instance state).
*/
ErrorCode _checkForInvocationError(Expression target, bool useStaticContext,
Element element, DartType type, String name) {
// Prefix is not declared, instead "prefix.id" are declared.
if (element is PrefixElement) {
return CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT;
} else if (element is PropertyAccessorElement) {
//
// This is really a function expression invocation.
//
// TODO(brianwilkerson) Consider the possibility of re-writing the AST.
FunctionType getterType = element.type;
if (getterType != null) {
DartType returnType = getterType.returnType;
return _getErrorCodeForExecuting(returnType);
}
} else if (element is ExecutableElement) {
return null;
} else if (element is MultiplyDefinedElement) {
// The error has already been reported
return null;
} else if (element == null && target is SuperExpression) {
// TODO(jwren) We should split the UNDEFINED_METHOD into two error codes,
// this one, and a code that describes the situation where the method was
// found, but it was not accessible from the current library.
return StaticTypeWarningCode.UNDEFINED_SUPER_METHOD;
} else {
//
// This is really a function expression invocation.
//
// TODO(brianwilkerson) Consider the possibility of re-writing the AST.
if (element is PropertyInducingElement) {
PropertyAccessorElement getter = element.getter;
FunctionType getterType = getter.type;
if (getterType != null) {
DartType returnType = getterType.returnType;
return _getErrorCodeForExecuting(returnType);
}
} else if (element is VariableElement) {
return _getErrorCodeForExecuting(type);
} else {
if (target == null) {
ClassElement enclosingClass = _resolver.enclosingClass;
if (enclosingClass == null) {
return StaticTypeWarningCode.UNDEFINED_FUNCTION;
} else if (element == null) {
// Proxy-conditional warning, based on state of
// resolver.getEnclosingClass()
return StaticTypeWarningCode.UNDEFINED_METHOD;
} else {
return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION;
}
} else {
DartType targetType;
if (useStaticContext) {
targetType = _getStaticType(target);
} else {
// Compute and use the propagated type, if it is null, then it may
// be the case that static type is some type, in which the static
// type should be used.
targetType = _getBestType(target);
}
if (targetType == null) {
if (target is Identifier &&
_resolver.nameScope.shouldIgnoreUndefined(target)) {
return null;
}
return StaticTypeWarningCode.UNDEFINED_FUNCTION;
} else if (targetType.isVoid) {
return StaticWarningCode.USE_OF_VOID_RESULT;
} else if (!targetType.isDynamic && target is! NullLiteral) {
// Proxy-conditional warning, based on state of
// targetType.getElement()
return StaticTypeWarningCode.UNDEFINED_METHOD;
} else if (targetType.isDynamic) {
PropertyAccessorElement getter =
_resolver.typeProvider.objectType.getGetter(name);
if (getter != null && getter.returnType is! FunctionType) {
return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION;
}
}
}
}
}
return null;
}
/**
* Check that the given index [expression] was resolved, otherwise a
* [StaticTypeWarningCode.UNDEFINED_OPERATOR] is generated. The [target] is
@ -1274,50 +974,6 @@ class ElementResolver extends SimpleAstVisitor<Object> {
return null;
}
/**
* If the given [element] is a setter, return the getter associated with it.
* Otherwise, return the element unchanged.
*/
Element _convertSetterToGetter(Element element) {
// TODO(brianwilkerson) Determine whether and why the element could ever be
// a setter.
if (element is PropertyAccessorElement) {
return element.variable.getter;
}
return element;
}
/**
* Return the best type of the given [expression] that is to be used for
* type analysis.
*/
DartType _getBestType(Expression expression) {
DartType bestType = _resolveTypeParameter(expression.staticType);
if (bestType is FunctionType) {
//
// All function types are subtypes of 'Function', which is itself a
// subclass of 'Object'.
//
bestType = _resolver.typeProvider.functionType;
}
return bestType;
}
/**
* Return an error if the [type], which is presumably being invoked, is not a
* function. The errors for non functions may be broken up by type; currently,
* it returns a special value for when the type is `void`.
*/
ErrorCode _getErrorCodeForExecuting(DartType type) {
if (_isExecutableType(type)) {
return null;
}
return type.isVoid
? StaticWarningCode.USE_OF_VOID_RESULT
: StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION;
}
/**
* Assuming that the given [identifier] is a prefix for a deferred import,
* return the library that is being imported.
@ -1329,28 +985,6 @@ class ElementResolver extends SimpleAstVisitor<Object> {
return imports[0].importedLibrary;
}
/**
* Given an element, computes the type of the invocation.
*
* For executable elements (like methods, functions) this is just their type.
*
* For variables it is their type taking into account any type promotion.
*
* For calls to getters in Dart, we invoke the function that is returned by
* the getter, so the invoke type is the getter's returnType.
*/
DartType _getInvokeType(Element element) {
DartType invokeType;
if (element is PropertyAccessorElement) {
invokeType = element.returnType;
} else if (element is ExecutableElement) {
invokeType = element.type;
} else if (element is VariableElement) {
invokeType = _promoteManager.getStaticType(element);
}
return invokeType ?? DynamicTypeImpl.instance;
}
/**
* Return the name of the method invoked by the given postfix [expression].
*/
@ -1460,25 +1094,6 @@ class ElementResolver extends SimpleAstVisitor<Object> {
return false;
}
/**
* Return `true` if the given [type] represents an object that could be
* invoked using the call operator '()'.
*/
bool _isExecutableType(DartType type) {
type = type?.resolveToBound(_resolver.typeProvider.objectType);
if (type.isDynamic || type is FunctionType) {
return true;
} else if (type.isDartCoreFunction) {
return true;
} else if (type is InterfaceType) {
ClassElement classElement = type.element;
MethodElement methodElement = classElement.lookUpMethod(
FunctionElement.CALL_METHOD_NAME, _definingLibrary);
return methodElement != null;
}
return false;
}
/**
* Return `true` if the given [element] is a static element.
*/
@ -1582,18 +1197,18 @@ class ElementResolver extends SimpleAstVisitor<Object> {
/**
* Look up the [FunctionType] of a getter or a method with the given [name]
* in the given [targetType]. The [target] is the target of the invocation,
* or `null` if there is no target.
* in the given [targetType].
*/
FunctionType _lookUpGetterType(
Expression target, DartType targetType, String name) {
FunctionType _lookUpGetterType(DartType targetType, String name,
{bool concrete: false, bool forSuper: false}) {
targetType = _resolveTypeParameter(targetType);
if (targetType is InterfaceType) {
var nameObject = new Name(_definingLibrary.source.uri, name);
return _inheritance.getMember(
targetType,
nameObject,
forSuper: target is SuperExpression,
concrete: concrete,
forSuper: forSuper,
);
}
return null;
@ -1894,12 +1509,14 @@ class ElementResolver extends SimpleAstVisitor<Object> {
Expression leftOperand = node.leftOperand;
if (leftOperand != null) {
DartType leftType = _getStaticType(leftOperand);
var invokeType = _lookUpGetterType(leftOperand, leftType, methodName);
var isSuper = leftOperand is SuperExpression;
var invokeType = _lookUpGetterType(leftType, methodName,
concrete: isSuper, forSuper: isSuper);
var invokeElement = invokeType?.element;
node.staticElement = invokeElement;
node.staticInvokeType = invokeType;
if (_shouldReportMissingMember(leftType, invokeElement)) {
if (leftOperand is SuperExpression) {
if (isSuper) {
_recordUndefinedToken(
leftType.element,
StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR,
@ -1977,103 +1594,6 @@ class ElementResolver extends SimpleAstVisitor<Object> {
return null;
}
/**
* Given an invocation of the form 'm(a1, ..., an)', resolve 'm' to the
* element being invoked. If the returned element is a method, then the method
* will be invoked. If the returned element is a getter, the getter will be
* invoked without arguments and the result of that invocation will then be
* invoked with the arguments. The [methodName] is the name of the method
* being invoked ('m').
*/
Element _resolveInvokedElement(SimpleIdentifier methodName) {
//
// Look first in the lexical scope.
//
Element element = _resolver.nameScope.lookup(methodName, _definingLibrary);
if (element == null) {
//
// If it isn't defined in the lexical scope, and the invocation is within
// a class, then look in the inheritance scope.
//
ClassElement enclosingClass = _resolver.enclosingClass;
if (enclosingClass != null) {
InterfaceType enclosingType = enclosingClass.type;
element = _lookUpMethod(null, enclosingType, methodName.name);
if (element == null) {
//
// If there's no method, then it's possible that 'm' is a getter that
// returns a function.
//
element = _lookUpGetter(null, enclosingType, methodName.name);
}
}
}
// TODO(brianwilkerson) Report this error.
return element;
}
/**
* Given an invocation of the form 'e.m(a1, ..., an)', resolve 'e.m' to the
* element being invoked. If the returned element is a method, then the method
* will be invoked. If the returned element is a getter, the getter will be
* invoked without arguments and the result of that invocation will then be
* invoked with the arguments. The [target] is the target of the invocation
* ('e'). The [targetType] is the type of the target. The [methodName] is th
* name of the method being invoked ('m'). [isConditional] indicates
* whether the invocation uses a '?.' operator.
*/
Element _resolveInvokedElementWithTarget(Expression target,
DartType targetType, SimpleIdentifier methodName, bool isConditional) {
String name = methodName.name;
if (targetType is InterfaceType) {
Element element = _lookUpMethod(target, targetType, name);
if (element == null) {
//
// If there's no method, then it's possible that 'm' is a getter that
// returns a function.
//
// TODO (collinsn): need to add union type support here too, in the
// style of [lookUpMethod].
element = _lookUpGetter(target, targetType, name);
}
return element;
} else if (targetType is FunctionType &&
_resolver.typeProvider.isObjectMethod(name)) {
return _resolver.typeProvider.objectType.element.getMethod(name);
} else if (target is SimpleIdentifier) {
Element targetElement = target.staticElement;
if (targetType is FunctionType &&
name == FunctionElement.CALL_METHOD_NAME) {
return targetElement;
}
if (targetElement is PrefixElement) {
if (isConditional) {
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
target,
[target.name]);
}
//
// Look to see whether the name of the method is really part of a
// prefixed identifier for an imported top-level function or top-level
// getter that returns a function.
//
Identifier functionName =
new PrefixedIdentifierImpl.temp(target, methodName);
Element element =
_resolver.nameScope.lookup(functionName, _definingLibrary);
if (element != null) {
// TODO(brianwilkerson) This isn't a method invocation, it's a
// function invocation where the function name is a prefixed
// identifier. Consider re-writing the AST.
return element;
}
}
}
// TODO(brianwilkerson) Report this error.
return null;
}
/**
* Given a [node] that can have annotations associated with it, resolve the
* annotations in the element model representing annotations to the node.

View file

@ -4154,7 +4154,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
var superMemberType = _inheritanceManager.getMember(
enclosingType, nameObject,
forMixinIndex: mixinIndex, forSuper: true);
forMixinIndex: mixinIndex, concrete: true, forSuper: true);
if (superMemberType == null) {
_errorReporter.reportErrorForNode(

View file

@ -517,7 +517,9 @@ class CodeChecker extends RecursiveAstVisitor {
visitMethodInvocation(MethodInvocation node) {
var target = node.realTarget;
var element = node.methodName.staticElement;
if (element == null && !typeProvider.isObjectMethod(node.methodName.name)) {
if (element == null &&
!typeProvider.isObjectMethod(node.methodName.name) &&
node.methodName.name != FunctionElement.CALL_METHOD_NAME) {
_recordDynamicInvoke(node, target);
// Mark the tear-off as being dynamic, too. This lets us distinguish

View file

@ -5214,23 +5214,6 @@ f() {
verify([source]);
}
test_prefix_conditionalPropertyAccess_call() async {
addNamedSource('/lib.dart', '''
library lib;
g() {}
''');
Source source = addSource('''
import 'lib.dart' as p;
f() {
p?.g();
}
''');
await computeAnalysisResult(source);
assertErrors(
source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
verify([source]);
}
test_prefix_conditionalPropertyAccess_call_loadLibrary() async {
addNamedSource('/lib.dart', '''
library lib;
@ -5313,36 +5296,6 @@ f() {
verify([source]);
}
test_prefix_unqualified_invocation_in_method() async {
addNamedSource('/lib.dart', 'librarylib;');
Source source = addSource('''
import 'lib.dart' as p;
class C {
f() {
p();
}
}
''');
await computeAnalysisResult(source);
assertErrors(
source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
verify([source]);
}
test_prefix_unqualified_invocation_not_in_method() async {
addNamedSource('/lib.dart', 'librarylib;');
Source source = addSource('''
import 'lib.dart' as p;
f() {
p();
}
''');
await computeAnalysisResult(source);
assertErrors(
source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
verify([source]);
}
test_prefixCollidesWithTopLevelMembers_functionTypeAlias() async {
addNamedSource("/lib.dart", r'''
library lib;

View file

@ -829,31 +829,6 @@ class ElementResolverTest extends EngineTestCase with ResourceProviderMixin {
_listener.assertNoErrors();
}
test_visitMethodInvocation_namedParameter() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
String methodName = "m";
String parameterName = "p";
MethodElementImpl method = ElementFactory.methodElement(methodName, null);
ParameterElement parameter = ElementFactory.namedParameter(parameterName);
method.parameters = <ParameterElement>[parameter];
classA.methods = <MethodElement>[method];
SimpleIdentifier left = AstTestFactory.identifier3("i");
left.staticType = classA.type;
MethodInvocation invocation = AstTestFactory.methodInvocation(
left, methodName, [
AstTestFactory.namedExpression2(parameterName, AstTestFactory.integer(0))
]);
_resolveNode(invocation);
expect(invocation.methodName.staticElement, same(method));
expect(
(invocation.argumentList.arguments[0] as NamedExpression)
.name
.label
.staticElement,
same(parameter));
_listener.assertNoErrors();
}
test_visitPostfixExpression() async {
InterfaceType numType = _typeProvider.numType;
SimpleIdentifier operand = AstTestFactory.identifier3("i");

View file

@ -3980,38 +3980,6 @@ import 'lib1.dart' show a;''');
verify([source]);
}
test_undefinedMethod() async {
Source source = addSource(r'''
f() {
var a = 'str';
a.notAMethodOnString();
}''');
await computeAnalysisResult(source);
if (previewDart2) {
assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
} else {
assertErrors(source, [HintCode.UNDEFINED_METHOD]);
}
}
test_undefinedMethod_assignmentExpression() async {
Source source = addSource(r'''
class A {}
class B {
f(var a, var a2) {
a = new A();
a2 = new A();
a += a2;
}
}''');
await computeAnalysisResult(source);
if (previewDart2) {
assertNoErrors(source);
} else {
assertErrors(source, [HintCode.UNDEFINED_METHOD]);
}
}
test_undefinedOperator_binaryExpression() async {
Source source = addSource(r'''
class A {}

View file

@ -29,12 +29,6 @@ class NonErrorResolverTest_Driver extends NonErrorResolverTestBase {
return super.test_intLiteralInDoubleContext_const_exact();
}
@override
@failingTest
test_null_callMethod() {
return super.test_null_callMethod();
}
@override
@failingTest
test_null_callOperator() {

View file

@ -104,12 +104,6 @@ class NonErrorResolverTest extends NonErrorResolverTestBase {
return super.test_mixinInference_with_actual_mixins_supermixins_enabled();
}
@override
@failingTest
test_null_callMethod() {
return super.test_null_callMethod();
}
@override
@failingTest
test_null_callOperator() {
@ -3590,86 +3584,6 @@ class A<E> {
verify([source]);
}
test_invocationOfNonFunction_dynamic() async {
Source source = addSource(r'''
class A {
var f;
}
class B extends A {
g() {
f();
}
}''');
await computeAnalysisResult(source);
assertNoErrors(source);
verify([source]);
}
test_invocationOfNonFunction_functionTypeTypeParameter() async {
Source source = addSource(r'''
typedef void Action<T>(T x);
class C<T, U extends Action<T>> {
T value;
U action;
C(this.value, [this.action]);
void act() {
action(value);
}
}
''');
await computeAnalysisResult(source);
assertNoErrors(source);
verify([source]);
}
test_invocationOfNonFunction_getter() async {
Source source = addSource(r'''
class A {
var g;
}
f() {
A a;
a.g();
}''');
await computeAnalysisResult(source);
assertNoErrors(source);
verify([source]);
}
test_invocationOfNonFunction_localVariable() async {
Source source = addSource(r'''
f() {
var g;
g();
}''');
await computeAnalysisResult(source);
assertNoErrors(source);
verify([source]);
}
test_invocationOfNonFunction_localVariable_dynamic() async {
Source source = addSource(r'''
f() {}
main() {
var v = f;
v();
}''');
await computeAnalysisResult(source);
assertNoErrors(source);
verify([source]);
}
test_invocationOfNonFunction_Object() async {
Source source = addSource(r'''
main() {
Object v = null;
v();
}''');
await computeAnalysisResult(source);
assertErrors(source, [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]);
verify([source]);
}
Future test_issue32114() async {
addNamedSource('/a.dart', '''
class O {}
@ -4984,15 +4898,6 @@ class A {
verify([source]);
}
test_null_callMethod() async {
Source source = addSource(r'''
main() {
null.m();
}''');
await computeAnalysisResult(source);
assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
}
test_null_callOperator() async {
Source source = addSource(r'''
main() {

View file

@ -930,24 +930,6 @@ class D<T extends dynamic> {
assertNoErrors(source);
}
test_undefinedMethod_inSubtype() async {
Source source = addSource(r'''
class A {}
class B extends A {
b() {}
}
f() {
var a = new A();
a.b();
}''');
await computeAnalysisResult(source);
if (previewDart2) {
assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
} else {
assertNoErrors(source);
}
}
test_undefinedMethod_unionType_all() async {
Source source = addSource(r'''
class A {

View file

@ -2,12 +2,9 @@
// 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/error/error.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/java_core.dart' show formatList;
import 'package:analyzer/src/generated/source_io.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'resolver_test_case.dart';
@ -95,21 +92,6 @@ E e() {
}''', [StaticTypeWarningCode.UNDEFINED_ENUM_CONSTANT]);
}
test_ambiguousImport_function() async {
Source source = addSource(r'''
import 'lib1.dart';
import 'lib2.dart';
g() { return f(); }''');
addNamedSource("/lib1.dart", r'''
library lib1;
f() {}''');
addNamedSource("/lib2.dart", r'''
library lib2;
f() {}''');
await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]);
}
test_assert_message_suppresses_type_promotion() async {
// If a variable is assigned to inside the expression for an assert
// message, type promotion should be suppressed, just as it would be if the
@ -522,16 +504,6 @@ class C {
''', [StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE]);
}
test_instanceAccessToStaticMember_method_invocation() async {
await assertErrorsInCode(r'''
class A {
static m() {}
}
main(A a) {
a.m();
}''', [StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER]);
}
test_instanceAccessToStaticMember_method_reference() async {
await assertErrorsInCode(r'''
class A {
@ -682,85 +654,6 @@ class A {
}''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
}
test_invocationOfNonFunction_class() async {
await assertErrorsInCode(r'''
class A {
void m() {
A();
}
}''', previewDart2 ? [] : [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]);
}
test_invocationOfNonFunction_dynamic() async {
await assertErrorsInCode(r'''
main() {
dynamic d;
d.hashCode();
}
''', [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]);
}
test_invocationOfNonFunction_localGenericFunction() async {
// Invoking `.call` on a `Function` type works similarly to invoking it on
// `dynamic`--the invocation is accepted at compile time, and all type
// checking is deferred until runtime.
await assertErrorsInCode('''
f(Function f) {
return f();
}''', []);
}
test_invocationOfNonFunction_localObject() async {
await assertErrorsInCode('''
f(Object o) {
return o();
}''', [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]);
}
test_invocationOfNonFunction_localVariable() async {
await assertErrorsInCode(r'''
f() {
int x;
return x();
}''', [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]);
}
test_invocationOfNonFunction_ordinaryInvocation() async {
await assertErrorsInCode(r'''
class A {
static int x;
}
class B {
m() {
A.x();
}
}''', [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]);
// A call to verify(source) fails as A.x() cannot be resolved.
}
test_invocationOfNonFunction_staticInvocation() async {
await assertErrorsInCode(r'''
class A {
static int get g => 0;
f() {
A.g();
}
}''', [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]);
// A call to verify(source) fails as g() cannot be resolved.
}
test_invocationOfNonFunction_superExpression() async {
await assertErrorsInCode(r'''
class A {
int get g => 0;
}
class B extends A {
m() {
var v = super.g();
}
}''', [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]);
}
test_invocationOfNonFunctionExpression_literal() async {
await assertErrorsInCode(r'''
f() {
@ -1413,34 +1306,6 @@ main(A<V> p) {
}''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
}
test_undefinedFunction() async {
await assertErrorsInCode(r'''
void f() {
g();
}''', [StaticTypeWarningCode.UNDEFINED_FUNCTION]);
}
test_undefinedFunction_inCatch() async {
await assertErrorsInCode(r'''
void f() {
try {
} on Object {
g();
}
}''', [StaticTypeWarningCode.UNDEFINED_FUNCTION]);
}
test_undefinedFunction_inImportedLib() async {
Source source = addSource(r'''
import 'lib.dart' as f;
main() { return f.g(); }''');
addNamedSource("/lib.dart", r'''
library lib;
h() {}''');
await computeAnalysisResult(source);
assertErrors(source, [StaticTypeWarningCode.UNDEFINED_FUNCTION]);
}
test_undefinedGetter() async {
await assertErrorsInUnverifiedCode(r'''
class T {}
@ -1536,15 +1401,6 @@ main(A<NoSuchType> a) {
}''', [StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT]);
}
test_undefinedMethod() async {
await assertErrorsInCode(r'''
class A {
void m() {
n();
}
}''', [StaticTypeWarningCode.UNDEFINED_METHOD]);
}
test_undefinedMethod_assignmentExpression() async {
await assertErrorsInCode(r'''
class A {}
@ -1556,17 +1412,6 @@ class B {
}''', [StaticTypeWarningCode.UNDEFINED_METHOD]);
}
test_undefinedMethod_generic_function_call() async {
// Invoking `.call` on a `Function` type works similarly to invoking it on
// `dynamic`--the invocation is accepted at compile time, and all type
// checking is deferred until runtime.
await assertErrorsInCode('''
f(Function f) {
f.call();
}
''', []);
}
test_undefinedMethod_ignoreTypePropagation() async {
await assertErrorsInCode(r'''
class A {}
@ -1586,14 +1431,6 @@ class C {
[StaticTypeWarningCode.UNDEFINED_METHOD]);
}
test_undefinedMethod_object_call() async {
await assertErrorsInCode('''
f(Object o) {
o.call();
}
''', [StaticTypeWarningCode.UNDEFINED_METHOD]);
}
test_undefinedMethod_ofNull() async {
// TODO(scheglov) Track https://github.com/dart-lang/sdk/issues/28430 to
// decide whether a warning should be reported here.
@ -1605,54 +1442,6 @@ main() {
''', [StaticTypeWarningCode.UNDEFINED_METHOD]);
}
test_undefinedMethod_private() async {
addNamedSource("/lib.dart", r'''
library lib;
class A {
_foo() {}
}''');
await assertErrorsInCode(r'''
import 'lib.dart';
class B extends A {
test() {
_foo();
}
}''', [StaticTypeWarningCode.UNDEFINED_METHOD]);
}
test_undefinedMethod_proxy_annotation_fakeProxy() async {
await assertErrorsInCode(r'''
library L;
class Fake {
const Fake();
}
const proxy = const Fake();
@proxy class PrefixProxy {}
main() {
new PrefixProxy().foo();
}''', [StaticTypeWarningCode.UNDEFINED_METHOD]);
}
test_undefinedMethod_typeLiteral_cascadeTarget() async {
await assertErrorsInCode('''
class T {
static void foo() {}
}
main() {
T..foo();
}
''', [StaticTypeWarningCode.UNDEFINED_METHOD]);
}
test_undefinedMethod_typeLiteral_conditionalAccess() async {
// When applied to a type literal, the conditional access operator '?.'
// cannot be used to access instance methods of Type.
await assertErrorsInCode('''
class A {}
f() => A?.toString();
''', [StaticTypeWarningCode.UNDEFINED_METHOD]);
}
test_undefinedMethodWithConstructor() async {
// TODO(brianwilkerson) We cannot verify in previewDart2 because 'C' could
// not be resolved.
@ -1766,18 +1555,6 @@ class B extends A {
''', [StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER]);
}
test_unqualifiedReferenceToNonLocalStaticMember_method() async {
await assertErrorsInCode(r'''
class A {
static void a() {}
}
class B extends A {
void b() {
a();
}
}''', [StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER]);
}
test_unqualifiedReferenceToNonLocalStaticMember_setter() async {
await assertErrorsInCode(r'''
class A {
@ -1948,26 +1725,6 @@ class StrongModeStaticTypeWarningCodeTest extends ResolverTestCase {
resetWith(options: options);
}
test_genericMethodWrongNumberOfTypeArguments() async {
Source source = addSource('''
f() {}
main() {
f<int>();
}
''');
TestAnalysisResult analysisResult = await computeAnalysisResult(source);
assertErrors(
source, [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD]);
for (AnalysisError error in analysisResult.errors) {
if (error.errorCode ==
StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS) {
expect(error.message,
formatList(error.errorCode.message, ['() → dynamic', 0, 1]));
}
}
verify([source]);
}
test_legalAsyncGeneratorReturnType_function_supertypeOfStream() async {
await assertErrorsInCode('''
import 'dart:async';

View file

@ -275,24 +275,6 @@ var v;''');
assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]);
}
test_ambiguousImport_withPrefix() async {
Source source = addSource(r'''
library test;
import 'lib1.dart' as p;
import 'lib2.dart' as p;
main() {
p.f();
}''');
addNamedSource("/lib1.dart", r'''
library lib1;
f() {}''');
addNamedSource("/lib2.dart", r'''
library lib2;
f() {}''');
await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]);
}
test_argumentTypeNotAssignable_ambiguousClassName() async {
// See dartbug.com/19624
Source source = addNamedSource("/lib1.dart", r'''
@ -1342,51 +1324,6 @@ void main() {
}
}
test_generalizedVoid_invocationOfVoidFieldError() async {
Source source = addSource(r'''
class Container<T>{
T value;
}
void main(Container<void> voidContainer) {
voidContainer.value();
}
''');
await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
}
test_generalizedVoid_invocationOfVoidLocalError() async {
Source source = addSource(r'''
void main() {
void x;
x();
}
''');
await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
}
test_generalizedVoid_invocationOfVoidResultError() async {
Source source = addSource(r'''
void main() {
main()();
}
''');
await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
}
test_generalizedVoid_invocationOfVoidToplevelError() async {
Source source = addSource(r'''
void x;
void main() {
x();
}
''');
await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
}
test_generalizedVoid_negateVoidValueError() async {
Source source = addSource(r'''
void main() {
@ -1534,28 +1471,6 @@ void main() {
assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
}
test_generalizedVoid_useOfVoidCallMethodError() async {
Source source = addSource(r'''
void main() {
void x;
x.toString();
}
''');
await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
}
test_generalizedVoid_useOfVoidCallMethodWithNullError() async {
Source source = addSource(r'''
void main() {
void x;
x?.toString();
}
''');
await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
}
test_generalizedVoid_useOfVoidCallSetterError() async {
Source source = addSource(r'''
void main() {
@ -1567,17 +1482,6 @@ void main() {
assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
}
test_generalizedVoid_useOfVoidCascadeError() async {
Source source = addSource(r'''
void main() {
void x;
x..toString();
}
''');
await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
}
test_generalizedVoid_useOfVoidCastsOk() async {
Source source = addSource(r'''
void use(dynamic x) { }
@ -3991,29 +3895,6 @@ f(var p) {
assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
}
test_undefinedStaticMethodOrGetter_method() async {
Source source = addSource(r'''
class C {}
f(var p) {
f(C.m());
}''');
await computeAnalysisResult(source);
assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
}
test_undefinedStaticMethodOrGetter_method_inSuperclass() async {
Source source = addSource(r'''
class S {
static m() {}
}
class C extends S {}
f(var p) {
f(C.m());
}''');
await computeAnalysisResult(source);
assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
}
test_undefinedStaticMethodOrGetter_setter_inSuperclass() async {
Source source = addSource(r'''
class S {

View file

@ -2927,17 +2927,6 @@ main() {
expectInitializerType('foo', 'int');
}
test_dynamicObjectMethod_toString() async {
String code = r'''
main() {
dynamic a = null;
var foo = a.toString();
}
''';
await resolveTestUnit(code);
expectInitializerType('foo', 'String');
}
test_futureOr_promotion1() async {
// Test that promotion from FutureOr<T> to T works for concrete types
String code = r'''
@ -3612,22 +3601,6 @@ class D extends C {
verify([source]);
}
test_genericMethod_partiallyAppliedErrorWithBound() async {
await resolveTestUnit(r'''
void f<X extends List, Y>() => null;
void test() {
f<int>();
}
''', noErrors: false);
assertErrors(testSource, [
// Make sure to catch both the missing parameter:
StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD,
// And the incorrect parameter:
StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
]);
}
test_genericMethod_propagatedType_promotion() async {
// Regression test for:
// https://github.com/dart-lang/sdk/issues/25340

View file

@ -3567,7 +3567,6 @@ main() {
assertType(aRef, 'int');
}
@failingTest
test_invalid_methodInvocation_simpleIdentifier() async {
addTestFile(r'''
int foo = 0;
@ -5388,8 +5387,8 @@ main(double computation(int p)) {
expect(target.staticType.toString(), '(int) → double');
SimpleIdentifier methodName = invocation.methodName;
expect(methodName.staticElement, same(parameter));
expect(methodName.staticType, parameter.type);
expect(methodName.staticElement, isNull);
expect(methodName.staticType, dynamicType);
}
test_methodInvocation_instanceMethod_forwardingStub() async {
@ -8737,69 +8736,6 @@ main() {
expect(identifier.staticType, isDynamicType);
}
test_unresolved_static_call() async {
addTestFile('''
class C {
static f() => C.g();
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var g = findNode.simple('g()');
assertElementNull(g);
assertTypeDynamic(g);
var invocation = g.parent as MethodInvocation;
assertTypeDynamic(invocation);
expect(invocation.staticInvokeType, isDynamicType);
}
test_unresolved_static_call_arguments() async {
addTestFile('''
int x;
class C {
static f() => C.g(x);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var x = findNode.simple('x)');
assertElement(x, findElement.topGet('x'));
assertType(x, 'int');
}
test_unresolved_static_call_same_name_as_type_param() async {
addTestFile('''
class C<T> {
static f() => C.T();
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var t = findNode.simple('T()');
assertElementNull(t);
assertTypeDynamic(t);
var invocation = t.parent as MethodInvocation;
assertTypeDynamic(invocation);
expect(invocation.staticInvokeType, isDynamicType);
}
test_unresolved_static_call_type_arguments() async {
addTestFile('''
class C {
static f() => C.g<int>();
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var intRef = findNode.simple('int>');
assertElement(intRef, intType.element);
assertType(intRef, 'int');
}
/// Assert that the [argument] is associated with the [expected]. If the
/// [argument] is a [NamedExpression], the name must be resolved to the
/// parameter.

View file

@ -55,28 +55,7 @@ class Baz extends Bar {
assertTestErrors([CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE]);
assertElement(
findNode.simple('foo; // ref'),
findElement.getter('foo', className: 'Foo'),
);
}
test_abstractSuperMemberReference_method_invocation() async {
addTestFile(r'''
abstract class A {
foo();
}
abstract class B extends A {
bar() {
super.foo(); // ref
}
foo() {} // does not matter
}
''');
await resolveTestFile();
assertTestErrors([CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE]);
assertElement(
findNode.simple('foo(); // ref'),
findElement.method('foo', of: 'A'),
findElement.getter('foo', of: 'Foo'),
);
}
@ -123,31 +102,6 @@ class C extends A with B {
);
}
test_abstractSuperMemberReference_OK_mixinHasConcrete2_method() async {
addTestFile('''
class A {
}
class M {
void foo() {}
}
class B = A with M;
class C extends B {
void bar() {
super.foo(); // ref
}
}
''');
await resolveTestFile();
assertNoTestErrors();
assertElement(
findNode.simple('foo(); // ref'),
findElement.method('foo', of: 'M'),
);
}
test_abstractSuperMemberReference_OK_superHasConcrete_mixinHasAbstract_method() async {
addTestFile('''
class A {
@ -190,31 +144,7 @@ class C extends B {
assertNoTestErrors();
assertElement(
findNode.simple('foo; // ref'),
findElement.getter('foo', className: 'A'),
);
}
test_abstractSuperMemberReference_OK_superSuperHasConcrete_method() async {
addTestFile('''
abstract class A {
void foo() {}
}
abstract class B extends A {
void foo();
}
class C extends B {
void bar() {
super.foo(); // ref
}
}
''');
await resolveTestFile();
assertNoTestErrors();
assertElement(
findNode.simple('foo(); // ref'),
findElement.method('foo', of: 'A'),
findElement.getter('foo', of: 'A'),
);
}

View file

@ -108,9 +108,9 @@ class FindElement {
fail('Not found generic type alias: $name');
}
PropertyAccessorElement getter(String name, {String className}) {
PropertyAccessorElement getter(String name, {String of}) {
for (var class_ in unitElement.types) {
if (className != null && class_.name != className) {
if (of != null && class_.name != of) {
continue;
}
for (var accessor in class_.accessors) {
@ -143,6 +143,25 @@ class FindElement {
return class_(name).type;
}
FunctionElement localFunction(String name) {
FunctionElement result;
unit.accept(new FunctionAstVisitor(
functionDeclarationStatement: (node) {
var element = node.functionDeclaration.declaredElement;
if (element is FunctionElement) {
if (result != null) {
throw new StateError('Local function name $name is not unique.');
}
result = element;
}
},
));
if (result == null) {
fail('Not found local function: $name');
}
return result;
}
LocalVariableElement localVar(String name) {
LocalVariableElement result;
unit.accept(new FunctionAstVisitor(

View file

@ -7,10 +7,23 @@ import 'package:analyzer/dart/ast/visitor.dart';
/// [RecursiveAstVisitor] that delegates visit methods to functions.
class FunctionAstVisitor extends RecursiveAstVisitor<void> {
final void Function(FunctionDeclarationStatement)
functionDeclarationStatement;
final void Function(SimpleIdentifier) simpleIdentifier;
final void Function(VariableDeclaration) variableDeclaration;
FunctionAstVisitor({this.simpleIdentifier, this.variableDeclaration});
FunctionAstVisitor(
{this.functionDeclarationStatement,
this.simpleIdentifier,
this.variableDeclaration});
@override
void visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
if (functionDeclarationStatement != null) {
functionDeclarationStatement(node);
}
super.visitFunctionDeclarationStatement(node);
}
@override
void visitSimpleIdentifier(SimpleIdentifier node) {

File diff suppressed because it is too large Load diff

View file

@ -61,6 +61,16 @@ abstract class ResolutionTest implements ResourceProviderMixin {
newFile('/test/lib/test.dart', content: content);
}
/// Assert that the given [identifier] is a reference to a class, in the
/// form that is not a separate expression, e.g. in a static method
/// invocation like `C.staticMethod()`, or a type annotation `C c = null`.
void assertClassRef(
SimpleIdentifier identifier, ClassElement expectedElement) {
assertElement(identifier, expectedElement);
// TODO(scheglov) Enforce this.
// assertTypeNull(identifier);
}
void assertConstructorElement(
ConstructorElement expected, ConstructorElement actual) {
if (expected is ConstructorMember && actual is ConstructorMember) {
@ -168,6 +178,11 @@ abstract class ResolutionTest implements ResourceProviderMixin {
assertType(ref, type);
}
void assertImportPrefix(SimpleIdentifier identifier, PrefixElement element) {
assertElement(identifier, element);
assertTypeNull(identifier);
}
void assertInstanceCreation(InstanceCreationExpression creation,
ClassElement expectedClassElement, String expectedType,
{String constructorName,
@ -232,10 +247,51 @@ abstract class ResolutionTest implements ResourceProviderMixin {
expect(actual.baseElement, same(expectedBase));
}
void assertMethodInvocation(MethodInvocation invocation,
Element expectedElement, String expectedInvokeType,
{String expectedNameType, String expectedType}) {
// TODO(scheglov) Check for Member.
var element = invocation.methodName.staticElement;
if (element is Member) {
element = (element as Member).baseElement;
expect(element, same(expectedElement));
} else {
assertElement(invocation.methodName, expectedElement);
}
// TODO(scheglov) Should we enforce this?
// if (expectedNameType == null) {
// if (expectedElement is ExecutableElement) {
// expectedNameType = expectedElement.type.displayName;
// } else if (expectedElement is VariableElement) {
// expectedNameType = expectedElement.type.displayName;
// }
// }
// assertType(invocation.methodName, expectedNameType);
assertInvokeType(invocation, expectedInvokeType);
expectedType ??= _extractReturnType(expectedInvokeType);
assertType(invocation, expectedType);
}
void assertNamedParameterRef(String search, String name) {
var ref = findNode.simple(search);
assertElement(ref, findElement.parameter(name));
assertTypeNull(ref);
}
void assertNoTestErrors() {
assertTestErrors(const <ErrorCode>[]);
}
void assertSuperExpression(SuperExpression superExpression) {
// TODO(scheglov) I think `super` does not have type itself.
// It is just a signal to look for implemented method in the supertype.
// With mixins there isn't a type anyway.
// assertTypeNull(superExpression);
}
void assertTestErrors(List<ErrorCode> expected) {
assertErrors(result.errors, expected);
}
@ -334,6 +390,12 @@ abstract class ResolutionTest implements ResourceProviderMixin {
}
return element;
}
static String _extractReturnType(String invokeType) {
int arrowIndex = invokeType.indexOf('');
expect(arrowIndex, isNonNegative);
return invokeType.substring(arrowIndex + 1).trim();
}
}
class TestAnalysisResult {

View file

@ -6,7 +6,6 @@ import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'assignment_test.dart' as assignment_test;
import 'class_test.dart' as class_test;
import 'optional_const_test.dart' as optional_const_test;
import 'enum_test.dart' as enum_test;
import 'for_in_test.dart' as for_in_test;
import 'generic_type_alias_test.dart' as generic_type_alias_test;
@ -16,7 +15,9 @@ import 'instance_member_inference_class_test.dart'
as instance_member_inference_class_test;
import 'instance_member_inference_mixin_test.dart'
as instance_member_inference_mixin_test;
import 'method_invocation_test.dart' as method_invocation_test;
import 'mixin_test.dart' as mixin_test;
import 'optional_const_test.dart' as optional_const_test;
import 'top_type_inference_test.dart' as top_type_inference_test;
main() {
@ -30,6 +31,7 @@ main() {
instance_creation_test.main();
instance_member_inference_class_test.main();
instance_member_inference_mixin_test.main();
method_invocation_test.main();
mixin_test.main();
optional_const_test.main();
top_type_inference_test.main();

View file

@ -4483,24 +4483,10 @@ class InferredTypeTest_Driver extends AbstractStrongTest
.test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr1();
}
@failingTest
@override
test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr2() async {
await super
.test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr2();
}
@failingTest
@override
test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1() {
return super
.test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1();
}
@failingTest
@override
test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr2() async {
await super
.test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr2();
}
}

View file

@ -11,8 +11,6 @@ accessor_conflict_import2_test: CompileTimeError # Issue 25626
accessor_conflict_import_prefixed2_test: CompileTimeError # Issue 25626
accessor_conflict_import_prefixed_test: CompileTimeError # Issue 25626
accessor_conflict_import_test: CompileTimeError # Issue 25626
additional_interface_adds_optional_args_test: CompileTimeError # Issue #30568
bug32372_test: Skip
cascaded_forwarding_stubs_test: CompileTimeError # Issue 34329
config_import_corelib_test: CompileTimeError, StaticWarning, OK # failing-by-design: Will never pass, see Issue #34332
conflicting_generic_interfaces_hierarchy_loop_infinite_test: Skip # Issue #34333 (loops forever)
@ -77,7 +75,6 @@ issue34498_test: MissingCompileTimeError # Issue 34500
large_class_declaration_test: Slow, Pass
malformed2_test: Pass, MissingCompileTimeError # Flaky: issue 31056.
mixin_declaration/mixin_declaration_factory_test/02: Crash # Issue 34809
mixin_declaration/mixin_declaration_invalid_superinvocation_test/10: CompileTimeError # Issue 30552
mixin_method_override_test/01: MissingCompileTimeError
mixin_of_mixin_test: Skip
mixin_super_2_test: Skip
@ -105,7 +102,6 @@ mixin_type_parameter_inference_error_test: Skip
mixin_type_parameter_inference_previous_mixin_test: Skip
mixin_type_parameter_inference_test: Skip
mock_writable_final_private_field_test: CompileTimeError # failing-by-design, see Issue #34377
multiple_interface_inheritance_test: CompileTimeError # Issue 30552
nested_generic_closure_test: CompileTimeError # Issue #28515
no_main_test/01: Fail # failing-by-design, the analyzer has no restriction that a library include a main function.
no_such_constructor2_test: StaticWarning
@ -122,7 +118,6 @@ regress_27617_test/1: MissingCompileTimeError
regress_29025_test: CompileTimeError # Issue 29081
regress_29405_test: CompileTimeError # Issue 29421
regress_29784_test/02: MissingCompileTimeError # Issue 29784
regress_30121_test: CompileTimeError # Issue 31087
regress_30339_test: CompileTimeError
regress_33479_test/01: Crash # Issue #33479
setter3_test/01: CompileTimeError # Invalid test, see https://github.com/dart-lang/sdk/issues/33837

View file

@ -10,7 +10,6 @@ accessor_conflict_import2_test: CompileTimeError # Issue 25626
accessor_conflict_import_prefixed2_test: CompileTimeError # Issue 25626
accessor_conflict_import_prefixed_test: CompileTimeError # Issue 25626
accessor_conflict_import_test: CompileTimeError # Issue 25626
additional_interface_adds_optional_args_test: CompileTimeError # Issue #30568
assertion_test: RuntimeError # Issue 30326; Expect.equals(expected: <1>, actual: <0>) fails.
async_star_test/01: RuntimeError
async_star_test/03: RuntimeError
@ -89,7 +88,7 @@ invalid_returns/sync_invalid_return_02_test/none: CompileTimeError # issue #3431
invalid_returns/sync_invalid_return_03_test/none: CompileTimeError # issue #34319
invalid_returns/sync_invalid_return_04_test/none: CompileTimeError # issue #34319
invalid_returns/sync_invalid_return_05_test/none: CompileTimeError # issue #34319
issue31596_implement_covariant_test: CompileTimeError
issue31596_implement_covariant_test: CompileTimeError # Issue #31596
issue31596_override_test/01: CompileTimeError
issue31596_override_test/02: CompileTimeError
issue31596_override_test/03: CompileTimeError
@ -152,7 +151,6 @@ mixin_declaration/mixin_declaration_inference_valid_C11_test: CompileTimeError #
mixin_declaration/mixin_declaration_inference_valid_C12_test: CompileTimeError # Issue #34164
mixin_declaration/mixin_declaration_inference_valid_C13_test: CompileTimeError # Issue #34164
mixin_declaration/mixin_declaration_inference_valid_mixin_applications_test: CompileTimeError # https://github.com/dart-lang/sdk/issues/34164
mixin_declaration/mixin_declaration_invalid_superinvocation_test/10: CompileTimeError # Analyzer chooses wrong(?) super method.
mixin_method_override_test/01: MissingCompileTimeError
mixin_of_mixin_test: Skip
mixin_super_2_test: Skip
@ -184,7 +182,6 @@ mixin_type_parameter_inference_test/07: MissingCompileTimeError
mixin_type_parameter_inference_test/08: RuntimeError
mixin_type_parameter_inference_test/09: RuntimeError
mock_writable_final_private_field_test: CompileTimeError # Issue 30848
multiple_interface_inheritance_test: CompileTimeError # Issue 30552
nested_generic_closure_test: CompileTimeError
override_inheritance_field_test/42: CompileTimeError
part_of_multiple_libs_test/01: MissingCompileTimeError
@ -199,7 +196,6 @@ regress_29025_test: CompileTimeError # Issue 29081
regress_29405_test: CompileTimeError # Issue 29421
regress_29784_test/02: Crash # assert initializers not implemented
regress_29784_test/02: MissingCompileTimeError
regress_30121_test: CompileTimeError # Issue 31087
regress_30339_test: CompileTimeError # As expected. Should we make this a multi test?
regress_33479_test/01: Crash # Issue #33479
setter3_test/01: CompileTimeError # Invalid test, see https://github.com/dart-lang/sdk/issues/33837