// 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 dart2js.inferrer.type_graph_dump;

import '../../compiler_new.dart';
import '../elements/entities.dart';
import '../elements/entity_utils.dart' as utils;
import 'abstract_value_domain.dart';
import 'inferrer_engine.dart';
import 'type_graph_nodes.dart';
import 'debug.dart';

/// Dumps the type inference graph in Graphviz Dot format into the `typegraph`
/// subfolder of the current working directory. Each function body is dumped in
/// a separate file.
///
/// The resulting .dot files must be processed using the Graphviz `dot` command,
/// which can be obtained from `http://www.graphviz.org`, or installed using
/// most package managers (search for `graphviz` or `dot`).
///
/// Example commands:
///
///     dot -Tpng -O typegraph/main.dot
///     open typegraph/main.dot.png
///
///     dot -Tpng -O typegraph/dart._internal.Sort._dualPivotQuicksort.dot
///     open typegraph/dart._internal.Sort._dualPivotQuicksort.dot.png
///
class TypeGraphDump {
  static const String outputDir = 'typegraph';

  final CompilerOutput compilerOutput;
  final InferrerEngine inferrer;
  final Map<TypeInformation, Set<TypeInformation>> assignmentsBeforeAnalysis =
      <TypeInformation, Set<TypeInformation>>{};
  final Map<TypeInformation, Set<TypeInformation>> assignmentsBeforeTracing =
      <TypeInformation, Set<TypeInformation>>{};
  final Set<String> usedFilenames = new Set<String>();

  TypeGraphDump(this.compilerOutput, this.inferrer);

  /// Take a copy of the assignment set for each node, since that may change
  /// during the analysis.
  void beforeAnalysis() {
    for (TypeInformation node in inferrer.types.allTypes) {
      Set<TypeInformation> copy = node.inputs.toSet();
      if (!copy.isEmpty) {
        assignmentsBeforeAnalysis[node] = copy;
      }
    }
  }

  /// Like [beforeAnalysis], takes a copy of the assignment sets.
  void beforeTracing() {
    for (TypeInformation node in inferrer.types.allTypes) {
      Set<TypeInformation> copy = node.inputs.toSet();
      if (!copy.isEmpty) {
        assignmentsBeforeTracing[node] = copy;
      }
    }
  }

  /// Dumps the entire graph.
  void afterAnalysis() {
    // Group all the type nodes by their context member.
    Map<MemberEntity, List<TypeInformation>> nodes =
        <MemberEntity, List<TypeInformation>>{};
    for (TypeInformation node in inferrer.types.allTypes) {
      if (node.contextMember != null) {
        nodes
            .putIfAbsent(node.contextMember, () => <TypeInformation>[])
            .add(node);
      }
    }
    // Print every group separately.
    for (MemberEntity element in nodes.keys) {
      OutputSink output;
      try {
        String name = filenameFromElement(element);
        output = compilerOutput.createOutputSink(
            '$outputDir/$name', 'dot', OutputType.debug);
        _GraphGenerator visitor = new _GraphGenerator(
            this, element, output, inferrer.abstractValueDomain.getCompactText);
        for (TypeInformation node in nodes[element]) {
          visitor.visit(node);
        }
        visitor.addMissingNodes();
        visitor.finish();
      } finally {
        if (output != null) {
          output.close();
        }
      }
    }
  }

  /// Returns the filename (without extension) in which to dump the type
  /// graph for [element].
  ///
  /// Will never return the a given filename more than once, even if called with
  /// the same element.
  String filenameFromElement(MemberEntity element) {
    // The toString method of elements include characters that are unsuitable
    // for URIs and file systems.
    List<String> parts = <String>[];
    parts.add(element.library.canonicalUri.pathSegments.last);
    parts.add(element.enclosingClass?.name);
    if (element.isGetter) {
      parts.add('get-${element.name}');
    } else if (element.isSetter) {
      parts.add('set-${element.name}');
    } else if (element.isConstructor) {
      if (element.name.isEmpty) {
        parts.add('-constructor');
      } else {
        parts.add(element.name);
      }
    } else {
      parts.add(
          utils.operatorNameToIdentifier(element.name).replaceAll(r'$', '-'));
    }
    String filename = parts.where((x) => x != null && x != '').join('.');
    if (usedFilenames.add(filename)) return filename;
    // The filename has already been used by another method. Append a serial
    // number to ensure we don't overwrite it.
    int serialNumber = 2;
    while (!usedFilenames.add('$filename-$serialNumber')) {
      ++serialNumber;
    }
    return '$filename-$serialNumber';
  }
}

/// Builds the Graphviz Dot file for one function body.
class _GraphGenerator extends TypeInformationVisitor {
  final TypeGraphDump global;
  final Set<TypeInformation> seen = new Set<TypeInformation>();
  final List<TypeInformation> worklist = <TypeInformation>[];
  final Map<TypeInformation, int> nodeId = <TypeInformation, int>{};
  final String Function(AbstractValue) formatType;
  int usedIds = 0;
  final OutputSink output;
  final MemberEntity element;
  TypeInformation returnValue;

