// 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.

import 'dart:convert';

import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary/base.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/link.dart';
import 'package:analyzer/src/summary/package_bundle_reader.dart';

/**
 * Collect the inferred types from all the summary files listed in [args] and
 * print them in alphabetical order.
 */
main(List<String> args) {
  SummaryDataStore summaryDataStore = new SummaryDataStore(args);
  InferredTypeCollector collector = new InferredTypeCollector(
      (String uri) => summaryDataStore.linkedMap[uri],
      (String uri) => summaryDataStore.unlinkedMap[uri]);
  collector.visitSummaryDataStore(summaryDataStore);
  collector.dumpCollectedTypes();
}

/**
 * Visitor class that visits the contents of a summary file and collects the
 * inferred types in it.
 */
class InferredTypeCollector {
  UnlinkedUnit unlinkedUnit;
  LinkedUnit linkedUnit;
  CompilationUnitElementForLink unitForLink;
  final Map<String, String> inferredTypes = <String, String>{};
  List<String> typeParamsInScope = <String>[];
  final Linker _linker;

  InferredTypeCollector(
      GetDependencyCallback getDependency, GetUnitCallback getUnit)
      : _linker =
            new Linker({}, getDependency, getUnit, null, AnalysisOptionsImpl());

  /**
   * If an inferred type exists matching the given [slot], record that it is the
   * type of the entity reachable via [path].
   */
  void collectInferredType(int slot, String path) {
    for (EntityRef type in linkedUnit.types) {
      if (type.slot == slot) {
        inferredTypes[path] = formatType(type);
        return;
      }
    }
  }

  /**
   * Collect the inferred type in summary object [obj] (if any), which is
   * reachable via [path].
   *
   * This method may modify [properties] in order to affect how sub-elements
   * are visited.
   */
  void collectInferredTypes(
      SummaryClass obj, Map<String, Object> properties, String path) {
    if (obj is UnlinkedVariable) {
      collectInferredType(obj.inferredTypeSlot, path);
      // As a temporary measure, prevent recursion into the variable's
      // initializer, since AST-based type inference doesn't infer its type
      // correctly yet.  TODO(paulberry): fix.
      properties.remove('initializer');
    } else if (obj is UnlinkedExecutable) {
      collectInferredType(obj.inferredReturnTypeSlot, path);
      // As a temporary measure, prevent recursion into the executable's local
      // variables and local functions, since AST-based type inference doesn't
      // infer locals correctly yet.  TODO(paulberry): fix if necessary.
      properties.remove('localFunctions');
      properties.remove('localVariables');
    } else if (obj is UnlinkedParam) {
      collectInferredType(obj.inferredTypeSlot, path);
      // As a temporary measure, prevent recursion into the parameter's
      // initializer, since AST-based type inference doesn't infer its type
      // correctly yet.  TODO(paulberry): fix.
      properties.remove('initializer');
    }
  }

  /**
   * Print out all the inferred types collected so far, in alphabetical order.
   */
  void dumpCollectedTypes() {
    print('Collected types (${inferredTypes.length}):');
    List<String> paths = inferredTypes.keys.toList();
    paths.sort();
    for (String path in paths) {
      print('$path -> ${inferredTypes[path]}');
    }
  }

  /**
   * Format the given [type] as a string.  Unlike the type's [toString] method,
   * this formats types using their complete URI to avoid ambiguity.
   */
  String formatDartType(DartType type) {
    if (type is FunctionType) {
      List<String> argStrings =
          type.normalParameterTypes.map(formatDartType).toList();
      List<DartType> optionalParameterTypes = type.optionalParameterTypes;
      if (optionalParameterTypes.isNotEmpty) {
        List<String> optionalArgStrings =
            optionalParameterTypes.map(formatDartType).toList();
        argStrings.add('[${optionalArgStrings.join(', ')}]');
      }
      Map<String, DartType> namedParameterTypes = type.namedParameterTypes;
      if (namedParameterTypes.isNotEmpty) {
        List<String> namedArgStrings = <String>[];
        namedParameterTypes.forEach((String name, DartType type) {
          namedArgStrings.add('$name: ${formatDartType(type)}');
        });
        argStrings.add('{${namedArgStrings.join(', ')}}');
      }
      return '(${argStrings.join(', ')}) → ${formatDartType(type.returnType)}';
    } else if (type is InterfaceType) {
      if (type.typeArguments.isNotEmpty) {
        // TODO(paulberry): implement.
        throw new UnimplementedError('type args');
      }
      return formatElement(type.element);
    } else if (type is DynamicTypeImpl) {
      return type.toString();
    } else {
      // TODO(paulberry): implement.
      throw new UnimplementedError(
          "Don't know how to format type of type ${type.runtimeType}");
    }
  }

