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

/**
 * This file contains code to output a description of tasks and their
 * dependencies in ".dot" format.  Prior to running, the user should run "pub
 * get" in the analyzer directory to ensure that a "packages" folder exists.
 *
 * The ".dot" file is output to standard out.  To convert it to a pdf, store it
 * in a file (e.g. "tasks.dot"), and post-process it with
 * "dot tasks.dart -Tpdf -O".
 *
 * TODO(paulberry):
 * - Add general.dart and html.dart for completeness.
 * - Use Graphviz's "record" feature to produce more compact output
 *   (http://www.graphviz.org/content/node-shapes#record)
 * - Produce a warning if a result descriptor is found which isn't the output
 *   of exactly one task.
 * - Convert this tool to use package_config to find the package map.
 */
library task_dependency_graph;

import 'dart:io' hide File;

import 'package:analyzer/analyzer.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/java_io.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/sdk_io.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:path/path.dart' as path;

main() {
  new Driver().run();
}

typedef void ResultDescriptorFinderCallback(PropertyAccessorElement element);

class Driver {
  PhysicalResourceProvider resourceProvider;
  AnalysisContext context;
  InterfaceType resultDescriptorType;
  String rootDir;

  void findResultDescriptors(
      AstNode node, void callback(String descriptorName)) {
    Set<PropertyAccessorElement> resultDescriptors =
        new Set<PropertyAccessorElement>();
    node.accept(new ResultDescriptorFinder(
        resultDescriptorType, resultDescriptors.add));
    for (PropertyAccessorElement resultDescriptor in resultDescriptors) {
      callback(resultDescriptor.name);
    }
  }

  /**
   * Find the root directory of the analyzer package by proceeding
   * upward to the 'tool' dir, and then going up one more directory.
   */
  String findRoot(String pathname) {
    while (path.basename(pathname) != 'tool') {
      String parent = path.dirname(pathname);
      if (parent.length >= pathname.length) {
        throw new Exception("Can't find root directory");
      }
      pathname = parent;
    }
    return path.dirname(pathname);
  }

  CompilationUnit getUnit(Source source) =>
      context.resolveCompilationUnit2(source, source);

  void run() {
    rootDir = findRoot(Platform.script.toFilePath(windows: Platform.isWindows));
    resourceProvider = PhysicalResourceProvider.INSTANCE;
    DartSdk sdk = DirectoryBasedDartSdk.defaultSdk;
    context = AnalysisEngine.instance.createAnalysisContext();
    JavaFile packagesDir = new JavaFile(path.join(rootDir, 'packages'));
    List<UriResolver> uriResolvers = [
      new DartUriResolver(sdk),
      new PackageUriResolver(<JavaFile>[packagesDir]),
      new FileUriResolver()
    ];
    context.sourceFactory = new SourceFactory(uriResolvers);
    Source taskSource =
        setupSource(path.join('lib', 'src', 'task', 'dart.dart'));
    Source modelSource = setupSource(path.join('lib', 'task', 'model.dart'));
    CompilationUnitElement modelElement = getUnit(modelSource).element;
    InterfaceType analysisTaskType = modelElement.getType('AnalysisTask').type;
    DartType dynamicType = context.typeProvider.dynamicType;
    resultDescriptorType = modelElement
        .getType('ResultDescriptor')
        .type
        .substitute4([dynamicType]);
    CompilationUnit taskUnit = getUnit(taskSource);
    CompilationUnitElement taskUnitElement = taskUnit.element;
    print('digraph G {');
    Set<String> results = new Set<String>();
    for (ClassElement cls in taskUnitElement.types) {
      if (!cls.isAbstract && cls.type.isSubtypeOf(analysisTaskType)) {
        String task = cls.name;
        // TODO(paulberry): node is deprecated.  What am I supposed to do
        // instead?
        findResultDescriptors(cls.getMethod('buildInputs').node,
            (String input) {
          results.add(input);
          print('  $input -> $task');
        });
        findResultDescriptors(cls.getField('DESCRIPTOR').node, (String output) {
          results.add(output);
          print('  $task -> $output');
        });
      }
    }
    for (String result in results) {
      print('  $result [shape=box]');
    }
    print('}');
  }

  Source setupSource(String filename) {
    String filePath = path.join(rootDir, filename);
    File file = resourceProvider.getResource(filePath);
    Source source = file.createSource();
    Uri restoredUri = context.sourceFactory.restoreUri(source);
    if (restoredUri != null) {
      source = file.createSource(restoredUri);
    }
    ChangeSet changeSet = new ChangeSet();
    changeSet.addedSource(source);
    context.applyChanges(changeSet);
    return source;
  }
}

class ResultDescriptorFinder extends GeneralizingAstVisitor {
  final InterfaceType resultDescriptorType;
  final ResultDescriptorFinderCallback callback;

  ResultDescriptorFinder(this.resultDescriptorType, this.callback);

  @override
  visitIdentifier(Identifier node) {
    Element element = node.staticElement;
    if (element is PropertyAccessorElement &&
        element.isGetter &&
        element.returnType.isSubtypeOf(resultDescriptorType)) {
      callback(element);
    }
  }
}
