// Copyright (c) 2015, 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.

library dart2js.js_helpers.impact;

import '../common/names.dart';
import '../common_elements.dart' show CommonElements, ElementEnvironment;
import '../elements/types.dart' show InterfaceType;
import '../elements/entities.dart';
import '../options.dart' show CompilerOptions;
import '../universe/selector.dart';
import '../universe/world_impact.dart'
    show WorldImpact, WorldImpactBuilder, WorldImpactBuilderImpl;
import '../universe/use.dart';
import '../util/enumset.dart';

/// Backend specific features required by a backend impact.
enum BackendFeature {
  needToInitializeIsolateAffinityTag,
  needToInitializeDispatchProperty,
}

/// A set of JavaScript backend dependencies.
class BackendImpact {
  final List<FunctionEntity> staticUses;
  final List<FunctionEntity> globalUses;
  final List<Selector> dynamicUses;
  final List<InterfaceType> instantiatedTypes;
  final List<ClassEntity> instantiatedClasses;
  final List<ClassEntity> globalClasses;
  final List<BackendImpact> otherImpacts;
  final EnumSet<BackendFeature> _features;

  const BackendImpact(
      {this.staticUses: const <FunctionEntity>[],
      this.globalUses: const <FunctionEntity>[],
      this.dynamicUses: const <Selector>[],
      this.instantiatedTypes: const <InterfaceType>[],
      this.instantiatedClasses: const <ClassEntity>[],
      this.globalClasses: const <ClassEntity>[],
      this.otherImpacts: const <BackendImpact>[],
      EnumSet<BackendFeature> features: const EnumSet<BackendFeature>.fixed(0)})
      : this._features = features;

  Iterable<BackendFeature> get features =>
      _features.iterable(BackendFeature.values);

  WorldImpact createImpact(ElementEnvironment elementEnvironment) {
    WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
    registerImpact(impactBuilder, elementEnvironment);
    return impactBuilder;
  }

  /// Register this backend impact to the [worldImpactBuilder].
  void registerImpact(WorldImpactBuilder worldImpactBuilder,
      ElementEnvironment elementEnvironment) {
    for (FunctionEntity staticUse in staticUses) {
      assert(staticUse != null);
      worldImpactBuilder
          .registerStaticUse(new StaticUse.implicitInvoke(staticUse));
    }
    for (FunctionEntity staticUse in globalUses) {
      assert(staticUse != null);
      worldImpactBuilder
          .registerStaticUse(new StaticUse.implicitInvoke(staticUse));
    }
    for (Selector selector in dynamicUses) {
      assert(selector != null);
      worldImpactBuilder.registerDynamicUse(new DynamicUse(selector));
    }
    for (InterfaceType instantiatedType in instantiatedTypes) {
      worldImpactBuilder
          .registerTypeUse(new TypeUse.instantiation(instantiatedType));
    }
    for (ClassEntity cls in instantiatedClasses) {
      worldImpactBuilder.registerTypeUse(
          new TypeUse.instantiation(elementEnvironment.getRawType(cls)));
    }
    for (ClassEntity cls in globalClasses) {
      worldImpactBuilder.registerTypeUse(
          new TypeUse.instantiation(elementEnvironment.getRawType(cls)));
    }
    for (BackendImpact otherImpact in otherImpacts) {
      otherImpact.registerImpact(worldImpactBuilder, elementEnvironment);
    }
  }
}

/// The JavaScript backend dependencies for various features.
class BackendImpacts {
  final CompilerOptions _options;
  final CommonElements _commonElements;

  BackendImpacts(this._options, this._commonElements);

  BackendImpact _getRuntimeTypeArgument;

  BackendImpact get getRuntimeTypeArgument {
    return _getRuntimeTypeArgument ??= new BackendImpact(globalUses: [
      _commonElements.getRuntimeTypeArgumentIntercepted,
      _commonElements.getRuntimeTypeArgument,
      _commonElements.getTypeArgumentByIndex,
    ]);
  }

  BackendImpact _computeSignature;

  BackendImpact get computeSignature {
    return _computeSignature ??= new BackendImpact(globalUses: [
      _commonElements.setRuntimeTypeInfo,
      _commonElements.getRuntimeTypeInfo,
      _commonElements.computeSignature,
      _commonElements.getRuntimeTypeArguments
    ], otherImpacts: [
      listValues
    ]);
  }

