// Copyright (c) 2013, 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 dump_info;

import 'dart:convert'
    show HtmlEscape, JsonEncoder, StringConversionSink, ChunkedConversionSink;

import 'package:dart2js_info/info.dart';

import 'common/tasks.dart' show
    CompilerTask;
import 'constants/values.dart' show ConstantValue;
import 'compiler.dart' show
    Compiler;
import 'diagnostics/messages.dart' show
    MessageKind;
import 'diagnostics/spannable.dart' show
    NO_LOCATION_SPANNABLE;
import 'elements/elements.dart';
import 'elements/visitor.dart';
import 'types/types.dart' show
    TypeMask;
import 'deferred_load.dart' show
    OutputUnit;
import 'js_backend/js_backend.dart' show
    JavaScriptBackend;
import 'js_emitter/full_emitter/emitter.dart' as full show
    Emitter;
import 'js/js.dart' as jsAst;
import 'universe/universe.dart' show
    UniverseSelector;
import 'info/send_info.dart' show collectSendMeasurements;

class ElementInfoCollector extends BaseElementVisitor<Info, dynamic> {
  final Compiler compiler;

  final AllInfo result = new AllInfo();
  final Map<Element, Info> _elementToInfo = <Element, Info>{};
  final Map<ConstantValue, Info> _constantToInfo = <ConstantValue, Info>{};
  final Map<OutputUnit, OutputUnitInfo> _outputToInfo = {};

  ElementInfoCollector(this.compiler);

  void run() {
    compiler.dumpInfoTask._constantToNode.forEach((constant, node) {
      // TODO(sigmund): add dependencies on other constants
      var size = compiler.dumpInfoTask._nodeToSize[node];
      var code = jsAst.prettyPrint(node, compiler).getText();
      var info = new ConstantInfo(size: size, code: code);
      _constantToInfo[constant] = info;
      result.constants.add(info);

    });
    compiler.libraryLoader.libraries.forEach(visit);
  }

  Info visit(Element e, [_]) => e.accept(this, null);

  /// Whether to emit information about [element].
  ///
  /// By default we emit information for any element that contributes to the
  /// output size. Either becuase the it is a function being emitted or inlined,
  /// or because it is an element that holds dependencies to other elements.
  bool shouldKeep(Element element) {
    return compiler.dumpInfoTask.selectorsFromElement.containsKey(element) ||
        compiler.dumpInfoTask.inlineCount.containsKey(element);
  }

  /// Visits [element] and produces it's corresponding info.
  Info process(Element element) {
    // TODO(sigmund): change the visit order to eliminate the need to check
    // whether or not an element has been processed.
    return _elementToInfo.putIfAbsent(element, () => visit(element));
  }

  Info visitElement(Element element, _) => null;

  FunctionInfo visitConstructorBodyElement(ConstructorBodyElement e, _) {
    return visitFunctionElement(e.constructor, _);
  }

  LibraryInfo visitLibraryElement(LibraryElement element, _) {
    String libname = element.hasLibraryName ? element.libraryName : "<unnamed>";
    int size = compiler.dumpInfoTask.sizeOf(element);
    LibraryInfo info =
      new LibraryInfo(libname, element.canonicalUri, null, size);
    _elementToInfo[element] = info;

    LibraryElement realElement = element.isPatched ? element.patch : element;
    realElement.forEachLocalMember((Element member) {
      Info child = this.process(member);
      if (child is ClassInfo) {
        info.classes.add(child);
        child.parent = info;
      } else if (child is FunctionInfo) {
        info.topLevelFunctions.add(child);
        child.parent = info;
      } else if (child is FieldInfo) {
        info.topLevelVariables.add(child);
        child.parent = info;
      } else if (child is TypedefInfo) {
        info.typedefs.add(child);
        child.parent = info;
      } else if (child != null) {
        print('unexpected child of $info: $child ==> ${child.runtimeType}');
        assert(false);
      }
    });

    if (info.isEmpty && !shouldKeep(element)) return null;
    result.libraries.add(info);
    return info;
  }

