|  | #!/usr/bin/env dart | 
|  |  | 
|  | /// Generates the repo's ".dart_tool/package_config.json" file. | 
|  | import 'dart:convert'; | 
|  | import 'dart:io'; | 
|  |  | 
|  | import 'package:path/path.dart' as p; | 
|  | import 'package:pub_semver/pub_semver.dart'; | 
|  | import 'package:yaml/yaml.dart'; | 
|  |  | 
|  | final repoRoot = p.dirname(p.dirname(p.fromUri(Platform.script))); | 
|  | final configFilePath = p.join(repoRoot, '.dart_tool/package_config.json'); | 
|  |  | 
|  | void main(List<String> args) { | 
|  | var packageDirs = [ | 
|  | ...listSubdirectories('pkg'), | 
|  | ...listSubdirectories('third_party/pkg'), | 
|  | ...listSubdirectories('third_party/pkg_tested'), | 
|  | ...listSubdirectories('third_party/pkg/test/pkgs'), | 
|  | packageDirectory('runtime/observatory'), | 
|  | packageDirectory( | 
|  | 'runtime/observatory/tests/service/observatory_test_package'), | 
|  | packageDirectory('sdk/lib/_internal/sdk_library_metadata'), | 
|  | packageDirectory('sdk/lib/_internal/js_runtime'), | 
|  | packageDirectory('third_party/pkg/protobuf/protobuf'), | 
|  | ]; | 
|  |  | 
|  | var cfePackageDirs = [ | 
|  | packageDirectory('pkg/front_end/testcases/'), | 
|  | ]; | 
|  |  | 
|  | var feAnalyzerSharedPackageDirs = [ | 
|  | packageDirectory( | 
|  | 'pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/'), | 
|  | packageDirectory( | 
|  | 'pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/'), | 
|  | packageDirectory( | 
|  | 'pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/'), | 
|  | packageDirectory('pkg/_fe_analyzer_shared/test/flow_analysis/nullability/'), | 
|  | packageDirectory( | 
|  | 'pkg/_fe_analyzer_shared/test/flow_analysis/reachability/'), | 
|  | packageDirectory( | 
|  | 'pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/'), | 
|  | packageDirectory('pkg/_fe_analyzer_shared/test/inheritance/'), | 
|  | ]; | 
|  |  | 
|  | var packages = [ | 
|  | ...makePackageConfigs(packageDirs), | 
|  | ...makeCfePackageConfigs(cfePackageDirs), | 
|  | ...makeFeAnalyzerSharedPackageConfigs(feAnalyzerSharedPackageDirs) | 
|  | ]; | 
|  | packages.sort((a, b) => a["name"].compareTo(b["name"])); | 
|  |  | 
|  | var year = DateTime.now().year; | 
|  | var config = <String, dynamic>{ | 
|  | 'copyright': [ | 
|  | 'Copyright (c) $year, 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.' | 
|  | ], | 
|  | 'comment': [ | 
|  | 'Package configuration for all packages in /pkg, and checked out by DEPS', | 
|  | 'into /third_party/pkg and /third_party/pkg_tested.', | 
|  | 'If you add a package to DEPS or /pkg or change a package\'s SDK', | 
|  | 'constraint, update this by running tools/generate_package_config.dart.' | 
|  | ], | 
|  | 'configVersion': 2, | 
|  | 'generated': DateTime.now().toIso8601String(), | 
|  | 'generator': 'tools/generate_package_config.dart', | 
|  | 'packages': packages, | 
|  | }; | 
|  |  | 
|  | // TODO(rnystrom): Consider using package_config_v2 to generate this instead. | 
|  | var json = JsonEncoder.withIndent('  ').convert(config); | 
|  | File(p.join(repoRoot, '.dart_tool', 'package_config.json')) | 
|  | .writeAsStringSync(json); | 
|  | print('Generated .dart_tool/package_config.dart containing ' | 
|  | '${packages.length} packages.'); | 
|  | } | 
|  |  | 
|  | /// Generates package configurations for each package in [packageDirs]. | 
|  | Iterable<Map<String, String>> makePackageConfigs( | 
|  | List<String> packageDirs) sync* { | 
|  | for (var packageDir in packageDirs) { | 
|  | var version = pubspecLanguageVersion(packageDir); | 
|  | var hasLibDirectory = Directory(p.join(packageDir, 'lib')).existsSync(); | 
|  |  | 
|  | // TODO(rnystrom): Currently, the pre-built SDK does not allow language | 
|  | // version 2.9.0. Until that's fixed, if we see that version, just write | 
|  | // no version at all so that implementations use the current language | 
|  | // version. | 
|  | if (version.toString() == '2.9.0') version = null; | 
|  |  | 
|  | yield { | 
|  | 'name': p.basename(packageDir), | 
|  | 'rootUri': p | 
|  | .toUri(p.relative(packageDir, from: p.dirname(configFilePath))) | 
|  | .toString(), | 
|  | if (hasLibDirectory) 'packageUri': 'lib/', | 
|  | if (version != null) | 
|  | 'languageVersion': '${version.major}.${version.minor}' | 
|  | }; | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Generates package configurations for the special pseudo-packages used by | 
|  | /// the CFE unit tests (`pkg/front_end/test/unit_test_suites.dart`). | 
|  | Iterable<Map<String, String>> makeCfePackageConfigs( | 
|  | List<String> packageDirs) sync* { | 
|  | for (var packageDir in packageDirs) { | 
|  | yield { | 
|  | 'name': 'front_end_${p.basename(packageDir)}', | 
|  | 'rootUri': p | 
|  | .toUri(p.relative(packageDir, from: p.dirname(configFilePath))) | 
|  | .toString(), | 
|  | 'packageUri': '.nonexisting/', | 
|  | }; | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Generates package configurations for the special pseudo-packages used by | 
|  | /// the _fe_analyzer_shared id tests. | 
|  | Iterable<Map<String, String>> makeFeAnalyzerSharedPackageConfigs( | 
|  | List<String> packageDirs) sync* { | 
|  | for (var packageDir in packageDirs) { | 
|  | yield { | 
|  | 'name': '_fe_analyzer_shared_${p.basename(packageDir)}', | 
|  | 'rootUri': p | 
|  | .toUri(p.relative(packageDir, from: p.dirname(configFilePath))) | 
|  | .toString(), | 
|  | 'packageUri': '.nonexisting/', | 
|  | }; | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Generates a path to [relativePath] within the repo. | 
|  | String packageDirectory(String relativePath) => p.join(repoRoot, relativePath); | 
|  |  | 
|  | /// Finds the paths of the immediate subdirectories of [packagesDir] that | 
|  | /// contain pubspecs. | 
|  | Iterable<String> listSubdirectories(String packagesDir) sync* { | 
|  | for (var entry in Directory(p.join(repoRoot, packagesDir)).listSync()) { | 
|  | if (entry is! Directory) continue; | 
|  | if (!File(p.join(entry.path, 'pubspec.yaml')).existsSync()) continue; | 
|  | yield entry.path; | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Infers the language version from the SDK constraint in the pubspec for | 
|  | /// [packageDir]. | 
|  | /// | 
|  | /// Returns `null` if there is no pubspec or no SDK constraint. | 
|  | Version pubspecLanguageVersion(String packageDir) { | 
|  | var pubspecFile = File(p.join(packageDir, 'pubspec.yaml')); | 
|  |  | 
|  | if (!pubspecFile.existsSync()) return null; | 
|  |  | 
|  | var pubspec = | 
|  | loadYaml(pubspecFile.readAsStringSync()) as Map<dynamic, dynamic>; | 
|  | if (!pubspec.containsKey('environment')) return null; | 
|  |  | 
|  | var environment = pubspec['environment'] as Map<dynamic, dynamic>; | 
|  | if (!environment.containsKey('sdk')) return null; | 
|  |  | 
|  | var sdkConstraint = VersionConstraint.parse(environment['sdk'] as String); | 
|  | if (sdkConstraint is VersionRange) return sdkConstraint.min; | 
|  |  | 
|  | return null; | 
|  | } |