  BackendImpact _mainWithArguments;

  BackendImpact get mainWithArguments {
    return _mainWithArguments ??= new BackendImpact(instantiatedClasses: [
      _commonElements.jsArrayClass,
      _commonElements.jsStringClass
    ]);
  }

  BackendImpact _asyncBody;

  BackendImpact get asyncBody => _asyncBody ??= () {
        var staticUses = [
          _commonElements.asyncHelperAwait,
          _commonElements.asyncHelperReturn,
          _commonElements.asyncHelperRethrow,
          _commonElements.streamIteratorConstructor,
          _commonElements.wrapBody
        ];
        if (_options.startAsyncSynchronously) {
          staticUses.add(_commonElements.asyncHelperStartSync);
        } else {
          staticUses.add(_commonElements.asyncHelperStart);
        }
        return new BackendImpact(staticUses: staticUses);
      }();

  BackendImpact _syncStarBody;

  BackendImpact get syncStarBody {
    return _syncStarBody ??= new BackendImpact(staticUses: [
      _commonElements.endOfIteration,
      _commonElements.yieldStar,
      _commonElements.syncStarUncaughtError,
    ]);
  }

  BackendImpact _asyncStarBody;

  BackendImpact get asyncStarBody {
    return _asyncStarBody ??= new BackendImpact(staticUses: [
      _commonElements.asyncStarHelper,
      _commonElements.streamOfController,
      _commonElements.yieldSingle,
      _commonElements.yieldStar,
      _commonElements.streamIteratorConstructor,
      _commonElements.wrapBody,
    ]);
  }

  BackendImpact _typeVariableBoundCheck;

  BackendImpact get typeVariableBoundCheck {
    return _typeVariableBoundCheck ??= new BackendImpact(staticUses: [
      _commonElements.throwTypeError,
      _commonElements.assertIsSubtype
    ]);
  }

  BackendImpact _abstractClassInstantiation;

  BackendImpact get abstractClassInstantiation {
    return _abstractClassInstantiation ??= new BackendImpact(
        staticUses: [_commonElements.throwAbstractClassInstantiationError],
        otherImpacts: [_needsString('Needed to encode the message.')]);
  }

  BackendImpact _fallThroughError;

  BackendImpact get fallThroughError {
    return _fallThroughError ??=
        new BackendImpact(staticUses: [_commonElements.fallThroughError]);
  }

  BackendImpact _asCheck;

  BackendImpact get asCheck {
    return _asCheck ??=
        new BackendImpact(staticUses: [_commonElements.throwRuntimeError]);
  }

  BackendImpact _throwNoSuchMethod;

  BackendImpact get throwNoSuchMethod {
    return _throwNoSuchMethod ??= new BackendImpact(staticUses: [
      _commonElements.throwNoSuchMethod,
    ], otherImpacts: [
      // Also register the types of the arguments passed to this method.
      _needsList('Needed to encode the arguments for throw NoSuchMethodError.'),
      _needsString('Needed to encode the name for throw NoSuchMethodError.'),
      mapLiteralClass, // noSuchMethod helpers are passed a Map.
    ]);
  }

  BackendImpact _stringValues;

  BackendImpact get stringValues {
    return _stringValues ??=
        new BackendImpact(instantiatedClasses: [_commonElements.jsStringClass]);
  }

  BackendImpact _numValues;

  BackendImpact get numValues {
    return _numValues ??= new BackendImpact(instantiatedClasses: [
      _commonElements.jsIntClass,
      _commonElements.jsPositiveIntClass,
      _commonElements.jsUInt32Class,
      _commonElements.jsUInt31Class,
      _commonElements.jsNumberClass,
      _commonElements.jsDoubleClass
    ]);
  }

  BackendImpact get intValues => numValues;

  BackendImpact get doubleValues => numValues;

  BackendImpact _boolValues;

  BackendImpact get boolValues {
    return _boolValues ??=
        new BackendImpact(instantiatedClasses: [_commonElements.jsBoolClass]);
  }

  BackendImpact _nullValue;

  BackendImpact get nullValue {
    return _nullValue ??=
        new BackendImpact(instantiatedClasses: [_commonElements.jsNullClass]);
  }

  BackendImpact _listValues;