  TypedefInfo visitTypedefElement(TypedefElement element, _) {
    if (element.alias == null) return null;
    TypedefInfo info = new TypedefInfo(element.name, '${element.alias}',
        _unitInfoForElement(element));
    _elementToInfo[element] = info;
    result.typedefs.add(info);
    return info;
  }

  FieldInfo visitFieldElement(FieldElement element, _) {
    TypeMask inferredType =
        compiler.typesTask.getGuaranteedTypeOfElement(element);
    // If a field has an empty inferred type it is never used.
    if (inferredType == null || inferredType.isEmpty) return null;

    int size = compiler.dumpInfoTask.sizeOf(element);
    String code = compiler.dumpInfoTask.codeOf(element);
    if (code != null) size += code.length;

    FieldInfo info = new FieldInfo(
        name: element.name,
        // We use element.hashCode because it is globally unique and it is
        // available while we are doing codegen.
        coverageId: '${element.hashCode}',
        type: '${element.type}',
        inferredType: '$inferredType',
        size: size,
        code: code,
        outputUnit: _unitInfoForElement(element),
        isConst: element.isConst);
    _elementToInfo[element] = info;
    if (element.isConst) {
      var value = compiler.backend.constantCompilerTask
          .getConstantValueForVariable(element);
      if (value != null) {
        info.initializer = _constantToInfo[value];
      }
    }

    List<FunctionInfo> nestedClosures = <FunctionInfo>[];
    for (Element closure in element.nestedClosures) {
      Info child = this.process(closure);
      if (child != null) {
        ClassInfo parent = this.process(closure.enclosingElement);
        if (parent != null) {
          child.name = "${parent.name}.${child.name}";
        }
        nestedClosures.add(child);
        size += child.size;
      }
    }
    info.closures = nestedClosures;
    result.fields.add(info);
    return info;
  }

  ClassInfo visitClassElement(ClassElement element, _) {
    ClassInfo classInfo = new ClassInfo(
        name: element.name,
        isAbstract: element.isAbstract,
        outputUnit: _unitInfoForElement(element));
    _elementToInfo[element] = classInfo;

    int size = compiler.dumpInfoTask.sizeOf(element);
    element.forEachLocalMember((Element member) {
      Info info = this.process(member);
      if (info == null) return;
      if (info is FieldInfo) {
        classInfo.fields.add(info);
        info.parent = classInfo;
      } else {
        assert(info is FunctionInfo);
        classInfo.functions.add(info);
        info.parent = classInfo;
      }

      // Closures are placed in the library namespace, but we want to attribute
      // them to a function, and by extension, this class.  Process and add the
      // sizes here.
      if (member is MemberElement) {
        for (Element closure in member.nestedClosures) {
          FunctionInfo closureInfo = this.process(closure);
          if (closureInfo == null) continue;

          // TODO(sigmund): remove this legacy update on the name, represent the
          // information explicitly in the info format.
          // Look for the parent element of this closure might be the enclosing
          // class or an enclosing function.
          Element parent = closure.enclosingElement;
          ClassInfo parentInfo = this.process(parent);
          if (parentInfo != null) {
            closureInfo.name = "${parentInfo.name}.${closureInfo.name}";
          }
          size += closureInfo.size;
        }
      }
    });

    classInfo.size = size;

    // Omit element if it is not needed.
    JavaScriptBackend backend = compiler.backend;
    if (!backend.emitter.neededClasses.contains(element) &&
        classInfo.fields.isEmpty &&
        classInfo.functions.isEmpty) {
      return null;
    }
    result.classes.add(classInfo);
    return classInfo;
  }

