From 807660f323ec90b3f357b946f662c06880c6e0b9 Mon Sep 17 00:00:00 2001 From: Nicholas Shahan Date: Mon, 7 Oct 2024 21:21:30 +0000 Subject: [PATCH] [ddc] Create new options.dart library This is a step towards organizing the code from shared_command.dart and eventually deleting it. - Move `SharedCompilerOptions` and rename to `Options` from shared_command.dart along with helpers. Change-Id: Ic9edfb47fc2425a28b1e948d94fad96a2f594108 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/388048 Reviewed-by: Johnni Winther Reviewed-by: Mark Zhou Reviewed-by: Sigmund Cherem Reviewed-by: Nate Biggs Commit-Queue: Nicholas Shahan --- pkg/dev_compiler/lib/dev_compiler.dart | 2 +- pkg/dev_compiler/lib/src/command/options.dart | 363 ++++++++++++++++++ .../lib/src/compiler/shared_command.dart | 362 +---------------- pkg/dev_compiler/lib/src/kernel/command.dart | 9 +- pkg/dev_compiler/lib/src/kernel/compiler.dart | 6 +- .../lib/src/kernel/compiler_new.dart | 8 +- .../kernel/expression_compiler_worker.dart | 4 +- .../lib/src/kernel/nullable_inference.dart | 5 +- .../expression_compiler/test_compiler.dart | 5 +- pkg/dev_compiler/test/memory_compiler.dart | 2 +- .../module_symbols_test_shared.dart | 5 +- .../test/nullable_inference_test.dart | 6 +- .../lib/src/javascript_bundle.dart | 2 +- 13 files changed, 390 insertions(+), 389 deletions(-) create mode 100644 pkg/dev_compiler/lib/src/command/options.dart diff --git a/pkg/dev_compiler/lib/dev_compiler.dart b/pkg/dev_compiler/lib/dev_compiler.dart index 53f5cb257dd7..dba271bd7b31 100644 --- a/pkg/dev_compiler/lib/dev_compiler.dart +++ b/pkg/dev_compiler/lib/dev_compiler.dart @@ -4,9 +4,9 @@ // The dev_compiler does not have a publishable public API, instead this is // intended for other consumers within the Dart SDK. +export 'src/command/options.dart' show Options; export 'src/compiler/module_builder.dart' show ModuleFormat, parseModuleFormat, libraryUriToJsIdentifier; -export 'src/compiler/shared_command.dart' show SharedCompilerOptions; export 'src/kernel/command.dart' show jsProgramToCode; export 'src/kernel/compiler.dart' show Compiler, ProgramCompiler; export 'src/kernel/compiler_new.dart' show LibraryBundleCompiler; diff --git a/pkg/dev_compiler/lib/src/command/options.dart b/pkg/dev_compiler/lib/src/command/options.dart new file mode 100644 index 000000000000..80001367fd3b --- /dev/null +++ b/pkg/dev_compiler/lib/src/command/options.dart @@ -0,0 +1,363 @@ +// Copyright (c) 2024, 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 'package:args/args.dart'; + +import 'package:front_end/src/api_unstable/ddc.dart' + show parseExperimentalArguments; +import 'package:path/path.dart' as p; + +import '../compiler/module_builder.dart'; + +/// Compiler options for the `dartdevc` backend. +class Options { + /// Whether to emit the source mapping file. + /// + /// This supports debugging the original source code instead of the generated + /// code. + final bool sourceMap; + + /// Whether to emit the source mapping file in the program text, so the + /// runtime can enable synchronous stack trace deobfuscation. + final bool inlineSourceMap; + + /// Whether to emit the full compiled kernel. + /// + /// This is used by expression compiler worker, launched from the debugger + /// in webdev and google3 scenarios, for expression evaluation features. + /// Full kernel for compiled files is needed to be able to compile + /// expressions on demand in the current scope of a breakpoint. + final bool emitFullCompiledKernel; + + /// Whether to emit a summary file containing API signatures. + /// + /// This is required for a modular build process. + final bool summarizeApi; + + // Whether to enable assertions. + final bool enableAsserts; + + /// Whether to compile code in a more permissive REPL mode allowing access + /// to private members across library boundaries. + /// + /// This should only set `true` by our REPL compiler. + bool replCompile; + + /// Whether to emit the debug metadata + /// + /// Debugger uses this information about to construct mapping between + /// modules and libraries that otherwise requires expensive communication with + /// the browser. + final bool emitDebugMetadata; + + /// Whether to emit the debug symbols + /// + /// Debugger uses this information about to construct mapping between + /// dart and js objects that otherwise requires expensive communication with + /// the browser. + final bool emitDebugSymbols; + + final Map summaryModules; + + final List moduleFormats; + + /// The name of the module. + /// + /// This is used to support file concatenation. The JS module will contain its + /// module name inside itself, allowing it to declare the module name + /// independently of the file. + final String moduleName; + + /// Custom scheme to indicate a multi-root uri. + final String multiRootScheme; + + /// Path to set multi-root files relative to when generating source-maps. + final String? multiRootOutputPath; + + /// Experimental language features that are enabled/disabled, see + /// [the spec](https://github.com/dart-lang/sdk/blob/master/docs/process/experimental-flags.md) + /// for more details. + final Map experiments; + + final bool soundNullSafety; + + /// Whether or not the `--canary` flag was specified during compilation. + final bool canaryFeatures; + + /// When `true` the [Component] will be compiled into a format compatible with + /// hot reload. + /// + /// The output will still be a single file containing each library in an + /// isolated namespace. + final bool emitLibraryBundle; + + /// Whether the compiler is generating a dynamic module. + final bool dynamicModule; + + /// When `true` stars "*" will appear to represent legacy types when printing + /// runtime types in the compiled application. + final bool printLegacyStars = false; + + /// Raw precompiled macro options, each of the format + /// `;`. + /// + /// Multiple library URIs may be provided separated by additional semicolons. + final List precompiledMacros; + + /// The serialization mode to use for macro communication. + final String? macroSerializationMode; + + Options( + {this.sourceMap = true, + this.inlineSourceMap = false, + this.summarizeApi = true, + this.enableAsserts = true, + this.replCompile = false, + this.emitDebugMetadata = false, + this.emitDebugSymbols = false, + this.emitFullCompiledKernel = false, + this.summaryModules = const {}, + this.moduleFormats = const [], + required this.moduleName, + this.multiRootScheme = 'org-dartlang-app', + this.multiRootOutputPath, + this.experiments = const {}, + this.soundNullSafety = true, + this.canaryFeatures = false, + this.dynamicModule = false, + this.precompiledMacros = const [], + this.macroSerializationMode}) + : emitLibraryBundle = canaryFeatures && + moduleFormats.length == 1 && + moduleFormats.single == ModuleFormat.ddc; + + Options.fromArguments(ArgResults args) + : this( + sourceMap: args['source-map'] as bool, + inlineSourceMap: args['inline-source-map'] as bool, + summarizeApi: args['summarize'] as bool, + enableAsserts: args['enable-asserts'] as bool, + replCompile: args['repl-compile'] as bool, + emitDebugMetadata: args['experimental-emit-debug-metadata'] as bool, + emitDebugSymbols: args['emit-debug-symbols'] as bool, + emitFullCompiledKernel: + args['experimental-output-compiled-kernel'] as bool, + summaryModules: + _parseCustomSummaryModules(args['summary'] as List), + moduleFormats: parseModuleFormatOption(args), + moduleName: _getModuleName(args), + multiRootScheme: args['multi-root-scheme'] as String, + multiRootOutputPath: args['multi-root-output-path'] as String?, + experiments: parseExperimentalArguments( + args['enable-experiment'] as List), + soundNullSafety: args['sound-null-safety'] as bool, + canaryFeatures: args['canary'] as bool, + dynamicModule: args['dynamic-module'] as bool, + precompiledMacros: args['precompiled-macro'] as List, + macroSerializationMode: + args['macro-serialization-mode'] as String?); + + Options.fromSdkRequiredArguments(ArgResults args) + : this( + summarizeApi: false, + moduleFormats: parseModuleFormatOption(args), + // When compiling the SDK use dart_sdk as the default. This is the + // assumed name in various places around the build systems. + moduleName: + args['module-name'] != null ? _getModuleName(args) : 'dart_sdk', + multiRootScheme: args['multi-root-scheme'] as String, + multiRootOutputPath: args['multi-root-output-path'] as String?, + experiments: parseExperimentalArguments( + args['enable-experiment'] as List), + soundNullSafety: args['sound-null-safety'] as bool, + canaryFeatures: args['canary'] as bool); + + static void addArguments(ArgParser parser, {bool hide = true}) { + addSdkRequiredArguments(parser, hide: hide); + + parser + ..addMultiOption('summary', + abbr: 's', + help: 'API summary file(s) of imported libraries, optionally\n' + 'with module import path: -s path.dill=js/import/path') + ..addFlag('summarize', + help: 'Emit an API summary file.', defaultsTo: true, hide: hide) + ..addFlag('source-map', + help: 'Emit source mapping.', defaultsTo: true, hide: hide) + ..addFlag('inline-source-map', + help: 'Emit source mapping inline.', defaultsTo: false, hide: hide) + ..addFlag('enable-asserts', + help: 'Enable assertions.', defaultsTo: true, hide: hide) + ..addFlag('repl-compile', + help: 'Compile in a more permissive REPL mode, allowing access' + ' to private members across library boundaries. This should' + ' only be used by debugging tools.', + defaultsTo: false, + hide: hide) + // TODO(41852) Define a process for breaking changes before graduating from + // experimental. + ..addFlag('experimental-emit-debug-metadata', + help: 'Experimental option for compiler development.\n' + 'Output a metadata file for debug tools next to the .js output.', + defaultsTo: false, + hide: true) + ..addFlag('emit-debug-symbols', + help: 'Experimental option for compiler development.\n' + 'Output a symbols file for debug tools next to the .js output.', + defaultsTo: false, + hide: true) + ..addFlag('experimental-output-compiled-kernel', + help: 'Experimental option for compiler development.\n' + 'Output a full kernel file for currently compiled module next to ' + 'the .js output.', + defaultsTo: false, + hide: true) + ..addMultiOption('precompiled-macro', + help: + 'Configuration for precompiled macro binaries or kernel files.\n' + 'The expected format of this option is as follows: ' + ';\nFor example: ' + '--precompiled-macro="/path/to/compiled/macro;' + 'package:some_macro/some_macro.dart". Multiple library uris may be ' + 'passed as well (separated by semicolons).', + hide: true) + ..addOption('macro-serialization-mode', + help: 'The serialization mode for communicating with macros.', + allowed: ['bytedata', 'json'], + defaultsTo: 'bytedata') + ..addFlag('dynamic-module', + help: 'Compile to generate a dynamic module', + negatable: false, + defaultsTo: false); + } + + /// Adds only the arguments used to compile the SDK from a full dill file. + /// + /// NOTE: The 'module-name' option will have a special default value of + /// 'dart_sdk' when compiling the SDK. + /// See [SharedOptions.fromSdkRequiredArguments]. + static void addSdkRequiredArguments(ArgParser parser, {bool hide = true}) { + addModuleFormatOptions(parser, hide: hide); + parser + ..addMultiOption('out', abbr: 'o', help: 'Output file (required).') + ..addOption('module-name', + help: 'The output module name, used in some JS module formats.\n' + 'Defaults to the output file name (without .js).') + ..addOption('multi-root-scheme', + help: 'The custom scheme to indicate a multi-root uri.', + defaultsTo: 'org-dartlang-app') + ..addOption('multi-root-output-path', + help: 'Path to set multi-root files relative to when generating' + ' source-maps.', + hide: true) + ..addMultiOption('enable-experiment', + help: 'Enable/disable experimental language features.', hide: hide) + ..addFlag('sound-null-safety', + help: 'Compile for sound null safety at runtime.', + negatable: true, + defaultsTo: true) + ..addFlag('canary', + help: 'Enable all compiler features under active development. ' + 'This option is intended for compiler development only. ' + 'Canary features are likely to be unstable and can be removed ' + 'without warning.', + defaultsTo: false, + hide: true); + } + + static String _getModuleName(ArgResults args) { + var moduleName = args['module-name'] as String?; + if (moduleName == null) { + var outPaths = args['out'] as List; + if (outPaths.isEmpty) { + throw UnsupportedError( + 'No module name provided and unable to synthesize one without any ' + 'output paths.'); + } + var outPath = outPaths.first; + moduleName = p.basenameWithoutExtension(outPath); + } + // TODO(jmesserly): this should probably use sourcePathToUri. + // + // Also we should not need this logic if the user passed in the module name + // explicitly. It is here for backwards compatibility until we can confirm + // that build systems do not depend on passing windows-style paths here. + return p.toUri(moduleName).toString(); + } +} + +/// Finds explicit module names of the form `path=name` in [summaryPaths], +/// and returns the path to mapping in an ordered map from `path` to `name`. +/// +/// A summary path can contain "=" followed by an explicit module name to +/// allow working with summaries whose physical location is outside of the +/// module root directory. +Map _parseCustomSummaryModules(List summaryPaths, + [String? moduleRoot, String? summaryExt]) { + var pathToModule = {}; + for (var summaryPath in summaryPaths) { + var equalSign = summaryPath.indexOf('='); + String modulePath; + var summaryPathWithoutExt = summaryExt != null + ? summaryPath.substring( + 0, + // Strip off the extension, including the last `.`. + summaryPath.length - (summaryExt.length + 1)) + : p.withoutExtension(summaryPath); + if (equalSign != -1) { + modulePath = summaryPath.substring(equalSign + 1); + summaryPath = summaryPath.substring(0, equalSign); + } else if (moduleRoot != null && p.isWithin(moduleRoot, summaryPath)) { + // TODO: Determine if this logic is still needed. + modulePath = p.url.joinAll( + p.split(p.relative(summaryPathWithoutExt, from: moduleRoot))); + } else { + modulePath = p.basename(summaryPathWithoutExt); + } + pathToModule[summaryPath] = modulePath; + } + return pathToModule; +} + +/// Taken from analyzer to implement `--ignore-unrecognized-flags` +List filterUnknownArguments(List args, ArgParser parser) { + if (!args.contains('--ignore-unrecognized-flags')) return args; + + var knownOptions = {}; + var knownAbbreviations = {}; + parser.options.forEach((String name, Option option) { + knownOptions.add(name); + var abbreviation = option.abbr; + if (abbreviation != null) { + knownAbbreviations.add(abbreviation); + } + if (option.negatable != null && option.negatable!) { + knownOptions.add('no-$name'); + } + }); + + String optionName(int prefixLength, String arg) { + var equalsOffset = arg.lastIndexOf('='); + if (equalsOffset < 0) { + return arg.substring(prefixLength); + } + return arg.substring(prefixLength, equalsOffset); + } + + var filtered = []; + for (var arg in args) { + if (arg.startsWith('--') && arg.length > 2) { + if (knownOptions.contains(optionName(2, arg))) { + filtered.add(arg); + } + } else if (arg.startsWith('-') && arg.length > 1) { + if (knownAbbreviations.contains(optionName(1, arg))) { + filtered.add(arg); + } + } else { + filtered.add(arg); + } + } + return filtered; +} diff --git a/pkg/dev_compiler/lib/src/compiler/shared_command.dart b/pkg/dev_compiler/lib/src/compiler/shared_command.dart index 5235a13460ec..de808240e3a9 100644 --- a/pkg/dev_compiler/lib/src/compiler/shared_command.dart +++ b/pkg/dev_compiler/lib/src/compiler/shared_command.dart @@ -4,375 +4,15 @@ import 'dart:io'; -import 'package:args/args.dart'; import 'package:front_end/src/api_prototype/macros.dart' as macros show isMacroLibraryUri; import 'package:front_end/src/api_unstable/ddc.dart' - show InitializedCompilerState, parseExperimentalArguments; + show InitializedCompilerState; import 'package:path/path.dart' as p; -import 'module_builder.dart'; - // TODO(nshahan) Merge all of this file the locations where they are used in // the kernel (only) version of DDC. -/// Previously was shared code between Analyzer and Kernel CLI interfaces. -/// -/// This file should only implement functionality that does not depend on -/// Analyzer/Kernel imports. - -/// Compiler options for the `dartdevc` backend. -class SharedCompilerOptions { - /// Whether to emit the source mapping file. - /// - /// This supports debugging the original source code instead of the generated - /// code. - final bool sourceMap; - - /// Whether to emit the source mapping file in the program text, so the - /// runtime can enable synchronous stack trace deobfuscation. - final bool inlineSourceMap; - - /// Whether to emit the full compiled kernel. - /// - /// This is used by expression compiler worker, launched from the debugger - /// in webdev and google3 scenarios, for expression evaluation features. - /// Full kernel for compiled files is needed to be able to compile - /// expressions on demand in the current scope of a breakpoint. - final bool emitFullCompiledKernel; - - /// Whether to emit a summary file containing API signatures. - /// - /// This is required for a modular build process. - final bool summarizeApi; - - // Whether to enable assertions. - final bool enableAsserts; - - /// Whether to compile code in a more permissive REPL mode allowing access - /// to private members across library boundaries. - /// - /// This should only set `true` by our REPL compiler. - bool replCompile; - - /// Whether to emit the debug metadata - /// - /// Debugger uses this information about to construct mapping between - /// modules and libraries that otherwise requires expensive communication with - /// the browser. - final bool emitDebugMetadata; - - /// Whether to emit the debug symbols - /// - /// Debugger uses this information about to construct mapping between - /// dart and js objects that otherwise requires expensive communication with - /// the browser. - final bool emitDebugSymbols; - - final Map summaryModules; - - final List moduleFormats; - - /// The name of the module. - /// - /// This is used to support file concatenation. The JS module will contain its - /// module name inside itself, allowing it to declare the module name - /// independently of the file. - final String moduleName; - - /// Custom scheme to indicate a multi-root uri. - final String multiRootScheme; - - /// Path to set multi-root files relative to when generating source-maps. - final String? multiRootOutputPath; - - /// Experimental language features that are enabled/disabled, see - /// [the spec](https://github.com/dart-lang/sdk/blob/master/docs/process/experimental-flags.md) - /// for more details. - final Map experiments; - - final bool soundNullSafety; - - /// Whether or not the `--canary` flag was specified during compilation. - final bool canaryFeatures; - - /// When `true` the [Component] will be compiled into a format compatible with - /// hot reload. - /// - /// The output will still be a single file containing each library in an - /// isolated namespace. - final bool emitLibraryBundle; - - /// Whether the compiler is generating a dynamic module. - final bool dynamicModule; - - /// When `true` stars "*" will appear to represent legacy types when printing - /// runtime types in the compiled application. - final bool printLegacyStars = false; - - /// Raw precompiled macro options, each of the format - /// `;`. - /// - /// Multiple library URIs may be provided separated by additional semicolons. - final List precompiledMacros; - - /// The serialization mode to use for macro communication. - final String? macroSerializationMode; - - SharedCompilerOptions( - {this.sourceMap = true, - this.inlineSourceMap = false, - this.summarizeApi = true, - this.enableAsserts = true, - this.replCompile = false, - this.emitDebugMetadata = false, - this.emitDebugSymbols = false, - this.emitFullCompiledKernel = false, - this.summaryModules = const {}, - this.moduleFormats = const [], - required this.moduleName, - this.multiRootScheme = 'org-dartlang-app', - this.multiRootOutputPath, - this.experiments = const {}, - this.soundNullSafety = true, - this.canaryFeatures = false, - this.dynamicModule = false, - this.precompiledMacros = const [], - this.macroSerializationMode}) - : emitLibraryBundle = canaryFeatures && - moduleFormats.length == 1 && - moduleFormats.single == ModuleFormat.ddc; - - SharedCompilerOptions.fromArguments(ArgResults args) - : this( - sourceMap: args['source-map'] as bool, - inlineSourceMap: args['inline-source-map'] as bool, - summarizeApi: args['summarize'] as bool, - enableAsserts: args['enable-asserts'] as bool, - replCompile: args['repl-compile'] as bool, - emitDebugMetadata: args['experimental-emit-debug-metadata'] as bool, - emitDebugSymbols: args['emit-debug-symbols'] as bool, - emitFullCompiledKernel: - args['experimental-output-compiled-kernel'] as bool, - summaryModules: - _parseCustomSummaryModules(args['summary'] as List), - moduleFormats: parseModuleFormatOption(args), - moduleName: _getModuleName(args), - multiRootScheme: args['multi-root-scheme'] as String, - multiRootOutputPath: args['multi-root-output-path'] as String?, - experiments: parseExperimentalArguments( - args['enable-experiment'] as List), - soundNullSafety: args['sound-null-safety'] as bool, - canaryFeatures: args['canary'] as bool, - dynamicModule: args['dynamic-module'] as bool, - precompiledMacros: args['precompiled-macro'] as List, - macroSerializationMode: - args['macro-serialization-mode'] as String?); - - SharedCompilerOptions.fromSdkRequiredArguments(ArgResults args) - : this( - summarizeApi: false, - moduleFormats: parseModuleFormatOption(args), - // When compiling the SDK use dart_sdk as the default. This is the - // assumed name in various places around the build systems. - moduleName: - args['module-name'] != null ? _getModuleName(args) : 'dart_sdk', - multiRootScheme: args['multi-root-scheme'] as String, - multiRootOutputPath: args['multi-root-output-path'] as String?, - experiments: parseExperimentalArguments( - args['enable-experiment'] as List), - soundNullSafety: args['sound-null-safety'] as bool, - canaryFeatures: args['canary'] as bool); - - static void addArguments(ArgParser parser, {bool hide = true}) { - addSdkRequiredArguments(parser, hide: hide); - - parser - ..addMultiOption('summary', - abbr: 's', - help: 'API summary file(s) of imported libraries, optionally\n' - 'with module import path: -s path.dill=js/import/path') - ..addFlag('summarize', - help: 'Emit an API summary file.', defaultsTo: true, hide: hide) - ..addFlag('source-map', - help: 'Emit source mapping.', defaultsTo: true, hide: hide) - ..addFlag('inline-source-map', - help: 'Emit source mapping inline.', defaultsTo: false, hide: hide) - ..addFlag('enable-asserts', - help: 'Enable assertions.', defaultsTo: true, hide: hide) - ..addFlag('repl-compile', - help: 'Compile in a more permissive REPL mode, allowing access' - ' to private members across library boundaries. This should' - ' only be used by debugging tools.', - defaultsTo: false, - hide: hide) - // TODO(41852) Define a process for breaking changes before graduating from - // experimental. - ..addFlag('experimental-emit-debug-metadata', - help: 'Experimental option for compiler development.\n' - 'Output a metadata file for debug tools next to the .js output.', - defaultsTo: false, - hide: true) - ..addFlag('emit-debug-symbols', - help: 'Experimental option for compiler development.\n' - 'Output a symbols file for debug tools next to the .js output.', - defaultsTo: false, - hide: true) - ..addFlag('experimental-output-compiled-kernel', - help: 'Experimental option for compiler development.\n' - 'Output a full kernel file for currently compiled module next to ' - 'the .js output.', - defaultsTo: false, - hide: true) - ..addMultiOption('precompiled-macro', - help: - 'Configuration for precompiled macro binaries or kernel files.\n' - 'The expected format of this option is as follows: ' - ';\nFor example: ' - '--precompiled-macro="/path/to/compiled/macro;' - 'package:some_macro/some_macro.dart". Multiple library uris may be ' - 'passed as well (separated by semicolons).', - hide: true) - ..addOption('macro-serialization-mode', - help: 'The serialization mode for communicating with macros.', - allowed: ['bytedata', 'json'], - defaultsTo: 'bytedata') - ..addFlag('dynamic-module', - help: 'Compile to generate a dynamic module', - negatable: false, - defaultsTo: false); - } - - /// Adds only the arguments used to compile the SDK from a full dill file. - /// - /// NOTE: The 'module-name' option will have a special default value of - /// 'dart_sdk' when compiling the SDK. - /// See [SharedCompilerOptions.fromSdkRequiredArguments]. - static void addSdkRequiredArguments(ArgParser parser, {bool hide = true}) { - addModuleFormatOptions(parser, hide: hide); - parser - ..addMultiOption('out', abbr: 'o', help: 'Output file (required).') - ..addOption('module-name', - help: 'The output module name, used in some JS module formats.\n' - 'Defaults to the output file name (without .js).') - ..addOption('multi-root-scheme', - help: 'The custom scheme to indicate a multi-root uri.', - defaultsTo: 'org-dartlang-app') - ..addOption('multi-root-output-path', - help: 'Path to set multi-root files relative to when generating' - ' source-maps.', - hide: true) - ..addMultiOption('enable-experiment', - help: 'Enable/disable experimental language features.', hide: hide) - ..addFlag('sound-null-safety', - help: 'Compile for sound null safety at runtime.', - negatable: true, - defaultsTo: true) - ..addFlag('canary', - help: 'Enable all compiler features under active development. ' - 'This option is intended for compiler development only. ' - 'Canary features are likely to be unstable and can be removed ' - 'without warning.', - defaultsTo: false, - hide: true); - } - - static String _getModuleName(ArgResults args) { - var moduleName = args['module-name'] as String?; - if (moduleName == null) { - var outPaths = args['out'] as List; - if (outPaths.isEmpty) { - throw UnsupportedError( - 'No module name provided and unable to synthesize one without any ' - 'output paths.'); - } - var outPath = outPaths.first; - moduleName = p.basenameWithoutExtension(outPath); - } - // TODO(jmesserly): this should probably use sourcePathToUri. - // - // Also we should not need this logic if the user passed in the module name - // explicitly. It is here for backwards compatibility until we can confirm - // that build systems do not depend on passing windows-style paths here. - return p.toUri(moduleName).toString(); - } -} - -/// Finds explicit module names of the form `path=name` in [summaryPaths], -/// and returns the path to mapping in an ordered map from `path` to `name`. -/// -/// A summary path can contain "=" followed by an explicit module name to -/// allow working with summaries whose physical location is outside of the -/// module root directory. -Map _parseCustomSummaryModules(List summaryPaths, - [String? moduleRoot, String? summaryExt]) { - var pathToModule = {}; - for (var summaryPath in summaryPaths) { - var equalSign = summaryPath.indexOf('='); - String modulePath; - var summaryPathWithoutExt = summaryExt != null - ? summaryPath.substring( - 0, - // Strip off the extension, including the last `.`. - summaryPath.length - (summaryExt.length + 1)) - : p.withoutExtension(summaryPath); - if (equalSign != -1) { - modulePath = summaryPath.substring(equalSign + 1); - summaryPath = summaryPath.substring(0, equalSign); - } else if (moduleRoot != null && p.isWithin(moduleRoot, summaryPath)) { - // TODO: Determine if this logic is still needed. - modulePath = p.url.joinAll( - p.split(p.relative(summaryPathWithoutExt, from: moduleRoot))); - } else { - modulePath = p.basename(summaryPathWithoutExt); - } - pathToModule[summaryPath] = modulePath; - } - return pathToModule; -} - -/// Taken from analyzer to implement `--ignore-unrecognized-flags` -List filterUnknownArguments(List args, ArgParser parser) { - if (!args.contains('--ignore-unrecognized-flags')) return args; - - var knownOptions = {}; - var knownAbbreviations = {}; - parser.options.forEach((String name, Option option) { - knownOptions.add(name); - var abbreviation = option.abbr; - if (abbreviation != null) { - knownAbbreviations.add(abbreviation); - } - if (option.negatable != null && option.negatable!) { - knownOptions.add('no-$name'); - } - }); - - String optionName(int prefixLength, String arg) { - var equalsOffset = arg.lastIndexOf('='); - if (equalsOffset < 0) { - return arg.substring(prefixLength); - } - return arg.substring(prefixLength, equalsOffset); - } - - var filtered = []; - for (var arg in args) { - if (arg.startsWith('--') && arg.length > 2) { - if (knownOptions.contains(optionName(2, arg))) { - filtered.add(arg); - } - } else if (arg.startsWith('-') && arg.length > 1) { - if (knownAbbreviations.contains(optionName(1, arg))) { - filtered.add(arg); - } - } else { - filtered.add(arg); - } - } - return filtered; -} - /// Convert a [source] string to a Uri, where the source may be a /// dart/file/package URI or a local win/mac/linux path. Uri sourcePathToUri(String source, {bool? windows}) { diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart index 6dc0b845ef8e..39bcc2562c36 100644 --- a/pkg/dev_compiler/lib/src/kernel/command.dart +++ b/pkg/dev_compiler/lib/src/kernel/command.dart @@ -20,6 +20,7 @@ import 'package:path/path.dart' as p; import 'package:source_maps/source_maps.dart' show SourceMapBuilder; import '../command/arguments.dart'; +import '../command/options.dart'; import '../compiler/js_names.dart' as js_ast; import '../compiler/module_builder.dart'; import '../compiler/shared_command.dart'; @@ -111,7 +112,7 @@ Future _compile(List args, help: 'The path to the libraries.json file for the sdk.') ..addOption('used-inputs-file', help: 'If set, the file to record inputs used.', hide: true); - SharedCompilerOptions.addArguments(argParser); + Options.addArguments(argParser); var declaredVariables = parseAndRemoveDeclaredVariables(args); ArgResults argResults; try { @@ -139,7 +140,7 @@ Future _compile(List args, return CompilerResult(0); } - var options = SharedCompilerOptions.fromArguments(argResults); + var options = Options.fromArguments(argResults); addGeneratedVariables(declaredVariables, enableAsserts: options.enableAsserts); @@ -540,7 +541,7 @@ Future _compile(List args, // TODO(sigmund): refactor the underlying pieces to reduce the code duplication. Future compileSdkFromDill(List args) async { var argParser = ArgParser(allowTrailingOptions: true); - SharedCompilerOptions.addSdkRequiredArguments(argParser); + Options.addSdkRequiredArguments(argParser); ArgResults argResults; try { @@ -590,7 +591,7 @@ Future compileSdkFromDill(List args) async { } var coreTypes = CoreTypes(component); var hierarchy = ClassHierarchy(component, coreTypes); - var options = SharedCompilerOptions.fromSdkRequiredArguments(argResults); + var options = Options.fromSdkRequiredArguments(argResults); var compiler = options.emitLibraryBundle ? LibraryBundleCompiler(component, hierarchy, options, const {}, const {}, diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart index a23f4e0aea09..7bab32c40853 100644 --- a/pkg/dev_compiler/lib/src/kernel/compiler.dart +++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart @@ -22,13 +22,13 @@ import 'package:kernel/type_environment.dart'; import 'package:path/path.dart' as p; import 'package:source_span/source_span.dart' show SourceLocation; +import '../command/options.dart' show Options; import '../compiler/js_names.dart' as js_ast; import '../compiler/js_utils.dart' as js_ast; import '../compiler/module_builder.dart' show isSdkInternalRuntimeUri, libraryUriToJsIdentifier; import '../compiler/module_containers.dart' show ModuleItemContainer; import '../compiler/rewrite_async.dart'; -import '../compiler/shared_command.dart' show SharedCompilerOptions; import '../js_ast/js_ast.dart' as js_ast; import '../js_ast/js_ast.dart' show ModuleItem, js; import '../js_ast/source_map_printer.dart' @@ -63,7 +63,7 @@ class ProgramCompiler extends ComputeOnceConstantVisitor StatementVisitor, ExpressionVisitor, Compiler { - final SharedCompilerOptions _options; + final Options _options; /// Maps each `Class` node compiled in the module to the `Identifier`s used to /// name the class in JavaScript. @@ -432,7 +432,7 @@ class ProgramCompiler extends ComputeOnceConstantVisitor factory ProgramCompiler( Component component, ClassHierarchy hierarchy, - SharedCompilerOptions options, + Options options, Map importToSummary, Map summaryToModule, { CoreTypes? coreTypes, diff --git a/pkg/dev_compiler/lib/src/kernel/compiler_new.dart b/pkg/dev_compiler/lib/src/kernel/compiler_new.dart index 3e52d8f81fdf..ab5af9327855 100644 --- a/pkg/dev_compiler/lib/src/kernel/compiler_new.dart +++ b/pkg/dev_compiler/lib/src/kernel/compiler_new.dart @@ -22,13 +22,13 @@ import 'package:kernel/type_environment.dart'; import 'package:path/path.dart' as p; import 'package:source_span/source_span.dart' show SourceLocation; +import '../command/options.dart' show Options; import '../compiler/js_names.dart' as js_ast; import '../compiler/js_utils.dart' as js_ast; import '../compiler/module_builder.dart' show isSdkInternalRuntimeUri, libraryUriToJsIdentifier; import '../compiler/module_containers.dart' show ModuleItemContainer; import '../compiler/rewrite_async.dart'; -import '../compiler/shared_command.dart' show SharedCompilerOptions; import '../js_ast/js_ast.dart' as js_ast; import '../js_ast/js_ast.dart' show ModuleItem, js; import '../js_ast/source_map_printer.dart' @@ -88,7 +88,7 @@ class SymbolData { /// Compiles a kernel [Component] to a bundle of individual libraries. class LibraryBundleCompiler implements old.Compiler { final ClassHierarchy _hierarchy; - final SharedCompilerOptions _options; + final Options _options; final Map _importToSummary; final Map _summaryToModule; final CoreTypes _coreTypes; @@ -209,7 +209,7 @@ class LibraryCompiler extends ComputeOnceConstantVisitor implements StatementVisitor, ExpressionVisitor { - final SharedCompilerOptions _options; + final Options _options; final SymbolData _symbolData; /// Maps each `Class` node compiled in the module to the `Identifier`s used to @@ -596,7 +596,7 @@ class LibraryCompiler extends ComputeOnceConstantVisitor factory LibraryCompiler( Component component, ClassHierarchy hierarchy, - SharedCompilerOptions options, + Options options, Map importToSummary, Map summaryToModule, { CoreTypes? coreTypes, diff --git a/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart b/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart index 57b76c3c4144..b66b4fd4d4d0 100644 --- a/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart +++ b/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart @@ -19,9 +19,9 @@ import 'package:kernel/src/tool/find_referenced_libraries.dart' show duplicateLibrariesReachable; import 'package:kernel/target/targets.dart' show TargetFlags; +import '../command/options.dart' show Options; import '../compiler/js_names.dart'; import '../compiler/module_builder.dart' show ModuleFormat, parseModuleFormat; -import '../compiler/shared_command.dart' show SharedCompilerOptions; import 'asset_file_system.dart'; import 'command.dart'; import 'compiler.dart' show ProgramCompiler; @@ -468,7 +468,7 @@ class ExpressionCompilerWorker { var kernel2jsCompiler = ProgramCompiler( finalComponent, hierarchy, - SharedCompilerOptions( + Options( sourceMap: true, summarizeApi: false, moduleName: moduleName, diff --git a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart index a109d4334533..d015168c4246 100644 --- a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart +++ b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart @@ -8,7 +8,7 @@ import 'package:kernel/core_types.dart'; import 'package:kernel/kernel.dart'; import 'package:kernel/type_environment.dart'; -import '../compiler/shared_command.dart' show SharedCompilerOptions; +import '../command/options.dart' show Options; import 'js_typerep.dart'; import 'kernel_helpers.dart'; @@ -53,8 +53,7 @@ class NullableInference extends ExpressionVisitor final bool _soundNullSafety; - NullableInference(this.jsTypeRep, this._staticTypeContext, - {SharedCompilerOptions? options}) + NullableInference(this.jsTypeRep, this._staticTypeContext, {Options? options}) : coreTypes = jsTypeRep.coreTypes, _soundNullSafety = options?.soundNullSafety ?? true { _variableInference._nullInference = this; diff --git a/pkg/dev_compiler/test/expression_compiler/test_compiler.dart b/pkg/dev_compiler/test/expression_compiler/test_compiler.dart index 8b3932e2606d..8312b653b6ec 100644 --- a/pkg/dev_compiler/test/expression_compiler/test_compiler.dart +++ b/pkg/dev_compiler/test/expression_compiler/test_compiler.dart @@ -6,8 +6,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io' show File; -import 'package:dev_compiler/src/compiler/shared_command.dart' - show SharedCompilerOptions; +import 'package:dev_compiler/src/command/options.dart' show Options; import 'package:dev_compiler/src/kernel/command.dart'; import 'package:dev_compiler/src/kernel/compiler.dart' show ProgramCompiler; import 'package:dev_compiler/src/kernel/expression_compiler.dart' @@ -59,7 +58,7 @@ class TestExpressionCompiler { var moduleName = p.basenameWithoutExtension(output.toFilePath()); var classHierarchy = compilerResult.classHierarchy!; - var compilerOptions = SharedCompilerOptions( + var compilerOptions = Options( replCompile: true, moduleName: moduleName, experiments: experiments, diff --git a/pkg/dev_compiler/test/memory_compiler.dart b/pkg/dev_compiler/test/memory_compiler.dart index fca401efbc9a..815c32414cab 100644 --- a/pkg/dev_compiler/test/memory_compiler.dart +++ b/pkg/dev_compiler/test/memory_compiler.dart @@ -49,7 +49,7 @@ Future compileFromMemory( .entityForUri(memoryDirectory.resolve(entry.key)) .writeAsStringSync(entry.value); } - var options = SharedCompilerOptions(moduleName: 'test'); + var options = Options(moduleName: 'test'); var compilerState = fe.initializeCompiler( null, false, diff --git a/pkg/dev_compiler/test/module_symbols/module_symbols_test_shared.dart b/pkg/dev_compiler/test/module_symbols/module_symbols_test_shared.dart index 83614fe24e6d..c70dba9ee41e 100644 --- a/pkg/dev_compiler/test/module_symbols/module_symbols_test_shared.dart +++ b/pkg/dev_compiler/test/module_symbols/module_symbols_test_shared.dart @@ -4,10 +4,9 @@ import 'dart:io' show Directory, File; +import 'package:dev_compiler/src/command/options.dart' show Options; import 'package:dev_compiler/src/compiler/module_builder.dart' show ModuleFormat; -import 'package:dev_compiler/src/compiler/shared_command.dart' - show SharedCompilerOptions; import 'package:dev_compiler/src/kernel/command.dart'; import 'package:dev_compiler/src/kernel/compiler.dart' show ProgramCompiler; import 'package:dev_compiler/src/kernel/module_symbols.dart'; @@ -35,7 +34,7 @@ class TestCompiler { // Initialize DDC. var moduleName = 'foo.dart'; var classHierarchy = compilerResult.classHierarchy!; - var compilerOptions = SharedCompilerOptions( + var compilerOptions = Options( replCompile: true, moduleName: moduleName, soundNullSafety: setup.soundNullSafety, diff --git a/pkg/dev_compiler/test/nullable_inference_test.dart b/pkg/dev_compiler/test/nullable_inference_test.dart index b0fc14238aa2..b716175f617d 100644 --- a/pkg/dev_compiler/test/nullable_inference_test.dart +++ b/pkg/dev_compiler/test/nullable_inference_test.dart @@ -6,7 +6,7 @@ import 'dart:async'; import 'dart:convert' show jsonEncode; import 'dart:io'; -import 'package:dev_compiler/src/compiler/shared_command.dart'; +import 'package:dev_compiler/src/command/options.dart'; import 'package:dev_compiler/src/kernel/command.dart' show addGeneratedVariables, getSdkPath; import 'package:dev_compiler/src/kernel/js_typerep.dart'; @@ -657,7 +657,7 @@ class _TestRecursiveVisitor extends RecursiveVisitor { int _functionNesting = 0; late TypeEnvironment _typeEnvironment; late StatefulStaticTypeContext _staticTypeContext; - late SharedCompilerOptions _options; + late Options _options; _TestRecursiveVisitor(this.librariesFromDill); @@ -671,7 +671,7 @@ class _TestRecursiveVisitor extends RecursiveVisitor { ); _typeEnvironment = jsTypeRep.types; _staticTypeContext = StatefulStaticTypeContext.stacked(_typeEnvironment); - _options = SharedCompilerOptions(moduleName: 'module_for_test'); + _options = Options(moduleName: 'module_for_test'); inference ??= NullableInference(jsTypeRep, _staticTypeContext, options: _options); diff --git a/pkg/frontend_server/lib/src/javascript_bundle.dart b/pkg/frontend_server/lib/src/javascript_bundle.dart index 6df1e3347995..c12907fec67b 100644 --- a/pkg/frontend_server/lib/src/javascript_bundle.dart +++ b/pkg/frontend_server/lib/src/javascript_bundle.dart @@ -200,7 +200,7 @@ class IncrementalJavaScriptBundler { // use full path for tracking if module uri is not a package uri. final String moduleUrl = urlForComponentUri(moduleUri, packageConfig); final String moduleName = makeModuleName(moduleUrl); - final SharedCompilerOptions ddcOptions = new SharedCompilerOptions( + final Options ddcOptions = new Options( sourceMap: true, summarizeApi: false, emitDebugMetadata: emitDebugMetadata,