// 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 '../parser.dart' show FormalParameterKind;

import '../parser/formal_parameter_kind.dart'
    show
        isMandatoryFormalParameterKind,
        isOptionalNamedFormalParameterKind,
        isOptionalPositionalFormalParameterKind;

import 'builder.dart'
    show LibraryBuilder, MetadataBuilder, ModifierBuilder, TypeBuilder;

import 'package:kernel/ast.dart' show VariableDeclaration;

import '../constant_context.dart' show ConstantContext;

import '../modifier.dart' show finalMask, initializingFormalMask, requiredMask;

import '../scanner.dart' show Token;

import '../scope.dart' show Scope;

import '../source/source_library_builder.dart' show SourceLibraryBuilder;

import '../source/source_loader.dart' show SourceLoader;

import '../kernel/body_builder.dart' show BodyBuilder;

import '../kernel/kernel_builder.dart'
    show
        ClassBuilder,
        Builder,
        ConstructorBuilder,
        FieldBuilder,
        LibraryBuilder,
        MetadataBuilder,
        TypeBuilder;

import '../kernel/kernel_shadow_ast.dart' show VariableDeclarationJudgment;

/// A builder for a formal parameter, i.e. a parameter on a method or
/// constructor.
class FormalParameterBuilder extends ModifierBuilder {
  /// List of metadata builders for the metadata declared on this parameter.
  final List<MetadataBuilder> metadata;

  final int modifiers;

  final TypeBuilder type;

  final String name;

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

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

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

  FormalParameterBuilder(this.metadata, this.modifiers, this.type, this.name,
      LibraryBuilder compilationUnit, int charOffset)
      : super(compilationUnit, charOffset);

  String get debugName => "FormalParameterBuilder";

  // TODO(johnniwinther): Cleanup `isRequired` semantics in face of required
  // named parameters.
  bool get isRequired => isMandatoryFormalParameterKind(kind);

  bool get isNamedRequired => (modifiers & requiredMask) != 0;

  bool get isPositional {
    return isOptionalPositionalFormalParameterKind(kind) ||
        isMandatoryFormalParameterKind(kind);
  }

  bool get isNamed => isOptionalNamedFormalParameterKind(kind);

  bool get isOptional => !isRequired;

  bool get isLocal => true;

  @override
  String get fullNameForErrors => name;

  VariableDeclaration get target => variable;

  VariableDeclaration build(
      SourceLibraryBuilder library, int functionNestingLevel) {
    if (variable == null) {
      variable = new VariableDeclarationJudgment(name, functionNestingLevel,
          type: type?.build(library),
          isFinal: isFinal,
          isConst: isConst,
          isFieldFormal: isInitializingFormal,
          isCovariant: isCovariant,
          isRequired: isNamedRequired)
        ..fileOffset = charOffset;
    }
    return variable;
  }

  FormalParameterBuilder clone(List<TypeBuilder> newTypes) {
    // TODO(dmitryas):  It's not clear how [metadata] is used currently, and
    // how it should be cloned.  Consider cloning it instead of reusing it.
    return new FormalParameterBuilder(
        metadata, modifiers, type?.clone(newTypes), name, parent, charOffset)
      ..kind = kind;
  }

  FormalParameterBuilder forFormalParameterInitializerScope() {
    assert(variable != null);
    return !isInitializingFormal
        ? this
        : (new FormalParameterBuilder(
            metadata,
            modifiers | finalMask | initializingFormalMask,
            type,
            name,
            null,
            charOffset)
          ..parent = parent
          ..variable = variable);
  }

  void finalizeInitializingFormal() {
    Object cls = parent.parent;
    if (cls is ClassBuilder) {
      Builder fieldBuilder = cls.scope.lookup(name, charOffset, fileUri);
      if (fieldBuilder is FieldBuilder) {
        variable.type = fieldBuilder.field.type;
      }
    }
  }

  /// Builds the default value from this [initializerToken] if this is a
  /// formal parameter on a const constructor or instance method.
  void buildOutlineExpressions(LibraryBuilder library) {
    // For modular compilation we need to include initializers for optional
    // and named parameters of const constructors into the outline - to enable
    // constant evaluation. Similarly we need to include initializers for
    // optional and named parameters of instance methods because these might be
    // needed to generated noSuchMethod forwarders.
    bool isConstConstructorParameter = false;
    if (parent is ConstructorBuilder) {
      ConstructorBuilder constructorBuilder = parent;
      isConstConstructorParameter = constructorBuilder.constructor.isConst;
    }
    if ((isConstConstructorParameter || parent.isClassInstanceMember) &&
        initializerToken != null) {
      final ClassBuilder classBuilder = parent.parent;
      Scope scope = classBuilder.scope;
      BodyBuilder bodyBuilder = library.loader
          .createBodyBuilderForOutlineExpression(
              library, classBuilder, this, scope, fileUri);
      bodyBuilder.constantContext = ConstantContext.required;
      variable.initializer = bodyBuilder.parseFieldInitializer(initializerToken)
        ..parent = variable;
      bodyBuilder.typeInferrer?.inferParameterInitializer(
          bodyBuilder, variable.initializer, variable.type);
      if (library.loader is SourceLoader) {
        SourceLoader loader = library.loader;
        loader.transformPostInference(variable,
            bodyBuilder.transformSetLiterals, bodyBuilder.transformCollections);
      }
      bodyBuilder.resolveRedirectingFactoryTargets();
    }
    initializerToken = null;
  }
}
