Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2269)

Unified Diff: pkg/analyzer/test/src/task/strong/strong_test_helper.dart

Issue 2705323005: Make src/task/strong tests into classes and asynchronous. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/analyzer/test/src/task/strong/strong_test_helper.dart
diff --git a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
index c2debb8bddcbe088e9e8f2b7c568c668e6c33777..8361c123e80264d4d20ac68a0d1d9ad942e1b493 100644
--- a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
+++ b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
@@ -6,6 +6,8 @@
// package:dev_compiler's tests
library analyzer.test.src.task.strong.strong_test_helper;
+import 'dart:async';
+
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_resolution_map.dart';
import 'package:analyzer/dart/ast/token.dart';
@@ -15,6 +17,7 @@ import 'package:analyzer/error/listener.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
import 'package:analyzer/source/error_processor.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart';
@@ -24,119 +27,6 @@ import 'package:test/test.dart';
import '../../context/mock_sdk.dart';
-MemoryResourceProvider files;
-bool _checkCalled;
-
-/// Adds a file to check. The file should contain:
-///
-/// * all expected failures are listed in the source code using comments
-/// immediately in front of the AST node that should contain the error.
-///
-/// * errors are formatted as a token `severity:ErrorCode`, where
-/// `severity` is the ErrorSeverity the error would be reported at, and
-/// `ErrorCode` is the error code's name.
-///
-/// For example to check that an assignment produces a type error, you can
-/// create a file like:
-///
-/// addFile('''
-/// String x = /*error:STATIC_TYPE_ERROR*/3;
-/// ''');
-/// check();
-///
-/// For a single file, you may also use [checkFile].
-void addFile(String content, {String name: '/main.dart'}) {
- name = name.replaceFirst('^package:', '/packages/');
- files.newFile(files.convertPath(name), content);
-}
-
-/// Run the checker on a program, staring from '/main.dart', and verifies that
-/// errors/warnings/hints match the expected value.
-///
-/// See [addFile] for more information about how to encode expectations in
-/// the file text.
-///
-/// Returns the main resolved library. This can be used for further checks.
-CompilationUnit check(
- {bool implicitCasts: true,
- bool implicitDynamic: true,
- List<String> nonnullableTypes: AnalysisOptionsImpl.NONNULLABLE_TYPES}) {
- _checkCalled = true;
-
- File mainFile = files.getFile(files.convertPath('/main.dart'));
- expect(mainFile.exists, true, reason: '`/main.dart` is missing');
-
- var uriResolver = new _TestUriResolver(files);
- // Enable task model strong mode
- var context = AnalysisEngine.instance.createAnalysisContext();
- AnalysisOptionsImpl options = context.analysisOptions as AnalysisOptionsImpl;
- options.strongMode = true;
- options.strongModeHints = true;
- options.implicitCasts = implicitCasts;
- options.implicitDynamic = implicitDynamic;
- options.nonnullableTypes = nonnullableTypes;
- var mockSdk = new MockSdk(resourceProvider: files);
- (mockSdk.context.analysisOptions as AnalysisOptionsImpl).strongMode = true;
- context.sourceFactory =
- new SourceFactory([new DartUriResolver(mockSdk), uriResolver]);
-
- // Run the checker on /main.dart.
- Source mainSource = uriResolver.resolveAbsolute(mainFile.toUri());
- var initialLibrary = context.resolveCompilationUnit2(mainSource, mainSource);
-
- var collector = new _ErrorCollector(context);
-
- // Extract expectations from the comments in the test files, and
- // check that all errors we emit are included in the expected map.
- var allLibraries = _reachableLibraries(
- resolutionMap.elementDeclaredByCompilationUnit(initialLibrary).library);
- for (var lib in allLibraries) {
- for (var unit in lib.units) {
- var errors = <AnalysisError>[];
- collector.errors = errors;
-
- var source = unit.source;
- if (source.uri.scheme == 'dart') continue;
-
- var librarySource = context.getLibrariesContaining(source).single;
- var resolved = context.resolveCompilationUnit2(source, librarySource);
-
- errors.addAll(context.computeErrors(source).where((e) =>
- // TODO(jmesserly): these are usually intentional dynamic calls.
- e.errorCode.name != 'UNDEFINED_METHOD' &&
- // We don't care about any of these:
- e.errorCode != HintCode.UNUSED_ELEMENT &&
- e.errorCode != HintCode.UNUSED_FIELD &&
- e.errorCode != HintCode.UNUSED_IMPORT &&
- e.errorCode != HintCode.UNUSED_LOCAL_VARIABLE &&
- e.errorCode != TodoCode.TODO));
- _expectErrors(context, resolved, errors);
- }
- }
-
- return initialLibrary;
-}
-
-/// Adds a file using [addFile] and calls [check].
-///
-/// Also returns the resolved compilation unit.
-CompilationUnit checkFile(String content) {
- addFile(content);
- return check();
-}
-
-void doSetUp() {
- AnalysisEngine.instance.processRequiredPlugins();
- files = new MemoryResourceProvider();
- _checkCalled = false;
-}
-
-void doTearDown() {
- // This is a sanity check, in case only addFile is called.
- expect(_checkCalled, true, reason: 'must call check() method in test case');
- files = null;
-}
-
SourceSpanWithContext _createSpanHelper(
LineInfo lineInfo, int start, Source source, String content,
{int end}) {
@@ -173,15 +63,13 @@ String _errorCodeName(ErrorCode errorCode) {
}
}
-ErrorSeverity _errorSeverity(AnalysisContext context, AnalysisError error) {
- // Attempt to process severity in a similar way to analyzer_cli and server.
- return ErrorProcessor
- .getProcessor(context.analysisOptions, error)
- ?.severity ??
+ErrorSeverity _errorSeverity(
+ AnalysisOptions analysisOptions, AnalysisError error) {
+ return ErrorProcessor.getProcessor(analysisOptions, error)?.severity ??
error.errorCode.errorSeverity;
}
-void _expectErrors(AnalysisContext context, CompilationUnit unit,
+void _expectErrors(AnalysisOptions analysisOptions, CompilationUnit unit,
List<AnalysisError> actualErrors) {
var expectedErrors = _findExpectedErrors(unit.beginToken);
@@ -190,7 +78,8 @@ void _expectErrors(AnalysisContext context, CompilationUnit unit,
int delta = x.offset.compareTo(y.offset);
if (delta != 0) return delta;
- delta = _errorSeverity(context, x).compareTo(_errorSeverity(context, y));
+ delta = _errorSeverity(analysisOptions, x)
+ .compareTo(_errorSeverity(analysisOptions, y));
if (delta != 0) return delta;
return _errorCodeName(x.errorCode).compareTo(_errorCodeName(y.errorCode));
@@ -212,7 +101,7 @@ void _expectErrors(AnalysisContext context, CompilationUnit unit,
for (var expected in expectedErrors) {
AnalysisError actual = expected._removeMatchingActual(actualErrors);
if (actual != null) {
- if (_errorSeverity(context, actual) != expected.severity ||
+ if (_errorSeverity(analysisOptions, actual) != expected.severity ||
_errorCodeName(actual.errorCode) != expected.typeName) {
different[expected] = actual;
}
@@ -225,7 +114,7 @@ void _expectErrors(AnalysisContext context, CompilationUnit unit,
List<AnalysisError> unexpected = actualErrors;
if (unreported.isNotEmpty || unexpected.isNotEmpty || different.isNotEmpty) {
- _reportFailure(context, unit, unreported, unexpected, different);
+ _reportFailure(analysisOptions, unit, unreported, unexpected, different);
}
}
@@ -264,15 +153,14 @@ SourceLocation _locationForOffset(LineInfo lineInfo, Uri uri, int offset) {
}
/// Returns all libraries transitively imported or exported from [start].
-List<LibraryElement> _reachableLibraries(LibraryElement start) {
- var results = <LibraryElement>[];
- var seen = new Set();
- void find(LibraryElement lib) {
- if (seen.contains(lib)) return;
- seen.add(lib);
- results.add(lib);
- lib.importedLibraries.forEach(find);
- lib.exportedLibraries.forEach(find);
+Set<LibraryElement> _reachableLibraries(LibraryElement start) {
+ Set<LibraryElement> results = new Set<LibraryElement>();
+
+ void find(LibraryElement library) {
+ if (results.add(library)) {
+ library.importedLibraries.forEach(find);
+ library.exportedLibraries.forEach(find);
+ }
}
find(start);
@@ -280,7 +168,7 @@ List<LibraryElement> _reachableLibraries(LibraryElement start) {
}
void _reportFailure(
- AnalysisContext context,
+ AnalysisOptions analysisOptions,
CompilationUnit unit,
List<_ErrorExpectation> unreported,
List<AnalysisError> unexpected,
@@ -296,7 +184,7 @@ void _reportFailure(
var span = _createSpanHelper(unit.lineInfo, offset,
resolutionMap.elementDeclaredByCompilationUnit(unit).source, sourceCode,
end: offset + length);
- var levelName = _errorSeverity(context, error).displayName;
+ var levelName = _errorSeverity(analysisOptions, error).displayName;
return '@$offset $levelName:${_errorCodeName(error.errorCode)}\n' +
span.message(error.message);
}
@@ -334,17 +222,163 @@ void _reportFailure(
fail('Checker errors do not match expected errors:\n\n$message');
}
+class AbstractStrongTest {
+ MemoryResourceProvider _resourceProvider = new MemoryResourceProvider();
+ bool _checkCalled = false;
+
+ bool get enableNewAnalysisDriver => false;
+
+ /// Adds a file to check. The file should contain:
+ ///
+ /// * all expected failures are listed in the source code using comments
+ /// immediately in front of the AST node that should contain the error.
+ ///
+ /// * errors are formatted as a token `severity:ErrorCode`, where
+ /// `severity` is the ErrorSeverity the error would be reported at, and
+ /// `ErrorCode` is the error code's name.
+ ///
+ /// For example to check that an assignment produces a type error, you can
+ /// create a file like:
+ ///
+ /// addFile('''
+ /// String x = /*error:STATIC_TYPE_ERROR*/3;
+ /// ''');
+ /// check();
+ ///
+ /// For a single file, you may also use [checkFile].
+ void addFile(String content, {String name: '/main.dart'}) {
+ name = name.replaceFirst('^package:', '/packages/');
+ _resourceProvider.newFile(_resourceProvider.convertPath(name), content);
+ }
+
+ /// Run the checker on a program, staring from '/main.dart', and verifies that
+ /// errors/warnings/hints match the expected value.
+ ///
+ /// See [addFile] for more information about how to encode expectations in
+ /// the file text.
+ ///
+ /// Returns the main resolved library. This can be used for further checks.
+ Future<CompilationUnit> check(
+ {bool implicitCasts: true,
+ bool implicitDynamic: true,
+ List<String> nonnullableTypes:
+ AnalysisOptionsImpl.NONNULLABLE_TYPES}) async {
+ _checkCalled = true;
+
+ File mainFile =
+ _resourceProvider.getFile(_resourceProvider.convertPath('/main.dart'));
+ expect(mainFile.exists, true, reason: '`/main.dart` is missing');
+
+ AnalysisOptionsImpl analysisOptions = new AnalysisOptionsImpl();
+ analysisOptions.strongMode = true;
+ analysisOptions.strongModeHints = true;
+ analysisOptions.implicitCasts = implicitCasts;
+ analysisOptions.implicitDynamic = implicitDynamic;
+ analysisOptions.nonnullableTypes = nonnullableTypes;
+
+ var mockSdk = new MockSdk(resourceProvider: _resourceProvider);
+ mockSdk.context.analysisOptions = analysisOptions;
+
+ SourceFactory sourceFactory;
+ {
+ var uriResolver = new _TestUriResolver(_resourceProvider);
+ sourceFactory =
+ new SourceFactory([new DartUriResolver(mockSdk), uriResolver]);
+ }
+
+ CompilationUnit mainUnit;
+ AnalysisContext context = null;
+ AnalysisDriver driver = null;
+ if (enableNewAnalysisDriver) {
+ // TODO(scheglov)
+ } else {
+ context = AnalysisEngine.instance.createAnalysisContext();
+ context.analysisOptions = analysisOptions;
+ context.sourceFactory = sourceFactory;
+
+ // Run the checker on /main.dart.
+ Source mainSource = sourceFactory.forUri2(mainFile.toUri());
+ mainUnit = context.resolveCompilationUnit2(mainSource, mainSource);
+ }
+
+ var collector = new _ErrorCollector(analysisOptions);
+
+ // Extract expectations from the comments in the test files, and
+ // check that all errors we emit are included in the expected map.
+ LibraryElement mainLibrary =
+ resolutionMap.elementDeclaredByCompilationUnit(mainUnit).library;
+ Set<LibraryElement> allLibraries = _reachableLibraries(mainLibrary);
+ for (LibraryElement library in allLibraries) {
+ for (CompilationUnitElement unit in library.units) {
+ var errors = <AnalysisError>[];
+ collector.errors = errors;
+
+ var source = unit.source;
+ if (source.uri.scheme == 'dart') {
+ continue;
+ }
+
+ var analysisResult = await _resolve(context, driver, source);
+
+ errors.addAll(analysisResult.errors.where((e) =>
+ // TODO(jmesserly): these are usually intentional dynamic calls.
+ e.errorCode.name != 'UNDEFINED_METHOD' &&
+ // We don't care about any of these:
+ e.errorCode != HintCode.UNUSED_ELEMENT &&
+ e.errorCode != HintCode.UNUSED_FIELD &&
+ e.errorCode != HintCode.UNUSED_IMPORT &&
+ e.errorCode != HintCode.UNUSED_LOCAL_VARIABLE &&
+ e.errorCode != TodoCode.TODO));
+ _expectErrors(analysisOptions, analysisResult.unit, errors);
+ }
+ }
+
+ return mainUnit;
+ }
+
+ /// Adds a file using [addFile] and calls [check].
+ ///
+ /// Also returns the resolved compilation unit.
+ Future<CompilationUnit> checkFile(String content) async {
+ addFile(content);
+ return check();
+ }
+
+ void setUp() {
+ AnalysisEngine.instance.processRequiredPlugins();
+ }
+
+ void tearDown() {
+ // This is a sanity check, in case only addFile is called.
+ expect(_checkCalled, true, reason: 'must call check() method in test case');
+ AnalysisEngine.instance.clearCaches();
+ }
+
+ Future<_TestAnalysisResult> _resolve(
+ AnalysisContext context, AnalysisDriver driver, Source source) async {
+ if (enableNewAnalysisDriver) {
+ // TODO(scheglov) implement
+ throw new UnimplementedError();
+ } else {
+ List<Source> libraries = context.getLibrariesContaining(source);
+ var unit = context.resolveCompilationUnit2(source, libraries.single);
+ var errors = context.computeErrors(source);
+ return new _TestAnalysisResult(source, unit, errors);
+ }
+ }
+}
+
class _ErrorCollector implements AnalysisErrorListener {
- final AnalysisContext _context;
+ final AnalysisOptions analysisOptions;
List<AnalysisError> errors;
final bool hints;
- _ErrorCollector(this._context, {this.hints: true});
+ _ErrorCollector(this.analysisOptions, {this.hints: true});
void onError(AnalysisError error) {
// Unless DDC hints are requested, filter them out.
var HINT = ErrorSeverity.INFO.ordinal;
- if (hints || _errorSeverity(_context, error).ordinal > HINT) {
+ if (hints || _errorSeverity(analysisOptions, error).ordinal > HINT) {
errors.add(error);
}
}
@@ -399,6 +433,13 @@ class _ErrorExpectation {
}
}
+class _TestAnalysisResult {
+ final Source source;
+ final CompilationUnit unit;
+ final List<AnalysisError> errors;
+ _TestAnalysisResult(this.source, this.unit, this.errors);
+}
+
class _TestUriResolver extends ResourceUriResolver {
final MemoryResourceProvider provider;
_TestUriResolver(provider)

Powered by Google App Engine
This is Rietveld 408576698