[dartdevc] fix #35013, move DDC off Analyzer task model
The new file pkg/dev_compiler/lib/src/analyzer/driver.dart handles
building the linked summary for a build unit, and then is capable of
doing analysis using LibraryAnalyzer.
The algorithm is very similar to analyzer_cli's build mode. The
biggest difference is that `dartdevc` has existing support for
discovering source files from the explicit source list (rather than
requiring every source to be listed on the command line). We don't want
to break that support, so there's a bit of logic to follow imports,
exports, and parts.
After the linked summary is produced, DDC gets the analysis results
(errors and resolved AST) for each library, and compiles it into a JS
module.
Change-Id: I7bf1ce1eca73fd036002e498de5924c488b534dc
Reviewed-on: https://dart-review.googlesource.com/c/82469
Commit-Queue: Jenny Messerly <jmesserly@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
Reviewed-by: Vijay Menon <vsm@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index c387512..2a05e11 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -81,11 +81,14 @@
// TODO(brianwilkerson) Determine whether this await is necessary.
await null;
return PerformanceStatistics.analysis.makeCurrentWhileAsync(() async {
- return _analyze();
+ return analyzeSync();
});
}
- Map<FileState, UnitAnalysisResult> _analyze() {
+ /**
+ * Compute analysis results for all units of the library.
+ */
+ Map<FileState, UnitAnalysisResult> analyzeSync() {
Map<FileState, CompilationUnit> units = {};
// Parse all files.
diff --git a/pkg/dev_compiler/bin/dartdevc.dart b/pkg/dev_compiler/bin/dartdevc.dart
index 2e7ec1e..28b950d 100755
--- a/pkg/dev_compiler/bin/dartdevc.dart
+++ b/pkg/dev_compiler/bin/dartdevc.dart
@@ -38,7 +38,7 @@
class _CompilerWorker extends AsyncWorkerLoop {
/// The original args supplied to the executable.
final ParsedArguments _startupArgs;
- InitializedCompilerState _compilerState;
+ CompilerResult _result;
_CompilerWorker(this._startupArgs, AsyncWorkerConnection workerConnection)
: super(connection: workerConnection);
@@ -47,14 +47,13 @@
Future<WorkResponse> performRequest(WorkRequest request) async {
var args = _startupArgs.merge(request.arguments);
var output = StringBuffer();
- var result = await runZoned(
- () => compile(args, compilerState: _compilerState), zoneSpecification:
+ _result = await runZoned(() => compile(args, previousResult: _result),
+ zoneSpecification:
ZoneSpecification(print: (self, parent, zone, message) {
output.writeln(message.toString());
}));
- _compilerState = result.compilerState;
return WorkResponse()
- ..exitCode = result.success ? 0 : 1
+ ..exitCode = _result.success ? 0 : 1
..output = output.toString();
}
}
@@ -68,7 +67,7 @@
print('>>> BATCH START');
String line;
- InitializedCompilerState compilerState;
+ CompilerResult result;
while ((line = stdin.readLineSync(encoding: utf8))?.isNotEmpty == true) {
totalTests++;
@@ -76,8 +75,7 @@
String outcome;
try {
- var result = await compile(args, compilerState: compilerState);
- compilerState = result.compilerState;
+ result = await compile(args, previousResult: result);
outcome = result.success ? 'PASS' : (result.crashed ? 'CRASH' : 'FAIL');
} catch (e, s) {
outcome = 'CRASH';
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index fda58dd..e6d3e29 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -6,6 +6,7 @@
import 'dart:math' show min, max;
import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
+import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
import 'package:analyzer/dart/ast/standard_resolution_map.dart';
import 'package:analyzer/dart/ast/token.dart' show Token, TokenType;
@@ -13,23 +14,15 @@
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/token.dart' show StringToken;
import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/handle.dart';
import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/dart/sdk/sdk.dart';
import 'package:analyzer/src/generated/constant.dart'
show DartObject, DartObjectImpl;
-import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
import 'package:analyzer/src/generated/resolver.dart'
show TypeProvider, NamespaceBuilder;
import 'package:analyzer/src/generated/type_system.dart'
show StrongTypeSystemImpl;
-import 'package:analyzer/src/summary/idl.dart' show UnlinkedUnit;
-import 'package:analyzer/src/summary/link.dart' as summary_link;
import 'package:analyzer/src/summary/package_bundle_reader.dart';
-import 'package:analyzer/src/summary/summarize_ast.dart'
- show serializeAstUnlinked;
-import 'package:analyzer/src/summary/summarize_elements.dart'
- show PackageBundleAssembler;
-import 'package:analyzer/src/summary/summary_sdk.dart';
import 'package:analyzer/src/task/strong/ast_properties.dart';
import 'package:path/path.dart' as path;
import 'package:source_span/source_span.dart' show SourceLocation;
@@ -43,6 +36,7 @@
import '../js_ast/js_ast.dart' show js;
import '../js_ast/source_map_printer.dart' show NodeEnd, NodeSpan, HoverComment;
import 'ast_builder.dart';
+import 'driver.dart';
import 'element_helpers.dart';
import 'error_helpers.dart';
import 'extension_types.dart' show ExtensionTypeSet;
@@ -73,7 +67,6 @@
class CodeGenerator extends Object
with NullableTypeInference, SharedCompiler<LibraryElement>
implements AstVisitor<JS.Node> {
- final AnalysisContext context;
final SummaryDataStore summaryData;
final CompilerOptions options;
@@ -200,38 +193,45 @@
final _usedCovariantPrivateMembers = HashSet<ExecutableElement>();
- CodeGenerator(AnalysisContext c, this.summaryData, this.options,
- this._extensionTypes, this.errors)
- : context = c,
- rules = StrongTypeSystemImpl(c.typeProvider),
- types = c.typeProvider,
- _asyncStreamIterator = getClass(c, 'dart:async', 'StreamIterator').type,
- _coreIdentical = _getLibrary(c, 'dart:core')
+ final DeclaredVariables declaredVariables;
+
+ CodeGenerator(LinkedAnalysisDriver driver, this.types, this.summaryData,
+ this.options, this._extensionTypes, this.errors)
+ : rules = StrongTypeSystemImpl(types),
+ declaredVariables = driver.declaredVariables,
+ _asyncStreamIterator =
+ driver.getClass('dart:async', 'StreamIterator').type,
+ _coreIdentical = driver
+ .getLibrary('dart:core')
.publicNamespace
.get('identical') as FunctionElement,
- _jsArray = getClass(c, 'dart:_interceptors', 'JSArray'),
- interceptorClass = getClass(c, 'dart:_interceptors', 'Interceptor'),
- coreLibrary = _getLibrary(c, 'dart:core'),
- boolClass = getClass(c, 'dart:core', 'bool'),
- intClass = getClass(c, 'dart:core', 'int'),
- doubleClass = getClass(c, 'dart:core', 'double'),
- numClass = getClass(c, 'dart:core', 'num'),
- nullClass = getClass(c, 'dart:core', 'Null'),
- objectClass = getClass(c, 'dart:core', 'Object'),
- stringClass = getClass(c, 'dart:core', 'String'),
- functionClass = getClass(c, 'dart:core', 'Function'),
- privateSymbolClass = getClass(c, 'dart:_js_helper', 'PrivateSymbol'),
+ _jsArray = driver.getClass('dart:_interceptors', 'JSArray'),
+ interceptorClass = driver.getClass('dart:_interceptors', 'Interceptor'),
+ coreLibrary = driver.getLibrary('dart:core'),
+ boolClass = driver.getClass('dart:core', 'bool'),
+ intClass = driver.getClass('dart:core', 'int'),
+ doubleClass = driver.getClass('dart:core', 'double'),
+ numClass = driver.getClass('dart:core', 'num'),
+ nullClass = driver.getClass('dart:core', 'Null'),
+ objectClass = driver.getClass('dart:core', 'Object'),
+ stringClass = driver.getClass('dart:core', 'String'),
+ functionClass = driver.getClass('dart:core', 'Function'),
+ privateSymbolClass =
+ driver.getClass('dart:_js_helper', 'PrivateSymbol'),
linkedHashMapImplType =
- getClass(c, 'dart:_js_helper', 'LinkedMap').type,
+ driver.getClass('dart:_js_helper', 'LinkedMap').type,
identityHashMapImplType =
- getClass(c, 'dart:_js_helper', 'IdentityMap').type,
- linkedHashSetImplType = getClass(c, 'dart:collection', '_HashSet').type,
+ driver.getClass('dart:_js_helper', 'IdentityMap').type,
+ linkedHashSetImplType =
+ driver.getClass('dart:collection', '_HashSet').type,
identityHashSetImplType =
- getClass(c, 'dart:collection', '_IdentityHashSet').type,
- syncIterableType = getClass(c, 'dart:_js_helper', 'SyncIterable').type,
- asyncStarImplType = getClass(c, 'dart:async', '_AsyncStarImpl').type,
- dartJSLibrary = _getLibrary(c, 'dart:js') {
- jsTypeRep = JSTypeRep(rules, c);
+ driver.getClass('dart:collection', '_IdentityHashSet').type,
+ syncIterableType =
+ driver.getClass('dart:_js_helper', 'SyncIterable').type,
+ asyncStarImplType =
+ driver.getClass('dart:async', '_AsyncStarImpl').type,
+ dartJSLibrary = driver.getLibrary('dart:js') {
+ jsTypeRep = JSTypeRep(rules, driver);
}
LibraryElement get currentLibrary => _currentElement.library;
@@ -248,92 +248,12 @@
///
/// Takes the metadata for the build unit, as well as resolved trees and
/// errors, and computes the output module code and optionally the source map.
- JSModuleFile compile(List<CompilationUnit> compilationUnits) {
+ JS.Program compile(List<CompilationUnit> compilationUnits) {
_libraryRoot = options.libraryRoot;
if (!_libraryRoot.endsWith(path.separator)) {
_libraryRoot += path.separator;
}
- var name = options.moduleName;
- invalidModule() =>
- JSModuleFile.invalid(name, formatErrors(context, errors), options);
-
- if (!options.unsafeForceCompile && errors.any(_isFatalError)) {
- return invalidModule();
- }
-
- try {
- var module = _emitModule(compilationUnits, name);
- if (!options.unsafeForceCompile && errors.any(_isFatalError)) {
- return invalidModule();
- }
-
- var dartApiSummary = _summarizeModule(compilationUnits);
- return JSModuleFile(
- name, formatErrors(context, errors), options, module, dartApiSummary);
- } catch (e) {
- if (errors.any(_isFatalError)) {
- // Force compilation failed. Suppress the exception and report
- // the static errors instead.
- assert(options.unsafeForceCompile);
- return invalidModule();
- }
- rethrow;
- }
- }
-
- bool _isFatalError(AnalysisError e) {
- if (errorSeverity(context, e) != ErrorSeverity.ERROR) return false;
-
- // These errors are not fatal in the REPL compile mode as we
- // allow access to private members across library boundaries
- // and those accesses will show up as undefined members unless
- // additional analyzer changes are made to support them.
- // TODO(jacobr): consider checking that the identifier name
- // referenced by the error is private.
- return !options.replCompile ||
- (e.errorCode != StaticTypeWarningCode.UNDEFINED_GETTER &&
- e.errorCode != StaticTypeWarningCode.UNDEFINED_SETTER &&
- e.errorCode != StaticTypeWarningCode.UNDEFINED_METHOD);
- }
-
- List<int> _summarizeModule(List<CompilationUnit> units) {
- if (!options.summarizeApi) return null;
-
- if (!units.any((u) => u.declaredElement.source.isInSystemLibrary)) {
- var sdk = context.sourceFactory.dartSdk;
- summaryData.addBundle(
- null,
- sdk is SummaryBasedDartSdk
- ? sdk.bundle
- : (sdk as FolderBasedDartSdk).getSummarySdkBundle());
- }
-
- var assembler = PackageBundleAssembler();
-
- var uriToUnit = Map<String, UnlinkedUnit>.fromIterables(
- units.map((u) => u.declaredElement.source.uri.toString()),
- units.map((unit) {
- var unlinked = serializeAstUnlinked(unit);
- assembler.addUnlinkedUnit(unit.declaredElement.source, unlinked);
- return unlinked;
- }));
-
- summary_link
- .link(
- uriToUnit.keys.toSet(),
- (uri) => summaryData.linkedMap[uri],
- (uri) => summaryData.unlinkedMap[uri] ?? uriToUnit[uri],
- context.declaredVariables.get)
- .forEach(assembler.addLinkedLibrary);
-
- var bundle = assembler.assemble();
- // Preserve only API-level information in the summary.
- bundle.flushInformative();
- return bundle.toBuffer();
- }
-
- JS.Program _emitModule(List<CompilationUnit> compilationUnits, String name) {
if (moduleItems.isNotEmpty) {
throw StateError('Can only call emitModule once.');
}
@@ -388,7 +308,7 @@
// Collect all class/type Element -> Node mappings
// in case we need to forward declare any classes.
- _declarationNodes = HashMap<TypeDefiningElement, AstNode>.identity();
+ _declarationNodes = HashMap<TypeDefiningElement, AstNode>();
for (var unit in compilationUnits) {
for (var declaration in unit.declarations) {
var element = declaration.declaredElement;
@@ -398,7 +318,7 @@
}
}
if (compilationUnits.isNotEmpty) {
- _constants = ConstFieldVisitor(context,
+ _constants = ConstFieldVisitor(types, declaredVariables,
dummySource: resolutionMap
.elementDeclaredByCompilationUnit(compilationUnits.first)
.source);
@@ -430,7 +350,7 @@
items.add(js.statement('const # = #;', [id, value]));
});
- _emitDebuggerExtensionInfo(name);
+ _emitDebuggerExtensionInfo(options.moduleName);
// Discharge the type table cache variables and
// hoisted definitions.
@@ -638,7 +558,7 @@
void _declareBeforeUse(TypeDefiningElement e) {
if (e == null) return;
- if (_topLevelClass != null && identical(_currentElement, _topLevelClass)) {
+ if (_topLevelClass != null && _currentElement == _topLevelClass) {
// If the item is from our library, try to emit it now.
_emitTypeDeclaration(e);
}
@@ -2147,7 +2067,7 @@
var extMembers = _classProperties.extensionMethods;
var staticMethods = <JS.Property>[];
var instanceMethods = <JS.Property>[];
- var classMethods = classElem.methods.where((m) => !m.isAbstract).toList();
+ var classMethods = List.of(classElem.methods.where((m) => !m.isAbstract));
for (var m in mockMembers.values) {
if (m is MethodElement) classMethods.add(m);
}
@@ -2327,8 +2247,11 @@
if (!element.parameters.any(_isCovariant)) return element.type;
var parameters = element.parameters
- .map((p) => ParameterElementImpl.synthetic(p.name,
- _isCovariant(p) ? objectClass.type : p.type, p.parameterKind))
+ .map((p) => ParameterElementImpl.synthetic(
+ p.name,
+ // ignore: deprecated_member_use
+ _isCovariant(p) ? objectClass.type : p.type,
+ p.parameterKind))
.toList();
var function = FunctionElementImpl("", -1)
@@ -4983,8 +4906,8 @@
variable ??= JS.TemporaryId(name);
- var idElement = TemporaryVariableElement.forNode(id, variable)
- ..enclosingElement = _currentElement;
+ var idElement =
+ TemporaryVariableElement.forNode(id, variable, _currentElement);
id.staticElement = idElement;
id.staticType = type;
setIsDynamicInvoke(id, dynamicInvoke ?? type.isDynamic);
@@ -6508,17 +6431,19 @@
class TemporaryVariableElement extends LocalVariableElementImpl {
final JS.Expression jsVariable;
- TemporaryVariableElement.forNode(Identifier name, this.jsVariable)
- : super.forNode(name);
+ TemporaryVariableElement.forNode(
+ Identifier name, this.jsVariable, Element enclosingElement)
+ : super.forNode(name) {
+ this.enclosingElement = enclosingElement is ElementHandle
+ ? enclosingElement.actualElement
+ : enclosingElement;
+ }
int get hashCode => identityHashCode(this);
bool operator ==(Object other) => identical(this, other);
}
-LibraryElement _getLibrary(AnalysisContext c, String uri) =>
- c.computeLibraryElement(c.sourceFactory.forUri(uri));
-
/// Returns `true` if [target] is a prefix for a deferred library and [name]
/// is "loadLibrary".
///
diff --git a/pkg/dev_compiler/lib/src/analyzer/command.dart b/pkg/dev_compiler/lib/src/analyzer/command.dart
index 300ab8b..97188e1 100644
--- a/pkg/dev_compiler/lib/src/analyzer/command.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/command.dart
@@ -11,8 +11,10 @@
import 'package:args/command_runner.dart' show UsageException;
import 'package:path/path.dart' as path;
+import '../compiler/shared_command.dart' show CompilerResult;
import 'context.dart' show AnalyzerOptions;
-import 'module_compiler.dart' show CompilerOptions, ModuleCompiler;
+import 'driver.dart';
+import 'module_compiler.dart';
const _binaryName = 'dartdevc';
@@ -23,9 +25,8 @@
/// This handles argument parsing, usage, error handling.
/// See bin/dartdevc.dart for the actual entry point, which includes Bazel
/// worker support.
-int compile(List<String> args, {void printFn(Object obj)}) {
- printFn ??= print;
-
+CompilerResult compile(List<String> args,
+ {CompilerAnalysisDriver compilerState}) {
ArgResults argResults;
AnalyzerOptions analyzerOptions;
try {
@@ -36,36 +37,36 @@
argResults = parser.parse(args);
analyzerOptions = AnalyzerOptions.fromArguments(argResults);
} on FormatException catch (error) {
- printFn('$error\n\n$_usageMessage');
- return 64;
+ print('$error\n\n$_usageMessage');
+ return CompilerResult(64);
}
_verbose = argResults['verbose'] as bool;
if (argResults['help'] as bool || args.isEmpty) {
- printFn(_usageMessage);
- return 0;
+ print(_usageMessage);
+ return CompilerResult(0);
}
if (argResults['version'] as bool) {
- printFn('$_binaryName version ${_getVersion()}');
- return 0;
+ print('$_binaryName version ${_getVersion()}');
+ return CompilerResult(0);
}
try {
- _compile(argResults, analyzerOptions, printFn);
- return 0;
+ var driver = _compile(argResults, analyzerOptions);
+ return CompilerResult(0, analyzerState: driver);
} on UsageException catch (error) {
// Incorrect usage, input file not found, etc.
- printFn('${error.message}\n\n$_usageMessage');
- return 64;
+ print('${error.message}\n\n$_usageMessage');
+ return CompilerResult(64);
} on ConflictingSummaryException catch (error) {
// Same input file appears in multiple provided summaries.
- printFn(error);
- return 65;
+ print(error);
+ return CompilerResult(65);
} on CompileErrorException catch (error) {
// Code has error(s) and failed to compile.
- printFn(error);
- return 1;
+ print(error);
+ return CompilerResult(1);
} catch (error, stackTrace) {
// Anything else is likely a compiler bug.
//
@@ -73,7 +74,7 @@
// crash while compiling
// (of course, output code may crash, if it had errors).
//
- printFn('''
+ print('''
We're sorry, you've found a bug in our compiler.
You can report this bug at:
https://github.com/dart-lang/sdk/issues/labels/area-dev-compiler
@@ -85,16 +86,20 @@
$error
$stackTrace
```''');
- return 70;
+ return CompilerResult(70);
}
}
-ArgParser ddcArgParser({bool hide = true}) {
- var argParser = ArgParser(allowTrailingOptions: true)
- ..addFlag('help',
+ArgParser ddcArgParser(
+ {bool hide = true, bool help = true, ArgParser argParser}) {
+ argParser ??= ArgParser(allowTrailingOptions: true);
+ if (help) {
+ argParser.addFlag('help',
abbr: 'h',
help: 'Display this message. Add -v to show hidden options.',
- negatable: false)
+ negatable: false);
+ }
+ argParser
..addFlag('verbose',
abbr: 'v', negatable: false, help: 'Verbose help output.', hide: hide)
..addFlag('version',
@@ -119,11 +124,16 @@
return false;
}
-void _compile(ArgResults argResults, AnalyzerOptions analyzerOptions,
- void printFn(Object obj)) {
+CompilerAnalysisDriver _compile(
+ ArgResults argResults, AnalyzerOptions analyzerOptions,
+ {CompilerAnalysisDriver compilerDriver}) {
var compilerOpts = CompilerOptions.fromArguments(argResults);
- var compiler = ModuleCompiler(analyzerOptions,
- summaryPaths: compilerOpts.summaryModules.keys);
+ var summaryPaths = compilerOpts.summaryModules.keys.toList();
+ if (compilerDriver == null ||
+ !compilerDriver.isCompatibleWith(analyzerOptions, summaryPaths)) {
+ compilerDriver =
+ CompilerAnalysisDriver(analyzerOptions, summaryPaths: summaryPaths);
+ }
var outPaths = argResults['out'] as List<String>;
var moduleFormats = compilerOpts.moduleFormats;
if (outPaths.isEmpty) {
@@ -138,8 +148,13 @@
'');
}
- var module = compiler.compile(argResults.rest, compilerOpts);
- module.errors.forEach(printFn);
+ var module = compileWithAnalyzer(
+ compilerDriver,
+ argResults.rest,
+ analyzerOptions,
+ compilerOpts,
+ );
+ module.errors.forEach(print);
if (!module.isValid) {
throw compilerOpts.unsafeForceCompile
@@ -151,7 +166,7 @@
for (var i = 0; i < outPaths.length; i++) {
module.writeCodeSync(moduleFormats[i], outPaths[i]);
}
- if (module.summaryBytes != null) {
+ if (compilerOpts.summarizeApi) {
var summaryPaths = compilerOpts.summaryOutPath != null
? [compilerOpts.summaryOutPath]
: outPaths.map((p) =>
@@ -169,6 +184,7 @@
}
}
}
+ return compilerDriver;
}
String get _usageMessage =>
diff --git a/pkg/dev_compiler/lib/src/analyzer/context.dart b/pkg/dev_compiler/lib/src/analyzer/context.dart
index e787e81..02e108e 100644
--- a/pkg/dev_compiler/lib/src/analyzer/context.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/context.dart
@@ -11,8 +11,8 @@
import 'package:analyzer/src/command_line/arguments.dart';
import 'package:analyzer/src/context/builder.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
-import 'package:analyzer/src/generated/source.dart'
- show DartUriResolver, SourceFactory, UriResolver;
+import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer/src/generated/source.dart' hide CustomUriResolver;
import 'package:analyzer/src/summary/package_bundle_reader.dart'
show InSummaryUriResolver, SummaryDataStore;
import 'package:args/args.dart' show ArgParser, ArgResults;
@@ -28,19 +28,17 @@
/// Custom URI mappings, such as "dart:foo" -> "path/to/foo.dart"
final Map<String, String> customUrlMappings;
- /// Package root when resolving 'package:' urls the standard way.
- String get packageRoot => contextBuilderOptions.defaultPackagesDirectoryPath;
-
/// Path to the dart-sdk, or `null` if the path couldn't be determined.
final String dartSdkPath;
- /// Path to the dart-sdk summary. If this is set, it will be used in favor
- /// of the unsummarized one.
- String get dartSdkSummaryPath => contextBuilderOptions.dartSdkSummaryPath;
+ /// File resolvers if explicitly configured, otherwise null.
+ List<UriResolver> fileResolvers;
- /// Defined variables used by `bool.fromEnvironment` etc.
- Map<String, String> get declaredVariables =>
- contextBuilderOptions.declaredVariables;
+ /// Stores the value of [resourceProvider].
+ ResourceProvider _resourceProvider;
+
+ /// The default analysis root.
+ String analysisRoot = path.current;
AnalyzerOptions._(
{this.contextBuilderOptions,
@@ -88,15 +86,30 @@
hide: hide);
}
- static Map<String, String> _parseUrlMappings(List<String> argument) {
- var mappings = <String, String>{};
- for (var mapping in argument) {
- var splitMapping = mapping.split(',');
- if (splitMapping.length >= 2) {
- mappings[splitMapping[0]] = path.absolute(splitMapping[1]);
- }
- }
- return mappings;
+ /// Package root when resolving 'package:' urls the standard way.
+ String get packageRoot => contextBuilderOptions.defaultPackagesDirectoryPath;
+
+ /// Resource provider if explicitly set, otherwise this defaults to use
+ /// the file system.
+ ResourceProvider get resourceProvider =>
+ _resourceProvider ??= PhysicalResourceProvider.INSTANCE;
+
+ set resourceProvider(ResourceProvider value) {
+ _resourceProvider = value;
+ }
+
+ /// Path to the dart-sdk summary. If this is set, it will be used in favor
+ /// of the unsummarized one.
+ String get dartSdkSummaryPath => contextBuilderOptions.dartSdkSummaryPath;
+
+ /// Defined variables used by `bool.fromEnvironment` etc.
+ Map<String, String> get declaredVariables =>
+ contextBuilderOptions.declaredVariables;
+
+ ContextBuilder createContextBuilder() {
+ return ContextBuilder(
+ resourceProvider, DartSdkManager(dartSdkPath, true), ContentCache(),
+ options: contextBuilderOptions);
}
}
@@ -105,11 +118,8 @@
/// If supplied, [fileResolvers] will override the default `file:` and
/// `package:` URI resolvers.
SourceFactory createSourceFactory(AnalyzerOptions options,
- {DartUriResolver sdkResolver,
- List<UriResolver> fileResolvers,
- SummaryDataStore summaryData,
- ResourceProvider resourceProvider}) {
- resourceProvider ??= PhysicalResourceProvider.INSTANCE;
+ {DartUriResolver sdkResolver, SummaryDataStore summaryData}) {
+ var resourceProvider = options.resourceProvider;
var resolvers = <UriResolver>[sdkResolver];
if (options.customUrlMappings.isNotEmpty) {
resolvers
@@ -119,26 +129,34 @@
resolvers.add(InSummaryUriResolver(resourceProvider, summaryData));
}
- fileResolvers ??=
- createFileResolvers(options, resourceProvider: resourceProvider);
+ var fileResolvers = options.fileResolvers ?? createFileResolvers(options);
resolvers.addAll(fileResolvers);
return SourceFactory(resolvers, null, resourceProvider);
}
-List<UriResolver> createFileResolvers(AnalyzerOptions options,
- {ResourceProvider resourceProvider}) {
- resourceProvider ??= PhysicalResourceProvider.INSTANCE;
- UriResolver packageResolver() {
- var builderOptions = ContextBuilderOptions();
- if (options.packageRoot != null) {
- builderOptions.defaultPackagesDirectoryPath = options.packageRoot;
- }
- var builder =
- ContextBuilder(resourceProvider, null, null, options: builderOptions);
+List<UriResolver> createFileResolvers(AnalyzerOptions options) {
+ var resourceProvider = options.resourceProvider;
- return PackageMapUriResolver(resourceProvider,
- builder.convertPackagesToMap(builder.createPackageMap(path.current)));
+ var builderOptions = ContextBuilderOptions();
+ if (options.packageRoot != null) {
+ builderOptions.defaultPackagesDirectoryPath = options.packageRoot;
}
+ var builder =
+ ContextBuilder(resourceProvider, null, null, options: builderOptions);
- return [ResourceUriResolver(resourceProvider), packageResolver()];
+ var packageResolver = PackageMapUriResolver(resourceProvider,
+ builder.convertPackagesToMap(builder.createPackageMap(path.current)));
+
+ return [ResourceUriResolver(resourceProvider), packageResolver];
+}
+
+Map<String, String> _parseUrlMappings(List<String> argument) {
+ var mappings = <String, String>{};
+ for (var mapping in argument) {
+ var splitMapping = mapping.split(',');
+ if (splitMapping.length >= 2) {
+ mappings[splitMapping[0]] = path.absolute(splitMapping[1]);
+ }
+ }
+ return mappings;
}
diff --git a/pkg/dev_compiler/lib/src/analyzer/driver.dart b/pkg/dev_compiler/lib/src/analyzer/driver.dart
new file mode 100644
index 0000000..bce3e8e
--- /dev/null
+++ b/pkg/dev_compiler/lib/src/analyzer/driver.dart
@@ -0,0 +1,399 @@
+// Copyright (c) 2018, 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:collection';
+import 'dart:typed_data';
+
+import 'package:analyzer/dart/analysis/declared_variables.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/file_system/file_system.dart' show ResourceProvider;
+import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/dart/analysis/byte_store.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart' show AnalysisDriver;
+import 'package:analyzer/src/dart/analysis/file_state.dart';
+import 'package:analyzer/src/dart/analysis/library_analyzer.dart';
+import 'package:analyzer/src/dart/analysis/performance_logger.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary/link.dart' as summary_link;
+import 'package:analyzer/src/summary/package_bundle_reader.dart';
+import 'package:analyzer/src/summary/resynthesize.dart';
+import 'package:analyzer/src/summary/summarize_ast.dart';
+import 'package:analyzer/src/summary/summarize_elements.dart';
+import 'package:meta/meta.dart';
+
+import '../compiler/shared_command.dart' show sdkLibraryVariables;
+import 'context.dart' show AnalyzerOptions, createSourceFactory;
+import 'extension_types.dart' show ExtensionTypeSet;
+
+/// The analysis driver for `dartdevc`.
+///
+/// [linkLibraries] can be used to link input sources and input summaries,
+/// producing a [LinkedAnalysisDriver] that can analyze those sources.
+///
+/// This class can be reused to link different input files if they share the
+/// same [analysisOptions] and [summaryData].
+class CompilerAnalysisDriver {
+ /// The Analyzer options used for analyzing the input sources.
+ final AnalysisOptionsImpl analysisOptions;
+
+ /// The input summaries used for analyzing/compiling the input sources.
+ ///
+ /// This should contain the summary of all imported/exported libraries and
+ /// transitive dependencies, including the Dart SDK.
+ final SummaryDataStore summaryData;
+
+ final ResourceProvider _resourceProvider;
+
+ final List<String> _summaryPaths;
+
+ @visibleForTesting
+ final DartSdk dartSdk;
+
+ /// SDK summary path, used by [isCompatibleWith] for batch/worker mode.
+ final String _dartSdkSummaryPath;
+
+ ExtensionTypeSet _extensionTypes;
+
+ CompilerAnalysisDriver._(this.dartSdk, this._summaryPaths, this.summaryData,
+ this.analysisOptions, this._resourceProvider, this._dartSdkSummaryPath) {
+ var bundle = dartSdk.getLinkedBundle();
+ if (bundle != null) summaryData.addBundle(null, bundle);
+ }
+
+ /// Information about native extension types.
+ ///
+ /// This will be `null` until [linkLibraries] has been called (because we
+ /// could be compiling the Dart SDK, so it would not be available yet).
+ ExtensionTypeSet get extensionTypes => _extensionTypes;
+
+ factory CompilerAnalysisDriver(AnalyzerOptions options,
+ {SummaryDataStore summaryData, List<String> summaryPaths = const []}) {
+ AnalysisEngine.instance.processRequiredPlugins();
+
+ var resourceProvider = options.resourceProvider;
+ var contextBuilder = options.createContextBuilder();
+
+ var analysisOptions =
+ contextBuilder.getAnalysisOptions(options.analysisRoot);
+ var dartSdk = contextBuilder.findSdk(null, analysisOptions);
+
+ // Read the summaries.
+ summaryData ??= SummaryDataStore(summaryPaths,
+ resourceProvider: resourceProvider,
+ // TODO(vsm): Reset this to true once we cleanup internal build rules.
+ disallowOverlappingSummaries: false);
+
+ return CompilerAnalysisDriver._(dartSdk, summaryPaths, summaryData,
+ analysisOptions, resourceProvider, options.dartSdkSummaryPath);
+ }
+
+ /// Whether this driver can be reused for the given [dartSdkSummaryPath] and
+ /// [summaryPaths].
+ bool isCompatibleWith(AnalyzerOptions options, List<String> summaryPaths) {
+ return _dartSdkSummaryPath == options.dartSdkSummaryPath &&
+ _summaryPaths.toSet().containsAll(summaryPaths);
+ }
+
+ /// Parses [explicitSources] and any imports/exports/parts (that are not
+ /// included in [summaryData]), and links the results so
+ /// [LinkedAnalysisDriver.analyzeLibrary] can be called.
+ ///
+ /// The analyzer [options] are used to configure URI resolution (Analyzer's
+ /// [SourceFactory]) and declared variables, if any (`-Dfoo=bar`).
+ LinkedAnalysisDriver linkLibraries(
+ List<Uri> explicitSources, AnalyzerOptions options) {
+ /// This code was ported from analyzer_cli (with a few changes/improvements).
+ ///
+ /// Here's a summary of the process:
+ ///
+ /// 1. starting with [explicitSources], visit all transitive
+ /// imports/exports/parts, and create an unlinked unit for each
+ /// (unless it's provided by an input summary). Add these to [assembler].
+ ///
+ /// 2. call [summary_link.link] to create the linked libraries, and add the
+ /// results to the assembler.
+ ///
+ /// 3. serialize the data into [summaryBytes], then deserialize it back into
+ /// the [bundle] that contains the summary for all [explicitSources] and
+ /// their transitive dependencies.
+ ///
+ /// 4. create the analysis [context] and element [resynthesizer], and use
+ /// them to return a new [LinkedAnalysisDriver] that can analyze all of
+ /// the compilation units (and provide the resolved AST/errors for each).
+ var assembler = PackageBundleAssembler();
+
+ /// The URI resolution logic for this build unit.
+ var sourceFactory = createSourceFactory(options,
+ sdkResolver: DartUriResolver(dartSdk), summaryData: summaryData);
+
+ /// A fresh file system state for this list of [explicitSources].
+ var fsState = _createFileSystemState(sourceFactory);
+
+ var uriToUnit = <String, UnlinkedUnit>{};
+
+ /// The sources that have been added to [sourcesToProcess], used to ensure
+ /// we only visit a given source once.
+ var knownSources = HashSet<Uri>.from(explicitSources);
+
+ /// The pending list of sources to visit.
+ var sourcesToProcess = Queue<Uri>.from(explicitSources);
+
+ /// Prepare URIs of unlinked units (for libraries) that should be linked.
+ var libraryUris = <String>[];
+
+ /// Ensure that the [UnlinkedUnit] for [absoluteUri] is available.
+ ///
+ /// If the unit is in the input [summaryData], do nothing.
+ /// Otherwise compute it and store into the [uriToUnit] and [assembler].
+ void prepareUnlinkedUnit(Uri uri) {
+ var absoluteUri = uri.toString();
+ // Maybe an input package contains the source.
+ if (summaryData.unlinkedMap[absoluteUri] != null) {
+ return;
+ }
+ // Parse the source and serialize its AST.
+ var source = sourceFactory.forUri2(uri);
+ if (source == null || !source.exists()) {
+ // Skip this source. We don't need to report an error here because it
+ // will be reported later during analysis.
+ return;
+ }
+ var file = fsState.getFileForPath(source.fullName);
+ var unit = file.parse();
+ var unlinkedUnit = serializeAstUnlinked(unit);
+ uriToUnit[absoluteUri] = unlinkedUnit;
+ assembler.addUnlinkedUnit(source, unlinkedUnit);
+
+ /// The URI to resolve imports/exports/parts against.
+ var baseUri = uri;
+ if (baseUri.scheme == 'dart' && baseUri.pathSegments.length == 1) {
+ // Add a trailing slash so relative URIs will resolve correctly, e.g.
+ // "map.dart" from "dart:core/" yields "dart:core/map.dart".
+ baseUri = Uri(scheme: 'dart', path: baseUri.path + '/');
+ }
+
+ void enqueueSource(String relativeUri) {
+ var sourceUri = baseUri.resolve(relativeUri);
+ if (knownSources.add(sourceUri)) {
+ sourcesToProcess.add(sourceUri);
+ }
+ }
+
+ // Add reachable imports/exports/parts, if any.
+ var isPart = false;
+ for (var directive in unit.directives) {
+ if (directive is UriBasedDirective) {
+ enqueueSource(directive.uri.stringValue);
+ // Handle conditional imports.
+ if (directive is NamespaceDirective) {
+ for (var config in directive.configurations) {
+ enqueueSource(config.uri.stringValue);
+ }
+ }
+ } else if (directive is PartOfDirective) {
+ isPart = true;
+ }
+ }
+
+ // Remember library URIs, so we can use it for linking libraries and
+ // compiling them.
+ if (!isPart) libraryUris.add(absoluteUri);
+ }
+
+ // Collect the unlinked units for all transitive sources.
+ //
+ // TODO(jmesserly): consider using parallelism via asynchronous IO here,
+ // once we fix debugger extension (web/web_command.dart) to allow async.
+ //
+ // It would let computation tasks (parsing/serializing unlinked units)
+ // proceed in parallel with reading the sources from disk.
+ while (sourcesToProcess.isNotEmpty) {
+ prepareUnlinkedUnit(sourcesToProcess.removeFirst());
+ }
+
+ /// Gets the URIs to link.
+ ///
+ /// Unlike analyzer_cli, this only includes library URIs, not all
+ /// compilation units. This appears to be what [summary_link.link] wants as
+ /// input. If all units are passed in, the resulting summary has extra data
+ /// in the linkedLibraries list, which appears to be unnecessary.
+ var unlinkedUris = Set<String>.from(summaryData.uriToSummaryPath.keys)
+ ..addAll(libraryUris);
+ var declaredVariables = DeclaredVariables.fromMap(
+ Map.of(options.declaredVariables)..addAll(sdkLibraryVariables));
+
+ /// Perform the linking step and store the result.
+ ///
+ /// TODO(jmesserly): can we pass in `getAst` to reuse existing ASTs we
+ /// created when we did `file.parse()` in [prepareUnlinkedUnit]?
+ var linkResult = summary_link.link(
+ unlinkedUris,
+ (uri) => summaryData.linkedMap[uri],
+ (uri) => summaryData.unlinkedMap[uri] ?? uriToUnit[uri],
+ declaredVariables.get);
+ linkResult.forEach(assembler.addLinkedLibrary);
+
+ var summaryBytes = assembler.assemble().toBuffer();
+ var bundle = PackageBundle.fromBuffer(summaryBytes);
+
+ /// Create an analysis context to contain the state for this build unit.
+ var context =
+ AnalysisEngine.instance.createAnalysisContext() as AnalysisContextImpl;
+ context.sourceFactory = sourceFactory;
+ var resultProvider = InputPackagesResultProvider(
+ context,
+ SummaryDataStore([])
+ ..addStore(summaryData)
+ ..addBundle(null, bundle));
+ context.resultProvider = resultProvider;
+ context.contentCache = _ContentCacheWrapper(fsState);
+
+ var resynthesizer = resultProvider.resynthesizer;
+ _extensionTypes ??= ExtensionTypeSet(context.typeProvider, resynthesizer);
+
+ return LinkedAnalysisDriver(analysisOptions, resynthesizer, sourceFactory,
+ libraryUris, declaredVariables, summaryBytes, fsState);
+ }
+
+ FileSystemState _createFileSystemState(SourceFactory sourceFactory) {
+ var unlinkedSalt =
+ Uint32List(1 + AnalysisOptionsImpl.unlinkedSignatureLength);
+ unlinkedSalt[0] = AnalysisDriver.DATA_VERSION;
+ unlinkedSalt.setAll(1, analysisOptions.unlinkedSignature);
+
+ var linkedSalt = Uint32List(1 + AnalysisOptions.signatureLength);
+ linkedSalt[0] = AnalysisDriver.DATA_VERSION;
+ linkedSalt.setAll(1, analysisOptions.signature);
+
+ return FileSystemState(
+ PerformanceLog(StringBuffer()),
+ MemoryByteStore(),
+ FileContentOverlay(),
+ _resourceProvider,
+ sourceFactory,
+ analysisOptions,
+ unlinkedSalt,
+ linkedSalt,
+ externalSummaries: summaryData);
+ }
+}
+
+/// The analysis driver used after linking all input summaries and explicit
+/// sources, produced by [CompilerAnalysisDriver.linkLibraries].
+class LinkedAnalysisDriver {
+ final AnalysisOptions analysisOptions;
+ final SummaryResynthesizer resynthesizer;
+ final SourceFactory sourceFactory;
+ final List<String> libraryUris;
+ final DeclaredVariables declaredVariables;
+
+ /// The summary bytes for this linked build unit.
+ final List<int> summaryBytes;
+
+ final FileSystemState _fsState;
+
+ LinkedAnalysisDriver(
+ this.analysisOptions,
+ this.resynthesizer,
+ this.sourceFactory,
+ this.libraryUris,
+ this.declaredVariables,
+ this.summaryBytes,
+ this._fsState);
+
+ AnalysisContextImpl get context => resynthesizer.context;
+
+ /// Clean up any state used by this driver.
+ void dispose() => context.dispose();
+
+ /// True if [uri] refers to a Dart library (i.e. a Dart source file exists
+ /// with this uri, and it is not a part file).
+ bool _isLibraryUri(String uri) {
+ return resynthesizer.hasLibrarySummary(uri);
+ }
+
+ /// Analyzes the library at [uri] and returns the results of analysis for all
+ /// file(s) in that library.
+ Map<FileState, UnitAnalysisResult> analyzeLibrary(String libraryUri) {
+ if (!_isLibraryUri(libraryUri)) {
+ throw ArgumentError('"$libraryUri" is not a library');
+ }
+
+ var libraryFile = _fsState.getFileForUri(Uri.parse(libraryUri));
+ var analyzer = LibraryAnalyzer(
+ analysisOptions,
+ declaredVariables,
+ resynthesizer.sourceFactory,
+ (uri) => _isLibraryUri('$uri'),
+ context,
+ resynthesizer,
+ libraryFile);
+ // TODO(jmesserly): ideally we'd use the existing public `analyze()` method,
+ // but it's async. We can't use `async` here because it would break our
+ // developer tools extension (see web/web_command.dart). We should be able
+ // to fix it, but it requires significant changes to code outside of this
+ // repository.
+ return analyzer.analyzeSync();
+ }
+
+ ClassElement getClass(String uri, String name) {
+ return getLibrary(uri).getType(name);
+ }
+
+ LibraryElement getLibrary(String uri) {
+ return resynthesizer.getLibraryElement(uri);
+ }
+}
+
+/// [ContentCache] wrapper around [FileSystemState].
+class _ContentCacheWrapper implements ContentCache {
+ final FileSystemState fsState;
+
+ _ContentCacheWrapper(this.fsState);
+
+ @override
+ void accept(ContentCacheVisitor visitor) {
+ throw new UnimplementedError();
+ }
+
+ @override
+ String getContents(Source source) {
+ return _getFileForSource(source).content;
+ }
+
+ @override
+ bool getExists(Source source) {
+ if (source.isInSystemLibrary) {
+ return true;
+ }
+ String uriStr = source.uri.toString();
+ if (fsState.externalSummaries != null &&
+ fsState.externalSummaries.hasUnlinkedUnit(uriStr)) {
+ return true;
+ }
+ return _getFileForSource(source).exists;
+ }
+
+ @override
+ int getModificationStamp(Source source) {
+ if (source.isInSystemLibrary) {
+ return 0;
+ }
+ return _getFileForSource(source).exists ? 0 : -1;
+ }
+
+ @override
+ String setContents(Source source, String contents) {
+ throw new UnimplementedError();
+ }
+
+ FileState _getFileForSource(Source source) {
+ String path = source.fullName;
+ return fsState.getFileForPath(path);
+ }
+}
diff --git a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
index 0578625..2d2480c 100644
--- a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
@@ -3,17 +3,17 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:collection';
-import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
-/// Helpers for Analyzer's Element model and corelib model.
-
+import 'package:analyzer/analyzer.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart'
show DartType, InterfaceType, ParameterizedType, FunctionType;
+import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/constant.dart'
show DartObject, DartObjectImpl;
+import 'package:analyzer/src/generated/constant.dart';
class Tuple2<T0, T1> {
final T0 e0;
@@ -382,9 +382,6 @@
return uri.scheme == 'dart' && path == libraryName;
}
-ClassElement getClass(AnalysisContext c, String uri, String name) =>
- c.computeLibraryElement(c.sourceFactory.forUri(uri)).getType(name);
-
/// Returns the integer value for [node] as a [BigInt].
///
/// `node.value` should not be used directly as it depends on platform integers
diff --git a/pkg/dev_compiler/lib/src/analyzer/error_helpers.dart b/pkg/dev_compiler/lib/src/analyzer/error_helpers.dart
index f08b46c..0e640ef 100644
--- a/pkg/dev_compiler/lib/src/analyzer/error_helpers.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/error_helpers.dart
@@ -3,7 +3,12 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/analyzer.dart'
- show AnalysisError, ErrorSeverity, ErrorType, StrongModeCode;
+ show
+ AnalysisError,
+ ErrorSeverity,
+ ErrorType,
+ StrongModeCode,
+ StaticTypeWarningCode;
import 'package:analyzer/source/error_processor.dart' show ErrorProcessor;
import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
import 'package:path/path.dart' as path;
@@ -87,6 +92,21 @@
errorCode.errorSeverity;
}
+bool isFatalError(AnalysisContext context, AnalysisError e, bool replCompile) {
+ if (errorSeverity(context, e) != ErrorSeverity.ERROR) return false;
+
+ // These errors are not fatal in the REPL compile mode as we
+ // allow access to private members across library boundaries
+ // and those accesses will show up as undefined members unless
+ // additional analyzer changes are made to support them.
+ // TODO(jacobr): consider checking that the identifier name
+ // referenced by the error is private.
+ return !replCompile ||
+ (e.errorCode != StaticTypeWarningCode.UNDEFINED_GETTER &&
+ e.errorCode != StaticTypeWarningCode.UNDEFINED_SETTER &&
+ e.errorCode != StaticTypeWarningCode.UNDEFINED_METHOD);
+}
+
const invalidImportDartMirrors = StrongModeCode(
ErrorType.COMPILE_TIME_ERROR,
'IMPORT_DART_MIRRORS',
diff --git a/pkg/dev_compiler/lib/src/analyzer/extension_types.dart b/pkg/dev_compiler/lib/src/analyzer/extension_types.dart
index 513a3f3..195fe89 100644
--- a/pkg/dev_compiler/lib/src/analyzer/extension_types.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/extension_types.dart
@@ -6,7 +6,8 @@
import 'package:analyzer/dart/element/element.dart'
show ClassElement, CompilationUnitElement, Element;
import 'package:analyzer/dart/element/type.dart' show DartType, InterfaceType;
-import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
+import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
+import 'package:analyzer/src/summary/resynthesize.dart';
import 'element_helpers.dart' show getAnnotationName, isBuiltinAnnotation;
/// Contains information about native JS types (those types provided by the
@@ -27,7 +28,7 @@
/// This will provide the [Iterable.first] property, without needing to add
/// `first` to the `Array.prototype`.
class ExtensionTypeSet {
- final AnalysisContext _context;
+ final SummaryResynthesizer _resynthesizer;
// Abstract types that may be implemented by both native and non-native
// classes.
@@ -37,7 +38,7 @@
final _nativeTypes = HashSet<ClassElement>();
final _pendingLibraries = HashSet<String>();
- ExtensionTypeSet(this._context) {
+ ExtensionTypeSet(TypeProvider types, this._resynthesizer) {
// TODO(vsm): Eventually, we want to make this extensible - i.e., find
// annotations in user code as well. It would need to be summarized in
// the element model - not searched this way on every compile. To make this
@@ -46,7 +47,6 @@
// First, core types:
// TODO(vsm): If we're analyzing against the main SDK, those
// types are not explicitly annotated.
- var types = _context.typeProvider;
_extensibleTypes.add(types.objectType.element);
_addExtensionType(types.intType, true);
_addExtensionType(types.doubleType, true);
@@ -108,16 +108,14 @@
}
void _addExtensionTypesForLibrary(String libraryUri, List<String> typeNames) {
- var sourceFactory = _context.sourceFactory.forUri(libraryUri);
- var library = _context.computeLibraryElement(sourceFactory);
+ var library = _resynthesizer.getLibraryElement(libraryUri);
for (var typeName in typeNames) {
_addExtensionType(library.getType(typeName).type);
}
}
void _addExtensionTypes(String libraryUri) {
- var sourceFactory = _context.sourceFactory.forUri(libraryUri);
- var library = _context.computeLibraryElement(sourceFactory);
+ var library = _resynthesizer.getLibraryElement(libraryUri);
_visitCompilationUnit(library.definingCompilationUnit);
library.parts.forEach(_visitCompilationUnit);
}
diff --git a/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart b/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart
index ba24ee2..67a3b9b 100644
--- a/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart
@@ -4,12 +4,11 @@
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/element.dart' show ClassElement;
-import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:analyzer/src/generated/type_system.dart'
show StrongTypeSystemImpl;
import '../compiler/js_typerep.dart';
-import 'element_helpers.dart' show getClass;
+import 'driver.dart';
class JSTypeRep extends SharedJSTypeRep<DartType> {
final StrongTypeSystemImpl rules;
@@ -19,11 +18,11 @@
final ClassElement _jsNumber;
final ClassElement _jsString;
- JSTypeRep(this.rules, AnalysisContext c)
- : types = c.typeProvider,
- _jsBool = getClass(c, 'dart:_interceptors', 'JSBool'),
- _jsString = getClass(c, 'dart:_interceptors', 'JSString'),
- _jsNumber = getClass(c, 'dart:_interceptors', 'JSNumber');
+ JSTypeRep(this.rules, LinkedAnalysisDriver driver)
+ : types = driver.context.typeProvider,
+ _jsBool = driver.getClass('dart:_interceptors', 'JSBool'),
+ _jsString = driver.getClass('dart:_interceptors', 'JSString'),
+ _jsNumber = driver.getClass('dart:_interceptors', 'JSNumber');
@override
JSType typeFor(DartType type) {
diff --git a/pkg/dev_compiler/lib/src/analyzer/module_compiler.dart b/pkg/dev_compiler/lib/src/analyzer/module_compiler.dart
index f0bd87c..570a7c5 100644
--- a/pkg/dev_compiler/lib/src/analyzer/module_compiler.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/module_compiler.dart
@@ -2,31 +2,16 @@
// 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:collection' show HashSet, Queue;
import 'dart:convert' show json;
import 'dart:io' show File;
import 'package:analyzer/analyzer.dart'
show AnalysisError, CompilationUnit, StaticWarningCode;
-import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/element/element.dart'
show LibraryElement, UriReferencedElement;
-import 'package:analyzer/file_system/file_system.dart' show ResourceProvider;
-import 'package:analyzer/file_system/physical_file_system.dart'
- show PhysicalResourceProvider;
-import 'package:analyzer/src/context/builder.dart' show ContextBuilder;
-import 'package:analyzer/src/context/context.dart' show AnalysisContextImpl;
-import 'package:analyzer/src/generated/engine.dart'
- show AnalysisContext, AnalysisEngine;
-import 'package:analyzer/src/generated/sdk.dart' show DartSdkManager;
-import 'package:analyzer/src/generated/source.dart'
- show ContentCache, DartUriResolver;
-import 'package:analyzer/src/generated/source_io.dart'
- show SourceKind, UriResolver;
-import 'package:analyzer/src/summary/package_bundle_reader.dart'
- show InSummarySource, InputPackagesResultProvider, SummaryDataStore;
+
+import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
import 'package:args/args.dart' show ArgParser, ArgResults;
-import 'package:args/src/usage_exception.dart' show UsageException;
import 'package:path/path.dart' as path;
import 'package:source_maps/source_maps.dart';
@@ -38,9 +23,10 @@
import '../js_ast/js_ast.dart' show js;
import '../js_ast/source_map_printer.dart' show SourceMapPrintingContext;
import 'code_generator.dart' show CodeGenerator;
-import 'context.dart' show AnalyzerOptions, createSourceFactory;
+import 'context.dart';
+
+import 'driver.dart';
import 'error_helpers.dart';
-import 'extension_types.dart' show ExtensionTypeSet;
/// Compiles a set of Dart files into a single JavaScript module.
///
@@ -64,170 +50,95 @@
/// not any caching is performed. By default an analysis context will assume
/// sources are immutable for the life of the context, and cache information
/// about them.
-class ModuleCompiler {
- final AnalysisContext context;
- final SummaryDataStore summaryData;
- final ExtensionTypeSet _extensionTypes;
+JSModuleFile compileWithAnalyzer(
+ CompilerAnalysisDriver compilerDriver,
+ List<String> sourcePaths,
+ AnalyzerOptions analyzerOptions,
+ CompilerOptions options) {
+ var trees = <CompilationUnit>[];
+ var errors = <AnalysisError>[];
- ModuleCompiler._(AnalysisContext context, this.summaryData)
- : context = context,
- _extensionTypes = ExtensionTypeSet(context);
-
- factory ModuleCompiler(AnalyzerOptions options,
- {ResourceProvider resourceProvider,
- String analysisRoot,
- List<UriResolver> fileResolvers,
- SummaryDataStore summaryData,
- Iterable<String> summaryPaths = const []}) {
- // TODO(danrubel): refactor with analyzer CLI into analyzer common code
- AnalysisEngine.instance.processRequiredPlugins();
-
- resourceProvider ??= PhysicalResourceProvider.INSTANCE;
- analysisRoot ??= path.current;
-
- var contextBuilder = ContextBuilder(resourceProvider,
- DartSdkManager(options.dartSdkPath, true), ContentCache(),
- options: options.contextBuilderOptions);
-
- var analysisOptions = contextBuilder.getAnalysisOptions(analysisRoot);
- var sdk = contextBuilder.findSdk(null, analysisOptions);
-
- var sdkResolver = DartUriResolver(sdk);
-
- // Read the summaries.
- summaryData ??= SummaryDataStore(summaryPaths,
- resourceProvider: resourceProvider,
- // TODO(vsm): Reset this to true once we cleanup internal build rules.
- disallowOverlappingSummaries: false);
-
- var sdkSummaryBundle = sdk.getLinkedBundle();
- if (sdkSummaryBundle != null) {
- summaryData.addBundle(null, sdkSummaryBundle);
+ var explicitSources = <Uri>[];
+ var compilingSdk = false;
+ for (var sourcePath in sourcePaths) {
+ var sourceUri = sourcePathToUri(sourcePath);
+ if (sourceUri.scheme == "dart") {
+ compilingSdk = true;
}
-
- var srcFactory = createSourceFactory(options,
- sdkResolver: sdkResolver,
- fileResolvers: fileResolvers,
- summaryData: summaryData,
- resourceProvider: resourceProvider);
-
- var context =
- AnalysisEngine.instance.createAnalysisContext() as AnalysisContextImpl;
- context.analysisOptions = analysisOptions;
- context.sourceFactory = srcFactory;
- if (sdkSummaryBundle != null) {
- context.resultProvider =
- InputPackagesResultProvider(context, summaryData);
- }
- var variables = Map<String, String>.from(options.declaredVariables)
- ..addAll(sdkLibraryVariables);
-
- context.declaredVariables = DeclaredVariables.fromMap(variables);
- if (!context.analysisOptions.strongMode) {
- throw ArgumentError('AnalysisContext must be strong mode');
- }
- if (!context.sourceFactory.dartSdk.context.analysisOptions.strongMode) {
- throw ArgumentError('AnalysisContext must have strong mode SDK');
- }
-
- return ModuleCompiler._(context, summaryData);
+ explicitSources.add(sourceUri);
}
- /// Compiles a single Dart build unit into a JavaScript module.
- ///
- /// *Warning* - this may require resolving the entire world.
- /// If that is not desired, the analysis context must be pre-configured using
- /// summaries before calling this method.
- JSModuleFile compile(List<String> sourcePaths, CompilerOptions options) {
- var trees = <CompilationUnit>[];
- var errors = <AnalysisError>[];
+ var driver = compilerDriver.linkLibraries(explicitSources, analyzerOptions);
- var librariesToCompile = Queue<LibraryElement>();
+ for (var libraryUri in driver.libraryUris) {
+ var library = driver.getLibrary(libraryUri);
- var compilingSdk = false;
- for (var sourcePath in sourcePaths) {
- var sourceUri = sourcePathToUri(sourcePath);
- if (sourceUri.scheme == "dart") {
- compilingSdk = true;
- }
- var source = context.sourceFactory.forUri2(sourceUri);
-
- var fileUsage = 'You need to pass at least one existing .dart file as an'
- ' argument.';
- if (source == null) {
- throw UsageException(
- 'Could not create a source for "$sourcePath". The file name is in'
- ' the wrong format or was not found.',
- fileUsage);
- } else if (!source.exists()) {
- throw UsageException(
- 'Given file "$sourcePath" does not exist.', fileUsage);
- }
-
- // Ignore parts. They need to be handled in the context of their library.
- if (context.computeKindOf(source) == SourceKind.PART) {
- continue;
- }
-
- librariesToCompile.add(context.computeLibraryElement(source));
- }
-
- var libraries = HashSet<LibraryElement>();
- while (librariesToCompile.isNotEmpty) {
- var library = librariesToCompile.removeFirst();
- if (library.source is InSummarySource) continue;
- if (!compilingSdk && library.source.isInSystemLibrary) continue;
- if (!libraries.add(library)) continue;
-
- librariesToCompile.addAll(library.importedLibraries);
- librariesToCompile.addAll(library.exportedLibraries);
-
- // TODO(jmesserly): remove "dart:mirrors" from DDC's SDK, and then remove
- // this special case error message.
- if (!compilingSdk && !options.emitMetadata) {
- var node = _getDartMirrorsImport(library);
- if (node != null) {
- errors.add(AnalysisError(library.source, node.uriOffset, node.uriEnd,
- invalidImportDartMirrors));
- }
- }
-
- var tree = context.resolveCompilationUnit(library.source, library);
- trees.add(tree);
-
- var unitErrors = context.computeErrors(library.source);
- errors.addAll(_filterJsErrors(library, unitErrors));
-
- for (var part in library.parts) {
- trees.add(context.resolveCompilationUnit(part.source, library));
-
- var unitErrors = context.computeErrors(part.source);
- errors.addAll(_filterJsErrors(library, unitErrors));
+ // TODO(jmesserly): remove "dart:mirrors" from DDC's SDK, and then remove
+ // this special case error message.
+ if (!compilingSdk && !options.emitMetadata) {
+ var node = _getDartMirrorsImport(library);
+ if (node != null) {
+ errors.add(AnalysisError(library.source, node.uriOffset, node.uriEnd,
+ invalidImportDartMirrors));
}
}
- var compiler =
- CodeGenerator(context, summaryData, options, _extensionTypes, errors);
- return compiler.compile(trees);
+ var analysisResults = driver.analyzeLibrary(libraryUri);
+ for (var result in analysisResults.values) {
+ errors.addAll(_filterJsErrors(libraryUri, result.errors));
+ trees.add(result.unit);
+ }
}
- Iterable<AnalysisError> _filterJsErrors(
- LibraryElement library, Iterable<AnalysisError> errors) {
- var libraryUriStr = library.source.uri.toString();
- if (libraryUriStr == 'dart:html' ||
- libraryUriStr == 'dart:svg' ||
- libraryUriStr == 'dart:_interceptors') {
- return errors.where((error) {
- return error.errorCode !=
- StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1 &&
- error.errorCode !=
- StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2 &&
- error.errorCode !=
- StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS;
- });
- }
- return errors;
+ var context = driver.context;
+
+ bool anyFatalErrors() {
+ return errors.any((e) => isFatalError(context, e, options.replCompile));
}
+
+ JS.Program jsProgram;
+ if (options.unsafeForceCompile || !anyFatalErrors()) {
+ var codeGenerator = CodeGenerator(
+ driver,
+ driver.context.typeProvider,
+ compilerDriver.summaryData,
+ options,
+ compilerDriver.extensionTypes,
+ errors);
+ try {
+ jsProgram = codeGenerator.compile(trees);
+ } catch (e) {
+ // If force compilation failed, suppress the exception and report the
+ // static errors instead. Otherwise, rethrow an internal compiler error.
+ if (!anyFatalErrors()) rethrow;
+ }
+
+ if (!options.unsafeForceCompile && anyFatalErrors()) {
+ jsProgram = null;
+ }
+ }
+
+ var jsModule = JSModuleFile(
+ formatErrors(context, errors), options, jsProgram, driver.summaryBytes);
+ driver.dispose();
+ return jsModule;
+}
+
+Iterable<AnalysisError> _filterJsErrors(
+ String libraryUriStr, Iterable<AnalysisError> errors) {
+ if (libraryUriStr == 'dart:html' ||
+ libraryUriStr == 'dart:svg' ||
+ libraryUriStr == 'dart:_interceptors') {
+ return errors.where((error) {
+ return error.errorCode !=
+ StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1 &&
+ error.errorCode !=
+ StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2 &&
+ error.errorCode !=
+ StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS;
+ });
+ }
+ return errors;
}
UriReferencedElement _getDartMirrorsImport(LibraryElement library) {
@@ -339,9 +250,6 @@
/// This contains the file contents of the JS module, as well as a list of
/// Dart libraries that are contained in this module.
class JSModuleFile {
- /// The name of this module.
- final String name;
-
/// The list of messages (errors and warnings)
final List<String> errors;
@@ -363,13 +271,15 @@
/// replace the ID once the source map is generated.
static String sourceMapHoleID = 'SourceMap3G5a8h6JVhHfdGuDxZr1EF9GQC8y0e6u';
- JSModuleFile(
- this.name, this.errors, this.options, this.moduleTree, this.summaryBytes);
+ JSModuleFile(this.errors, this.options, this.moduleTree, this.summaryBytes);
- JSModuleFile.invalid(this.name, this.errors, this.options)
+ JSModuleFile.invalid(this.errors, this.options)
: moduleTree = null,
summaryBytes = null;
+ /// The name of this module.
+ String get name => options.moduleName;
+
/// True if this library was successfully compiled.
bool get isValid => moduleTree != null;
diff --git a/pkg/dev_compiler/lib/src/analyzer/side_effect_analysis.dart b/pkg/dev_compiler/lib/src/analyzer/side_effect_analysis.dart
index 5a10072..145219f 100644
--- a/pkg/dev_compiler/lib/src/analyzer/side_effect_analysis.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/side_effect_analysis.dart
@@ -8,7 +8,7 @@
import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/error/listener.dart'
show AnalysisErrorListener, ErrorReporter;
-import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:analyzer/src/generated/source.dart' show Source;
import 'package:analyzer/src/dart/ast/ast.dart';
@@ -102,10 +102,11 @@
class ConstFieldVisitor {
final ConstantVisitor constantVisitor;
- ConstFieldVisitor(AnalysisContext context, {Source dummySource})
+ ConstFieldVisitor(
+ TypeProvider typeProvider, DeclaredVariables declaredVariables,
+ {Source dummySource})
: constantVisitor = ConstantVisitor(
- ConstantEvaluationEngine(
- context.typeProvider, context.declaredVariables),
+ ConstantEvaluationEngine(typeProvider, declaredVariables),
ErrorReporter(AnalysisErrorListener.NULL_LISTENER, dummySource));
// TODO(jmesserly): this is used to determine if the field initialization is
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_command.dart b/pkg/dev_compiler/lib/src/compiler/shared_command.dart
index 459af25..a136652 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_command.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_command.dart
@@ -12,11 +12,9 @@
import 'package:path/path.dart' as path;
import 'module_builder.dart';
import '../analyzer/command.dart' as analyzer_compiler;
+import '../analyzer/driver.dart' show CompilerAnalysisDriver;
import '../kernel/command.dart' as kernel_compiler;
-export 'package:front_end/src/api_unstable/ddc.dart'
- show InitializedCompilerState;
-
/// Shared code between Analyzer and Kernel CLI interfaces.
///
/// This file should only implement functionality that does not depend on
@@ -344,22 +342,24 @@
/// Returns a [CompilerResult], with a success flag indicating whether the
/// program compiled without any fatal errors.
///
-/// The result may also contain a [compilerState], which can be passed back in
+/// The result may also contain a [previousResult], which can be passed back in
/// for batch/worker executions to attempt to existing state.
Future<CompilerResult> compile(ParsedArguments args,
- {InitializedCompilerState compilerState}) {
- if (compilerState != null && (!args.isBatchOrWorker || !args.isKernel)) {
- throw ArgumentError('compilerState requires --batch or --bazel_worker mode,'
- ' and --kernel to be set.');
+ {CompilerResult previousResult}) {
+ if (previousResult != null && !args.isBatchOrWorker) {
+ throw ArgumentError(
+ 'previousResult requires --batch or --bazel_worker mode/');
}
if (args.isKernel) {
- return kernel_compiler.compile(args.rest, compilerState: compilerState);
+ return kernel_compiler.compile(args.rest,
+ compilerState: previousResult?.kernelState);
} else {
- var exitCode = analyzer_compiler.compile(args.rest);
+ var result = analyzer_compiler.compile(args.rest,
+ compilerState: previousResult?.analyzerState);
if (args.isBatchOrWorker) {
AnalysisEngine.instance.clearCaches();
}
- return Future.value(CompilerResult(exitCode));
+ return Future.value(result);
}
}
@@ -377,12 +377,25 @@
/// compilation.
///
/// This field is unused when using the Analyzer-backend for DDC.
- final InitializedCompilerState compilerState;
+ final InitializedCompilerState kernelState;
+
+ /// Optionally provides the analyzer state from the previous compilation,
+ /// which can be passed to [compile] to potentially speeed up the next
+ /// compilation.
+ ///
+ /// This field is unused when using the Kernel-backend for DDC.
+ final CompilerAnalysisDriver analyzerState;
/// The process exit code of the compiler.
final int exitCode;
- CompilerResult(this.exitCode, [this.compilerState]);
+ CompilerResult(this.exitCode, {this.kernelState, this.analyzerState}) {
+ assert(kernelState == null || analyzerState == null,
+ 'kernel and analyzer state should not both be supplied');
+ }
+
+ /// Gets the kernel or analyzer compiler state, if any.
+ Object get compilerState => kernelState ?? analyzerState;
/// Whether the program compiled without any fatal errors (equivalent to
/// [exitCode] == 0).
diff --git a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
index 0921e35..b51b297 100644
--- a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
+++ b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
@@ -97,8 +97,9 @@
var summaryData = a.SummaryDataStore(summaryPaths,
resourceProvider: a.PhysicalResourceProvider.INSTANCE,
disallowOverlappingSummaries: false);
- var context = _createContextForSummaries(summaryData, analyzerSdkSummary);
- return AnalyzerToKernel._(context, summaryData);
+ var resynthesizer =
+ _createSummaryResynthesizer(summaryData, analyzerSdkSummary);
+ return AnalyzerToKernel._(resynthesizer.context, summaryData);
}
/// Converts the SDK summary to a Kernel component and returns it.
@@ -862,10 +863,17 @@
: (e.isAsynchronous ? AsyncMarker.Async : AsyncMarker.Sync);
}
+a.StoreBasedSummaryResynthesizer _createSummaryResynthesizer(
+ a.SummaryDataStore summaryData, String dartSdkPath) {
+ var context = _createContextForSummaries(summaryData, dartSdkPath);
+ return a.StoreBasedSummaryResynthesizer(
+ context, context.sourceFactory, /*strongMode*/ true, summaryData);
+}
+
/// Creates a dummy Analyzer context so we can use summary resynthesizer.
///
/// This is similar to Analyzer's `LibraryContext._createResynthesizingContext`.
-a.AnalysisContext _createContextForSummaries(
+a.AnalysisContextImpl _createContextForSummaries(
a.SummaryDataStore summaryData, String dartSdkPath) {
var sdk = a.SummaryBasedDartSdk(dartSdkPath, true,
resourceProvider: a.PhysicalResourceProvider.INSTANCE);
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index 6f27353..0d0dfa9 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -32,7 +32,7 @@
///
/// Returns `true` if the program compiled without any fatal errors.
Future<CompilerResult> compile(List<String> args,
- {InitializedCompilerState compilerState}) async {
+ {fe.InitializedCompilerState compilerState}) async {
try {
return await _compile(args, compilerState: compilerState);
} catch (error, stackTrace) {
@@ -60,7 +60,7 @@
'${ddcArgParser.usage}';
Future<CompilerResult> _compile(List<String> args,
- {InitializedCompilerState compilerState}) async {
+ {fe.InitializedCompilerState compilerState}) async {
// TODO(jmesserly): refactor options to share code with dartdevc CLI.
var argParser = ArgParser(allowTrailingOptions: true)
..addFlag('help',
@@ -180,12 +180,12 @@
fe.DdcResult result =
await fe.compile(compilerState, inputs, diagnosticMessageHandler);
if (result == null || !succeeded) {
- return CompilerResult(1, compilerState);
+ return CompilerResult(1, kernelState: compilerState);
}
var component = result.component;
if (!options.emitMetadata && _checkForDartMirrorsImport(component)) {
- return CompilerResult(1, compilerState);
+ return CompilerResult(1, kernelState: compilerState);
}
var file = File(output);
@@ -239,7 +239,7 @@
}
await Future.wait(outFiles);
- return CompilerResult(0, compilerState);
+ return CompilerResult(0, kernelState: compilerState);
}
/// The output of compiling a JavaScript module in a particular format.
diff --git a/pkg/dev_compiler/test/options/options_test.dart b/pkg/dev_compiler/test/options/options_test.dart
index b3c46d9..994bc65 100644
--- a/pkg/dev_compiler/test/options/options_test.dart
+++ b/pkg/dev_compiler/test/options/options_test.dart
@@ -11,6 +11,7 @@
import '../../lib/src/analyzer/context.dart';
import '../../lib/src/analyzer/command.dart';
+import '../../lib/src/analyzer/driver.dart';
import '../../lib/src/analyzer/module_compiler.dart';
import '../testing.dart' show repoDirectory, testDirectory;
@@ -24,21 +25,21 @@
main() {
test('basic', () {
- var options = AnalyzerOptions.basic();
- var compiler = ModuleCompiler(options, analysisRoot: optionsDir);
- var processors = compiler.context.analysisOptions.errorProcessors;
+ var options = AnalyzerOptions.basic()..analysisRoot = optionsDir;
+ var driver = CompilerAnalysisDriver(options);
+ var processors = driver.analysisOptions.errorProcessors;
expect(processors, hasLength(1));
expect(processors[0].code, CompileTimeErrorCode.UNDEFINED_CLASS.name);
});
test('basic sdk summary', () {
expect(File(sdkSummaryFile).existsSync(), isTrue);
- var options = AnalyzerOptions.basic(dartSdkSummaryPath: sdkSummaryFile);
- var compiler = ModuleCompiler(options, analysisRoot: optionsDir);
- var context = compiler.context;
- var sdk = context.sourceFactory.dartSdk;
+ var options = AnalyzerOptions.basic(dartSdkSummaryPath: sdkSummaryFile)
+ ..analysisRoot = optionsDir;
+ var driver = CompilerAnalysisDriver(options);
+ var sdk = driver.dartSdk;
expect(sdk, const TypeMatcher<SummaryBasedDartSdk>());
- var processors = context.analysisOptions.errorProcessors;
+ var processors = driver.analysisOptions.errorProcessors;
expect(processors, hasLength(1));
expect(processors[0].code, CompileTimeErrorCode.UNDEFINED_CLASS.name);
});
@@ -48,9 +49,10 @@
//TODO(danrubel) remove sdkSummaryArgs once all SDKs have summary file
args.addAll(sdkSummaryArgs);
var argResults = ddcArgParser().parse(args);
- var options = AnalyzerOptions.fromArguments(argResults);
- var compiler = ModuleCompiler(options, analysisRoot: optionsDir);
- var processors = compiler.context.analysisOptions.errorProcessors;
+ var options = AnalyzerOptions.fromArguments(argResults)
+ ..analysisRoot = optionsDir;
+ var driver = CompilerAnalysisDriver(options);
+ var processors = driver.analysisOptions.errorProcessors;
expect(processors, hasLength(1));
expect(processors[0].code, CompileTimeErrorCode.UNDEFINED_CLASS.name);
});
@@ -62,9 +64,10 @@
//TODO(danrubel) remove sdkSummaryArgs once all SDKs have summary file
args.addAll(sdkSummaryArgs);
var argResults = ddcArgParser().parse(args);
- var options = AnalyzerOptions.fromArguments(argResults);
- var compiler = ModuleCompiler(options, analysisRoot: optionsDir);
- var processors = compiler.context.analysisOptions.errorProcessors;
+ var options = AnalyzerOptions.fromArguments(argResults)
+ ..analysisRoot = optionsDir;
+ var driver = CompilerAnalysisDriver(options);
+ var processors = driver.analysisOptions.errorProcessors;
expect(processors, hasLength(1));
expect(processors[0].code, CompileTimeErrorCode.DUPLICATE_DEFINITION.name);
});
diff --git a/pkg/dev_compiler/test/sourcemap/sourcemaps_ddc_suite.dart b/pkg/dev_compiler/test/sourcemap/sourcemaps_ddc_suite.dart
index 44994e1..d8b3c1a 100644
--- a/pkg/dev_compiler/test/sourcemap/sourcemaps_ddc_suite.dart
+++ b/pkg/dev_compiler/test/sourcemap/sourcemaps_ddc_suite.dart
@@ -57,7 +57,8 @@
inputFile.toFilePath()
];
- var exitCode = compile(args);
+ var result = compile(args);
+ var exitCode = result?.exitCode;
if (exitCode != 0) {
throw "Exit code: $exitCode from ddc when running something like "
"$dartExecutable ${ddc.toFilePath()} "
diff --git a/pkg/dev_compiler/tool/build_pkgs.dart b/pkg/dev_compiler/tool/build_pkgs.dart
index 97d403d..9b003a6 100755
--- a/pkg/dev_compiler/tool/build_pkgs.dart
+++ b/pkg/dev_compiler/tool/build_pkgs.dart
@@ -5,8 +5,7 @@
import 'package:args/args.dart';
import 'package:path/path.dart' as p;
-import 'package:dev_compiler/src/analyzer/command.dart' as dartdevc;
-import 'package:dev_compiler/src/kernel/command.dart' as dartdevk;
+import 'package:dev_compiler/src/compiler/shared_command.dart';
final String scriptDirectory = p.dirname(p.fromUri(Platform.script));
@@ -127,15 +126,17 @@
/// [libs] and [deps] on other modules.
Future compileModule(String module,
{List<String> libs = const [], List<String> deps = const []}) async {
- makeArgs(bool kernel) {
+ makeArgs({bool kernel = false}) {
var pkgDirectory = p.join(outputDirectory, kernel ? 'pkg_kernel' : 'pkg');
Directory(pkgDirectory).createSync(recursive: true);
+ var args = <String>[];
+ if (kernel) args.add('-k');
- var args = [
+ args.addAll([
'--dart-sdk-summary=${kernel ? kernelSummary : analyzerSummary}',
'-o${pkgDirectory}/$module.js',
'package:$module/$module.dart'
- ];
+ ]);
for (var lib in libs) {
args.add('package:$module/$lib.dart');
}
@@ -146,13 +147,11 @@
}
if (analyzerSummary != null) {
- var args = makeArgs(false);
- var exitCode = dartdevc.compile(args);
- if (exitCode != 0) exit(exitCode);
+ var result = await compile(ParsedArguments.from(makeArgs()));
+ if (!result.success) exit(result.exitCode);
}
if (kernelSummary != null) {
- var args = makeArgs(true);
- var result = await dartdevk.compile(args);
- if (!result.success) exit(1);
+ var result = await compile(ParsedArguments.from(makeArgs(kernel: true)));
+ if (!result.success) exit(result.exitCode);
}
}
diff --git a/pkg/dev_compiler/tool/build_sdk.dart b/pkg/dev_compiler/tool/build_sdk.dart
index efac28d..5fc97e0 100644
--- a/pkg/dev_compiler/tool/build_sdk.dart
+++ b/pkg/dev_compiler/tool/build_sdk.dart
@@ -13,7 +13,7 @@
import 'package:dev_compiler/src/analyzer/command.dart';
-main(List<String> arguments) {
+main(List<String> arguments) async {
var args = ['--no-source-map', '--no-emit-metadata'];
args.addAll(arguments);
args.addAll([
@@ -49,6 +49,5 @@
'dart:web_sql'
]);
- var result = compile(args);
- exit(result);
+ exit((await compile(args)).exitCode);
}
diff --git a/pkg/dev_compiler/web/web_command.dart b/pkg/dev_compiler/web/web_command.dart
index 22e0228..31008db 100644
--- a/pkg/dev_compiler/web/web_command.dart
+++ b/pkg/dev_compiler/web/web_command.dart
@@ -10,16 +10,9 @@
import 'dart:html' show HttpRequest;
import 'dart:typed_data';
-import 'package:analyzer/dart/element/element.dart'
- show
- LibraryElement,
- ImportElement,
- ShowElementCombinator,
- HideElementCombinator;
import 'package:analyzer/file_system/file_system.dart' show ResourceUriResolver;
import 'package:analyzer/file_system/memory_file_system.dart'
show MemoryResourceProvider;
-import 'package:analyzer/src/context/context.dart' show AnalysisContextImpl;
import 'package:analyzer/src/summary/idl.dart' show PackageBundle;
import 'package:analyzer/src/summary/package_bundle_reader.dart'
show SummaryDataStore;
@@ -28,8 +21,9 @@
import 'package:args/command_runner.dart';
import 'package:dev_compiler/src/analyzer/context.dart' show AnalyzerOptions;
-import 'package:dev_compiler/src/analyzer/module_compiler.dart'
- show CompilerOptions, JSModuleFile, ModuleCompiler;
+import 'package:dev_compiler/src/analyzer/command.dart';
+import 'package:dev_compiler/src/analyzer/driver.dart';
+import 'package:dev_compiler/src/analyzer/module_compiler.dart';
import 'package:dev_compiler/src/compiler/module_builder.dart';
import 'package:js/js.dart';
@@ -72,7 +66,7 @@
WebCompileCommand({MessageHandler messageHandler})
: this.messageHandler = messageHandler ?? print {
- CompilerOptions.addArguments(argParser);
+ ddcArgParser(argParser: argParser, help: false);
}
@override
@@ -158,14 +152,11 @@
summaryData.addBundle(url, PackageBundle.fromBuffer(bytes));
compilerOptions.summaryModules[url] = moduleId;
}
+ options.analysisRoot = '/web-compile-root';
+ options.fileResolvers = [ResourceUriResolver(resources)];
+ options.resourceProvider = resources;
- var compiler = ModuleCompiler(options,
- analysisRoot: '/web-compile-root',
- fileResolvers: [ResourceUriResolver(resources)],
- resourceProvider: resources,
- summaryData: summaryData);
-
- var context = compiler.context as AnalysisContextImpl;
+ var driver = CompilerAnalysisDriver(options, summaryData: summaryData);
var resolveFn = (String url) {
var packagePrefix = 'package:';
@@ -237,14 +228,12 @@
var dir = path.dirname(existingLibrary);
// Need to pull in all the imports from the existing library and
// re-export all privates as privates in this library.
- var source = context.sourceFactory.forUri(existingLibrary);
- if (source == null) {
- throw "Unable to load source for library $existingLibrary";
- }
-
- LibraryElement libraryElement = context.computeLibraryElement(source);
- if (libraryElement == null) {
- throw "Unable to get library element.";
+ // Assumption: summaries are available for all libraries, including any
+ // source files that were compiled; we do not need to reconstruct any
+ // summary data here.
+ var unlinked = driver.summaryData.unlinkedMap[existingLibrary];
+ if (unlinked == null) {
+ throw "Unable to get library element for `$existingLibrary`.";
}
var sb = StringBuffer(imports);
sb.write('\n');
@@ -263,9 +252,9 @@
// importing that library and all libraries it imports.
sb.write('import ${json.encode(existingLibrary)};\n');
- for (ImportElement importElement in libraryElement.imports) {
- if (importElement.uri == null) continue;
- var uri = importElement.uri;
+ for (var import in unlinked.imports) {
+ if (import.uri == null) continue;
+ var uri = import.uri;
// dart: and package: uris are not relative but the path package
// thinks they are. We have to provide absolute uris as our library
// has a different directory than the library we are pretending to be.
@@ -275,13 +264,15 @@
uri = path.normalize(path.join(dir, uri));
}
sb.write('import ${json.encode(uri)}');
- if (importElement.prefix != null)
- sb.write(' as ${importElement.prefix.name}');
- for (var combinator in importElement.combinators) {
- if (combinator is ShowElementCombinator) {
- sb.write(' show ${combinator.shownNames.join(', ')}');
- } else if (combinator is HideElementCombinator) {
- sb.write(' hide ${combinator.hiddenNames.join(', ')}');
+ if (import.prefixReference != 0) {
+ var prefix = unlinked.references[import.prefixReference].name;
+ sb.write(' as $prefix');
+ }
+ for (var combinator in import.combinators) {
+ if (combinator.shows.isNotEmpty) {
+ sb.write(' show ${combinator.shows.join(', ')}');
+ } else if (combinator.hides.isNotEmpty) {
+ sb.write(' hide ${combinator.hides.join(', ')}');
} else {
throw 'Unexpected element combinator';
}
@@ -294,7 +285,8 @@
resources.newFile(fileName, sourceCode);
compilerOptions.moduleName = path.toUri(libraryName).toString();
- JSModuleFile module = compiler.compile([fileName], compilerOptions);
+ JSModuleFile module =
+ compileWithAnalyzer(driver, [fileName], options, compilerOptions);
var moduleCode = '';
if (module.isValid) {
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index 03dc93b..ebdd2ea 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -19,7 +19,6 @@
async_star_test/none: RuntimeError
await_future_test: Pass, Timeout # Issue 29920
bit_operations_test: RuntimeError # No bigints on web.
-bug32372_test: RuntimeError
built_in_identifier_prefix_test: CompileTimeError
built_in_identifier_type_annotation_test/dynamic-funarg: RuntimeError # Issue 28816
built_in_identifier_type_annotation_test/dynamic-funret: RuntimeError # Issue 28816
@@ -100,69 +99,15 @@
issue31596_super_test/none: CompileTimeError
issue31596_tearoff_test: CompileTimeError
issue31596_test: CompileTimeError
-issue32353_test: CompileTimeError # Issue 34846
-issue34404_flutter_modified_test: CompileTimeError # DDC doesn't support mixin inference
-issue34404_flutter_test: CompileTimeError # DDC doesn't support mixin inference
issue34498_test: MissingCompileTimeError # Issue 34500
-issue34635_test: MissingCompileTimeError
-issue34636_test: MissingCompileTimeError
label_test: RuntimeError
large_class_declaration_test: Slow, Pass
left_shift_test: RuntimeError # Ints and doubles are unified.
mixin_declaration/mixin_declaration_factory_test/02: Crash
-mixin_declaration/mixin_declaration_inference_invalid_03_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/34167
-mixin_declaration/mixin_declaration_inference_invalid_04_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/34167
-mixin_declaration/mixin_declaration_inference_invalid_05_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/34167
-mixin_declaration/mixin_declaration_inference_invalid_06_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/34167
-mixin_declaration/mixin_declaration_inference_invalid_08_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/34167
-mixin_declaration/mixin_declaration_inference_invalid_09_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/34167
-mixin_declaration/mixin_declaration_inference_invalid_10_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/34167
-mixin_declaration/mixin_declaration_inference_invalid_11_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/34167
-mixin_declaration/mixin_declaration_inference_valid_A00_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_A01_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_A02_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_A10_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_A11_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_A12_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_A20_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_A21_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_A22_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_A23_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_A30_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_A31_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_A42_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_B00_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_B01_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_B02_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_B03_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_B10_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_B11_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_B12_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_B13_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_C00_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_C01_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_C02_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_C03_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_C10_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_C11_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_C12_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_C13_test: CompileTimeError # Issue #34164
-mixin_declaration/mixin_declaration_inference_valid_mixin_applications_test: CompileTimeError # https://github.com/dart-lang/sdk/issues/34164
mixin_declaration/mixin_declaration_invalid_superinvocation_test/10: CompileTimeError # Analyzer chooses wrong(?) super method.
mixin_method_override_test/01: MissingCompileTimeError
mixin_super_2_test: CompileTimeError # Issue 34806
mixin_super_use_test: CompileTimeError # Issue 34806
-mixin_type_parameter_inference_previous_mixin_test/01: CompileTimeError
-mixin_type_parameter_inference_previous_mixin_test/02: CompileTimeError
-mixin_type_parameter_inference_previous_mixin_test/04: MissingCompileTimeError
-mixin_type_parameter_inference_previous_mixin_test/05: RuntimeError
-mixin_type_parameter_inference_test/01: CompileTimeError
-mixin_type_parameter_inference_test/02: CompileTimeError
-mixin_type_parameter_inference_test/03: CompileTimeError
-mixin_type_parameter_inference_test/06: MissingCompileTimeError
-mixin_type_parameter_inference_test/07: MissingCompileTimeError
-mixin_type_parameter_inference_test/08: RuntimeError
-mixin_type_parameter_inference_test/09: RuntimeError
mock_writable_final_private_field_test: CompileTimeError # Issue 30848
multiple_interface_inheritance_test: CompileTimeError # Issue 30552
nested_generic_closure_test: CompileTimeError
@@ -171,7 +116,7 @@
part_refers_to_core_library_test/01: Crash
prefix_shadow_test/01: MissingCompileTimeError # Issue 33005
private_method_tearoff_test: RuntimeError
-regress_23089_test: MissingCompileTimeError
+regress_22976_test: CompileTimeError # Issue 31935, test is not legal in Dart 2.
regress_23408_test: CompileTimeError
regress_24283_test: RuntimeError # Intended to fail, requires 64-bit numbers.
regress_27617_test/1: MissingCompileTimeError
@@ -200,7 +145,6 @@
truncdiv_test: RuntimeError # Issue 29920
try_catch_on_syntax_test/10: MissingCompileTimeError
try_catch_on_syntax_test/11: MissingCompileTimeError
-type_inference_circularity_test: MissingCompileTimeError
type_inference_inconsistent_inheritance_test: MissingCompileTimeError
type_promotion_functions_test/02: CompileTimeError # Issue 30895
type_promotion_functions_test/03: CompileTimeError # Issue 30895