mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 05:36:49 +00:00
8009c39d61
Change-Id: I905a81faead20b4339309521018291d0b4d90dda Cq-Include-Trybots: luci.dart.try:dart2wasm-linux-x64-d8-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/250786 Reviewed-by: Aske Simon Christensen <askesc@google.com> Commit-Queue: Joshua Litt <joshualitt@google.com>
145 lines
5.3 KiB
Dart
145 lines
5.3 KiB
Dart
// Copyright (c) 2012, 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.
|
|
|
|
part of dart.core;
|
|
|
|
/// Representation of the invocation of a member on an object.
|
|
///
|
|
/// This is the type of objects passed to [Object.noSuchMethod] when
|
|
/// an object doesn't support the member invocation that was attempted
|
|
/// on it.
|
|
abstract class Invocation {
|
|
Invocation();
|
|
|
|
/// Creates an invocation corresponding to a method invocation.
|
|
///
|
|
/// The method invocation has no type arguments.
|
|
/// If the named arguments are omitted, they default to no named arguments.
|
|
@pragma("wasm:entry-point")
|
|
factory Invocation.method(
|
|
Symbol memberName, Iterable<Object?>? positionalArguments,
|
|
[Map<Symbol, Object?>? namedArguments]) =>
|
|
_Invocation.method(memberName, null, positionalArguments, namedArguments);
|
|
|
|
/// Creates an invocation corresponding to a generic method invocation.
|
|
///
|
|
/// If [typeArguments] is `null` or empty, the constructor is equivalent to
|
|
/// calling [Invocation.method] with the remaining arguments.
|
|
/// All the individual type arguments must be non-null.
|
|
///
|
|
/// If the named arguments are omitted, they default to no named arguments.
|
|
@pragma("wasm:entry-point")
|
|
factory Invocation.genericMethod(Symbol memberName,
|
|
Iterable<Type>? typeArguments, Iterable<Object?>? positionalArguments,
|
|
[Map<Symbol, Object?>? namedArguments]) =>
|
|
_Invocation.method(
|
|
memberName, typeArguments, positionalArguments, namedArguments);
|
|
|
|
/// Creates an invocation corresponding to a getter invocation.
|
|
@pragma("wasm:entry-point")
|
|
factory Invocation.getter(Symbol name) = _Invocation.getter;
|
|
|
|
/// Creates an invocation corresponding to a setter invocation.
|
|
///
|
|
/// This constructor accepts any [Symbol] as [memberName], but remember that
|
|
/// *actual setter names* end in `=`, so the invocation corresponding
|
|
/// to `object.member = value` is
|
|
/// ```dart
|
|
/// Invocation.setter(const Symbol("member="), value)
|
|
/// ```
|
|
@pragma("wasm:entry-point")
|
|
factory Invocation.setter(Symbol memberName, Object? argument) =
|
|
_Invocation.setter;
|
|
|
|
/// The name of the invoked member.
|
|
Symbol get memberName;
|
|
|
|
/// An unmodifiable view of the type arguments of the call.
|
|
///
|
|
/// If the member is a getter, setter or operator,
|
|
/// the type argument list is always empty.
|
|
List<Type> get typeArguments => const <Type>[];
|
|
|
|
/// An unmodifiable view of the positional arguments of the call.
|
|
///
|
|
/// If the member is a getter, the positional arguments list is
|
|
/// always empty.
|
|
List<dynamic> get positionalArguments;
|
|
|
|
/// An unmodifiable view of the named arguments of the call.
|
|
///
|
|
/// If the member is a getter, setter or operator,
|
|
/// the named arguments map is always empty.
|
|
Map<Symbol, dynamic> get namedArguments;
|
|
|
|
/// Whether the invocation was a method call.
|
|
bool get isMethod;
|
|
|
|
/// Whether the invocation was a getter call.
|
|
/// If so, all three types of arguments lists are empty.
|
|
bool get isGetter;
|
|
|
|
/// Whether the invocation was a setter call.
|
|
///
|
|
/// If so, [positionalArguments] has exactly one positional
|
|
/// argument, [namedArguments] is empty, and typeArguments is
|
|
/// empty.
|
|
bool get isSetter;
|
|
|
|
/// Whether the invocation was a getter or a setter call.
|
|
bool get isAccessor => isGetter || isSetter;
|
|
}
|
|
|
|
/// Implementation of [Invocation] used by its factory constructors.
|
|
class _Invocation implements Invocation {
|
|
final Symbol memberName;
|
|
final List<Type> typeArguments;
|
|
// Positional arguments is `null` for getters only.
|
|
final List<Object?>? _positional;
|
|
// Named arguments is `null` for accessors only.
|
|
final Map<Symbol, Object?>? _named;
|
|
|
|
_Invocation.method(this.memberName, Iterable<Type>? types,
|
|
Iterable<Object?>? positional, Map<Symbol, Object?>? named)
|
|
: typeArguments = _ensureNonNullTypes(types),
|
|
_positional = positional == null
|
|
? const <Object?>[]
|
|
: List<Object?>.unmodifiable(positional),
|
|
_named = (named == null || named.isEmpty)
|
|
? const <Symbol, Object?>{}
|
|
: Map<Symbol, Object?>.unmodifiable(named);
|
|
|
|
_Invocation.getter(this.memberName)
|
|
: typeArguments = const <Type>[],
|
|
_positional = null,
|
|
_named = null;
|
|
|
|
_Invocation.setter(this.memberName, Object? argument)
|
|
: typeArguments = const <Type>[],
|
|
_positional = List<Object?>.unmodifiable([argument]),
|
|
_named = null;
|
|
|
|
List<dynamic> get positionalArguments => _positional ?? const <Object>[];
|
|
|
|
Map<Symbol, dynamic> get namedArguments => _named ?? const <Symbol, Object>{};
|
|
|
|
bool get isMethod => _named != null;
|
|
bool get isGetter => _positional == null;
|
|
bool get isSetter => _positional != null && _named == null;
|
|
bool get isAccessor => _named == null;
|
|
|
|
/// Checks that the elements of [types] are not null.
|
|
static List<Type> _ensureNonNullTypes(Iterable<Type>? types) {
|
|
if (types == null) return const <Type>[];
|
|
List<Type> typeArguments = List<Type>.unmodifiable(types);
|
|
for (int i = 0; i < typeArguments.length; i++) {
|
|
if (typeArguments[i] == null) {
|
|
throw ArgumentError.value(types, "types",
|
|
"Type arguments must be non-null, was null at index $i.");
|
|
}
|
|
}
|
|
return typeArguments;
|
|
}
|
|
}
|