<commit_before>// 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:io';

import 'package:yaml/yaml.dart';

/// A graph of the package dependencies for an application.
class PackageGraph {
  /// The root application package.
  final PackageNode root;

  /// All the package dependencies of [root], transitive and direct.
  Set<PackageNode> get allPackages {
    var seen = new Set<PackageNode>()..add(root);

    void addDeps(PackageNode package) {
      for (var dep in package.dependencies) {
        if (seen.contains(dep)) continue;
        seen.add(dep);
        addDeps(dep);
      }
    }
    addDeps(root);

    return seen;
  }

  PackageGraph._(this.root);

  /// Creates a [PackageGraph] for the package in which you are currently
  /// running.
  factory PackageGraph.forThisPackage() {
    /// Read in the pubspec file and parse it as yaml.
    var pubspec = new File('pubspec.yaml');
    if (!pubspec.existsSync()) {
      throw 'Unable to generate package graph, no `pubspec.yaml` found.';
    }
    var yaml = loadYaml(pubspec.readAsStringSync());

    /// Read in the `.packages` file to get the locations of all packages.
    var packagesFile = new File('.packages');
    if (!packagesFile.existsSync()) {
      throw 'Unable to generate package graph, no `.packages` found.';
    }
    var packageLocations = <String, Uri>{};
    packagesFile.readAsLinesSync().skip(1).forEach((line) {
      var firstColon = line.indexOf(':');
      var name = line.substring(0, firstColon);
      var uriString = line.substring(firstColon + 1);
      try {
        packageLocations[name] = Uri.parse(uriString);
      } on FormatException catch (_) {
        /// Some types of deps don't have a scheme, and just point to a relative
        /// path.
        packageLocations[name] = new Uri.file(uriString);
      }
    });

    /// Create all [PackageNode]s for all deps.
    var nodes = <String, PackageNode>{};
    PackageNode addNodeAndDeps(YamlMap yaml, PackageDependencyType type,
        {bool isRoot: false}) {
      var name = yaml['name'];
      assert(!nodes.containsKey(name));
      var node = new PackageNode._(name, yaml['version'], type);
      nodes[name] = node;

      _depsFromYaml(yaml, withOverrides: isRoot).forEach((name, source) {
        var dep = nodes[name];
        if (dep == null) {
          var pubspec = _pubspecForUri(packageLocations[name]);
          dep = addNodeAndDeps(pubspec, _dependencyType(source));
        }
        node._dependencies.add(dep);
      });

      return node;
    }

    var root = addNodeAndDeps(yaml, PackageDependencyType.Path, isRoot: true);
    return new PackageGraph._(root);
  }

  String toString() {
    var buffer = new StringBuffer();
    for (var package in allPackages) {
      buffer.writeln('$package');
    }
    return buffer.toString();
  }
}

/// A node in a [PackageGraph].
class PackageNode {
  /// The name of the package as listed in the pubspec.yaml
  final String name;

  /// The version of the package as listed in the pubspec.yaml
  final String version;

  /// The type of dependency being used to pull in this package.
  final PackageDependencyType dependencyType;

  /// All the packages that this package directly depends on.
  final List<PackageNode> _dependencies = [];
  Iterable<PackageNode> get dependencies => _dependencies.toList();

  PackageNode._(this.name, this.version, this.dependencyType);

  String toString() => '''
  $name:
    version: $version
    type: $dependencyType
    dependencies: [${dependencies.map((d) => d.name).join(', ')}]''';<commit_msg>add location to PackageNode, add [] operator to PackageGraph, and change allPackages to a Map<String, PackageNode><commit_after>// 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:io';

import 'package:yaml/yaml.dart';

/// A graph of the package dependencies for an application.
class PackageGraph {
  /// The root application package.
  final PackageNode root;

  /// All [PackageNodes] indexed by package name.
  final Map<String, PackageNode> allPackages;

  PackageGraph._(this.root, Map<String, PackageNode> allPackages)
      : allPackages = new Map.unmodifiable(allPackages);

  /// Creates a [PackageGraph] for the package in which you are currently
  /// running.
  factory PackageGraph.forThisPackage() {
    /// Read in the pubspec file and parse it as yaml.
    var pubspec = new File('pubspec.yaml');
    if (!pubspec.existsSync()) {
      throw 'Unable to generate package graph, no `pubspec.yaml` found. '
          'This program must be ran from the root directory of your package.';
    }
    var yaml = loadYaml(pubspec.readAsStringSync());

    /// Read in the `.packages` file to get the locations of all packages.
    var packagesFile = new File('.packages');
    if (!packagesFile.existsSync()) {
      throw 'Unable to generate package graph, no `.packages` found. '
          'This program must be ran from the root directory of your package.';
    }
    var packageLocations = <String, Uri>{};
    packagesFile.readAsLinesSync().skip(1).forEach((line) {
      var firstColon = line.indexOf(':');
      var name = line.substring(0, firstColon);
      var uriString = line.substring(firstColon + 1);
      try {
        packageLocations[name] = Uri.parse(uriString);
      } on FormatException catch (_) {
        /// Some types of deps don't have a scheme, and just point to a relative
        /// path.
        packageLocations[name] = new Uri.file(uriString);
      }
    });

    /// Create all [PackageNode]s for all deps.
    var nodes = <String, PackageNode>{};
    PackageNode addNodeAndDeps(YamlMap yaml, PackageDependencyType type,
        {bool isRoot: false}) {
      var name = yaml['name'];
      assert(!nodes.containsKey(name));
      var node = new PackageNode._(
          name, yaml['version'], type, packageLocations[name]);
      nodes[name] = node;

      _depsFromYaml(yaml, withOverrides: isRoot).forEach((name, source) {
        var dep = nodes[name];
        if (dep == null) {
          var pubspec = _pubspecForUri(packageLocations[name]);
          dep = addNodeAndDeps(pubspec, _dependencyType(source));
        }
        node._dependencies.add(dep);
      });

      return node;
    }

    var root = addNodeAndDeps(yaml, PackageDependencyType.Path, isRoot: true);
    return new PackageGraph._(root, nodes);
  }

  /// Shorthand to get a package by name.
  PackageNode operator[] (String packageName) => allPackages[packageName];

  String toString() {
    var buffer = new StringBuffer();
    for (var package in allPackages.values) {
      buffer.writeln('$package');
    }
    return buffer.toString();
  }
}

/// A node in a [PackageGraph].
class PackageNode {
  /// The name of the package as listed in the pubspec.yaml
  final String name;

  /// The version of the package as listed in the pubspec.yaml
  final String version;

  /// The type of dependency being used to pull in this package.
  final PackageDependencyType dependencyType;

  /// All the packages that this package directly depends on.
  final List<PackageNode> _dependencies = [];
  Iterable<PackageNode> get dependencies => _dependencies.toList();

  /// The location of the current version of this package.
  final Uri location;

  PackageNode._(this.name, this.version, this.dependencyType, this.location);

  String toString() => '''
  $name:
    version: $version
    type: $dependencyType
    location: $location
    dependencies: [${dependencies.map((d) => d.name).join(', ')}]''';
{'fraction_non_alphanumeric': 0.11658163265306122, 'fraction_numerical': 0.0017857142857142857, 'mean_word_length': 3.012794268167861, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '118642', 'n_tokens_mistral': 2276, 'n_tokens_neox': 2203, 'n_words': 750}