// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

library track_widget_constructor_locations;

// The kernel/src import below that requires lint `ignore_for_file`
// is a temporary state of things until kernel team builds better api that would
// replace api used below. This api was made private in an effort to discourage
// further use.
// ignore_for_file: implementation_imports
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:meta/meta.dart';
import 'package:vm/frontend_server.dart' show ProgramTransformer;

// Parameter name used to track were widget constructor calls were made from.
//
// The parameter name contains a randomly generate hex string to avoid collision
// with user generated parameters.
const String _creationLocationParameterName =
    r'$creationLocationd_0dea112b090073317d4';

/// Name of private field added to the Widget class and any other classes that
/// implement Widget.
///
/// Regardless of what library a class implementing Widget is defined in, the
/// private field will always be defined in the context of the widget_inspector
/// library ensuring no name conflicts with regular fields.
const String _locationFieldName = r'_location';

bool _hasNamedParameter(FunctionNode function, String name) {
  return function.namedParameters
      .any((VariableDeclaration parameter) => parameter.name == name);
}

bool _hasNamedArgument(Arguments arguments, String argumentName) {
  return arguments.named
      .any((NamedExpression argument) => argument.name == argumentName);
}

VariableDeclaration _getNamedParameter(
  FunctionNode function,
  String parameterName,
) {
  for (VariableDeclaration parameter in function.namedParameters) {
    if (parameter.name == parameterName) {
      return parameter;
    }
  }
  return null;
}

// TODO(jacobr): find a solution that supports optional positional parameters.
/// Add the creation location to the arguments list if possible.
///
/// Returns whether the creation location argument could be added. We cannot
/// currently add the named argument for functions with optional positional
/// parameters as the current scheme requires adding the creation location as a
/// named parameter. Fortunately that is not a significant issue in practice as
/// no Widget classes in package:flutter have optional positional parameters.
/// This code degrades gracefully for constructors with optional positional
/// parameters by skipping adding the creation location argument rather than
/// failing.
void _maybeAddCreationLocationArgument(
  Arguments arguments,
  FunctionNode function,
  Expression creationLocation,
  Class locationClass,
) {
  if (_hasNamedArgument(arguments, _creationLocationParameterName)) {
    return;
  }
  if (!_hasNamedParameter(function, _creationLocationParameterName)) {
    return;
  }

  final NamedExpression namedArgument =
      NamedExpression(_creationLocationParameterName, creationLocation);
  namedArgument.parent = arguments;
  arguments.named.add(namedArgument);
}

/// Adds a named parameter to a function if the function does not already have
/// a named parameter with the name or optional positional parameters.
bool _maybeAddNamedParameter(
  FunctionNode function,
  VariableDeclaration variable,
) {
  if (_hasNamedParameter(function, _creationLocationParameterName)) {
    // Gracefully handle if this method is called on a function that has already
    // been transformed.
    return false;
  }
  // Function has optional positional parameters so cannot have optional named
  // parameters.
  if (function.requiredParameterCount != function.positionalParameters.length) {
    return false;
  }
  variable.parent = function;
  function.namedParameters.add(variable);
  return true;
}

/// Transformer that modifies all calls to Widget constructors to include
/// a [DebugLocation] parameter specifying the location where the constructor
/// call was made.
///
/// This transformer requires that all Widget constructors have already been
/// transformed to have a named parameter with the name specified by
/// `_locationParameterName`.
class _WidgetCallSiteTransformer extends Transformer {
  final ClassHierarchy _hierarchy;

  /// The [Widget] class defined in the `package:flutter` library.
  ///
  /// Used to perform instanceof checks to determine whether Dart constructor
  /// calls are creating [Widget] objects.
  Class _widgetClass;

  /// The [DebugLocation] class defined in the `package:flutter` library.
  Class _locationClass;

  /// Current factory constructor that node being transformed is inside.
  ///
  /// Used to flow the location passed in as an argument to the factory to the
  /// actual constructor call within the factory.
  Procedure _currentFactory;

  _WidgetCallSiteTransformer(
    this._hierarchy, {
    @required Class widgetClass,
    @required Class locationClass,
  })
      : _widgetClass = widgetClass,
        _locationClass = locationClass;

