// Copyright (c) 2016, 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 fasta.formal_parameter_builder;

import 'package:_fe_analyzer_shared/src/parser/formal_parameter_kind.dart'
    show FormalParameterKind, FormalParameterKindExtension;
import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
import 'package:kernel/ast.dart'
    show DartType, DynamicType, Expression, VariableDeclaration;

import '../constant_context.dart' show ConstantContext;
import '../kernel/body_builder.dart' show BodyBuilder;
import '../kernel/internal_ast.dart' show VariableDeclarationImpl;
import '../modifier.dart';
import '../scope.dart' show Scope;
import '../source/source_factory_builder.dart';
import '../source/source_field_builder.dart';
import '../source/source_library_builder.dart';
import '../util/helpers.dart' show DelayedActionPerformer;
import 'builder.dart';
import 'class_builder.dart';
import 'constructor_builder.dart';
import 'library_builder.dart';
import 'metadata_builder.dart';
import 'modifier_builder.dart';
import 'named_type_builder.dart';
import 'type_builder.dart';
import 'variable_builder.dart';

abstract class ParameterBuilder {
  /// List of metadata builders for the metadata declared on this parameter.
  List<MetadataBuilder>? get metadata;
  TypeBuilder? get type;

  /// The kind of this parameter, i.e. if it's required, positional optional,
  /// or named optional.
  FormalParameterKind get kind;

  bool get isPositional;
  bool get isRequiredPositional;
  bool get isNamed;
  bool get isRequiredNamed;

  String? get name;

  ParameterBuilder clone(
      List<NamedTypeBuilder> newTypes,
      SourceLibraryBuilder contextLibrary,
      TypeParameterScopeBuilder contextDeclaration);
}

