| Index: pkg/analyzer/test/src/task/strong/front_end_inference_test.dart
|
| diff --git a/pkg/analyzer/test/src/task/strong/front_end_inference_test.dart b/pkg/analyzer/test/src/task/strong/front_end_inference_test.dart
|
| index 9d41aeebea4d97868622ccc4b74cb6d25273b279..60b23c52be61a16e95122e2b670d11059c959e4f 100644
|
| --- a/pkg/analyzer/test/src/task/strong/front_end_inference_test.dart
|
| +++ b/pkg/analyzer/test/src/task/strong/front_end_inference_test.dart
|
| @@ -2,32 +2,22 @@
|
| // 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:async';
|
| -import 'dart:convert';
|
| -import 'dart:io';
|
| -
|
| import 'package:analyzer/dart/ast/ast.dart';
|
| import 'package:analyzer/dart/ast/token.dart';
|
| import 'package:analyzer/dart/ast/visitor.dart';
|
| import 'package:analyzer/dart/element/element.dart';
|
| import 'package:analyzer/dart/element/type.dart';
|
| -import 'package:analyzer/src/dart/analysis/driver.dart';
|
| -import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
|
| -import 'package:analyzer/src/generated/parser.dart';
|
| +import 'package:analyzer/src/generated/resolver.dart';
|
| import 'package:analyzer/src/generated/scanner.dart';
|
| -import 'package:analyzer/src/generated/source.dart';
|
| -import 'package:analyzer/src/generated/utilities_dart.dart';
|
| import 'package:front_end/src/base/instrumentation.dart' as fasta;
|
| import 'package:front_end/src/fasta/compiler_context.dart' as fasta;
|
| import 'package:front_end/src/fasta/testing/validating_instrumentation.dart'
|
| as fasta;
|
| -import 'package:front_end/src/fasta/util/relativize.dart' show relativizeUri;
|
| import 'package:kernel/kernel.dart' as fasta;
|
| -import 'package:path/path.dart' as pathos;
|
| import 'package:test/test.dart';
|
| import 'package:test_reflective_loader/test_reflective_loader.dart';
|
|
|
| -import '../../dart/analysis/base.dart';
|
| +import 'front_end_test_common.dart';
|
|
|
| main() {
|
| // Use a group() wrapper to specify the timeout.
|
| @@ -38,306 +28,16 @@ main() {
|
| }, timeout: new Timeout(const Duration(seconds: 120)));
|
| }
|
|
|
| -/// Set this to `true` to cause expectation comments to be updated.
|
| -const bool fixProblems = false;
|
| -
|
| @reflectiveTest
|
| -class RunFrontEndInferenceTest {
|
| - test_run() async {
|
| - String pkgPath = _findPkgRoot();
|
| - String fePath = pathos.join(pkgPath, 'front_end', 'testcases', 'inference');
|
| - List<File> dartFiles = new Directory(fePath)
|
| - .listSync()
|
| - .where((entry) => entry is File && entry.path.endsWith('.dart'))
|
| - .map((entry) => entry as File)
|
| - .toList();
|
| -
|
| - var allProblems = new StringBuffer();
|
| - for (File file in dartFiles) {
|
| - var test = new _FrontEndInferenceTest();
|
| - await test.setUp();
|
| - try {
|
| - String code = file.readAsStringSync();
|
| - String problems = await test.runTest(file.path, code);
|
| - if (problems != null) {
|
| - allProblems.writeln(problems);
|
| - }
|
| - } finally {
|
| - await test.tearDown();
|
| - }
|
| - }
|
| - if (allProblems.isNotEmpty) {
|
| - fail(allProblems.toString());
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Expects that the [Platform.script] is a test inside of `pkg/analyzer/test`
|
| - * folder, and return the absolute path of the `pkg` folder.
|
| - */
|
| - String _findPkgRoot() {
|
| - String scriptPath = pathos.fromUri(Platform.script);
|
| - List<String> parts = pathos.split(scriptPath);
|
| - for (int i = 0; i < parts.length - 2; i++) {
|
| - if (parts[i] == 'pkg' &&
|
| - parts[i + 1] == 'analyzer' &&
|
| - parts[i + 2] == 'test') {
|
| - return pathos.joinAll(parts.sublist(0, i + 1));
|
| - }
|
| - }
|
| - throw new StateError('Unable to find sdk/pkg/ in $scriptPath');
|
| - }
|
| -}
|
| -
|
| -class _ElementNamer {
|
| - final ConstructorElement currentFactoryConstructor;
|
| -
|
| - _ElementNamer(this.currentFactoryConstructor);
|
| -
|
| - void appendElementName(StringBuffer buffer, Element element) {
|
| - // Synthetic FunctionElement(s) don't have a name or enclosing library.
|
| - if (element.isSynthetic && element is FunctionElement) {
|
| - return;
|
| - }
|
| -
|
| - var enclosing = element.enclosingElement;
|
| - if (enclosing is CompilationUnitElement) {
|
| - enclosing = enclosing.enclosingElement;
|
| - } else if (enclosing is ClassElement &&
|
| - currentFactoryConstructor != null &&
|
| - identical(enclosing, currentFactoryConstructor.enclosingElement) &&
|
| - element is TypeParameterElement) {
|
| - enclosing = currentFactoryConstructor;
|
| - }
|
| - if (enclosing != null) {
|
| - if (enclosing is LibraryElement &&
|
| - (enclosing.name == 'dart.core' ||
|
| - enclosing.name == 'dart.async' ||
|
| - enclosing.name == 'test')) {
|
| - // For brevity, omit library name
|
| - } else {
|
| - appendElementName(buffer, enclosing);
|
| - buffer.write('::');
|
| - }
|
| - }
|
| -
|
| - String name = element.name ?? '';
|
| - if (element is ConstructorElement && name == '') {
|
| - name = '•';
|
| - } else if (name.endsWith('=') &&
|
| - element is PropertyAccessorElement &&
|
| - element.isSetter) {
|
| - name = name.substring(0, name.length - 1);
|
| - }
|
| - buffer.write(name);
|
| - }
|
| -}
|
| -
|
| -class _FrontEndInferenceTest extends BaseAnalysisDriverTest {
|
| - @override
|
| - AnalysisOptionsImpl createAnalysisOptions() =>
|
| - super.createAnalysisOptions()..enableAssertInitializer = true;
|
| -
|
| - Future<String> runTest(String path, String code) {
|
| - return fasta.CompilerContext.runWithDefaultOptions((_) async {
|
| - Uri uri = provider.pathContext.toUri(path);
|
| -
|
| - List<int> lineStarts = new LineInfo.fromContent(code).lineStarts;
|
| - fasta.CompilerContext.current.uriToSource[relativizeUri(uri).toString()] =
|
| - new fasta.Source(lineStarts, UTF8.encode(code));
|
| -
|
| - var validation = new fasta.ValidatingInstrumentation();
|
| - await validation.loadExpectations(uri);
|
| -
|
| - _addFileAndImports(path, code);
|
| -
|
| - AnalysisResult result = await driver.getResult(path);
|
| - result.unit.accept(new _InstrumentationVisitor(validation, uri));
|
| -
|
| - validation.finish();
|
| -
|
| - if (validation.hasProblems) {
|
| - if (fixProblems) {
|
| - validation.fixSource(uri, true);
|
| - return null;
|
| - } else {
|
| - return validation.problemsAsString;
|
| - }
|
| - } else {
|
| - return null;
|
| - }
|
| - });
|
| - }
|
| -
|
| - void _addFileAndImports(String path, String code) {
|
| - provider.newFile(path, code);
|
| - var source = null;
|
| - var analysisErrorListener = null;
|
| - var scanner = new Scanner(
|
| - source, new CharSequenceReader(code), analysisErrorListener);
|
| - var token = scanner.tokenize();
|
| - var compilationUnit =
|
| - new Parser(source, analysisErrorListener).parseDirectives(token);
|
| - for (var directive in compilationUnit.directives) {
|
| - if (directive is UriBasedDirective) {
|
| - Uri uri = Uri.parse(directive.uri.stringValue);
|
| - if (uri.scheme == 'dart') {
|
| - // Ignore these--they should be in the mock SDK.
|
| - } else if (uri.scheme == '') {
|
| - var pathSegments = uri.pathSegments;
|
| - // For these tests we don't support any directory traversal; we just
|
| - // assume the URI is the name of a file in the same directory as all
|
| - // the other tests.
|
| - if (pathSegments.length != 1) fail('URI too complex: $uri');
|
| - var referencedPath =
|
| - pathos.join(pathos.dirname(path), pathSegments[0]);
|
| - if (!provider.getFile(referencedPath).exists) {
|
| - var referencedCode = new File(referencedPath).readAsStringSync();
|
| - _addFileAndImports(referencedPath, referencedCode);
|
| - }
|
| - }
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -/// Instance of [InstrumentationValue] describing an [ExecutableElement].
|
| -class _InstrumentationValueForExecutableElement
|
| - extends fasta.InstrumentationValue {
|
| - final ExecutableElement element;
|
| - final _ElementNamer elementNamer;
|
| -
|
| - _InstrumentationValueForExecutableElement(this.element, this.elementNamer);
|
| -
|
| +class RunFrontEndInferenceTest extends RunFrontEndTest {
|
| @override
|
| - String toString() {
|
| - StringBuffer buffer = new StringBuffer();
|
| - elementNamer.appendElementName(buffer, element);
|
| - return buffer.toString();
|
| - }
|
| -}
|
| -
|
| -/**
|
| - * Instance of [InstrumentationValue] describing a [DartType].
|
| - */
|
| -class _InstrumentationValueForType extends fasta.InstrumentationValue {
|
| - final DartType type;
|
| - final _ElementNamer elementNamer;
|
| -
|
| - _InstrumentationValueForType(this.type, this.elementNamer);
|
| + get testSubdir => 'inference';
|
|
|
| @override
|
| - String toString() {
|
| - StringBuffer buffer = new StringBuffer();
|
| - _appendType(buffer, type);
|
| - return buffer.toString();
|
| - }
|
| -
|
| - void _appendList<T>(StringBuffer buffer, String open, String close,
|
| - List<T> items, String separator, writeItem(T item),
|
| - {bool includeEmpty: false}) {
|
| - if (!includeEmpty && items.isEmpty) {
|
| - return;
|
| - }
|
| - buffer.write(open);
|
| - bool first = true;
|
| - for (T item in items) {
|
| - if (!first) {
|
| - buffer.write(separator);
|
| - }
|
| - writeItem(item);
|
| - first = false;
|
| - }
|
| - buffer.write(close);
|
| - }
|
| -
|
| - void _appendParameters(
|
| - StringBuffer buffer, List<ParameterElement> parameters) {
|
| - buffer.write('(');
|
| - bool first = true;
|
| - ParameterKind lastKind = ParameterKind.REQUIRED;
|
| - for (var parameter in parameters) {
|
| - if (!first) {
|
| - buffer.write(', ');
|
| - }
|
| - if (lastKind != parameter.parameterKind) {
|
| - if (parameter.parameterKind == ParameterKind.POSITIONAL) {
|
| - buffer.write('[');
|
| - } else if (parameter.parameterKind == ParameterKind.NAMED) {
|
| - buffer.write('{');
|
| - }
|
| - }
|
| - if (parameter.parameterKind == ParameterKind.NAMED) {
|
| - buffer.write(parameter.name);
|
| - buffer.write(': ');
|
| - }
|
| - _appendType(buffer, parameter.type);
|
| - lastKind = parameter.parameterKind;
|
| - first = false;
|
| - }
|
| - if (lastKind == ParameterKind.POSITIONAL) {
|
| - buffer.write(']');
|
| - } else if (lastKind == ParameterKind.NAMED) {
|
| - buffer.write('}');
|
| - }
|
| - buffer.write(')');
|
| + void visitUnit(TypeProvider typeProvider, CompilationUnit unit,
|
| + fasta.ValidatingInstrumentation validation, Uri uri) {
|
| + unit.accept(new _InstrumentationVisitor(validation, uri));
|
| }
|
| -
|
| - void _appendType(StringBuffer buffer, DartType type) {
|
| - if (type is FunctionType) {
|
| - if (type.typeFormals.isNotEmpty) {
|
| - _appendTypeFormals(buffer, type.typeFormals);
|
| - }
|
| - _appendParameters(buffer, type.parameters);
|
| - buffer.write(' -> ');
|
| - _appendType(buffer, type.returnType);
|
| - } else if (type is InterfaceType) {
|
| - ClassElement element = type.element;
|
| - elementNamer.appendElementName(buffer, element);
|
| - _appendTypeArguments(buffer, type.typeArguments);
|
| - } else if (type.isBottom) {
|
| - buffer.write('<BottomType>');
|
| - } else if (type is TypeParameterType) {
|
| - elementNamer.appendElementName(buffer, type.element);
|
| - } else {
|
| - buffer.write(type.toString());
|
| - }
|
| - }
|
| -
|
| - void _appendTypeArguments(StringBuffer buffer, List<DartType> typeArguments) {
|
| - _appendList<DartType>(buffer, '<', '>', typeArguments, ', ',
|
| - (type) => _appendType(buffer, type));
|
| - }
|
| -
|
| - void _appendTypeFormals(
|
| - StringBuffer buffer, List<TypeParameterElement> typeFormals) {
|
| - _appendList<TypeParameterElement>(buffer, '<', '>', typeFormals, ', ',
|
| - (formal) {
|
| - buffer.write(formal.name);
|
| - buffer.write(' extends ');
|
| - if (formal.bound == null) {
|
| - buffer.write('Object');
|
| - } else {
|
| - _appendType(buffer, formal.bound);
|
| - }
|
| - });
|
| - }
|
| -}
|
| -
|
| -/**
|
| - * Instance of [InstrumentationValue] describing a list of [DartType]s.
|
| - */
|
| -class _InstrumentationValueForTypeArgs extends fasta.InstrumentationValue {
|
| - final List<DartType> types;
|
| - final _ElementNamer elementNamer;
|
| -
|
| - const _InstrumentationValueForTypeArgs(this.types, this.elementNamer);
|
| -
|
| - @override
|
| - String toString() => types
|
| - .map((type) =>
|
| - new _InstrumentationValueForType(type, elementNamer).toString())
|
| - .join(', ');
|
| }
|
|
|
| /**
|
| @@ -346,7 +46,7 @@ class _InstrumentationValueForTypeArgs extends fasta.InstrumentationValue {
|
| class _InstrumentationVisitor extends RecursiveAstVisitor<Null> {
|
| final fasta.Instrumentation _instrumentation;
|
| final Uri uri;
|
| - _ElementNamer elementNamer = new _ElementNamer(null);
|
| + ElementNamer elementNamer = new ElementNamer(null);
|
|
|
| _InstrumentationVisitor(this._instrumentation, this.uri);
|
|
|
| @@ -357,7 +57,7 @@ class _InstrumentationVisitor extends RecursiveAstVisitor<Null> {
|
|
|
| @override
|
| visitConstructorDeclaration(ConstructorDeclaration node) {
|
| - _ElementNamer oldElementNamer = elementNamer;
|
| + ElementNamer oldElementNamer = elementNamer;
|
| if (node.factoryKeyword != null) {
|
| // Factory constructors are represented in kernel as static methods, so
|
| // their type parameters get replicated, e.g.:
|
| @@ -376,7 +76,7 @@ class _InstrumentationVisitor extends RecursiveAstVisitor<Null> {
|
| // }
|
| // So to match kernel behavior, we have to arrange for this renaming to
|
| // happen during output.
|
| - elementNamer = new _ElementNamer(node.element);
|
| + elementNamer = new ElementNamer(node.element);
|
| }
|
| super.visitConstructorDeclaration(node);
|
| elementNamer = oldElementNamer;
|
| @@ -404,7 +104,7 @@ class _InstrumentationVisitor extends RecursiveAstVisitor<Null> {
|
| uri,
|
| node.name.offset,
|
| isSetter ? 'topType' : 'returnType',
|
| - new _InstrumentationValueForType(
|
| + new InstrumentationValueForType(
|
| node.element.returnType, elementNamer));
|
| }
|
| var parameters = node.functionExpression.parameters;
|
| @@ -424,7 +124,7 @@ class _InstrumentationVisitor extends RecursiveAstVisitor<Null> {
|
| DartType type = node.staticType;
|
| if (type is FunctionType) {
|
| _instrumentation.record(uri, node.parameters.offset, 'returnType',
|
| - new _InstrumentationValueForType(type.returnType, elementNamer));
|
| + new InstrumentationValueForType(type.returnType, elementNamer));
|
| List<FormalParameter> parameters = node.parameters.parameters;
|
| for (int i = 0; i < parameters.length; i++) {
|
| FormalParameter parameter = parameters[i];
|
| @@ -569,7 +269,7 @@ class _InstrumentationVisitor extends RecursiveAstVisitor<Null> {
|
| DartType type = node.staticType;
|
| if (!identical(type, elementType)) {
|
| _instrumentation.record(uri, offset, 'promotedType',
|
| - new _InstrumentationValueForType(type, elementNamer));
|
| + new InstrumentationValueForType(type, elementNamer));
|
| }
|
| }
|
| }
|
| @@ -624,23 +324,23 @@ class _InstrumentationVisitor extends RecursiveAstVisitor<Null> {
|
| void _recordTarget(int offset, Element element) {
|
| if (element is ExecutableElement) {
|
| _instrumentation.record(uri, offset, 'target',
|
| - new _InstrumentationValueForExecutableElement(element, elementNamer));
|
| + new InstrumentationValueForExecutableElement(element, elementNamer));
|
| }
|
| }
|
|
|
| void _recordTopType(int offset, DartType type) {
|
| _instrumentation.record(uri, offset, 'topType',
|
| - new _InstrumentationValueForType(type, elementNamer));
|
| + new InstrumentationValueForType(type, elementNamer));
|
| }
|
|
|
| void _recordType(int offset, DartType type) {
|
| _instrumentation.record(uri, offset, 'type',
|
| - new _InstrumentationValueForType(type, elementNamer));
|
| + new InstrumentationValueForType(type, elementNamer));
|
| }
|
|
|
| void _recordTypeArguments(int offset, List<DartType> typeArguments) {
|
| _instrumentation.record(uri, offset, 'typeArgs',
|
| - new _InstrumentationValueForTypeArgs(typeArguments, elementNamer));
|
| + new InstrumentationValueForTypeArgs(typeArguments, elementNamer));
|
| }
|
|
|
| /// Based on DDC code generator's `_recoverTypeArguments`
|
|
|