  /// Builds a call to the const constructor of the [DebugLocation]
  /// object specifying the location where a constructor call was made and
  /// optionally the locations for all parameters passed in.
  ///
  /// Specifying the parameters passed in is an experimental feature. With
  /// access to the source code of an application you could determine the
  /// locations of the parameters passed in from the source location of the
  /// constructor call but it is convenient to bundle the location and names
  /// of the parameters passed in so that tools can show parameter locations
  /// without re-parsing the source code.
  ConstructorInvocation _constructLocation(
    Location location, {
    String name,
    ListLiteral parameterLocations,
    bool showFile = true,
  }) {
    final List<NamedExpression> arguments = <NamedExpression>[
      NamedExpression('line', IntLiteral(location.line)),
      NamedExpression('column', IntLiteral(location.column)),
    ];
    if (showFile) {
      arguments.add(NamedExpression(
          'file', StringLiteral(location.file.toString())));
    }
    if (name != null) {
      arguments.add(NamedExpression('name', StringLiteral(name)));
    }
    if (parameterLocations != null) {
      arguments
          .add(NamedExpression('parameterLocations', parameterLocations));
    }
    return ConstructorInvocation(
      _locationClass.constructors.first,
      Arguments(<Expression>[], named: arguments),
      isConst: true,
    );
  }

  @override
  Procedure visitProcedure(Procedure node) {
    if (node.isFactory) {
      _currentFactory = node;
      node.transformChildren(this);
      _currentFactory = null;
      return node;
    }
    return defaultTreeNode(node);
  }

  bool _isSubclassOfWidget(Class clazz) {
    // TODO(jacobr): use hierarchy.isSubclassOf once we are using the
    // non-deprecated ClassHierarchy constructor.
    return _hierarchy.isSubclassOf(clazz, _widgetClass);
  }

  @override
  StaticInvocation visitStaticInvocation(StaticInvocation node) {
    node.transformChildren(this);
    final Procedure target = node.target;
    if (!target.isFactory) {
      return node;
    }
    final Class constructedClass = target.enclosingClass;
    if (!_isSubclassOfWidget(constructedClass)) {
      return node;
    }

    _addLocationArgument(node, target.function, constructedClass);
    return node;
  }

  void _addLocationArgument(InvocationExpression node, FunctionNode function,
      Class constructedClass) {
    _maybeAddCreationLocationArgument(
      node.arguments,
      function,
      _computeLocation(node, function, constructedClass),
      _locationClass,
    );
  }

  @override
  ConstructorInvocation visitConstructorInvocation(ConstructorInvocation node) {
    node.transformChildren(this);

    final Constructor constructor = node.target;
    final Class constructedClass = constructor.enclosingClass;
    if (!_isSubclassOfWidget(constructedClass)) {
      return node;
    }

    _addLocationArgument(node, constructor.function, constructedClass);
    return node;
  }

  Expression _computeLocation(InvocationExpression node, FunctionNode function,
      Class constructedClass) {
    // For factory constructors we need to use the location specified as an
    // argument to the factory constructor rather than the location
    // TODO(jacobr): use hierarchy.isSubclassOf once we are using the
    // non-deprecated ClassHierarchy constructor.
    if (_currentFactory != null &&
        _hierarchy.isSubclassOf(constructedClass, _currentFactory.enclosingClass)) {
      final VariableDeclaration creationLocationParameter = _getNamedParameter(
        _currentFactory.function,
        _creationLocationParameterName,
      );
      if (creationLocationParameter != null) {
        return VariableGet(creationLocationParameter);
      }
    }

    final Arguments arguments = node.arguments;
    final Location location = node.location;
    final List<ConstructorInvocation> parameterLocations =
        <ConstructorInvocation>[];
    final List<VariableDeclaration> parameters = function.positionalParameters;
    for (int i = 0; i < arguments.positional.length; ++i) {
      final Expression expression = arguments.positional[i];
      final VariableDeclaration parameter = parameters[i];
      parameterLocations.add(_constructLocation(
        expression.location,
        name: parameter.name,
        showFile: false,
      ));
    }
    for (NamedExpression expression in arguments.named) {
      parameterLocations.add(_constructLocation(
        expression.location,
        name: expression.name,
        showFile: false,
      ));
    }
    return _constructLocation(
      location,
      parameterLocations: ListLiteral(
        parameterLocations,
        typeArgument: _locationClass.thisType,
        isConst: true,
      ),
    );
  }
}


/// Rewrites all widget constructors and constructor invocations to add a
/// parameter specifying the location the constructor was called from.
///
/// The creation location is stored as a private field named `_location`
/// on the base widget class and flowed through the constructors using a named
/// parameter.
class WidgetCreatorTracker implements ProgramTransformer {
  Class _widgetClass;
  Class _locationClass;

  /// Marker interface indicating that a private _location field is
  /// available.
  Class _hasCreationLocationClass;

