mirror of
https://github.com/dart-lang/sdk
synced 2024-09-21 03:13:14 +00:00
Introduce ParameterStructure
This is a substructure of FunctionType and FunctionSignature which doesn't contain type information. This allows us to let FunctionEntity have a ParameterStructure (which makes sense for both K and J elements) but not require FunctionEntity to have a type (which K elements have but J elements might not). R=efortuna@google.com Review-Url: https://codereview.chromium.org/2809603002 .
This commit is contained in:
parent
4d3c3b9305
commit
21a3455bd6
|
@ -867,7 +867,7 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
|||
|
||||
target.computeType(resolution);
|
||||
|
||||
if (!callStructure.signatureApplies(target.type)) {
|
||||
if (!callStructure.signatureApplies(target.parameterStructure)) {
|
||||
String name = Elements.constructorNameForDiagnostics(
|
||||
target.enclosingClass.name, target.name);
|
||||
reporter.reportErrorMessage(node,
|
||||
|
@ -1114,7 +1114,7 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
|||
}
|
||||
assert(invariant(
|
||||
node,
|
||||
callStructure.signatureApplies(constructor.type) ||
|
||||
callStructure.signatureApplies(constructor.parameterStructure) ||
|
||||
compiler.compilationFailed,
|
||||
message: "Call structure $callStructure does not apply to constructor "
|
||||
"$constructor."));
|
||||
|
|
|
@ -9,6 +9,7 @@ library elements.common;
|
|||
import '../common/names.dart' show Identifiers, Names, Uris;
|
||||
import '../common_elements.dart' show CommonElements;
|
||||
import '../util/util.dart' show Link;
|
||||
import 'entities.dart';
|
||||
import 'elements.dart';
|
||||
import 'resolution_types.dart'
|
||||
show ResolutionDartType, ResolutionInterfaceType, ResolutionFunctionType;
|
||||
|
@ -498,6 +499,8 @@ abstract class ClassElementCommon implements ClassElement {
|
|||
}
|
||||
|
||||
abstract class FunctionSignatureCommon implements FunctionSignature {
|
||||
ParameterStructure _parameterStructure;
|
||||
|
||||
ResolutionDartType get returnType => type.returnType;
|
||||
|
||||
void forEachRequiredParameter(void function(Element parameter)) {
|
||||
|
@ -555,6 +558,24 @@ abstract class FunctionSignatureCommon implements FunctionSignature {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ParameterStructure get parameterStructure {
|
||||
if (_parameterStructure == null) {
|
||||
int requiredParameters = requiredParameterCount;
|
||||
int positionalParameters;
|
||||
List<String> namedParameters;
|
||||
if (optionalParametersAreNamed) {
|
||||
namedParameters = type.namedParameters;
|
||||
positionalParameters = requiredParameters;
|
||||
} else {
|
||||
namedParameters = const <String>[];
|
||||
positionalParameters = requiredParameters + optionalParameterCount;
|
||||
}
|
||||
_parameterStructure = new ParameterStructure(
|
||||
requiredParameters, positionalParameters, namedParameters);
|
||||
}
|
||||
return _parameterStructure;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class MixinApplicationElementCommon
|
||||
|
|
|
@ -927,7 +927,7 @@ class Elements {
|
|||
// TODO(ngeoffray): Should the resolver do it instead?
|
||||
CallStructure callStructure = new CallStructure(
|
||||
signature.parameterCount, signature.type.namedParameters);
|
||||
if (!callStructure.signatureApplies(signature.type)) {
|
||||
if (!callStructure.signatureApplies(signature.parameterStructure)) {
|
||||
return false;
|
||||
}
|
||||
list.addAll(makeArgumentsList<T>(callStructure, nodes, callee,
|
||||
|
@ -1288,6 +1288,8 @@ abstract class FunctionSignature {
|
|||
void orderedForEachParameter(void function(FormalElement parameter));
|
||||
|
||||
bool isCompatibleWith(FunctionSignature constructorSignature);
|
||||
|
||||
ParameterStructure get parameterStructure;
|
||||
}
|
||||
|
||||
/// A top level, static or instance method, constructor, local function, or
|
||||
|
@ -1317,6 +1319,9 @@ abstract class FunctionElement extends Element
|
|||
|
||||
/// `true` if this function is external.
|
||||
bool get isExternal;
|
||||
|
||||
/// The structure of the function parameters.
|
||||
ParameterStructure get parameterStructure;
|
||||
}
|
||||
|
||||
/// A getter or setter.
|
||||
|
|
|
@ -119,6 +119,9 @@ abstract class FunctionEntity extends MemberEntity {
|
|||
/// Whether this function is external, i.e. the body is not defined in terms
|
||||
/// of Dart code.
|
||||
bool get isExternal;
|
||||
|
||||
/// The structure of the function parameters.
|
||||
ParameterStructure get parameterStructure;
|
||||
}
|
||||
|
||||
/// Stripped down super interface for constructor like entities.
|
||||
|
@ -158,3 +161,26 @@ abstract class Local extends Entity {
|
|||
/// defined.
|
||||
MemberEntity get memberContext;
|
||||
}
|
||||
|
||||
/// The structure of function parameters.
|
||||
class ParameterStructure {
|
||||
/// The number of required (positional) parameters.
|
||||
final int requiredParameters;
|
||||
|
||||
/// The number of positional parameters.
|
||||
final int positionalParameters;
|
||||
|
||||
/// The named parameters sorted alphabetically.
|
||||
final List<String> namedParameters;
|
||||
|
||||
const ParameterStructure(
|
||||
this.requiredParameters, this.positionalParameters, this.namedParameters);
|
||||
|
||||
const ParameterStructure.getter() : this(0, 0, const <String>[]);
|
||||
|
||||
const ParameterStructure.setter() : this(1, 1, const <String>[]);
|
||||
|
||||
/// The number of optional parameters (positional or named).
|
||||
int get optionalParameters =>
|
||||
positionalParameters - requiredParameters + namedParameters.length;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import '../tree/tree.dart';
|
|||
import '../util/util.dart';
|
||||
import 'common.dart';
|
||||
import 'elements.dart';
|
||||
import 'entities.dart';
|
||||
import 'resolution_types.dart';
|
||||
import 'visitor.dart' show ElementVisitor;
|
||||
|
||||
|
@ -245,6 +246,7 @@ class ErroneousElementX extends ElementX
|
|||
get type => unsupported();
|
||||
get cachedNode => unsupported();
|
||||
get functionSignature => unsupported();
|
||||
get parameterStructure => unsupported();
|
||||
get parameters => unsupported();
|
||||
get patch => null;
|
||||
get origin => this;
|
||||
|
@ -433,6 +435,11 @@ class ErroneousConstructorElementX extends ErroneousElementX
|
|||
throw new UnsupportedError("functionSignature=");
|
||||
}
|
||||
|
||||
@override
|
||||
get parameterStructure {
|
||||
throw new UnsupportedError("parameterStructure");
|
||||
}
|
||||
|
||||
@override
|
||||
get nestedClosures {
|
||||
throw new UnsupportedError("nestedClosures");
|
||||
|
@ -2015,6 +2022,9 @@ abstract class BaseFunctionElementX extends ElementX
|
|||
return isClassMember && !isConstructor && !isStatic;
|
||||
}
|
||||
|
||||
ParameterStructure get parameterStructure =>
|
||||
functionSignature.parameterStructure;
|
||||
|
||||
bool get hasFunctionSignature => _functionSignatureCache != null;
|
||||
|
||||
void _computeSignature(Resolution resolution) {
|
||||
|
|
|
@ -2324,7 +2324,8 @@ class ElementGraphBuilder extends ast.Visitor<TypeInformation>
|
|||
// In erroneous code the number of arguments in the selector might not
|
||||
// match the function element.
|
||||
// TODO(polux): return nonNullEmpty and check it doesn'TypeInformation break anything
|
||||
if (target.isMalformed || !callStructure.signatureApplies(target.type)) {
|
||||
if (target.isMalformed ||
|
||||
!callStructure.signatureApplies(target.parameterStructure)) {
|
||||
return types.dynamicType;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,8 @@ class ClosureTracerVisitor extends TracerVisitor {
|
|||
Selector selector = info.selector;
|
||||
TypeMask mask = info.mask;
|
||||
tracedElements.forEach((FunctionElement functionElement) {
|
||||
if (!selector.callStructure.signatureApplies(functionElement.type)) {
|
||||
if (!selector.callStructure
|
||||
.signatureApplies(functionElement.parameterStructure)) {
|
||||
return;
|
||||
}
|
||||
inferrer.updateParameterAssignments(
|
||||
|
|
|
@ -89,9 +89,11 @@ abstract class KMember implements MemberEntity {
|
|||
}
|
||||
|
||||
abstract class KFunction extends KMember implements FunctionEntity {
|
||||
final ParameterStructure parameterStructure;
|
||||
final bool isExternal;
|
||||
|
||||
KFunction(int memberIndex, KLibrary library, KClass enclosingClass, Name name,
|
||||
this.parameterStructure,
|
||||
{bool isStatic: false, this.isExternal: false})
|
||||
: super(memberIndex, library, enclosingClass, name, isStatic: isStatic);
|
||||
}
|
||||
|
@ -100,8 +102,9 @@ abstract class KConstructor extends KFunction implements ConstructorEntity {
|
|||
final bool isConst;
|
||||
|
||||
KConstructor(int memberIndex, KClass enclosingClass, Name name,
|
||||
{bool isExternal, this.isConst})
|
||||
ParameterStructure parameterStructure, {bool isExternal, this.isConst})
|
||||
: super(memberIndex, enclosingClass.library, enclosingClass, name,
|
||||
parameterStructure,
|
||||
isExternal: isExternal);
|
||||
|
||||
@override
|
||||
|
@ -121,8 +124,8 @@ abstract class KConstructor extends KFunction implements ConstructorEntity {
|
|||
|
||||
class KGenerativeConstructor extends KConstructor {
|
||||
KGenerativeConstructor(int constructorIndex, KClass enclosingClass, Name name,
|
||||
{bool isExternal, bool isConst})
|
||||
: super(constructorIndex, enclosingClass, name,
|
||||
ParameterStructure parameterStructure, {bool isExternal, bool isConst})
|
||||
: super(constructorIndex, enclosingClass, name, parameterStructure,
|
||||
isExternal: isExternal, isConst: isConst);
|
||||
|
||||
@override
|
||||
|
@ -134,8 +137,8 @@ class KGenerativeConstructor extends KConstructor {
|
|||
|
||||
class KFactoryConstructor extends KConstructor {
|
||||
KFactoryConstructor(int memberIndex, KClass enclosingClass, Name name,
|
||||
{bool isExternal, bool isConst})
|
||||
: super(memberIndex, enclosingClass, name,
|
||||
ParameterStructure parameterStructure, {bool isExternal, bool isConst})
|
||||
: super(memberIndex, enclosingClass, name, parameterStructure,
|
||||
isExternal: isExternal, isConst: isConst);
|
||||
|
||||
@override
|
||||
|
@ -149,8 +152,9 @@ class KMethod extends KFunction {
|
|||
final bool isAbstract;
|
||||
|
||||
KMethod(int memberIndex, KLibrary library, KClass enclosingClass, Name name,
|
||||
ParameterStructure parameterStructure,
|
||||
{bool isStatic, bool isExternal, this.isAbstract})
|
||||
: super(memberIndex, library, enclosingClass, name,
|
||||
: super(memberIndex, library, enclosingClass, name, parameterStructure,
|
||||
isStatic: isStatic, isExternal: isExternal);
|
||||
|
||||
@override
|
||||
|
@ -165,6 +169,7 @@ class KGetter extends KFunction {
|
|||
KGetter(int memberIndex, KLibrary library, KClass enclosingClass, Name name,
|
||||
{bool isStatic, bool isExternal, this.isAbstract})
|
||||
: super(memberIndex, library, enclosingClass, name,
|
||||
const ParameterStructure.getter(),
|
||||
isStatic: isStatic, isExternal: isExternal);
|
||||
|
||||
@override
|
||||
|
@ -179,6 +184,7 @@ class KSetter extends KFunction {
|
|||
KSetter(int memberIndex, KLibrary library, KClass enclosingClass, Name name,
|
||||
{bool isStatic, bool isExternal, this.isAbstract})
|
||||
: super(memberIndex, library, enclosingClass, name,
|
||||
const ParameterStructure.setter(),
|
||||
isStatic: isStatic, isExternal: isExternal);
|
||||
|
||||
@override
|
||||
|
|
|
@ -193,6 +193,16 @@ class KernelWorldBuilder extends KernelElementAdapterMixin {
|
|||
});
|
||||
}
|
||||
|
||||
ParameterStructure _getParameterStructure(ir.FunctionNode node) {
|
||||
// TODO(johnniwinther): Cache the computed function type.
|
||||
int requiredParameters = node.requiredParameterCount;
|
||||
int positionalParameters = node.positionalParameters.length;
|
||||
List<String> namedParameters =
|
||||
node.namedParameters.map((p) => p.name).toList()..sort();
|
||||
return new ParameterStructure(
|
||||
requiredParameters, positionalParameters, namedParameters);
|
||||
}
|
||||
|
||||
KConstructor _getConstructor(ir.Member node) {
|
||||
return _constructorMap.putIfAbsent(node, () {
|
||||
int memberIndex = _memberList.length;
|
||||
|
@ -200,12 +210,14 @@ class KernelWorldBuilder extends KernelElementAdapterMixin {
|
|||
KClass enclosingClass = _getClass(node.enclosingClass);
|
||||
Name name = getName(node.name);
|
||||
bool isExternal = node.isExternal;
|
||||
|
||||
if (node is ir.Constructor) {
|
||||
constructor = new KGenerativeConstructor(
|
||||
memberIndex, enclosingClass, name,
|
||||
constructor = new KGenerativeConstructor(memberIndex, enclosingClass,
|
||||
name, _getParameterStructure(node.function),
|
||||
isExternal: isExternal, isConst: node.isConst);
|
||||
} else if (node is ir.Procedure) {
|
||||
constructor = new KFactoryConstructor(memberIndex, enclosingClass, name,
|
||||
_getParameterStructure(node.function),
|
||||
isExternal: isExternal, isConst: node.isConst);
|
||||
} else {
|
||||
// TODO(johnniwinther): Convert `node.location` to a [SourceSpan].
|
||||
|
@ -245,6 +257,7 @@ class KernelWorldBuilder extends KernelElementAdapterMixin {
|
|||
case ir.ProcedureKind.Method:
|
||||
case ir.ProcedureKind.Operator:
|
||||
function = new KMethod(memberIndex, library, enclosingClass, name,
|
||||
_getParameterStructure(node.function),
|
||||
isStatic: isStatic,
|
||||
isExternal: isExternal,
|
||||
isAbstract: isAbstract);
|
||||
|
|
|
@ -202,7 +202,8 @@ class ClassResolverVisitor extends TypeDefinitionVisitor {
|
|||
} else {
|
||||
ConstructorElement superConstructor = superMember;
|
||||
superConstructor.computeType(resolution);
|
||||
if (!CallStructure.NO_ARGS.signatureApplies(superConstructor.type)) {
|
||||
if (!CallStructure.NO_ARGS
|
||||
.signatureApplies(superConstructor.parameterStructure)) {
|
||||
MessageKind kind = MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT;
|
||||
reporter.reportErrorMessage(node, kind);
|
||||
superMember = new ErroneousElementX(kind, {}, '', element);
|
||||
|
|
|
@ -275,7 +275,8 @@ class InitializerResolver {
|
|||
reportAndCreateErroneousConstructor(node, constructorName, kind, {});
|
||||
} else {
|
||||
lookedupConstructor.computeType(visitor.resolution);
|
||||
if (!callStructure.signatureApplies(lookedupConstructor.type)) {
|
||||
if (!callStructure
|
||||
.signatureApplies(lookedupConstructor.parameterStructure)) {
|
||||
MessageKind kind = isImplicitSuperCall
|
||||
? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT
|
||||
: MessageKind.NO_MATCHING_CONSTRUCTOR;
|
||||
|
|
|
@ -1569,7 +1569,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
|||
case AccessKind.SUPER_METHOD:
|
||||
MethodElement superMethod = semantics.element;
|
||||
superMethod.computeType(resolution);
|
||||
if (!callStructure.signatureApplies(superMethod.type)) {
|
||||
if (!callStructure.signatureApplies(superMethod.parameterStructure)) {
|
||||
registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
|
||||
registry.registerDynamicUse(new DynamicUse(selector, null));
|
||||
registry.registerFeature(Feature.SUPER_NO_SUCH_METHOD);
|
||||
|
@ -2503,7 +2503,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
|||
case AccessKind.LOCAL_FUNCTION:
|
||||
LocalFunctionElementX function = semantics.element;
|
||||
function.computeType(resolution);
|
||||
if (!callStructure.signatureApplies(function.type)) {
|
||||
if (!callStructure.signatureApplies(function.parameterStructure)) {
|
||||
registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
|
||||
registry.registerDynamicUse(new DynamicUse(selector, null));
|
||||
isIncompatibleInvoke = true;
|
||||
|
@ -2672,7 +2672,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
|||
case AccessKind.TOPLEVEL_METHOD:
|
||||
MethodElement method = semantics.element;
|
||||
method.computeType(resolution);
|
||||
if (!callStructure.signatureApplies(method.type)) {
|
||||
if (!callStructure.signatureApplies(method.parameterStructure)) {
|
||||
registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
|
||||
registry.registerDynamicUse(new DynamicUse(selector, null));
|
||||
isIncompatibleInvoke = true;
|
||||
|
@ -3859,7 +3859,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
|||
case ConstructorResultKind.GENERATIVE:
|
||||
// Ensure that the signature of [constructor] has been computed.
|
||||
constructor.computeType(resolution);
|
||||
if (!callStructure.signatureApplies(constructor.type)) {
|
||||
if (!callStructure.signatureApplies(constructor.parameterStructure)) {
|
||||
isInvalid = true;
|
||||
kind = ConstructorAccessKind.INCOMPATIBLE;
|
||||
registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
|
||||
|
@ -3870,7 +3870,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
|||
case ConstructorResultKind.FACTORY:
|
||||
// Ensure that the signature of [constructor] has been computed.
|
||||
constructor.computeType(resolution);
|
||||
if (!callStructure.signatureApplies(constructor.type)) {
|
||||
if (!callStructure.signatureApplies(constructor.parameterStructure)) {
|
||||
// The effective target might still be valid(!) so the is not an
|
||||
// invalid case in itself. For instance
|
||||
//
|
||||
|
|
|
@ -2116,7 +2116,8 @@ class NewInvokeStructure<R, A> extends NewStructure<R, A> {
|
|||
ConstructorElement effectiveTarget = constructor.effectiveTarget;
|
||||
ResolutionInterfaceType effectiveTargetType =
|
||||
constructor.computeEffectiveTargetType(semantics.type);
|
||||
if (callStructure.signatureApplies(effectiveTarget.type)) {
|
||||
if (callStructure
|
||||
.signatureApplies(effectiveTarget.parameterStructure)) {
|
||||
return visitor.visitRedirectingFactoryConstructorInvoke(
|
||||
node,
|
||||
semantics.element,
|
||||
|
@ -2136,7 +2137,7 @@ class NewInvokeStructure<R, A> extends NewStructure<R, A> {
|
|||
arg);
|
||||
}
|
||||
}
|
||||
if (callStructure.signatureApplies(constructor.type)) {
|
||||
if (callStructure.signatureApplies(constructor.parameterStructure)) {
|
||||
return visitor.visitFactoryConstructorInvoke(node, constructor,
|
||||
semantics.type, node.send.argumentsNode, callStructure, arg);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import '../constants/expressions.dart';
|
|||
import '../elements/resolution_types.dart';
|
||||
import '../elements/common.dart';
|
||||
import '../elements/elements.dart';
|
||||
import '../elements/entities.dart';
|
||||
import '../elements/modelx.dart' show FunctionSignatureX;
|
||||
import '../elements/visitor.dart';
|
||||
import '../io/source_file.dart';
|
||||
|
@ -850,6 +851,9 @@ abstract class ParametersMixin
|
|||
}
|
||||
return _parameters;
|
||||
}
|
||||
|
||||
ParameterStructure get parameterStructure =>
|
||||
functionSignature.parameterStructure;
|
||||
}
|
||||
|
||||
abstract class FunctionTypedElementMixin
|
||||
|
@ -1472,6 +1476,11 @@ class ForwardingConstructorElementZ extends ElementZ
|
|||
return definingConstructor.functionSignature;
|
||||
}
|
||||
|
||||
@override
|
||||
ParameterStructure get parameterStructure {
|
||||
return functionSignature.parameterStructure;
|
||||
}
|
||||
|
||||
@override
|
||||
bool get hasFunctionSignature {
|
||||
return _unsupported('hasFunctionSignature');
|
||||
|
|
|
@ -3374,7 +3374,8 @@ class SsaBuilder extends ast.Visitor
|
|||
// calling [makeStaticArgumentList].
|
||||
constructorImplementation = constructor.implementation;
|
||||
if (constructorImplementation.isMalformed ||
|
||||
!callStructure.signatureApplies(constructorImplementation.type)) {
|
||||
!callStructure
|
||||
.signatureApplies(constructorImplementation.parameterStructure)) {
|
||||
generateWrongArgumentCountError(send, constructor, send.arguments);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
library dart2js.call_structure;
|
||||
|
||||
import '../common/names.dart' show Names;
|
||||
import '../elements/types.dart' show FunctionType;
|
||||
import '../elements/entities.dart' show ParameterStructure;
|
||||
import '../util/util.dart';
|
||||
import 'selector.dart' show Selector;
|
||||
|
||||
|
@ -74,15 +74,14 @@ class CallStructure {
|
|||
return match(other);
|
||||
}
|
||||
|
||||
bool signatureApplies(FunctionType type) {
|
||||
int requiredParameterCount = type.parameterTypes.length;
|
||||
int optionalParameterCount =
|
||||
type.optionalParameterTypes.length + type.namedParameters.length;
|
||||
bool signatureApplies(ParameterStructure parameters) {
|
||||
int requiredParameterCount = parameters.requiredParameters;
|
||||
int optionalParameterCount = parameters.optionalParameters;
|
||||
int parameterCount = requiredParameterCount + optionalParameterCount;
|
||||
if (argumentCount > parameterCount) return false;
|
||||
if (positionalArgumentCount < requiredParameterCount) return false;
|
||||
|
||||
if (type.namedParameters.isEmpty) {
|
||||
if (parameters.namedParameters.isEmpty) {
|
||||
// We have already checked that the number of arguments are
|
||||
// not greater than the number of parameters. Therefore the
|
||||
// number of positional arguments are not greater than the
|
||||
|
@ -95,7 +94,7 @@ class CallStructure {
|
|||
if (namedArgumentCount > optionalParameterCount) return false;
|
||||
|
||||
int nameIndex = 0;
|
||||
List<String> namedParameters = type.namedParameters;
|
||||
List<String> namedParameters = parameters.namedParameters;
|
||||
for (String name in getOrderedNamedArguments()) {
|
||||
bool found = false;
|
||||
// Note: we start at the existing index because arguments are sorted.
|
||||
|
|
|
@ -243,8 +243,7 @@ class Selector {
|
|||
}
|
||||
|
||||
bool signatureApplies(MethodElement function) {
|
||||
if (Elements.isUnresolved(function)) return false;
|
||||
return callStructure.signatureApplies(function.type);
|
||||
return callStructure.signatureApplies(function.parameterStructure);
|
||||
}
|
||||
|
||||
bool applies(MemberElement element) {
|
||||
|
|
Loading…
Reference in a new issue