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

import 'package:front_end/src/fasta/type_inference/type_inference_listener.dart';
import 'package:kernel/ast.dart';

/// Type inference listener that records inferred types and file offsets for
/// later use by [ValidatingResolutionApplier].
class InstrumentedResolutionStorer extends ResolutionStorer {
  /// Indicates whether debug messages should be printed.
  static const bool _debug = false;

  final List<int> _typeOffsets;

  InstrumentedResolutionStorer(List<DartType> types, this._typeOffsets)
      : super(types);

  @override
  int _recordType(DartType type, int offset) {
    if (_debug) {
      print('Recording type $type for offset $offset');
    }
    assert(_types.length == _typeOffsets.length);
    _typeOffsets.add(offset);
    return super._recordType(type, offset);
  }
}

/// Type inference listener that records inferred types for later use by
/// [ResolutionApplier].
class ResolutionStorer extends TypeInferenceListener {
  final List<DartType> _types;

  /// Indices into [_types] which need to be filled in later.
  final _deferredTypeSlots = <int>[];

  ResolutionStorer(this._types);

  /// Verifies that all deferred work has been completed.
  void finished() {
    assert(_deferredTypeSlots.isEmpty);
  }

  @override
  bool genericExpressionEnter(
      String expressionType, Expression expression, DartType typeContext) {
    super.genericExpressionEnter(expressionType, expression, typeContext);
    return true;
  }

  @override
  void genericExpressionExit(
      String expressionType, Expression expression, DartType inferredType) {
    _recordType(inferredType, expression.fileOffset);
    super.genericExpressionExit(expressionType, expression, inferredType);
  }

  @override
  void methodInvocationBeforeArgs(Expression expression, bool isImplicitCall) {
    if (!isImplicitCall) {
      // We are visiting a method invocation like: a.f(args).  We have visited a
      // but we haven't visited the args yet.
      //
      // The analyzer AST will expect a type for f at this point.  (It can't
      // wait until later, because for all it knows, a.f might be a property
      // access, in which case the appropriate time for the type is now).  But
      // the type isn't known yet (because it may depend on type inference based
      // on arguments).
      //
      // So we add a `null` to our list of types; we'll update it with the
      // actual type later.
      _deferredTypeSlots.add(_recordType(null, expression.fileOffset));
    }
    super.methodInvocationBeforeArgs(expression, isImplicitCall);
  }

  @override
  void methodInvocationExit(Expression expression, Arguments arguments,
      bool isImplicitCall, DartType inferredType) {
    if (!isImplicitCall) {
      // TODO(paulberry): get the actual callee function type from the inference
      // engine
      var calleeType = const DynamicType();
      _types[_deferredTypeSlots.removeLast()] = calleeType;
    }
    _recordType(inferredType, arguments.fileOffset);
    super.genericExpressionExit("methodInvocation", expression, inferredType);
  }

  @override
  bool staticInvocationEnter(
      StaticInvocation expression, DartType typeContext) {
    // We are visiting a static invocation like: f(args), and we haven't visited
    // args yet.
    //
    // The analyzer AST will expect a type for f at this point.  (It can't wait
    // until later, because for all it knows, f is a method on `this`, and
    // methods need a type for f at this point--see comments in
    // [methodInvocationBeforeArgs]).  But the type isn't known yet (because it
    // may depend on type inference based on arguments).
    //
    // So we add a `null` to our list of types; we'll update it with the actual
    // type later.
    _deferredTypeSlots.add(_recordType(null, expression.fileOffset));
    return super.staticInvocationEnter(expression, typeContext);
  }

  @override
  void staticInvocationExit(
      StaticInvocation expression, DartType inferredType) {
    // TODO(paulberry): get the actual callee function type from the inference
    // engine
    var calleeType = const DynamicType();
    _types[_deferredTypeSlots.removeLast()] = calleeType;
    _recordType(inferredType, expression.arguments.fileOffset);
    super.genericExpressionExit("staticInvocation", expression, inferredType);
  }

  @override
  void variableDeclarationEnter(VariableDeclaration statement) {
    _recordType(statement.type, statement.fileOffset);
    super.variableDeclarationEnter(statement);
  }

  int _recordType(DartType type, int offset) {
    int slot = _types.length;
    _types.add(type);
    return slot;
  }
}