  FunctionInfo visitFunctionElement(FunctionElement element, _) {
    int size = compiler.dumpInfoTask.sizeOf(element);
    // TODO(sigmund): consider adding a small info to represent unreachable
    // code here.
    if (size == 0 && !shouldKeep(element)) return null;

    String name = element.name;
    int kind = FunctionInfo.TOP_LEVEL_FUNCTION_KIND;
    var enclosingElement = element.enclosingElement;
    if (enclosingElement.isField ||
        enclosingElement.isFunction ||
        element.isClosure ||
        enclosingElement.isConstructor) {
      kind = FunctionInfo.CLOSURE_FUNCTION_KIND;
      name = "<unnamed>";
    } else if (element.isStatic) {
      kind = FunctionInfo.TOP_LEVEL_FUNCTION_KIND;
    } else if (enclosingElement.isClass) {
      kind = FunctionInfo.METHOD_FUNCTION_KIND;
    }

    if (element.isConstructor) {
      name = name == ""
          ? "${element.enclosingElement.name}"
          : "${element.enclosingElement.name}.${element.name}";
      kind = FunctionInfo.CONSTRUCTOR_FUNCTION_KIND;
    }

    FunctionModifiers modifiers = new FunctionModifiers(
        isStatic: element.isStatic,
        isConst: element.isConst,
        isFactory: element.isFactoryConstructor,
        isExternal: element.isPatched);
    String code = compiler.dumpInfoTask.codeOf(element);

    List<ParameterInfo> parameters = <ParameterInfo>[];
    if (element.hasFunctionSignature) {
      FunctionSignature signature = element.functionSignature;
      signature.forEachParameter((parameter) {
        parameters.add(new ParameterInfo(
            parameter.name,
            '${compiler.typesTask.getGuaranteedTypeOfElement(parameter)}',
            '${parameter.node.type}'));
      });
    }

    String returnType = null;
    // TODO(sigmund): why all these checks?
    if (element.isInstanceMember &&
        !element.isAbstract &&
        compiler.world.allFunctions.contains(element)) {
      returnType = '${element.type.returnType}';
    }
    String inferredReturnType =
        '${compiler.typesTask.getGuaranteedReturnTypeOfElement(element)}';
    String sideEffects = '${compiler.world.getSideEffectsOfElement(element)}';

    int inlinedCount = compiler.dumpInfoTask.inlineCount[element];
    if (inlinedCount == null) inlinedCount = 0;

    FunctionInfo info = new FunctionInfo(
        name: name,
        // We use element.hashCode because it is globally unique and it is
        // available while we are doing codegen.
        coverageId: '${element.hashCode}',
        modifiers: modifiers,
        size: size,
        returnType: returnType,
        inferredReturnType: inferredReturnType,
        parameters: parameters,
        sideEffects: sideEffects,
        inlinedCount: inlinedCount,
        code: code,
        type: element.type.toString(),
        outputUnit: _unitInfoForElement(element));
    _elementToInfo[element] = info;

    List<FunctionInfo> nestedClosures = <FunctionInfo>[];
    if (element is MemberElement) {
      MemberElement member = element as MemberElement;
      for (Element closure in member.nestedClosures) {
        Info child = this.process(closure);
        if (child != null) {
          BasicInfo parent = this.process(closure.enclosingElement);
          if (parent != null) {
            child.name = "${parent.name}.${child.name}";
          }
          nestedClosures.add(child);
          child.parent = parent;
          size += child.size;
        }
      }
    }
    info.closures = nestedClosures;
    result.functions.add(info);
    if (const bool.fromEnvironment('send_stats')) {
      info.measurements = collectSendMeasurements(element, compiler);
    }
    return info;
  }

  OutputUnitInfo _unitInfoForElement(Element element) {
    OutputUnit outputUnit =
      compiler.deferredLoadTask.outputUnitForElement(element);
    return _outputToInfo.putIfAbsent(outputUnit, () {
      // Dump-info currently only works with the full emitter. If another
      // emitter is used it will fail here.
      JavaScriptBackend backend = compiler.backend;
      full.Emitter emitter = backend.emitter.emitter;
      OutputUnitInfo info = new OutputUnitInfo(
          outputUnit.name, emitter.outputBuffers[outputUnit].length);
      result.outputUnits.add(info);
      return info;
    });
  }
}