/// A builder for a formal parameter, i.e. a parameter on a method or
/// constructor.
class FormalParameterBuilder extends ModifierBuilderImpl
    implements VariableBuilder, ParameterBuilder {
  static const String noNameSentinel = 'no name sentinel';

  /// List of metadata builders for the metadata declared on this parameter.
  @override
  final List<MetadataBuilder>? metadata;

  @override
  final int modifiers;

  @override
  final TypeBuilder? type;

  @override
  final String name;

  @override
  final Uri? fileUri;

  @override
  final FormalParameterKind kind;

  /// The variable declaration created for this formal parameter.
  @override
  VariableDeclaration? variable;

  /// The first token of the default value, if any.
  ///
  /// This is stored until outlines have been built through
  /// [buildOutlineExpressions].
  Token? initializerToken;

  bool initializerWasInferred = false;

  /// True if the initializer was declared by the programmer.
  bool hasDeclaredInitializer = false;

  final bool isExtensionThis;

  FormalParameterBuilder(this.metadata, this.kind, this.modifiers, this.type,
      this.name, LibraryBuilder? compilationUnit, int charOffset,
      {Uri? fileUri, this.isExtensionThis: false})
      : this.fileUri = fileUri ?? compilationUnit?.fileUri,
        super(compilationUnit, charOffset);

  @override
  String get debugName => "FormalParameterBuilder";

  @override
  bool get isRequiredPositional => kind.isRequiredPositional;

  // TODO(johnniwinther): This was previously named `isOptional` so we might
  // have some uses that intended to use the now existing `isOptional` method.
  bool get isOptionalPositional => !isRequiredPositional;

  @override
  bool get isRequiredNamed => kind.isRequiredNamed;

  @override
  bool get isPositional => kind.isPositional;

  @override
  bool get isNamed => kind.isNamed;

  bool get isOptional => kind.isOptional;

  @override
  bool get isLocal => true;

  bool get isInitializingFormal => (modifiers & initializingFormalMask) != 0;

  bool get isSuperInitializingFormal =>
      (modifiers & superInitializingFormalMask) != 0;

  bool get isCovariantByDeclaration => (modifiers & covariantMask) != 0;

  // An initializing formal parameter might be final without its
  // VariableDeclaration being final. See
  // [ProcedureBuilder.computeFormalParameterInitializerScope]..
  @override
  bool get isAssignable =>
      variable!.isAssignable &&
      !isInitializingFormal &&
      !isSuperInitializingFormal;

  @override
  String get fullNameForErrors => name;

  VariableDeclaration build(
      SourceLibraryBuilder library, int functionNestingLevel) {
    if (variable == null) {
      DartType? builtType = type?.build(library);
      variable = new VariableDeclarationImpl(
          name == noNameSentinel ? null : name, functionNestingLevel,
          type: builtType,
          isFinal: isFinal,
          isConst: false,
          isInitializingFormal: isInitializingFormal,
          isCovariantByDeclaration: isCovariantByDeclaration,
          isRequired: isRequiredNamed,
          hasDeclaredInitializer: hasDeclaredInitializer,
          isLowered: isExtensionThis)
        ..fileOffset = charOffset;
    }
    return variable!;
  }

  @override
  ParameterBuilder clone(
      List<NamedTypeBuilder> newTypes,
      SourceLibraryBuilder contextLibrary,
      TypeParameterScopeBuilder contextDeclaration) {
    // TODO(cstefantsova):  It's not clear how [metadata] is used currently,
    // and how it should be cloned.  Consider cloning it instead of reusing it.
    return new FunctionTypeParameterBuilder(metadata, kind,
        type?.clone(newTypes, contextLibrary, contextDeclaration), name);
  }

  FormalParameterBuilder forFormalParameterInitializerScope() {
    // ignore: unnecessary_null_comparison
    assert(variable != null);
    if (isInitializingFormal) {
      return new FormalParameterBuilder(
          metadata,
          kind,
          modifiers | finalMask | initializingFormalMask,
          type,
          name,
          null,
          charOffset,
          fileUri: fileUri,
          isExtensionThis: isExtensionThis)
        ..parent = parent
        ..variable = variable;
    } else if (isSuperInitializingFormal) {
      return new FormalParameterBuilder(
          metadata,
          kind,
          modifiers | finalMask | superInitializingFormalMask,
          type,
          name,
          null,
          charOffset,
          fileUri: fileUri,
          isExtensionThis: isExtensionThis)
        ..parent = parent
        ..variable = variable;
    } else {
      return this;
    }
  }

  void finalizeInitializingFormal(ClassBuilder classBuilder) {
    Builder? fieldBuilder = classBuilder.lookupLocalMember(name);
    if (fieldBuilder is SourceFieldBuilder) {
      variable!.type = fieldBuilder.inferType();
    } else {
      variable!.type = const DynamicType();
    }
  }

  /// Builds the default value from this [initializerToken] if this is a
  /// formal parameter on a const constructor or instance method.
  void buildOutlineExpressions(SourceLibraryBuilder library,
      List<DelayedActionPerformer> delayedActionPerformers) {
    if (initializerToken != null) {
      // For modular compilation we need to include default values for optional
      // and named parameters in several cases:
      // * for const constructors to enable constant evaluation,
      // * for instance methods because these might be needed to generated
      //   noSuchMethod forwarders, and
      // * for generative constructors to support forwarding constructors
      //   in mixin applications.
      bool needsDefaultValues = false;
      if (parent is ConstructorBuilder) {
        needsDefaultValues = true;
      } else if (parent is SourceFactoryBuilder) {
        needsDefaultValues = parent!.isFactory && parent!.isConst;
      } else {
        needsDefaultValues = parent!.isClassInstanceMember;
      }
      if (needsDefaultValues) {
        final ClassBuilder classBuilder = parent!.parent as ClassBuilder;
        Scope scope = classBuilder.scope;
        BodyBuilder bodyBuilder = library.loader
            .createBodyBuilderForOutlineExpression(
                library, classBuilder, this, scope, fileUri!);
        bodyBuilder.constantContext = ConstantContext.required;
        assert(!initializerWasInferred);
        Expression initializer =
            bodyBuilder.parseFieldInitializer(initializerToken!);
        initializer = bodyBuilder.typeInferrer.inferParameterInitializer(
            bodyBuilder, initializer, variable!.type, hasDeclaredInitializer);
        variable!.initializer = initializer..parent = variable;
        library.loader.transformPostInference(
            variable!,
            bodyBuilder.transformSetLiterals,
            bodyBuilder.transformCollections,
            library.library);
        initializerWasInferred = true;
        bodyBuilder.performBacklogComputations(delayedActionPerformers);
      }
    }
    initializerToken = null;
  }
}

class FunctionTypeParameterBuilder implements ParameterBuilder {
  @override
  final List<MetadataBuilder>? metadata;

  @override
  final FormalParameterKind kind;

  @override
  final TypeBuilder? type;

  @override
  final String? name;

  FunctionTypeParameterBuilder(this.metadata, this.kind, this.type, this.name);

  @override
  ParameterBuilder clone(
      List<NamedTypeBuilder> newTypes,
      SourceLibraryBuilder contextLibrary,
      TypeParameterScopeBuilder contextDeclaration) {
    // TODO(cstefantsova):  It's not clear how [metadata] is used currently,
    // and how it should be cloned.  Consider cloning it instead of reusing it.
    return new FunctionTypeParameterBuilder(metadata, kind,
        type?.clone(newTypes, contextLibrary, contextDeclaration), name);
  }

  @override
  bool get isNamed => kind.isNamed;

  @override
  bool get isRequiredNamed => kind.isRequiredNamed;

  @override
  bool get isPositional => kind.isPositional;

  @override
  bool get isRequiredPositional => kind.isRequiredPositional;
}