  /// The [ClassHierarchy] that should be used after applying this transformer.
  /// If any class was updated, in general we need to create a new
  /// [ClassHierarchy] instance, with new dispatch targets; or at least let
  /// the existing instance know that some of its dispatch tables are not
  /// valid anymore.
  ClassHierarchy hierarchy;

  void _resolveFlutterClasses(Iterable<Library> libraries) {
    // If the Widget or Debug location classes have been updated we need to get
    // the latest version
    for (Library library in libraries) {
      final Uri importUri = library.importUri;
      if (!library.isExternal &&
          importUri != null &&
          importUri.scheme == 'package') {
        if (importUri.path == 'flutter/src/widgets/framework.dart') {
          for (Class class_ in library.classes) {
            if (class_.name == 'Widget') {
              _widgetClass = class_;
            }
          }
        } else {
          if (importUri.path == 'flutter/src/widgets/widget_inspector.dart') {
            for (Class class_ in library.classes) {
              if (class_.name == '_HasCreationLocation') {
                _hasCreationLocationClass = class_;
              } else if (class_.name == '_Location') {
                _locationClass = class_;
              }
            }
          }
        }
      }
    }
  }

  /// Modify [clazz] to add a field named [_locationFieldName] that is the
  /// first parameter of all constructors of the class.
  ///
  /// This method should only be called for classes that implement but do not
  /// extend [Widget].
  void _transformClassImplementingWidget(Class clazz) {
    if (clazz.fields
        .any((Field field) => field.name.name == _locationFieldName)) {
      // This class has already been transformed. Skip
      return;
    }
    clazz.implementedTypes
        .add(Supertype(_hasCreationLocationClass, <DartType>[]));
    // We intentionally use the library context of the _HasCreationLocation
    // class for the private field even if [clazz] is in a different library
    // so that all classes implementing Widget behave consistently.
    final Field locationField = Field(
      Name(
        _locationFieldName,
        _hasCreationLocationClass.enclosingLibrary,
      ),
      isFinal: true,
    );
    clazz.addMember(locationField);

    final Set<Constructor> _handledConstructors =
        Set<Constructor>.identity();

    void handleConstructor(Constructor constructor) {
      if (!_handledConstructors.add(constructor)) {
        return;
      }
      assert(!_hasNamedParameter(
        constructor.function,
        _creationLocationParameterName,
      ));
      final VariableDeclaration variable = VariableDeclaration(
        _creationLocationParameterName,
        type: _locationClass.thisType,
      );
      if (!_maybeAddNamedParameter(constructor.function, variable)) {
        return;
      }

      bool hasRedirectingInitializer = false;
      for (Initializer initializer in constructor.initializers) {
        if (initializer is RedirectingInitializer) {
          if (initializer.target.enclosingClass == clazz) {
            // We need to handle this constructor first or the call to
            // addDebugLocationArgument bellow will fail due to the named
            // parameter not yet existing on the constructor.
            handleConstructor(initializer.target);
          }
          _maybeAddCreationLocationArgument(
            initializer.arguments,
            initializer.target.function,
            VariableGet(variable),
            _locationClass,
          );
          hasRedirectingInitializer = true;
          break;
        }
      }
      if (!hasRedirectingInitializer) {
        constructor.initializers.add(FieldInitializer(
          locationField,
          VariableGet(variable),
        ));
        // TODO(jacobr): add an assert verifying the locationField is not
        // null. Currently, we cannot safely add this assert because we do not
        // handle Widget classes with optional positional arguments. There are
        // no Widget classes in the flutter repo with optional positional
        // arguments but it is possible users could add classes with optional
        // positional arguments.
        //
        // constructor.initializers.add(AssertInitializer(AssertStatement(
        //   IsExpression(
        //       VariableGet(variable), _locationClass.thisType),
        //   conditionStartOffset: constructor.fileOffset,
        //   conditionEndOffset: constructor.fileOffset,
        // )));
      }
    }

    // Add named parameters to all constructors.
    clazz.constructors.forEach(handleConstructor);
  }

  Component _computeFullProgram(Component deltaProgram) {
    final Set<Library> libraries = <Library>{};
    final List<Library> workList = <Library>[];
    for (Library library in deltaProgram.libraries) {
      if (libraries.add(library)) {
        workList.add(library);
      }
    }
    while (workList.isNotEmpty) {
      final Library library = workList.removeLast();
      for (LibraryDependency dependency in library.dependencies) {
        if (libraries.add(dependency.targetLibrary)) {
          workList.add(dependency.targetLibrary);
        }
      }
    }
    return Component()..libraries.addAll(libraries);
  }

