| 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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 ]), | 66 ]), |
| 67 'lib/src/fasta/kernel': new SubpackageRules(allowedDependencies: [ | 67 'lib/src/fasta/kernel': new SubpackageRules(allowedDependencies: [ |
| 68 'lib/src/fasta', | 68 'lib/src/fasta', |
| 69 'lib/src/fasta/builder', | 69 'lib/src/fasta/builder', |
| 70 'lib/src/fasta/dill', | 70 'lib/src/fasta/dill', |
| 71 'lib/src/fasta/parser', | 71 'lib/src/fasta/parser', |
| 72 'lib/src/fasta/scanner', | 72 'lib/src/fasta/scanner', |
| 73 'lib/src/fasta/source', | 73 'lib/src/fasta/source', |
| 74 'lib/src/fasta/util', | 74 'lib/src/fasta/util', |
| 75 ]), | 75 ]), |
| 76 'lib/src/fasta/parser': | 76 'lib/src/fasta/parser': new SubpackageRules(allowedDependencies: [ |
| 77 new SubpackageRules(allowSubdirs: true, allowedDependencies: [ | |
| 78 'lib/src/fasta', | 77 'lib/src/fasta', |
| 79 'lib/src/fasta/scanner', | 78 'lib/src/fasta/scanner', |
| 80 'lib/src/fasta/util', | 79 'lib/src/fasta/util', |
| 81 ]), | 80 ]), |
| 82 'lib/src/fasta/scanner': | 81 'lib/src/fasta/scanner': new SubpackageRules(allowedDependencies: [ |
| 83 new SubpackageRules(allowSubdirs: true, allowedDependencies: [ | |
| 84 'lib/src/fasta', | 82 'lib/src/fasta', |
| 85 'lib/src/fasta/parser', | 83 'lib/src/fasta/parser', |
| 86 // fasta scanner produces analyzer scanner tokens | 84 // fasta scanner produces analyzer scanner tokens |
| 87 'lib/src/scanner', | 85 'lib/src/scanner', |
| 88 'lib/src/fasta/util', | 86 'lib/src/fasta/util', |
| 89 ]), | 87 ]), |
| 90 'lib/src/fasta/source': new SubpackageRules(allowedDependencies: [ | 88 'lib/src/fasta/source': new SubpackageRules(allowedDependencies: [ |
| 91 'lib/src/fasta', | 89 'lib/src/fasta', |
| 92 'lib/src/fasta/builder', | 90 'lib/src/fasta/builder', |
| 93 'lib/src/fasta/dill', | 91 'lib/src/fasta/dill', |
| (...skipping 27 matching lines...) Expand all Loading... |
| 121 /// subpackage. | 119 /// subpackage. |
| 122 /// | 120 /// |
| 123 /// If `false`, any subdirectory of this subpackage must be a separate | 121 /// If `false`, any subdirectory of this subpackage must be a separate |
| 124 /// subpackage. | 122 /// subpackage. |
| 125 final bool allowSubdirs; | 123 final bool allowSubdirs; |
| 126 | 124 |
| 127 /// Indicates which other subpackages a given subpackage may directly depend | 125 /// Indicates which other subpackages a given subpackage may directly depend |
| 128 /// on. | 126 /// on. |
| 129 final List<String> allowedDependencies; | 127 final List<String> allowedDependencies; |
| 130 | 128 |
| 129 var actuallyContainsFiles = false; |
| 130 |
| 131 var actuallyImportsAnalyzer = false; |
| 132 |
| 133 var actuallyHasSubdirs = false; |
| 134 |
| 135 var actualDependencies = new Set<String>(); |
| 136 |
| 131 SubpackageRules( | 137 SubpackageRules( |
| 132 {this.mayImportAnalyzer: false, | 138 {this.mayImportAnalyzer: false, |
| 133 this.allowSubdirs: false, | 139 this.allowSubdirs: false, |
| 134 this.allowedDependencies: const []}); | 140 this.allowedDependencies: const []}); |
| 135 } | 141 } |
| 136 | 142 |
| 137 class _SubpackageRelationshipsTest { | 143 class _SubpackageRelationshipsTest { |
| 138 /// File uri of the front_end package's "lib" directory. | 144 /// File uri of the front_end package's "lib" directory. |
| 139 final frontEndLibUri = Platform.script.resolve('../lib/'); | 145 final frontEndLibUri = Platform.script.resolve('../lib/'); |
| 140 | 146 |
| 141 /// Indicates whether any problems have been reported yet. | 147 /// Indicates whether any problems have been reported yet. |
| 142 bool problemsReported = false; | 148 bool problemsReported = false; |
| 143 | 149 |
| 144 /// Check for problems resulting from URI [src] having a direct dependency on | 150 /// Check for problems resulting from URI [src] having a direct dependency on |
| 145 /// URI [dst]. | 151 /// URI [dst]. |
| 146 void checkDependency(Uri src, Uri dst) { | 152 void checkDependency(Uri src, Uri dst) { |
| 147 if (dst.scheme == 'dart') return; | 153 if (dst.scheme == 'dart') return; |
| 148 if (dst.scheme != 'package') { | 154 if (dst.scheme != 'package') { |
| 149 problem('$src depends on $dst, which is neither a package: or dart: URI'); | 155 problem('$src depends on $dst, which is neither a package: or dart: URI'); |
| 150 return; | 156 return; |
| 151 } | 157 } |
| 152 var srcSubpackage = subpackageForUri(src); | 158 var srcSubpackage = subpackageForUri(src); |
| 153 if (srcSubpackage == null) return; | 159 if (srcSubpackage == null) return; |
| 154 var srcSubpackageRules = subpackageRules[srcSubpackage]; | 160 var srcSubpackageRules = subpackageRules[srcSubpackage]; |
| 155 if (srcSubpackageRules == null) { | 161 if (srcSubpackageRules == null) { |
| 156 problem('$src is in subpackage "$srcSubpackage", which is not found in ' | 162 problem('$src is in subpackage "$srcSubpackage", which is not found in ' |
| 157 'subpackageRules'); | 163 'subpackageRules'); |
| 158 return; | 164 return; |
| 159 } | 165 } |
| 160 if (!srcSubpackageRules.mayImportAnalyzer && | 166 srcSubpackageRules.actuallyContainsFiles = true; |
| 161 dst.pathSegments[0] == 'analyzer') { | 167 if (dst.pathSegments[0] == 'analyzer') { |
| 162 problem('$src depends on $dst, but subpackage "$srcSubpackage" may not ' | 168 if (srcSubpackageRules.mayImportAnalyzer) { |
| 163 'import analyzer'); | 169 srcSubpackageRules.actuallyImportsAnalyzer = true; |
| 170 } else { |
| 171 problem('$src depends on $dst, but subpackage "$srcSubpackage" may not ' |
| 172 'import analyzer'); |
| 173 } |
| 164 } | 174 } |
| 165 var dstSubPackage = subpackageForUri(dst); | 175 var dstSubPackage = subpackageForUri(dst); |
| 166 if (dstSubPackage == null) return; | 176 if (dstSubPackage == null) return; |
| 167 if (dstSubPackage == srcSubpackage) return; | 177 if (dstSubPackage == srcSubpackage) return; |
| 168 if (!srcSubpackageRules.allowedDependencies.contains(dstSubPackage)) { | 178 if (srcSubpackageRules.allowedDependencies.contains(dstSubPackage)) { |
| 179 srcSubpackageRules.actualDependencies.add(dstSubPackage); |
| 180 } else { |
| 169 problem('$src depends on $dst, but subpackage "$srcSubpackage" is not ' | 181 problem('$src depends on $dst, but subpackage "$srcSubpackage" is not ' |
| 170 'allowed to depend on subpackage "$dstSubPackage"'); | 182 'allowed to depend on subpackage "$dstSubPackage"'); |
| 171 } | 183 } |
| 172 } | 184 } |
| 173 | 185 |
| 174 /// Finds all files in the front_end's "lib" directory and returns their Uris | 186 /// Finds all files in the front_end's "lib" directory and returns their Uris |
| 175 /// (as "package:" URIs). | 187 /// (as "package:" URIs). |
| 176 List<Uri> findFrontEndUris() { | 188 List<Uri> findFrontEndUris() { |
| 177 var frontEndUris = <Uri>[]; | 189 var frontEndUris = <Uri>[]; |
| 178 var frontEndLibPath = pathos.fromUri(frontEndLibUri); | 190 var frontEndLibPath = pathos.fromUri(frontEndLibUri); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 203 new CompilerOptions() | 215 new CompilerOptions() |
| 204 ..packagesFileUri = packagesFileUri | 216 ..packagesFileUri = packagesFileUri |
| 205 ..chaseDependencies = true); | 217 ..chaseDependencies = true); |
| 206 for (var i = 0; i < graph.topologicallySortedCycles.length; i++) { | 218 for (var i = 0; i < graph.topologicallySortedCycles.length; i++) { |
| 207 for (var library in graph.topologicallySortedCycles[i].libraries.values) { | 219 for (var library in graph.topologicallySortedCycles[i].libraries.values) { |
| 208 for (var dependency in library.dependencies) { | 220 for (var dependency in library.dependencies) { |
| 209 checkDependency(library.uri, dependency.uri); | 221 checkDependency(library.uri, dependency.uri); |
| 210 } | 222 } |
| 211 } | 223 } |
| 212 } | 224 } |
| 225 subpackageRules.forEach((subpackage, rule) { |
| 226 if (!rule.actuallyContainsFiles) { |
| 227 problem("$subpackage contains no files"); |
| 228 } |
| 229 if (rule.mayImportAnalyzer && !rule.actuallyImportsAnalyzer) { |
| 230 problem("$subpackage is allowed to import analyzer, but doesn't"); |
| 231 } |
| 232 if (rule.allowSubdirs && !rule.actuallyHasSubdirs) { |
| 233 problem("$subpackage is allowed to have subdirectories, but doesn't"); |
| 234 } |
| 235 for (var dep in rule.allowedDependencies |
| 236 .toSet() |
| 237 .difference(rule.actualDependencies)) { |
| 238 problem("$subpackage lists $dep as a dependency, but doesn't use it"); |
| 239 } |
| 240 }); |
| 213 return problemsReported ? 1 : 0; | 241 return problemsReported ? 1 : 0; |
| 214 } | 242 } |
| 215 | 243 |
| 216 /// Determines which subpackage [src] is in. | 244 /// Determines which subpackage [src] is in. |
| 217 /// | 245 /// |
| 218 /// If [src] is not part of the front end, `null` is returned. | 246 /// If [src] is not part of the front end, `null` is returned. |
| 219 String subpackageForUri(Uri src) { | 247 String subpackageForUri(Uri src) { |
| 220 if (src.scheme != 'package') return null; | 248 if (src.scheme != 'package') return null; |
| 221 if (src.pathSegments[0] != 'front_end') return null; | 249 if (src.pathSegments[0] != 'front_end') return null; |
| 222 var pathWithLib = 'lib/${src.pathSegments.skip(1).join('/')}'; | 250 var pathWithLib = 'lib/${src.pathSegments.skip(1).join('/')}'; |
| 223 String subpackage; | 251 String subpackage; |
| 224 String pathWithinSubpackage; | 252 String pathWithinSubpackage; |
| 225 for (var subpackagePath in subpackageRules.keys) { | 253 for (var subpackagePath in subpackageRules.keys) { |
| 226 var subpackagePathWithSlash = '$subpackagePath/'; | 254 var subpackagePathWithSlash = '$subpackagePath/'; |
| 227 if (pathWithLib.startsWith(subpackagePathWithSlash) && | 255 if (pathWithLib.startsWith(subpackagePathWithSlash) && |
| 228 (subpackage == null || subpackage.length < subpackagePath.length)) { | 256 (subpackage == null || subpackage.length < subpackagePath.length)) { |
| 229 subpackage = subpackagePath; | 257 subpackage = subpackagePath; |
| 230 pathWithinSubpackage = | 258 pathWithinSubpackage = |
| 231 pathWithLib.substring(subpackagePathWithSlash.length); | 259 pathWithLib.substring(subpackagePathWithSlash.length); |
| 232 } | 260 } |
| 233 } | 261 } |
| 234 if (subpackage == null) { | 262 if (subpackage == null) { |
| 235 problem('Uri $src is inside package:front_end but is not in any known ' | 263 problem('Uri $src is inside package:front_end but is not in any known ' |
| 236 'subpackage'); | 264 'subpackage'); |
| 237 } else if (!subpackageRules[subpackage].allowSubdirs && | 265 } else if (pathWithinSubpackage.contains('/')) { |
| 238 pathWithinSubpackage.contains('/')) { | 266 if (subpackageRules[subpackage].allowSubdirs) { |
| 239 problem('Uri $src is in a subfolder of $subpackage, but that ' | 267 subpackageRules[subpackage].actuallyHasSubdirs = true; |
| 240 'subpackage does not allow dart files in subdirectories.'); | 268 } else { |
| 269 problem('Uri $src is in a subfolder of $subpackage, but that ' |
| 270 'subpackage does not allow dart files in subdirectories.'); |
| 271 } |
| 241 } | 272 } |
| 242 return subpackage; | 273 return subpackage; |
| 243 } | 274 } |
| 244 } | 275 } |
| OLD | NEW |