  BackendImpact get listValues {
    return _listValues ??= new BackendImpact(globalClasses: [
      _commonElements.jsArrayClass,
      _commonElements.jsMutableArrayClass,
      _commonElements.jsFixedArrayClass,
      _commonElements.jsExtendableArrayClass,
      _commonElements.jsUnmodifiableArrayClass
    ]);
  }

  BackendImpact _throwRuntimeError;

  BackendImpact get throwRuntimeError {
    return _throwRuntimeError ??= new BackendImpact(staticUses: [
      _commonElements.throwRuntimeError,
    ], otherImpacts: [
      // Also register the types of the arguments passed to this method.
      stringValues
    ]);
  }

  BackendImpact _throwUnsupportedError;

  BackendImpact get throwUnsupportedError {
    return _throwUnsupportedError ??= new BackendImpact(staticUses: [
      _commonElements.throwUnsupportedError
    ], otherImpacts: [
      // Also register the types of the arguments passed to this method.
      stringValues
    ]);
  }

  BackendImpact _superNoSuchMethod;

  BackendImpact get superNoSuchMethod {
    return _superNoSuchMethod ??= new BackendImpact(staticUses: [
      _commonElements.createInvocationMirror,
      _commonElements.objectNoSuchMethod
    ], otherImpacts: [
      _needsInt('Needed to encode the invocation kind of super.noSuchMethod.'),
      _needsList('Needed to encode the arguments of super.noSuchMethod.'),
      _needsString('Needed to encode the name of super.noSuchMethod.')
    ]);
  }

  BackendImpact _constantMapLiteral;

  BackendImpact get constantMapLiteral {
    return _constantMapLiteral ??= new BackendImpact(instantiatedClasses: [
      _commonElements.constantMapClass,
      _commonElements.constantProtoMapClass,
      _commonElements.constantStringMapClass,
      _commonElements.generalConstantMapClass,
    ]);
  }

  BackendImpact _symbolConstructor;

  BackendImpact get symbolConstructor {
    return _symbolConstructor ??= new BackendImpact(
        staticUses: [_commonElements.symbolValidatedConstructor]);
  }

  BackendImpact _constSymbol;

  BackendImpact get constSymbol {
    return _constSymbol ??= new BackendImpact(
        instantiatedClasses: [_commonElements.symbolImplementationClass],
        staticUses: [_commonElements.symbolConstructorTarget]);
  }

  /// Helper for registering that `int` is needed.
  BackendImpact _needsInt(String reason) {
    // TODO(johnniwinther): Register [reason] for use in dump-info.
    return intValues;
  }

  /// Helper for registering that `List` is needed.
  BackendImpact _needsList(String reason) {
    // TODO(johnniwinther): Register [reason] for use in dump-info.
    return listValues;
  }

  /// Helper for registering that `String` is needed.
  BackendImpact _needsString(String reason) {
    // TODO(johnniwinther): Register [reason] for use in dump-info.
    return stringValues;
  }

  BackendImpact _assertWithoutMessage;

  BackendImpact get assertWithoutMessage {
    return _assertWithoutMessage ??=
        new BackendImpact(staticUses: [_commonElements.assertHelper]);
  }

  BackendImpact _assertWithMessage;

  BackendImpact get assertWithMessage {
    return _assertWithMessage ??= new BackendImpact(
        staticUses: [_commonElements.assertTest, _commonElements.assertThrow]);
  }

  BackendImpact _asyncForIn;

  BackendImpact get asyncForIn {
    return _asyncForIn ??= new BackendImpact(
        staticUses: [_commonElements.streamIteratorConstructor]);
  }

  BackendImpact _stringInterpolation;

  BackendImpact get stringInterpolation {
    return _stringInterpolation ??= new BackendImpact(
        dynamicUses: [Selectors.toString_],
        staticUses: [_commonElements.stringInterpolationHelper],
        otherImpacts: [_needsString('Strings are created.')]);
  }

  BackendImpact _stringJuxtaposition;

  BackendImpact get stringJuxtaposition {
    return _stringJuxtaposition ??= _needsString('String.concat is used.');
  }

  BackendImpact get nullLiteral => nullValue;

  BackendImpact get boolLiteral => boolValues;

  BackendImpact get intLiteral => intValues;

  BackendImpact get doubleLiteral => doubleValues;

  BackendImpact get stringLiteral => stringValues;