  /// Transform the given [program].
  ///
  /// It is safe to call this method on a delta program generated as part of
  /// performing a hot reload.
  @override
  void transform(Component program) {
    final List<Library> libraries = program.libraries;

    if (libraries.isEmpty) {
      return;
    }

    _resolveFlutterClasses(libraries);

    if (_widgetClass == null) {
      // This application doesn't actually use the package:flutter library.
      return;
    }

    // TODO(jacobr): once there is a working incremental ClassHierarchy
    // constructor switch to using it instead of building a ClassHierarchy off
    // the full program.
    hierarchy = ClassHierarchy(
      _computeFullProgram(program),
      onAmbiguousSupertypes: (Class cls, Supertype a, Supertype b) { },
    );

    final Set<Class> transformedClasses = Set<Class>.identity();
    final Set<Library> librariesToTransform = Set<Library>.identity()
      ..addAll(libraries);

    for (Library library in libraries) {
      if (library.isExternal) {
        continue;
      }
      for (Class class_ in library.classes) {
        _transformWidgetConstructors(
          librariesToTransform,
          transformedClasses,
          class_,
        );
      }
    }

    // Transform call sites to pass the location parameter.
    final _WidgetCallSiteTransformer callsiteTransformer =
        _WidgetCallSiteTransformer(
      hierarchy,
      widgetClass: _widgetClass,
      locationClass: _locationClass,
    );

    for (Library library in libraries) {
      if (library.isExternal) {
        continue;
      }
      library.transformChildren(callsiteTransformer);
    }
  }

  bool _isSubclassOfWidget(Class clazz) {
    if (clazz == null) {
      return false;
    }
    // TODO(jacobr): use hierarchy.isSubclassOf once we are using the
    // non-deprecated ClassHierarchy constructor.
    return hierarchy.isSubclassOf(clazz, _widgetClass);
  }

  void _transformWidgetConstructors(Set<Library> librariesToBeTransformed,
      Set<Class> transformedClasses, Class clazz) {
    if (!_isSubclassOfWidget(clazz) ||
        !librariesToBeTransformed.contains(clazz.enclosingLibrary) ||
        !transformedClasses.add(clazz)) {
      return;
    }

    // Ensure super classes have been transformed before this class.
    if (clazz.superclass != null &&
        !transformedClasses.contains(clazz.superclass)) {
      _transformWidgetConstructors(
        librariesToBeTransformed,
        transformedClasses,
        clazz.superclass,
      );
    }

    for (Procedure procedure in clazz.procedures) {
      if (procedure.isFactory) {
        _maybeAddNamedParameter(
          procedure.function,
          VariableDeclaration(
            _creationLocationParameterName,
            type: _locationClass.thisType,
          ),
        );
      }
    }

    // Handle the widget class and classes that implement but do not extend the
    // widget class.
    if (!_isSubclassOfWidget(clazz.superclass)) {
      _transformClassImplementingWidget(clazz);
      return;
    }

    final Set<Constructor> _handledConstructors =
        Set<Constructor>.identity();

    void handleConstructor(Constructor constructor) {
      if (!_handledConstructors.add(constructor)) {
        return;
      }

      final VariableDeclaration variable = VariableDeclaration(
        _creationLocationParameterName,
        type: _locationClass.thisType,
      );
      if (_hasNamedParameter(
          constructor.function, _creationLocationParameterName)) {
        // Constructor was already rewritten. TODO(jacobr): is this case actually hit?
        return;
      }
      if (!_maybeAddNamedParameter(constructor.function, variable)) {
        return;
      }
      for (Initializer initializer in constructor.initializers) {
        if (initializer is RedirectingInitializer) {
          if (initializer.target.enclosingClass == clazz) {
            // We need to handle this constructor first or the call to
            // addDebugLocationArgument could fail due to the named parameter
            // not existing.
            handleConstructor(initializer.target);
          }

          _maybeAddCreationLocationArgument(
            initializer.arguments,
            initializer.target.function,
            VariableGet(variable),
            _locationClass,
          );
        } else if (initializer is SuperInitializer &&
            _isSubclassOfWidget(initializer.target.enclosingClass)) {
          _maybeAddCreationLocationArgument(
            initializer.arguments,
            initializer.target.function,
            VariableGet(variable),
            _locationClass,
          );
        }
      }
    }

    clazz.constructors.forEach(handleConstructor);
  }
}