class Selection {
  final Element selectedElement;
  final TypeMask mask;
  Selection(this.selectedElement, this.mask);
}

class DumpInfoTask extends CompilerTask {
  DumpInfoTask(Compiler compiler) : super(compiler);

  String get name => "Dump Info";

  ElementInfoCollector infoCollector;

  /// The size of the generated output.
  int _programSize;

  // A set of javascript AST nodes that we care about the size of.
  // This set is automatically populated when registerElementAst()
  // is called.
  final Set<jsAst.Node> _tracking = new Set<jsAst.Node>();
  // A mapping from Dart Elements to Javascript AST Nodes.
  final Map<Element, List<jsAst.Node>> _elementToNodes =
      <Element, List<jsAst.Node>>{};
  final Map<ConstantValue, jsAst.Node> _constantToNode =
      <ConstantValue, jsAst.Node>{};
  // A mapping from Javascript AST Nodes to the size of their
  // pretty-printed contents.
  final Map<jsAst.Node, int> _nodeToSize = <jsAst.Node, int>{};

  final Map<Element, Set<UniverseSelector>> selectorsFromElement = {};
  final Map<Element, int> inlineCount = <Element, int>{};
  // A mapping from an element to a list of elements that are
  // inlined inside of it.
  final Map<Element, List<Element>> inlineMap = <Element, List<Element>>{};

  /// Register the size of the generated output.
  void reportSize(int programSize) {
    _programSize = programSize;
  }

  void registerInlined(Element element, Element inlinedFrom) {
    inlineCount.putIfAbsent(element, () => 0);
    inlineCount[element] += 1;
    inlineMap.putIfAbsent(inlinedFrom, () => new List<Element>());
    inlineMap[inlinedFrom].add(element);
  }

  /**
   * Registers that a function uses a selector in the
   * function body
   */
  void elementUsesSelector(Element element, UniverseSelector selector) {
    if (compiler.dumpInfo) {
      selectorsFromElement
          .putIfAbsent(element, () => new Set<UniverseSelector>())
          .add(selector);
    }
  }

  final Map<Element, Set<Element>> _dependencies = {};
  void registerDependency(Element source, Element target) {
    _dependencies.putIfAbsent(source, () => new Set()).add(target);
  }

  /**
   * Returns an iterable of [Selection]s that are used by
   * [element].  Each [Selection] contains an element that is
   * used and the selector that selected the element.
   */
  Iterable<Selection> getRetaining(Element element) {
    if (!selectorsFromElement.containsKey(element)) {
      return const <Selection>[];
    } else {
      return selectorsFromElement[element].expand((UniverseSelector selector) {
        return compiler.world.allFunctions
            .filter(selector.selector, selector.mask)
            .map((element) {
          return new Selection(element, selector.mask);
        });
      });
    }
  }

  // Returns true if we care about tracking the size of
  // this node.
  bool isTracking(jsAst.Node code) {
    if (compiler.dumpInfo) {
      return _tracking.contains(code);
    } else {
      return false;
    }
  }

  // Registers that a javascript AST node `code` was produced by the
  // dart Element `element`.
  void registerElementAst(Element element, jsAst.Node code) {
    if (compiler.dumpInfo) {
      _elementToNodes
          .putIfAbsent(element, () => new List<jsAst.Node>())
          .add(code);
      _tracking.add(code);
    }
  }

  void registerConstantAst(ConstantValue constant, jsAst.Node code) {
    if (compiler.dumpInfo) {
      assert(_constantToNode[constant] == null ||
          _constantToNode[constant] == code);
      _constantToNode[constant] = code;
      _tracking.add(code);
    }
  }