  BackendImpact _catchStatement;

  BackendImpact get catchStatement {
    return _catchStatement ??= new BackendImpact(staticUses: [
      _commonElements.exceptionUnwrapper
    ], instantiatedClasses: [
      _commonElements.jsPlainJavaScriptObjectClass,
      _commonElements.jsUnknownJavaScriptObjectClass
    ]);
  }

  BackendImpact _throwExpression;

  BackendImpact get throwExpression {
    return _throwExpression ??= new BackendImpact(
        // We don't know ahead of time whether we will need the throw in a
        // statement context or an expression context, so we register both
        // here, even though we may not need the throwExpression helper.
        staticUses: [
          _commonElements.wrapExceptionHelper,
          _commonElements.throwExpressionHelper
        ]);
  }

  BackendImpact _lazyField;

  BackendImpact get lazyField {
    return _lazyField ??=
        new BackendImpact(staticUses: [_commonElements.cyclicThrowHelper]);
  }

  BackendImpact _typeLiteral;

  BackendImpact get typeLiteral {
    return _typeLiteral ??= new BackendImpact(
        instantiatedClasses: [_commonElements.typeLiteralClass],
        staticUses: [_commonElements.createRuntimeType]);
  }

  BackendImpact _stackTraceInCatch;

  BackendImpact get stackTraceInCatch {
    return _stackTraceInCatch ??= new BackendImpact(
        instantiatedClasses: [_commonElements.stackTraceHelperClass],
        staticUses: [_commonElements.traceFromException]);
  }

  BackendImpact _syncForIn;

  BackendImpact get syncForIn {
    return _syncForIn ??= new BackendImpact(
        // The SSA builder recognizes certain for-in loops and can generate
        // calls to throwConcurrentModificationError.
        staticUses: [_commonElements.checkConcurrentModificationError]);
  }

  BackendImpact _typeVariableExpression;

  BackendImpact get typeVariableExpression {
    return _typeVariableExpression ??= new BackendImpact(staticUses: [
      _commonElements.setRuntimeTypeInfo,
      _commonElements.getRuntimeTypeInfo,
      _commonElements.runtimeTypeToString,
      _commonElements.createRuntimeType
    ], otherImpacts: [
      listValues,
      getRuntimeTypeArgument,
      _needsInt('Needed for accessing a type variable literal on this.')
    ]);
  }

  BackendImpact _typeCheck;

  BackendImpact get typeCheck {
    return _typeCheck ??= new BackendImpact(otherImpacts: [boolValues]);
  }

  BackendImpact _checkedModeTypeCheck;

  BackendImpact get checkedModeTypeCheck {
    return _checkedModeTypeCheck ??=
        new BackendImpact(staticUses: [_commonElements.throwRuntimeError]);
  }

  BackendImpact _malformedTypeCheck;

  BackendImpact get malformedTypeCheck {
    return _malformedTypeCheck ??= new BackendImpact(staticUses: [
      _commonElements.throwTypeError,
    ]);
  }

  BackendImpact _genericTypeCheck;

  BackendImpact get genericTypeCheck {
    return _genericTypeCheck ??= new BackendImpact(staticUses: [
      _commonElements.checkSubtype,
      // TODO(johnniwinther): Investigate why this is needed.
      _commonElements.setRuntimeTypeInfo,
      _commonElements.getRuntimeTypeInfo
    ], otherImpacts: [
      listValues,
      getRuntimeTypeArgument
    ]);
  }

  BackendImpact _genericIsCheck;

  BackendImpact get genericIsCheck {
    return _genericIsCheck ??= new BackendImpact(otherImpacts: [intValues]);
  }

  BackendImpact _genericCheckedModeTypeCheck;

  BackendImpact get genericCheckedModeTypeCheck {
    return _genericCheckedModeTypeCheck ??=
        new BackendImpact(staticUses: [_commonElements.assertSubtype]);
  }

  BackendImpact _typeVariableTypeCheck;

  BackendImpact get typeVariableTypeCheck {
    return _typeVariableTypeCheck ??= new BackendImpact(
        staticUses: [_commonElements.checkSubtypeOfRuntimeType]);
  }

  BackendImpact _typeVariableCheckedModeTypeCheck;