  /**
   * Format the given [element] as a string, assuming it represents a type.
   * Unlike the element's [toString] method, this formats elements using their
   * complete URI to avoid ambiguity.
   */
  String formatElement(Element element) {
    if (element is ClassElementForLink_Class ||
        element is MethodElementForLink ||
        element is ClassElementForLink_Enum ||
        element is SpecialTypeElementForLink ||
        element is FunctionTypeAliasElementForLink ||
        element is TopLevelFunctionElementForLink) {
      return element.toString();
    } else if (element is FunctionElementForLink_Local_NonSynthetic) {
      return formatDartType(element.type);
    } else if (element is UndefinedElementForLink) {
      return '???';
    } else {
      throw new UnimplementedError(
          "Don't know how to format reference of type ${element.runtimeType}");
    }
  }

  /**
   * Interpret the given [param] as a parameter in a synthetic typedef, and
   * format it as a string.
   */
  String formatParam(UnlinkedParam param) {
    if (param.isFunctionTyped) {
      // TODO(paulberry): fix this case.
      return 'BAD(${json.encode(param)})';
    }
    String result;
    if (param.type != null) {
      result = '${formatType(param.type)} ${param.name}';
    } else {
      result = param.name;
    }
    if (param.kind == UnlinkedParamKind.named) {
      result = '{$result}';
    } else if (param.kind == UnlinkedParamKind.positional) {
      result = '[$result]';
    }
    return result;
  }

  /**
   * Convert the reference with index [index] into a string.  If [typeOf] is
   * `true`, the reference is being used in the context of naming a type, so
   * if the entity being referenced is not a type, it will be enclosed in
   * `typeof()` for clarity.
   */
  String formatReference(int index, {bool typeOf: false}) {
    ReferenceableElementForLink element = unitForLink.resolveRef(index);
    return formatElement(element);
  }

  /**
   * Interpret the given [entityRef] as a reference to a type, and format it as
   * a string.
   */
  String formatType(EntityRef entityRef) {
    List<int> implicitFunctionTypeIndices =
        entityRef.implicitFunctionTypeIndices;
    if (entityRef.syntheticReturnType != null) {
      String params = entityRef.syntheticParams.map(formatParam).join(', ');
      String retType = formatType(entityRef.syntheticReturnType);
      return '($params) -> $retType';
    }
    if (entityRef.paramReference != 0) {
      return typeParamsInScope[
          typeParamsInScope.length - entityRef.paramReference];
    }
    String result = formatReference(entityRef.reference, typeOf: true);
    List<EntityRef> typeArguments = entityRef.typeArguments.toList();
    while (typeArguments.isNotEmpty && isDynamic(typeArguments.last)) {
      typeArguments.removeLast();
    }
    if (typeArguments.isNotEmpty) {
      result += '<${typeArguments.map(formatType).join(', ')}>';
    }
    if (implicitFunctionTypeIndices.isNotEmpty) {
      result =
          'parameterOf($result, ${implicitFunctionTypeIndices.join(', ')})';
    }
    return result;
  }

  /**
   * Determine if the given [entityRef] represents the pseudo-type `dynamic`.
   */
  bool isDynamic(EntityRef entityRef) {
    if (entityRef.syntheticReturnType != null ||
        entityRef.paramReference != 0) {
      return false;
    }
    return formatReference(entityRef.reference, typeOf: true) == 'dynamic';
  }

