blob: 9b5d27849a28c86fe2b33cd7f44e521c6be8577f [file] [log] [blame]
// 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/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/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:vm/modular/target/vm.dart' show VmTarget;
import 'utils/io_utils.dart' show computeRepoDirUri;
final Uri repoDir = computeRepoDirUri();
Set<String> allowlistedExternalDartFiles = {
"third_party/pkg/package_config/lib/package_config.dart",
"third_party/pkg/package_config/lib/package_config_types.dart",
"third_party/pkg/package_config/lib/src/discovery.dart",
"third_party/pkg/package_config/lib/src/errors.dart",
"third_party/pkg/package_config/lib/src/package_config_impl.dart",
"third_party/pkg/package_config/lib/src/package_config_io.dart",
"third_party/pkg/package_config/lib/src/package_config_json.dart",
"third_party/pkg/package_config/lib/src/package_config.dart",
"third_party/pkg/package_config/lib/src/packages_file.dart",
"third_party/pkg/package_config/lib/src/util.dart",
// TODO(johnniwinther): Fix to allow dependency of package:package_config.
"third_party/pkg/package_config/lib/src/util_io.dart",
// TODO(CFE-team): These files should not be included.
// The package isn't even in pubspec.yaml.
"pkg/meta/lib/meta.dart",
"pkg/meta/lib/meta_meta.dart",
};
Set<String> allowlistedThirdPartyPackages = {
"yaml",
// package:yaml dependencies
"core/pkgs/collection",
"core/pkgs/path",
"source_span",
"string_scanner",
"term_glyph",
};
/// 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);
}
}
List<Uri> result = await CompilerContext.runWithOptions<List<Uri>>(options,
(CompilerContext c) async {
UriTranslator uriTranslator = await c.options.getUriTranslator();
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();
return new List<Uri>.from(tracker.dependencies);
});
Set<Uri> otherDartUris = new Set<Uri>();
Set<Uri> otherNonDartUris = new Set<Uri>();
List<String> allowedRelativePaths = [
// Front-end.
"pkg/kernel/",
"pkg/_fe_analyzer_shared/",
// For VmTarget for macros.
"pkg/vm/lib/modular/",
// Platform.
"sdk/lib/",
"runtime/lib/",
"runtime/bin/",
// Macros.
"pkg/macros",
"pkg/_macros",
for (String package in allowlistedThirdPartyPackages)
"third_party/pkg/$package/",
];
List<String> allowedUriPrefixes = [
frontendLibUri.toString(),
for (String relativePath in allowedRelativePaths)
repoDir.resolve(relativePath).toString()
];
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"));
otherNonDartUris.remove(repoDir.resolve(".dart_tool/package_config.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");
}
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;
}