  BackendImpact get typeVariableCheckedModeTypeCheck {
    return _typeVariableCheckedModeTypeCheck ??= new BackendImpact(
        staticUses: [_commonElements.assertSubtypeOfRuntimeType]);
  }

  BackendImpact _functionTypeCheck;

  BackendImpact get functionTypeCheck {
    return _functionTypeCheck ??=
        new BackendImpact(staticUses: [/*helpers.functionTypeTestMetaHelper*/]);
  }

  BackendImpact _futureOrTypeCheck;

  BackendImpact get futureOrTypeCheck {
    return _futureOrTypeCheck ??=
        new BackendImpact(staticUses: [_commonElements.futureOrTest]);
  }

  BackendImpact _nativeTypeCheck;

  BackendImpact get nativeTypeCheck {
    return _nativeTypeCheck ??= new BackendImpact(staticUses: [
      // We will neeed to add the "$is" and "$as" properties on the
      // JavaScript object prototype, so we make sure
      // [:defineProperty:] is compiled.
      _commonElements.defineProperty
    ]);
  }

  BackendImpact _closure;

  BackendImpact get closure {
    return _closure ??=
        new BackendImpact(instantiatedClasses: [_commonElements.functionClass]);
  }

  BackendImpact _interceptorUse;

  BackendImpact get interceptorUse {
    return _interceptorUse ??= new BackendImpact(
        staticUses: [
          _commonElements.getNativeInterceptorMethod
        ],
        instantiatedClasses: [
          _commonElements.jsJavaScriptObjectClass,
          _commonElements.jsPlainJavaScriptObjectClass,
          _commonElements.jsJavaScriptFunctionClass
        ],
        features: new EnumSet<BackendFeature>.fromValues([
          BackendFeature.needToInitializeDispatchProperty,
          BackendFeature.needToInitializeIsolateAffinityTag
        ], fixed: true));
  }

  BackendImpact _numClasses;

  BackendImpact get numClasses {
    return _numClasses ??= new BackendImpact(
        // The backend will try to optimize number operations and use the
        // `iae` helper directly.
        globalUses: [_commonElements.throwIllegalArgumentException]);
  }

  BackendImpact _listOrStringClasses;

  BackendImpact get listOrStringClasses {
    return _listOrStringClasses ??= new BackendImpact(
        // The backend will try to optimize array and string access and use the
        // `ioore` and `iae` _commonElements directly.
        globalUses: [
          _commonElements.throwIndexOutOfRangeException,
          _commonElements.throwIllegalArgumentException
        ]);
  }

  BackendImpact _functionClass;

  BackendImpact get functionClass {
    return _functionClass ??=
        new BackendImpact(globalClasses: [_commonElements.closureClass]);
  }

  BackendImpact _mapClass;

  BackendImpact get mapClass {
    return _mapClass ??= new BackendImpact(
        // The backend will use a literal list to initialize the entries
        // of the map.
        globalClasses: [
          _commonElements.listClass,
          _commonElements.mapLiteralClass
        ]);
  }

  BackendImpact _boundClosureClass;

  BackendImpact get boundClosureClass {
    return _boundClosureClass ??=
        new BackendImpact(globalClasses: [_commonElements.boundClosureClass]);
  }

  BackendImpact _nativeOrExtendsClass;

  BackendImpact get nativeOrExtendsClass {
    return _nativeOrExtendsClass ??= new BackendImpact(globalUses: [
      _commonElements.getNativeInterceptorMethod
    ], globalClasses: [
      _commonElements.jsInterceptorClass,
      _commonElements.jsJavaScriptObjectClass,
      _commonElements.jsPlainJavaScriptObjectClass,
      _commonElements.jsJavaScriptFunctionClass
    ]);
  }

  BackendImpact _mapLiteralClass;

  BackendImpact get mapLiteralClass {
    return _mapLiteralClass ??= new BackendImpact(globalUses: [
      _commonElements.mapLiteralConstructor,
      _commonElements.mapLiteralConstructorEmpty,
      _commonElements.mapLiteralUntypedMaker,
      _commonElements.mapLiteralUntypedEmptyMaker
    ]);
  }

  BackendImpact _closureClass;

  BackendImpact get closureClass {
    return _closureClass ??=
        new BackendImpact(globalUses: [_commonElements.closureFromTearOff]);
  }

  BackendImpact _listClasses;

