| OLD | NEW |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import 'dart:async'; | 5 import 'dart:async'; |
| 6 import 'dart:io'; | 6 import 'dart:io'; |
| 7 | 7 |
| 8 import 'package:front_end/compiler_options.dart'; | 8 import 'package:front_end/compiler_options.dart'; |
| 9 import 'package:front_end/dependency_grapher.dart'; | 9 import 'package:front_end/dependency_grapher.dart'; |
| 10 import 'package:path/path.dart' as pathos; | 10 import 'package:path/path.dart' as pathos; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 | 43 |
| 44 /// Indicates which other subpackages a given subpackage may directly depend | 44 /// Indicates which other subpackages a given subpackage may directly depend |
| 45 /// on. | 45 /// on. |
| 46 final List<String> allowedDependencies; | 46 final List<String> allowedDependencies; |
| 47 | 47 |
| 48 SubpackageRules( | 48 SubpackageRules( |
| 49 {this.mayImportAnalyzer: false, this.allowedDependencies: const []}); | 49 {this.mayImportAnalyzer: false, this.allowedDependencies: const []}); |
| 50 } | 50 } |
| 51 | 51 |
| 52 class _SubpackageRelationshipsTest { | 52 class _SubpackageRelationshipsTest { |
| 53 /// File uri of the root of the front_end package. | 53 /// File uri of the front_end package's "lib" directory. |
| 54 final frontEndRootUri = Platform.script.resolve('..'); | 54 final frontEndLibUri = Platform.script.resolve('../lib/'); |
| 55 | 55 |
| 56 /// Indicates whether any problems have been reported yet. | 56 /// Indicates whether any problems have been reported yet. |
| 57 bool problemsReported = false; | 57 bool problemsReported = false; |
| 58 | 58 |
| 59 /// Check for problems resulting from URI [src] having a direct dependency on | 59 /// Check for problems resulting from URI [src] having a direct dependency on |
| 60 /// URI [dst]. | 60 /// URI [dst]. |
| 61 void checkDependency(Uri src, Uri dst) { | 61 void checkDependency(Uri src, Uri dst) { |
| 62 if (dst.scheme == 'dart') return; | 62 if (dst.scheme == 'dart') return; |
| 63 if (dst.scheme != 'package') { | 63 if (dst.scheme != 'package') { |
| 64 problem('$src depends on $dst, which is neither a package: or dart: URI'); | 64 problem('$src depends on $dst, which is neither a package: or dart: URI'); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 81 if (dstSubPackage == null) return; | 81 if (dstSubPackage == null) return; |
| 82 if (dstSubPackage == srcSubpackage) return; | 82 if (dstSubPackage == srcSubpackage) return; |
| 83 if (!srcSubpackageRules.allowedDependencies.contains(dstSubPackage)) { | 83 if (!srcSubpackageRules.allowedDependencies.contains(dstSubPackage)) { |
| 84 problem('$src depends on $dst, but subpackage "$srcSubpackage" is not ' | 84 problem('$src depends on $dst, but subpackage "$srcSubpackage" is not ' |
| 85 'allowed to depend on subpackage "$dstSubPackage"'); | 85 'allowed to depend on subpackage "$dstSubPackage"'); |
| 86 } | 86 } |
| 87 } | 87 } |
| 88 | 88 |
| 89 /// Finds all files in the front_end's "lib" directory and returns their Uris | 89 /// Finds all files in the front_end's "lib" directory and returns their Uris |
| 90 /// (as "package:" URIs). | 90 /// (as "package:" URIs). |
| 91 Future<List<Uri>> findFrontEndUris() async { | 91 List<Uri> findFrontEndUris() { |
| 92 var frontEndUris = <Uri>[]; | 92 var frontEndUris = <Uri>[]; |
| 93 var frontEndRootPath = pathos.fromUri(frontEndRootUri); | 93 var frontEndLibPath = pathos.fromUri(frontEndLibUri); |
| 94 await for (var entity in new Directory(frontEndRootPath) | 94 for (var entity in new Directory(frontEndLibPath) |
| 95 .list(recursive: true, followLinks: false)) { | 95 .listSync(recursive: true, followLinks: false)) { |
| 96 if (entity is File && entity.path.endsWith('.dart')) { | 96 if (entity is File && entity.path.endsWith('.dart')) { |
| 97 var posixRelativePath = pathos | 97 var posixRelativePath = pathos.url.joinAll( |
| 98 .relative(entity.path, from: frontEndRootPath) | 98 pathos.split(pathos.relative(entity.path, from: frontEndLibPath))); |
| 99 .replaceAll(pathos.separator, '/'); | 99 frontEndUris.add(Uri.parse('package:front_end/$posixRelativePath')); |
| 100 if (!posixRelativePath.startsWith('lib/')) continue; | |
| 101 frontEndUris.add(Uri.parse( | |
| 102 posixRelativePath.replaceFirst('lib/', 'package:front_end/'))); | |
| 103 } | 100 } |
| 104 } | 101 } |
| 105 return frontEndUris; | 102 return frontEndUris; |
| 106 } | 103 } |
| 107 | 104 |
| 108 /// Reports a single problem. | 105 /// Reports a single problem. |
| 109 void problem(String description) { | 106 void problem(String description) { |
| 110 print(description); | 107 print(description); |
| 111 problemsReported = true; | 108 problemsReported = true; |
| 112 } | 109 } |
| 113 | 110 |
| 114 /// Tests all subpackage relationships in the front end, and returns an | 111 /// Tests all subpackage relationships in the front end, and returns an |
| 115 /// appropriate exit code. | 112 /// appropriate exit code. |
| 116 Future<int> run() async { | 113 Future<int> run() async { |
| 117 var frontEndUris = await findFrontEndUris(); | 114 var frontEndUris = await findFrontEndUris(); |
| 118 var packagesFileUri = frontEndRootUri.resolve('../../.packages'); | 115 var packagesFileUri = frontEndLibUri.resolve('../../../.packages'); |
| 119 var graph = await graphForProgram( | 116 var graph = await graphForProgram( |
| 120 frontEndUris, | 117 frontEndUris, |
| 121 new CompilerOptions() | 118 new CompilerOptions() |
| 122 ..packagesFileUri = packagesFileUri | 119 ..packagesFileUri = packagesFileUri |
| 123 ..chaseDependencies = true); | 120 ..chaseDependencies = true); |
| 124 for (var i = 0; i < graph.topologicallySortedCycles.length; i++) { | 121 for (var i = 0; i < graph.topologicallySortedCycles.length; i++) { |
| 125 for (var library in graph.topologicallySortedCycles[i].libraries.values) { | 122 for (var library in graph.topologicallySortedCycles[i].libraries.values) { |
| 126 for (var dependency in library.dependencies) { | 123 for (var dependency in library.dependencies) { |
| 127 checkDependency(library.uri, dependency.uri); | 124 checkDependency(library.uri, dependency.uri); |
| 128 } | 125 } |
| 129 } | 126 } |
| 130 } | 127 } |
| 131 return problemsReported ? 1 : 0; | 128 return problemsReported ? 1 : 0; |
| 132 } | 129 } |
| 133 | 130 |
| 134 /// Determines which subpackage [src] is in. | 131 /// Determines which subpackage [src] is in. |
| 135 /// | 132 /// |
| 136 /// If [src] is not part of the front end, `null` is returned. | 133 /// If [src] is not part of the front end, `null` is returned. |
| 137 String subpackageForUri(Uri src) { | 134 String subpackageForUri(Uri src) { |
| 138 if (src.scheme != 'package') return null; | 135 if (src.scheme != 'package') return null; |
| 139 if (src.pathSegments[0] != 'front_end') return null; | 136 if (src.pathSegments[0] != 'front_end') return null; |
| 140 if (src.pathSegments[1] != 'src') return 'lib'; | 137 if (src.pathSegments[1] != 'src') return 'lib'; |
| 141 if (src.pathSegments.length == 3) return 'lib/src'; | 138 if (src.pathSegments.length == 3) return 'lib/src'; |
| 142 return 'lib/src/${src.pathSegments[2]}'; | 139 return 'lib/src/${src.pathSegments[2]}'; |
| 143 } | 140 } |
| 144 } | 141 } |
| OLD | NEW |