|  | // Copyright (c) 2019, 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:_fe_analyzer_shared/src/messages/severity.dart'; | 
|  | import 'package:expect/expect.dart' show Expect; | 
|  | import 'package:front_end/src/api_prototype/compiler_options.dart'; | 
|  | import 'package:front_end/src/api_prototype/standard_file_system.dart'; | 
|  | import 'package:front_end/src/base/compiler_context.dart'; | 
|  | import 'package:front_end/src/base/file_system_dependency_tracker.dart'; | 
|  | import 'package:front_end/src/base/import_chains.dart'; | 
|  | import 'package:front_end/src/base/processed_options.dart'; | 
|  | import 'package:front_end/src/base/ticker.dart'; | 
|  | import 'package:front_end/src/base/uri_translator.dart'; | 
|  | import 'package:front_end/src/builder/library_builder.dart'; | 
|  | import 'package:front_end/src/compute_platform_binaries_location.dart' | 
|  | show computePlatformBinariesLocation; | 
|  | import 'package:front_end/src/dill/dill_target.dart'; | 
|  | import 'package:front_end/src/kernel/kernel_target.dart'; | 
|  | import 'package:kernel/kernel.dart'; | 
|  | import 'package:kernel/target/targets.dart'; | 
|  | import 'package:package_config/src/package_config.dart'; | 
|  | import 'package:vm/modular/target/vm.dart' show VmTarget; | 
|  |  | 
|  | import 'utils/io_utils.dart' show computeRepoDirUri; | 
|  |  | 
|  | final Uri repoDir = computeRepoDirUri(); | 
|  |  | 
|  | Set<String> allowlistedExternalDartFiles = { | 
|  | // TODO(CFE-team): These files should not be included. | 
|  | // The package isn't even in pubspec.yaml. | 
|  | // They're included via at least | 
|  | // _fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart | 
|  | "pkg/meta/lib/meta.dart", | 
|  | "pkg/meta/lib/meta_meta.dart", | 
|  | }; | 
|  |  | 
|  | Set<String> allowedPackages = { | 
|  | "front_end", | 
|  | "kernel", | 
|  | "_fe_analyzer_shared", | 
|  | "package_config", | 
|  | "macros", | 
|  | "_macros", | 
|  | // package:front_end imports package:yaml for the 'dynamic modules' | 
|  | // experiment. | 
|  | "yaml", | 
|  | // package:yaml uses package:source_span, package:string_scanner and | 
|  | // package:collection. | 
|  | "source_span", | 
|  | "string_scanner", | 
|  | "collection", | 
|  | // package:source_span imports package:path. | 
|  | "path", | 
|  | // package:source_span imports package:term_glyph. | 
|  | "term_glyph", | 
|  | }; | 
|  |  | 
|  | List<String> allowedRelativePaths = [ | 
|  | // For VmTarget for macros. | 
|  | "pkg/vm/lib/modular/", | 
|  | // Platform. | 
|  | "sdk/lib/", | 
|  | ]; | 
|  |  | 
|  | /// Returns true on no errors and false if errors was found. | 
|  | Future<bool> main() async { | 
|  | Ticker ticker = new Ticker(isVerbose: false); | 
|  | CompilerOptions compilerOptions = getOptions(); | 
|  |  | 
|  | Uri packageConfigUri = repoDir.resolve(".dart_tool/package_config.json"); | 
|  | if (!new File.fromUri(packageConfigUri).existsSync()) { | 
|  | throw "Couldn't find .dart_tool/package_config.json"; | 
|  | } | 
|  | compilerOptions.packagesFileUri = packageConfigUri; | 
|  | FileSystemDependencyTracker tracker = new FileSystemDependencyTracker(); | 
|  | compilerOptions.fileSystem = StandardFileSystem.instanceWithTracking(tracker); | 
|  |  | 
|  | ProcessedOptions options = new ProcessedOptions(options: compilerOptions); | 
|  |  | 
|  | Uri frontendLibUri = repoDir.resolve("pkg/front_end/lib/"); | 
|  | List<FileSystemEntity> entities = | 
|  | new Directory.fromUri(frontendLibUri).listSync(recursive: true); | 
|  | for (FileSystemEntity entity in entities) { | 
|  | if (entity is File && entity.path.endsWith(".dart")) { | 
|  | options.inputs.add(entity.uri); | 
|  | } | 
|  | } | 
|  |  | 
|  | LoadedLibraries? loadedLibraries; | 
|  | Map<Uri, Uri> fileUriToImportUri = {}; | 
|  | List<String> allowedUriPrefixes = [ | 
|  | for (String relativePath in allowedRelativePaths) | 
|  | repoDir.resolve(relativePath).toString() | 
|  | ]; | 
|  |  | 
|  | List<Uri> result = await CompilerContext.runWithOptions<List<Uri>>(options, | 
|  | (CompilerContext c) async { | 
|  | UriTranslator uriTranslator = await c.options.getUriTranslator(); | 
|  | for (Package package in uriTranslator.packages.packages) { | 
|  | if (allowedPackages.contains(package.name)) { | 
|  | allowedUriPrefixes.add(package.packageUriRoot.toString()); | 
|  | } | 
|  | } | 
|  | DillTarget dillTarget = | 
|  | new DillTarget(c, ticker, uriTranslator, c.options.target); | 
|  | KernelTarget kernelTarget = | 
|  | new KernelTarget(c, c.fileSystem, false, dillTarget, uriTranslator); | 
|  | Uri? platform = c.options.sdkSummary; | 
|  | if (platform != null) { | 
|  | var bytes = new File.fromUri(platform).readAsBytesSync(); | 
|  | var platformComponent = loadComponentFromBytes(bytes); | 
|  | dillTarget.loader | 
|  | .appendLibraries(platformComponent, byteCount: bytes.length); | 
|  | } | 
|  |  | 
|  | kernelTarget.setEntryPoints(c.options.inputs); | 
|  | dillTarget.buildOutlines(); | 
|  | await kernelTarget.loader.buildOutlines(); | 
|  |  | 
|  | { | 
|  | List<CompilationUnit> compilationUnits = | 
|  | kernelTarget.loader.compilationUnits.toList(growable: false); | 
|  | List<CompilationUnit> rootCompilationUnits = []; | 
|  | Set<Uri> inputs = new Set.of(options.inputs); | 
|  | for (CompilationUnit unit in compilationUnits) { | 
|  | fileUriToImportUri[unit.fileUri] = unit.importUri; | 
|  | if (inputs.contains(unit.fileUri) || inputs.contains(unit.importUri)) { | 
|  | rootCompilationUnits.add(unit); | 
|  | } | 
|  | } | 
|  | loadedLibraries = | 
|  | new LoadedLibrariesImpl(rootCompilationUnits, compilationUnits); | 
|  | } | 
|  |  | 
|  | return new List<Uri>.from(tracker.dependencies); | 
|  | }); | 
|  |  | 
|  | Set<Uri> otherDartUris = new Set<Uri>(); | 
|  | Set<Uri> otherNonDartUris = new Set<Uri>(); | 
|  | for (Uri uri in result) { | 
|  | final String uriAsString = uri.toString(); | 
|  | bool allowed = false; | 
|  | for (String prefix in allowedUriPrefixes) { | 
|  | if (uriAsString.startsWith(prefix)) { | 
|  | allowed = true; | 
|  | break; | 
|  | } | 
|  | } | 
|  | if (!allowed) { | 
|  | if (uri.toString().endsWith(".dart")) { | 
|  | otherDartUris.add(uri); | 
|  | } else { | 
|  | otherNonDartUris.add(uri); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // Remove allow-listed non-dart files. | 
|  | otherNonDartUris.remove(packageConfigUri); | 
|  | otherNonDartUris.remove(repoDir.resolve("sdk/lib/libraries.json")); | 
|  |  | 
|  | // Remove allow-listed dart files. | 
|  | for (String s in allowlistedExternalDartFiles) { | 
|  | otherDartUris.remove(repoDir.resolve(s)); | 
|  | } | 
|  |  | 
|  | // Everything else is an error. | 
|  | if (otherNonDartUris.isNotEmpty || otherDartUris.isNotEmpty) { | 
|  | print("The following files was imported without being allowlisted:"); | 
|  | for (Uri uri in otherNonDartUris) { | 
|  | print(" - $uri"); | 
|  | } | 
|  | for (Uri uri in otherDartUris) { | 
|  | print(" - $uri"); | 
|  | if (loadedLibraries != null) { | 
|  | Uri? importUri = fileUriToImportUri[uri]; | 
|  | if (importUri != null) { | 
|  | Set<String> importChains = (computeImportChainsFor( | 
|  | Uri.parse("<entry>"), loadedLibraries!, importUri, | 
|  | verbose: false)); | 
|  | for (String s in importChains) { | 
|  | print(" => $s"); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | exitCode = 1; | 
|  | return false; | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | CompilerOptions getOptions() { | 
|  | // Compile sdk because when this is run from a lint it uses the checked-in sdk | 
|  | // and we might not have a suitable compiled platform.dill file. | 
|  | Uri sdkRoot = computePlatformBinariesLocation(forceBuildDir: true); | 
|  | CompilerOptions options = new CompilerOptions() | 
|  | ..sdkRoot = sdkRoot | 
|  | ..compileSdk = true | 
|  | ..target = new VmTarget(new TargetFlags()) | 
|  | ..librariesSpecificationUri = repoDir.resolve("sdk/lib/libraries.json") | 
|  | ..omitPlatform = true | 
|  | ..onDiagnostic = (DiagnosticMessage message) { | 
|  | if (message.severity == Severity.error) { | 
|  | Expect.fail( | 
|  | "Unexpected error: ${message.plainTextFormatted.join('\n')}"); | 
|  | } | 
|  | } | 
|  | ..environmentDefines = const {}; | 
|  | return options; | 
|  | } |