  _GraphGenerator(this.global, this.element, this.output, this.formatType) {
    returnValue = global.inferrer.types.getInferredTypeOfMember(element);
    getNode(returnValue); // Ensure return value is part of graph.
    append('digraph {');
  }

  void finish() {
    append('}');
  }

  /// Ensures that all nodes which have been referenced are generated.
  ///
  /// Sometimes an input to a TypeInformation node does not belong to the same
  /// function body, and the graph looks confusing if they are missing.
  void addMissingNodes() {
    while (worklist.isNotEmpty) {
      TypeInformation node = worklist.removeLast();
      assert(nodeId.containsKey(node));
      visit(node);
    }
  }

  void visit(TypeInformation info) {
    if (seen.contains(info)) return;
    info.accept(this);
  }

  void append(String string) {
    output..add(string)..add('\n');
  }

  String shorten(String text) {
    if (text.length > 40) {
      return text.substring(0, 19) + '...' + text.substring(text.length - 18);
    }
    return text;
  }

  int getFreshId() => ++usedIds;

  /// Obtains a unique ID for the node representing [info].
  String getNode(TypeInformation info) {
    int id = nodeId.putIfAbsent(info, () {
      worklist.add(info); // Ensure that the referenced node is generated.
      return getFreshId();
    });
    return '$id';
  }

  final RegExp escapeRegexp = new RegExp('["{}<>|]');

  /// Escapes characters in [text] so it can be used as part of a label.
  String escapeLabel(String text) {
    return text.replaceAllMapped(escapeRegexp, (m) => '\\${m.group(0)}');
  }

  /// Creates an edge from [src] to [dst].
  ///
  /// If [dst] is a record type node, [port] may refer to one of the fields
  /// defined in that record (e.g. `obj`, `arg0`, `arg1`, etc)
  void addEdge(TypeInformation src, TypeInformation dst,
      {String port, String color: 'black'}) {
    if (isExternal(src) && isExternal(dst)) {
      return; // Do not add edges between external nodes.
    }
    String dstText = getNode(dst);
    if (port != null) {
      dstText += ':$port';
    }
    if (src is ConcreteTypeInformation) {
      // Concrete types can have a huge number of uses which will flood the
      // graph with very long hard-to-follow edges. Copy the concrete nodes
      // for every use to enhance readability.
      int id = getFreshId();
      String type = escapeLabel('${formatType(src.type)}');
      String text = 'Concrete';
      String label = '{$text|<returnType> $type}';
      append('$id [shape=record,style=dotted,label="$label"]');
      append('$id -> $dstText [color="$color"]');
    } else {
      append('${getNode(src)}:returnType -> $dstText [color="$color"]');
    }
  }

  // Some graphs are flooded by a huge number of phi and narrow nodes.
  // We color the nodes so the "interesting" nodes stand out more.
  static const String defaultNodeColor = '#eeffee';
  static const String phiColor = '#eeffff';
  static const String narrowColor = phiColor;
  static const String callColor = '#ffffee';

  // Colors for edges based on whether they were added or removed during the
  // analysis.
  static const String unchangedEdge = 'black';
  static const String addedEdge = 'green4';
  static const String removedEdge = 'red3';
  static const String temporaryEdge = 'orange'; // Added and then removed again.

  bool isExternal(TypeInformation node) {
    return node != returnValue && node.contextMember != element;
  }

  String getStyleForNode(TypeInformation node, String color) {
    return isExternal(node)
        ? 'style=dotted'
        : 'style=filled,fillcolor="$color"';
  }

  /// Adds details that are not specific to a subclass of [TypeInformation].
  String appendDetails(TypeInformation node, String text) {
    if (node == returnValue) {
      return '$text\n(return value)';
    }
    if (node.contextMember != null && node.contextMember != element) {
      return '$text\n(from ${node.contextMember})';
    }
    return text;
  }

  /// Creates a node for [node] displaying the given [text] in its box.
  ///
  /// [inputs] specify named inputs to the node. If omitted, edges will be
  /// based on [node.inputs].
  void addNode(TypeInformation node, String text,
      {String color: defaultNodeColor, Map<String, TypeInformation> inputs}) {
    seen.add(node);
    String style = getStyleForNode(node, color);
    text = appendDetails(node, text);
    text = escapeLabel(text);
    String id = getNode(node);
    String returnType = escapeLabel(formatType(node.type));
    if (inputs != null) {
      Iterable<String> keys = inputs.keys.where((key) => inputs[key] != null);
      String header = keys.map((key) => '<a$key> $key').join('|');
      String label = '{{$header}|$text|<returnType> $returnType}';
      append('$id [shape=record,label="$label",$style]');
      for (String key in keys) {
        addEdge(inputs[key], node, port: 'a$key');
      }
    } else {
      String label = '{$text|<returnType> $returnType}';
      append('$id [shape=record,label="$label",$style]');
      // Add assignment edges. Color the edges based on whether they were
      // added, removed, temporary, or unchanged.
      dynamic originalSet = global.assignmentsBeforeAnalysis[node] ?? const [];
      var tracerSet = global.assignmentsBeforeTracing[node] ?? const [];
      var currentSet = node.inputs.toSet();
      for (TypeInformation assignment in currentSet) {
        String color =
            originalSet.contains(assignment) ? unchangedEdge : addedEdge;
        addEdge(assignment, node, color: color);
      }
      for (TypeInformation assignment in originalSet) {
        if (!currentSet.contains(assignment)) {
          addEdge(assignment, node, color: removedEdge);
        }
      }
      for (TypeInformation assignment in tracerSet) {
        if (!currentSet.contains(assignment) &&
            !originalSet.contains(assignment)) {
          addEdge(assignment, node, color: temporaryEdge);
        }
      }
    }
    if (PRINT_GRAPH_ALL_NODES) {
      for (TypeInformation user in node.users) {
        if (!isExternal(user)) {
          visit(user);
        }
      }
    }
  }

