[dartdevc] fix to pass in analysis options to analysis context
Also switch to using the RestrictedAnalysisContext.
Change-Id: Ia9a07331592a3eaacacddb8b27ca08598d2c0773
Reviewed-on: https://dart-review.googlesource.com/c/88749
Commit-Queue: Jenny Messerly <jmesserly@google.com>
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index 6edbe05..d8063b5 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -74,7 +74,7 @@
final Dart2TypeSystem rules;
/// Errors that were produced during compilation, if any.
- final List<AnalysisError> errors;
+ final ErrorCollector errors;
JSTypeRep jsTypeRep;
@@ -5681,8 +5681,10 @@
var nearest = (lexeme.startsWith("0x") || lexeme.startsWith("0X"))
? '0x${valueInJS.toRadixString(16)}'
: '$valueInJS';
- errors.add(AnalysisError(_currentCompilationUnit.source, node.offset,
- node.length, invalidJSInteger, [lexeme, nearest]));
+ errors.add(
+ _currentCompilationUnit.lineInfo,
+ AnalysisError(_currentCompilationUnit.source, node.offset,
+ node.length, invalidJSInteger, [lexeme, nearest]));
}
return JS.LiteralNumber('$valueInJS');
}
diff --git a/pkg/dev_compiler/lib/src/analyzer/driver.dart b/pkg/dev_compiler/lib/src/analyzer/driver.dart
index ec38410..cec419b 100644
--- a/pkg/dev_compiler/lib/src/analyzer/driver.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/driver.dart
@@ -9,14 +9,15 @@
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/dart/analysis/restricted_analysis_context.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary/idl.dart';
@@ -241,17 +242,13 @@
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 context = RestrictedAnalysisContext(
+ analysisOptions, declaredVariables, sourceFactory);
var resultProvider = InputPackagesResultProvider(
context,
SummaryDataStore([])
..addStore(summaryData)
..addBundle(null, bundle));
- context.resultProvider = resultProvider;
- context.contentCache = _ContentCacheWrapper(fsState);
- context.analysisOptions = analysisOptions;
var resynthesizer = resultProvider.resynthesizer;
_extensionTypes ??= ExtensionTypeSet(context.typeProvider, resynthesizer);
@@ -316,10 +313,7 @@
this._fsState,
this._resourceProvider);
- AnalysisContextImpl get context => resynthesizer.context;
-
- /// Clean up any state used by this driver.
- void dispose() => context.dispose();
+ TypeProvider get typeProvider => resynthesizer.typeProvider;
/// 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).
@@ -340,9 +334,9 @@
declaredVariables,
resynthesizer.sourceFactory,
(uri) => _isLibraryUri('$uri'),
- context,
+ resynthesizer.context,
resynthesizer,
- InheritanceManager2(context.typeSystem),
+ InheritanceManager2(resynthesizer.typeSystem),
libraryFile,
_resourceProvider);
// TODO(jmesserly): ideally we'd use the existing public `analyze()` method,
@@ -361,51 +355,3 @@
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/error_helpers.dart b/pkg/dev_compiler/lib/src/analyzer/error_helpers.dart
index 0943c39..1528546 100644
--- a/pkg/dev_compiler/lib/src/analyzer/error_helpers.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/error_helpers.dart
@@ -2,33 +2,87 @@
// 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 'package:analyzer/error/error.dart';
import 'package:analyzer/source/error_processor.dart' show ErrorProcessor;
+import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
+import 'package:analyzer/src/generated/engine.dart' show AnalysisOptions;
import 'package:path/path.dart' as path;
-/// Sorts and formats errors, returning the error messages.
-List<String> formatErrors(AnalysisContext context, List<AnalysisError> errors) {
- sortErrors(context, errors);
- var result = <String>[];
- for (var e in errors) {
- var m = formatError(context, e);
- if (m != null) result.add(m);
- }
- return result;
-}
+class ErrorCollector {
+ final bool _replCompile;
+ final AnalysisOptions _options;
+ SplayTreeMap<AnalysisError, String> _errors;
-// TODO(jmesserly): this code was taken from analyzer_cli.
-// It really should be in some common place so we can share it.
-// TODO(jmesserly): this shouldn't depend on `context` but we need it to compute
-// `errorSeverity` due to some APIs that need fixing.
-void sortErrors(AnalysisContext context, List<AnalysisError> errors) {
- errors.sort((AnalysisError error1, AnalysisError error2) {
+ ErrorCollector(this._options, this._replCompile) {
+ _errors = SplayTreeMap<AnalysisError, String>(_compareErrors);
+ }
+
+ bool get hasFatalErrors => _errors.keys.any(_isFatalError);
+
+ Iterable<String> get formattedErrors => _errors.values;
+
+ void add(LineInfo lineInfo, AnalysisError error) {
+ if (_shouldIgnoreError(error)) return;
+
+ // Skip hints, some like TODOs are not useful.
+ if (_errorSeverity(error).ordinal <= ErrorSeverity.INFO.ordinal) return;
+
+ _errors[error] = _formatError(lineInfo, error);
+ }
+
+ void addAll(LineInfo lineInfo, Iterable<AnalysisError> errors) {
+ for (var e in errors) add(lineInfo, e);
+ }
+
+ ErrorSeverity _errorSeverity(AnalysisError error) {
+ var errorCode = error.errorCode;
+ if (errorCode == StrongModeCode.TOP_LEVEL_FUNCTION_LITERAL_BLOCK ||
+ errorCode == StrongModeCode.TOP_LEVEL_INSTANCE_GETTER ||
+ errorCode == StrongModeCode.TOP_LEVEL_INSTANCE_METHOD) {
+ // These are normally hints, but they should be errors when running DDC, so
+ // that users won't be surprised by behavioral differences between DDC and
+ // dart2js.
+ return ErrorSeverity.ERROR;
+ }
+
+ // TODO(jmesserly): remove support for customizing error levels via
+ // analysis_options from DDC. (it won't work with --kernel).
+ return ErrorProcessor.getProcessor(_options, error)?.severity ??
+ errorCode.errorSeverity;
+ }
+
+ String _formatError(LineInfo lineInfo, AnalysisError error) {
+ var location = lineInfo.getLocation(error.offset);
+
+ // [warning] 'foo' is not a... (/Users/.../tmp/foo.dart, line 1, col 2)
+ return (StringBuffer()
+ ..write('[${_errorSeverity(error).displayName}] ')
+ ..write(error.message)
+ ..write(' (${path.prettyUri(error.source.uri)}')
+ ..write(
+ ', line ${location.lineNumber}, col ${location.columnNumber})'))
+ .toString();
+ }
+
+ bool _shouldIgnoreError(AnalysisError error) {
+ var uri = error.source.uri;
+ if (uri.scheme != 'dart') return false;
+ var sdkLib = uri.pathSegments[0];
+ if (sdkLib == 'html' || sdkLib == 'svg' || sdkLib == '_interceptors') {
+ var c = error.errorCode;
+ return c == StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1 ||
+ c == StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2 ||
+ c == StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS;
+ }
+ return false;
+ }
+
+ int _compareErrors(AnalysisError error1, AnalysisError error2) {
// severity
- var severity1 = errorSeverity(context, error1);
- var severity2 = errorSeverity(context, error2);
- int compare = severity2.compareTo(severity1);
+ int compare = _errorSeverity(error2).compareTo(_errorSeverity(error1));
if (compare != 0) return compare;
// path
@@ -42,64 +96,22 @@
// compare message, in worst case.
return error1.message.compareTo(error2.message);
- });
-}
-
-// TODO(jmesserly): this was from analyzer_cli, we should factor it differently.
-String formatError(AnalysisContext context, AnalysisError error) {
- var severity = errorSeverity(context, error);
- // Skip hints, some like TODOs are not useful.
- if (severity.ordinal <= ErrorSeverity.INFO.ordinal) return null;
-
- var lineInfo = context.computeLineInfo(error.source);
- var location = lineInfo.getLocation(error.offset);
-
- // [warning] 'foo' is not a... (/Users/.../tmp/foo.dart, line 1, col 2)
- return (StringBuffer()
- ..write('[${severity.displayName}] ')
- ..write(error.message)
- ..write(' (${path.prettyUri(error.source.uri)}')
- ..write(', line ${location.lineNumber}, col ${location.columnNumber})'))
- .toString();
-}
-
-ErrorSeverity errorSeverity(AnalysisContext context, AnalysisError error) {
- var errorCode = error.errorCode;
- if (errorCode == StrongModeCode.TOP_LEVEL_FUNCTION_LITERAL_BLOCK ||
- errorCode == StrongModeCode.TOP_LEVEL_INSTANCE_GETTER ||
- errorCode == StrongModeCode.TOP_LEVEL_INSTANCE_METHOD) {
- // These are normally hints, but they should be errors when running DDC, so
- // that users won't be surprised by behavioral differences between DDC and
- // dart2js.
- return ErrorSeverity.ERROR;
}
- // TODO(jmesserly): this Analyzer API totally bonkers, but it's what
- // analyzer_cli and server use.
- //
- // Among the issues with ErrorProcessor.getProcessor:
- // * it needs to be called per-error, so it's a performance trap.
- // * it can return null
- // * using AnalysisError directly is now suspect, it's a correctness trap
- // * it requires an AnalysisContext
- return ErrorProcessor.getProcessor(context.analysisOptions, error)
- ?.severity ??
- errorCode.errorSeverity;
-}
+ bool _isFatalError(AnalysisError e) {
+ if (_errorSeverity(e) != ErrorSeverity.ERROR) return false;
-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);
+ // 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(
diff --git a/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart b/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart
index 120f7dc..851d47b 100644
--- a/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart
@@ -18,7 +18,7 @@
final ClassElement _jsString;
JSTypeRep(this.rules, LinkedAnalysisDriver driver)
- : types = driver.context.typeProvider,
+ : types = driver.typeProvider,
_jsBool = driver.getClass('dart:_interceptors', 'JSBool'),
_jsString = driver.getClass('dart:_interceptors', 'JSString'),
_jsNumber = driver.getClass('dart:_interceptors', 'JSNumber');
diff --git a/pkg/dev_compiler/lib/src/analyzer/module_compiler.dart b/pkg/dev_compiler/lib/src/analyzer/module_compiler.dart
index f62c54c..179dbb1 100644
--- a/pkg/dev_compiler/lib/src/analyzer/module_compiler.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/module_compiler.dart
@@ -10,7 +10,6 @@
show LibraryElement, UriReferencedElement;
import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
import 'package:args/args.dart' show ArgParser, ArgResults;
import 'package:path/path.dart' as path;
@@ -57,7 +56,6 @@
AnalyzerOptions analyzerOptions,
CompilerOptions options) {
var trees = <CompilationUnit>[];
- var errors = <AnalysisError>[];
var explicitSources = <Uri>[];
var compilingSdk = false;
@@ -70,7 +68,17 @@
}
var driver = compilerDriver.linkLibraries(explicitSources, analyzerOptions);
+ var errors = ErrorCollector(driver.analysisOptions, options.replCompile);
for (var libraryUri in driver.libraryUris) {
+ var analysisResults = driver.analyzeLibrary(libraryUri);
+
+ CompilationUnit definingUnit;
+ for (var result in analysisResults.values) {
+ if (result.file.uriStr == libraryUri) definingUnit = result.unit;
+ errors.addAll(result.unit.lineInfo, result.errors);
+ trees.add(result.unit);
+ }
+
var library = driver.getLibrary(libraryUri);
// TODO(jmesserly): remove "dart:mirrors" from DDC's SDK, and then remove
@@ -78,29 +86,19 @@
if (!compilingSdk && !options.emitMetadata) {
var node = _getDartMirrorsImport(library);
if (node != null) {
- errors.add(AnalysisError(library.source, node.uriOffset, node.uriEnd,
- invalidImportDartMirrors));
+ errors.add(
+ definingUnit.lineInfo,
+ AnalysisError(library.source, node.uriOffset, node.uriEnd,
+ invalidImportDartMirrors));
}
}
-
- var analysisResults = driver.analyzeLibrary(libraryUri);
- for (var result in analysisResults.values) {
- errors.addAll(_filterJsErrors(libraryUri, result.errors));
- trees.add(result.unit);
- }
- }
-
- var context = driver.context;
-
- bool anyFatalErrors() {
- return errors.any((e) => isFatalError(context, e, options.replCompile));
}
JS.Program jsProgram;
- if (options.unsafeForceCompile || !anyFatalErrors()) {
+ if (options.unsafeForceCompile || !errors.hasFatalErrors) {
var codeGenerator = CodeGenerator(
driver,
- driver.context.typeProvider,
+ driver.typeProvider,
compilerDriver.summaryData,
options,
compilerDriver.extensionTypes,
@@ -110,37 +108,19 @@
} 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 (!errors.hasFatalErrors) rethrow;
}
- if (!options.unsafeForceCompile && anyFatalErrors()) {
+ if (!options.unsafeForceCompile && errors.hasFatalErrors) {
jsProgram = null;
}
}
var jsModule = JSModuleFile(
- formatErrors(context, errors), options, jsProgram, driver.summaryBytes);
- driver.dispose();
+ errors.formattedErrors.toList(), options, jsProgram, driver.summaryBytes);
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) {
return library.imports.firstWhere(_isDartMirrorsImort, orElse: () => null) ??
library.exports.firstWhere(_isDartMirrorsImort, orElse: () => null);
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 503c60f..5c91caa 100644
--- a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
+++ b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
@@ -883,8 +883,7 @@
summaryData.addBundle(null, sdkSummaryBundle);
}
- // TODO(jmesserly): can we avoid creating an analysis context entirely?
- // It doesn't look like StoreBasedSummaryResynthesizer uses much of it.
+ // TODO(jmesserly): use RestrictedAnalysisContext.
var context = a.AnalysisEngine.instance.createAnalysisContext()
as a.AnalysisContextImpl;
context.sourceFactory = a.SourceFactory(