  /**
   * Collect all the inferred types contained in [obj], which is reachable via
   * [path].  [properties] is the result of calling `obj.toMap()`, and may be
   * modified before returning.
   */
  void visit(SummaryClass obj, Map<String, Object> properties, String path) {
    List<String> oldTypeParamsInScope = typeParamsInScope;
    Object newTypeParams = properties['typeParameters'];
    if (newTypeParams is List && newTypeParams.isNotEmpty) {
      typeParamsInScope = typeParamsInScope.toList();
      for (Object typeParam in newTypeParams) {
        if (typeParam is UnlinkedTypeParam) {
          typeParamsInScope.add(typeParam.name);
        } else {
          throw new StateError(
              'Unexpected type param type: ${typeParam.runtimeType}');
        }
      }
    }
    collectInferredTypes(obj, properties, path);
    properties.forEach((String key, Object value) {
      if (value is SummaryClass) {
        visit(value, value.toMap(), '$path.$key');
      } else if (value is List) {
        for (int i = 0; i < value.length; i++) {
          Object item = value[i];
          if (item is SummaryClass) {
            Map<String, Object> itemProperties = item.toMap();
            String indexOrName = itemProperties['name'] ?? i.toString();
            visit(item, itemProperties, '$path.$key[$indexOrName]');
          }
        }
      }
    });
    typeParamsInScope = oldTypeParamsInScope;
  }

  /**
   * Collect all the inferred types contained in [summaryDataStore].
   */
  void visitSummaryDataStore(SummaryDataStore summaryDataStore) {
    // Figure out which unlinked units are a part of another library so we won't
    // visit them redundantly.
    Set<String> partOfUris = new Set<String>();
    summaryDataStore.unlinkedMap
        .forEach((String unitUriString, UnlinkedUnit unlinkedUnit) {
      Uri unitUri = Uri.parse(unitUriString);
      for (String relativePartUriString in unlinkedUnit.publicNamespace.parts) {
        partOfUris.add(
            resolveRelativeUri(unitUri, Uri.parse(relativePartUriString))
                .toString());
      }
    });
    summaryDataStore.linkedMap
        .forEach((String libraryUriString, LinkedLibrary linkedLibrary) {
      if (partOfUris.contains(libraryUriString)) {
        return;
      }
      if (libraryUriString.startsWith('dart:')) {
        // Don't bother dumping inferred types from the SDK.
        return;
      }
      Uri libraryUri = Uri.parse(libraryUriString);
      UnlinkedUnit definingUnlinkedUnit =
          summaryDataStore.unlinkedMap[libraryUriString];
      if (definingUnlinkedUnit != null) {
        visitUnit(
            definingUnlinkedUnit, linkedLibrary.units[0], libraryUriString, 0);
        for (int i = 0;
            i < definingUnlinkedUnit.publicNamespace.parts.length;
            i++) {
          Uri relativePartUri =
              Uri.parse(definingUnlinkedUnit.publicNamespace.parts[i]);
          String unitUriString =
              resolveRelativeUri(libraryUri, relativePartUri).toString();
          UnlinkedUnit unlinkedUnit =
              summaryDataStore.unlinkedMap[unitUriString];
          if (unlinkedUnit != null) {
            visitUnit(unlinkedUnit, linkedLibrary.units[i + 1],
                libraryUriString, i + 1);
          }
        }
      }
    });
  }

  /**
   * Collect all the inferred types contained in the compilation unit described
   * by [unlinkedUnit] and [linkedUnit], which has URI [libraryUriString].
   */
  void visitUnit(UnlinkedUnit unlinkedUnit, LinkedUnit linkedUnit,
      String libraryUriString, int unitNum) {
    this.unlinkedUnit = unlinkedUnit;
    this.linkedUnit = linkedUnit;
    this.unitForLink =
        _linker.getLibrary(Uri.parse(libraryUriString)).units[unitNum];
    visit(unlinkedUnit, unlinkedUnit.toMap(), libraryUriString);
    this.unlinkedUnit = null;
    this.linkedUnit = null;
    this.unitForLink = null;
  }
}