  // Records the size of a dart AST node after it has been
  // pretty-printed into the output buffer.
  void recordAstSize(jsAst.Node node, int size) {
    if (isTracking(node)) {
      //TODO: should I be incrementing here instead?
      _nodeToSize[node] = size;
    }
  }

  // Returns the size of the source code that
  // was generated for an element.  If no source
  // code was produced, return 0.
  int sizeOf(Element element) {
    if (_elementToNodes.containsKey(element)) {
      return _elementToNodes[element].map(sizeOfNode).fold(0, (a, b) => a + b);
    } else {
      return 0;
    }
  }

  int sizeOfNode(jsAst.Node node) {
    // TODO(sigmund): switch back to null aware operators (issue #24136)
    var size = _nodeToSize[node];
    return size == null ? 0 : size;
  }

  String codeOf(Element element) {
    List<jsAst.Node> code = _elementToNodes[element];
    if (code == null) return null;
    // Concatenate rendered ASTs.
    StringBuffer sb = new StringBuffer();
    for (jsAst.Node ast in code) {
      sb.writeln(jsAst.prettyPrint(ast, compiler).getText());
    }
    return sb.toString();
  }

  void dumpInfo() {
    measure(() {
      infoCollector = new ElementInfoCollector(compiler)..run();
      StringBuffer jsonBuffer = new StringBuffer();
      dumpInfoJson(jsonBuffer);
      compiler.outputProvider('', 'info.json')
        ..add(jsonBuffer.toString())
        ..close();
    });
  }

  void dumpInfoJson(StringSink buffer) {
    JsonEncoder encoder = const JsonEncoder.withIndent('  ');
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.start();

    // Recursively build links to function uses
    Iterable<Element> functionElements =
        infoCollector._elementToInfo.keys.where((k) => k is FunctionElement);
    for (FunctionElement element in functionElements) {
      FunctionInfo info = infoCollector._elementToInfo[element];
      Iterable<Selection> uses = getRetaining(element);
      // Don't bother recording an empty list of dependencies.
      for (Selection selection in uses) {
        // Don't register dart2js builtin functions that are not recorded.
        Info useInfo = infoCollector._elementToInfo[selection.selectedElement];
        if (useInfo == null) continue;
        info.uses.add(new DependencyInfo(useInfo, '${selection.mask}'));
      }
    }

    // Track dependencies that come from inlining.
    for (Element element in inlineMap.keys) {
      CodeInfo outerInfo = infoCollector._elementToInfo[element];
      if (outerInfo == null) continue;
      for (Element inlined in inlineMap[element]) {
        Info inlinedInfo = infoCollector._elementToInfo[inlined];
        if (inlinedInfo == null) continue;
        outerInfo.uses.add(new DependencyInfo(inlinedInfo, 'inlined'));
      }
    }

    AllInfo result = infoCollector.result;

    for (Element element in _dependencies.keys) {
      var a = infoCollector._elementToInfo[element];
      if (a == null) continue;
      result.dependencies[a] = _dependencies[element]
        .map((o) => infoCollector._elementToInfo[o])
        .where((o) => o != null)
        .toList();
    }

    result.deferredFiles = compiler.deferredLoadTask.computeDeferredMap();
    stopwatch.stop();
    result.program = new ProgramInfo(
        size: _programSize,
        dart2jsVersion: compiler.hasBuildId ? compiler.buildId : null,
        compilationMoment: new DateTime.now(),
        compilationDuration: compiler.totalCompileTime.elapsed,
        toJsonDuration: stopwatch.elapsedMilliseconds,
        dumpInfoDuration: this.timing,
        noSuchMethodEnabled: compiler.backend.enabledNoSuchMethod,
        minified: compiler.enableMinification);

    ChunkedConversionSink<Object> sink = encoder.startChunkedConversion(
        new StringConversionSink.fromStringSink(buffer));
    sink.add(result.toJson());
    reporter.reportInfo(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, {
      'text': "View the dumped .info.json file at "
          "https://dart-lang.github.io/dump-info-visualizer"
    });
  }
}
