| // 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. | 
 |   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. | 
 |   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. | 
 |   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) | 
 |   /// ``` | 
 |   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; | 
 |   } | 
 | } |