  BackendImpact get listClasses {
    return _listClasses ??= new BackendImpact(
        // Literal lists can be translated into calls to these functions:
        globalUses: [
          _commonElements.jsArrayTypedConstructor,
          _commonElements.setRuntimeTypeInfo,
          _commonElements.getTypeArgumentByIndex
        ]);
  }

  BackendImpact _jsIndexingBehavior;

  BackendImpact get jsIndexingBehavior {
    return _jsIndexingBehavior ??= new BackendImpact(
        // These two _commonElements are used by the emitter and the codegen.
        // Because we cannot enqueue elements at the time of emission,
        // we make sure they are always generated.
        globalUses: [_commonElements.isJsIndexable]);
  }

  BackendImpact _enableTypeAssertions;

  BackendImpact get enableTypeAssertions {
    return _enableTypeAssertions ??= new BackendImpact(
        // Register the helper that checks if the expression in an if/while/for
        // is a boolean.
        // TODO(johnniwinther): Should this be registered through a [Feature]
        // instead?
        globalUses: [_commonElements.boolConversionCheck]);
  }

  BackendImpact _traceHelper;

  BackendImpact get traceHelper {
    return _traceHelper ??=
        new BackendImpact(globalUses: [_commonElements.traceHelper]);
  }

  BackendImpact _assertUnreachable;

  BackendImpact get assertUnreachable {
    return _assertUnreachable ??= new BackendImpact(
        globalUses: [_commonElements.assertUnreachableMethod]);
  }

  BackendImpact _runtimeTypeSupport;

  BackendImpact get runtimeTypeSupport {
    return _runtimeTypeSupport ??= new BackendImpact(globalClasses: [
      _commonElements.listClass
    ], globalUses: [
      _commonElements.setRuntimeTypeInfo,
      _commonElements.getRuntimeTypeInfo
    ], otherImpacts: [
      getRuntimeTypeArgument,
      computeSignature
    ]);
  }

  BackendImpact _deferredLoading;

  BackendImpact get deferredLoading {
    return _deferredLoading ??=
        new BackendImpact(globalUses: [_commonElements.checkDeferredIsLoaded],
            // Also register the types of the arguments passed to this method.
            globalClasses: [_commonElements.stringClass]);
  }

  BackendImpact _noSuchMethodSupport;

  BackendImpact get noSuchMethodSupport {
    return _noSuchMethodSupport ??= new BackendImpact(
        staticUses: [_commonElements.createInvocationMirror],
        dynamicUses: [Selectors.noSuchMethod_]);
  }

  BackendImpact _loadLibrary;

  /// Backend impact for accessing a `loadLibrary` function on a deferred
  /// prefix.
  BackendImpact get loadLibrary {
    return _loadLibrary ??= new BackendImpact(globalUses: [
      // TODO(redemption): delete wrapper when we sunset the old frontend.
      _commonElements.loadLibraryWrapper,
      _commonElements.loadDeferredLibrary,
    ]);
  }

  BackendImpact _memberClosure;

  /// Backend impact for performing member closurization.
  BackendImpact get memberClosure {
    return _memberClosure ??=
        new BackendImpact(globalClasses: [_commonElements.boundClosureClass]);
  }

  BackendImpact _staticClosure;

  /// Backend impact for performing closurization of a top-level or static
  /// function.
  BackendImpact get staticClosure {
    return _staticClosure ??=
        new BackendImpact(globalClasses: [_commonElements.closureClass]);
  }

  BackendImpact _typeVariableMirror;

  /// Backend impact for type variables through mirrors.
  BackendImpact get typeVariableMirror {
    return _typeVariableMirror ??= new BackendImpact(staticUses: [
      _commonElements.typeVariableConstructor,
      _commonElements.createRuntimeType
    ], instantiatedClasses: [
      _commonElements.typeVariableClass
    ]);
  }

  BackendImpact _genericInstantiation;

  BackendImpact get genericInstantiation =>
      _genericInstantiation ??= new BackendImpact(staticUses: [
        _commonElements.instantiate1,
        _commonElements.instantiate2,
        _commonElements.instantiate3,
        _commonElements.instantiatedGenericFunctionType,
      ], instantiatedClasses: [
        _commonElements.instantiation1Class,
        _commonElements.instantiation2Class,
        _commonElements.instantiation3Class,
      ]);
}