  @override
  void visitNarrowTypeInformation(NarrowTypeInformation info) {
    // Omit unused Narrows.
    if (!PRINT_GRAPH_ALL_NODES && info.users.isEmpty) return;
    addNode(info, 'Narrow\n${formatType(info.typeAnnotation)}',
        color: narrowColor);
  }

  @override
  void visitPhiElementTypeInformation(PhiElementTypeInformation info) {
    // Omit unused Phis.
    if (!PRINT_GRAPH_ALL_NODES && info.users.isEmpty) return;
    addNode(info, 'Phi ${info.variable?.name ?? ''}', color: phiColor);
  }

  @override
  void visitElementInContainerTypeInformation(
      ElementInContainerTypeInformation info) {
    addNode(info, 'ElementInContainer');
  }

  @override
  void visitElementInSetTypeInformation(ElementInSetTypeInformation info) {
    addNode(info, 'ElementInSet');
  }

  @override
  void visitKeyInMapTypeInformation(KeyInMapTypeInformation info) {
    addNode(info, 'KeyInMap');
  }

  @override
  void visitValueInMapTypeInformation(ValueInMapTypeInformation info) {
    addNode(info, 'ValueInMap');
  }

  @override
  void visitListTypeInformation(ListTypeInformation info) {
    addNode(info, 'List');
  }

  @override
  void visitSetTypeInformation(SetTypeInformation info) {
    addNode(info, 'Set');
  }

  @override
  void visitMapTypeInformation(MapTypeInformation info) {
    addNode(info, 'Map');
  }

  @override
  void visitConcreteTypeInformation(ConcreteTypeInformation info) {
    addNode(info, 'Concrete');
  }

  @override
  void visitStringLiteralTypeInformation(StringLiteralTypeInformation info) {
    String text = shorten(info.value).replaceAll('\n', '\\n');
    addNode(info, 'StringLiteral\n"$text"');
  }

  @override
  void visitBoolLiteralTypeInformation(BoolLiteralTypeInformation info) {
    addNode(info, 'BoolLiteral\n${info.value}');
  }

  void handleCall(CallSiteTypeInformation info, String text,
      Map<String, TypeInformation> inputs) {
    String sourceCode = shorten('${info.debugName}');
    text = '$text\n$sourceCode';
    if (info.arguments != null) {
      for (int i = 0; i < info.arguments.positional.length; ++i) {
        inputs['arg$i'] = info.arguments.positional[i];
      }
      for (String argName in info.arguments.named.keys) {
        inputs[argName] = info.arguments.named[argName];
      }
    }
    addNode(info, text, color: callColor, inputs: inputs);
  }

  @override
  void visitClosureCallSiteTypeInformation(
      ClosureCallSiteTypeInformation info) {
    handleCall(info, 'ClosureCallSite', {});
  }

  @override
  void visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
    handleCall(info, 'StaticCallSite', {});
  }

  @override
  void visitIndirectDynamicCallSiteTypeInformation(
      IndirectDynamicCallSiteTypeInformation info) {
    handleCall(info, 'IndirectDynamicCallSite', {});
  }

  @override
  void visitDynamicCallSiteTypeInformation(
      DynamicCallSiteTypeInformation info) {
    handleCall(info, 'DynamicCallSite', {'obj': info.receiver});
  }

  @override
  void visitMemberTypeInformation(MemberTypeInformation info) {
    addNode(info, 'Member\n${info.debugName}');
  }

  @override
  void visitParameterTypeInformation(ParameterTypeInformation info) {
    addNode(info, 'Parameter ${info.debugName}');
  }

  @override
  void visitIndirectParameterTypeInformation(
      IndirectParameterTypeInformation info) {
    addNode(info, 'IndirectParameter ${info.debugName}');
  }

  @override
  void visitClosureTypeInformation(ClosureTypeInformation info) {
    String text = shorten('${info.debugName}');
    addNode(info, 'Closure\n$text');
  }

  @override
  void visitAwaitTypeInformation(AwaitTypeInformation info) {
    String text = shorten('${info.debugName}');
    addNode(info, 'Await\n$text');
  }

  @override
  void visitYieldTypeInformation(YieldTypeInformation info) {
    String text = shorten('${info.debugName}');
    addNode(info, 'Yield\n$text');
  }
}
