blob: c39a719f4fcc16bc629abf5d4c44363dd2b433a3 [file] [log] [blame]
// 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:async';
import 'dart:io' show File;
import 'package:analyzer/analyzer.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/fasta/ast_body_builder.dart';
import 'package:analyzer/src/generated/resolver.dart';
import "package:front_end/src/api_prototype/front_end.dart";
import "package:front_end/src/api_prototype/memory_file_system.dart";
import "package:front_end/src/base/processed_options.dart";
import "package:front_end/src/compute_platform_binaries_location.dart";
import 'package:front_end/src/fasta/compiler_context.dart';
import 'package:front_end/src/fasta/constant_context.dart';
import 'package:front_end/src/fasta/dill/dill_target.dart';
import "package:front_end/src/fasta/fasta_codes.dart";
import 'package:front_end/src/fasta/kernel/body_builder.dart' hide Identifier;
import 'package:front_end/src/fasta/kernel/forest.dart';
import 'package:front_end/src/fasta/kernel/kernel_builder.dart';
import "package:front_end/src/fasta/kernel/kernel_target.dart";
import 'package:front_end/src/fasta/modifier.dart' as Modifier;
import 'package:front_end/src/fasta/parser/parser.dart';
import 'package:front_end/src/fasta/scanner.dart';
import 'package:front_end/src/fasta/ticker.dart';
import 'package:front_end/src/fasta/type_inference/type_inferrer.dart';
import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart';
import 'package:front_end/src/fasta/uri_translator_impl.dart';
import 'package:kernel/class_hierarchy.dart' as kernel;
import 'package:kernel/core_types.dart' as kernel;
import 'package:kernel/kernel.dart' as kernel;
import '../../generated/parser_test.dart';
import '../../generated/test_support.dart';
/**
* Implementation of [AbstractParserTestCase] specialized for testing building
* Analyzer AST using the fasta [Forest] API.
*/
class FastaBodyBuilderTestCase extends Object
with ParserTestHelpers
implements AbstractParserTestCase {
// TODO(danrubel): Consider HybridFileSystem.
static final MemoryFileSystem fs =
new MemoryFileSystem(Uri.parse("org-dartlang-test:///"));
/// The custom URI used to locate the dill file in the MemoryFileSystem.
static final Uri sdkSummary = fs.currentDirectory.resolve("vm_platform.dill");
/// The in memory test code URI
static final Uri entryPoint = fs.currentDirectory.resolve("main.dart");
static ProcessedOptions options;
static KernelTarget kernelTarget;
static TypeProvider _typeProvider;
final bool resolveTypes;
FastaBodyBuilderTestCase(this.resolveTypes);
TypeProvider get typeProvider => _typeProvider;
@override
void assertNoErrors() {
// TODO(brianwilkerson) Implement this.
}
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
@override
Expression parseAdditiveExpression(String code) {
return parseExpression(code);
}
@override
Expression parseAssignableExpression(String code, bool primaryAllowed) {
return parseExpression(code);
}
@override
Expression parseAssignableSelector(String code, bool optional,
{bool allowConditional: true}) {
return parseExpression(code);
}
@override
AwaitExpression parseAwaitExpression(String code) {
return parseExpression(code);
}
@override
Expression parseBitwiseAndExpression(String code) {
return parseExpression(code);
}
@override
Expression parseBitwiseOrExpression(String code) {
return parseExpression(code);
}
@override
Expression parseBitwiseXorExpression(String code) {
return parseExpression(code);
}
@override
Expression parseCascadeSection(String code) {
return parseExpression(code);
}
@override
CompilationUnit parseCompilationUnit(String source,
{List<ErrorCode> codes, List<ExpectedError> errors}) {
return _parse(source, (parser, token) => parser.parseUnit(token.next));
}
@override
ConditionalExpression parseConditionalExpression(String code) {
return parseExpression(code);
}
@override
Expression parseConstExpression(String code) {
return parseExpression(code);
}
@override
ConstructorInitializer parseConstructorInitializer(String code) {
throw new UnimplementedError();
}
@override
CompilationUnit parseDirectives(String source,
[List<ErrorCode> errorCodes = const <ErrorCode>[]]) {
throw new UnimplementedError();
}
@override
BinaryExpression parseEqualityExpression(String code) {
return parseExpression(code);
}
@override
Expression parseExpression(String source,
{List<ErrorCode> codes,
List<ExpectedError> errors,
int expectedEndOffset}) {
// TODO(brianwilkerson) Check error codes.
return _parse(source, (parser, token) => parser.parseExpression(token));
}
@override
List<Expression> parseExpressionList(String code) {
throw new UnimplementedError();
}
@override
Expression parseExpressionWithoutCascade(String code) {
return parseExpression(code);
}
@override
FormalParameter parseFormalParameter(String code, ParameterKind kind,
{List<ErrorCode> errorCodes: const <ErrorCode>[]}) {
throw new UnimplementedError();
}
@override
FormalParameterList parseFormalParameterList(String code,
{bool inFunctionType: false,
List<ErrorCode> errorCodes: const <ErrorCode>[],
List<ExpectedError> errors}) {
throw new UnimplementedError();
}
@override
CompilationUnitMember parseFullCompilationUnitMember() {
throw new UnimplementedError();
}
@override
Directive parseFullDirective() {
throw new UnimplementedError();
}
@override
FunctionExpression parseFunctionExpression(String code) {
return parseExpression(code);
}
@override
InstanceCreationExpression parseInstanceCreationExpression(
String code, Token newToken) {
return parseExpression(code);
}
@override
ListLiteral parseListLiteral(
Token token, String typeArgumentsCode, String code) {
return parseExpression(code);
}
@override
TypedLiteral parseListOrMapLiteral(Token modifier, String code) {
return parseExpression(code);
}
@override
Expression parseLogicalAndExpression(String code) {
return parseExpression(code);
}
@override
Expression parseLogicalOrExpression(String code) {
return parseExpression(code);
}
@override
MapLiteral parseMapLiteral(
Token token, String typeArgumentsCode, String code) {
return parseExpression(code);
}
@override
MapLiteralEntry parseMapLiteralEntry(String code) {
throw new UnimplementedError();
}
@override
Expression parseMultiplicativeExpression(String code) {
return parseExpression(code);
}
@override
InstanceCreationExpression parseNewExpression(String code) {
return parseExpression(code);
}
@override
NormalFormalParameter parseNormalFormalParameter(String code,
{bool inFunctionType: false,
List<ErrorCode> errorCodes: const <ErrorCode>[]}) {
throw new UnimplementedError();
}
@override
Expression parsePostfixExpression(String code) {
return parseExpression(code);
}
@override
Identifier parsePrefixedIdentifier(String code) {
return parseExpression(code);
}
@override
Expression parsePrimaryExpression(String code,
{int expectedEndOffset, List<ExpectedError> errors}) {
return parseExpression(code,
expectedEndOffset: expectedEndOffset, errors: errors);
}
@override
Expression parseRelationalExpression(String code) {
return parseExpression(code);
}
@override
RethrowExpression parseRethrowExpression(String code) {
return parseExpression(code);
}
@override
BinaryExpression parseShiftExpression(String code) {
return parseExpression(code);
}
@override
SimpleIdentifier parseSimpleIdentifier(String code) {
return parseExpression(code);
}
@override
Statement parseStatement(String source,
{bool enableLazyAssignmentOperators, int expectedEndOffset}) {
// TODO(brianwilkerson) Check error codes.
return _parse(source, (parser, token) => parser.parseStatement(token));
}
@override
Expression parseStringLiteral(String code) {
return parseExpression(code);
}
@override
SymbolLiteral parseSymbolLiteral(String code) {
return parseExpression(code);
}
@override
Expression parseThrowExpression(String code) {
return parseExpression(code);
}
@override
Expression parseThrowExpressionWithoutCascade(String code) {
return parseExpression(code);
}
@override
PrefixExpression parseUnaryExpression(String code) {
return parseExpression(code);
}
@override
VariableDeclarationList parseVariableDeclarationList(String source) {
throw new UnimplementedError();
}
Future setUp() async {
// TODO(danrubel): Tear down once all tests in group have been run.
if (options != null) {
return;
}
// Read the dill file containing kernel platform summaries into memory.
List<int> sdkSummaryBytes = await new File.fromUri(
computePlatformBinariesLocation().resolve("vm_platform.dill"))
.readAsBytes();
fs.entityForUri(sdkSummary).writeAsBytesSync(sdkSummaryBytes);
final CompilerOptions optionBuilder = new CompilerOptions()
..strongMode = false // TODO(danrubel): enable strong mode.
..reportMessages = true
..verbose = false
..fileSystem = fs
..sdkSummary = sdkSummary
..onProblem = (FormattedMessage problem, Severity severity,
List<FormattedMessage> context) {
// TODO(danrubel): Capture problems and check against expectations.
// print(problem.formatted);
};
options = new ProcessedOptions(optionBuilder, false, [entryPoint]);
UriTranslatorImpl uriTranslator = await options.getUriTranslator();
await CompilerContext.runWithOptions(options, (CompilerContext c) async {
DillTarget dillTarget = new DillTarget(
new Ticker(isVerbose: false), uriTranslator, options.target);
kernelTarget = new KernelTarget(fs, true, dillTarget, uriTranslator);
// Load the dill file containing platform code.
dillTarget.loader.read(Uri.parse('dart:core'), -1, fileUri: sdkSummary);
kernel.Component sdkComponent =
kernel.loadComponentFromBytes(sdkSummaryBytes);
dillTarget.loader
.appendLibraries(sdkComponent, byteCount: sdkSummaryBytes.length);
await dillTarget.buildOutlines();
await kernelTarget.buildOutlines();
kernelTarget.computeCoreTypes();
assert(kernelTarget.loader.coreTypes != null);
// Initialize the typeProvider if types should be resolved.
Map<String, Element> map = <String, Element>{};
var coreTypes = kernelTarget.loader.coreTypes;
for (var coreType in [
coreTypes.boolClass,
coreTypes.doubleClass,
coreTypes.functionClass,
coreTypes.futureClass,
coreTypes.futureOrClass,
coreTypes.intClass,
coreTypes.iterableClass,
coreTypes.iteratorClass,
coreTypes.listClass,
coreTypes.mapClass,
coreTypes.nullClass,
coreTypes.numClass,
coreTypes.objectClass,
coreTypes.stackTraceClass,
coreTypes.streamClass,
coreTypes.stringClass,
coreTypes.symbolClass,
coreTypes.typeClass
]) {
map[coreType.name] = _buildElement(coreType);
}
Namespace namespace = new Namespace(map);
_typeProvider = new TypeProviderImpl.forNamespaces(namespace, namespace);
});
}
Element _buildElement(kernel.Class coreType) {
ClassElementImpl element =
new ClassElementImpl(coreType.name, coreType.fileOffset);
element.typeParameters = coreType.typeParameters.map((parameter) {
TypeParameterElementImpl element =
new TypeParameterElementImpl(parameter.name, parameter.fileOffset);
element.type = new TypeParameterTypeImpl(element);
return element;
}).toList();
return element;
}
T _parse<T>(
String source, void parseFunction(Parser parser, Token previousToken)) {
ScannerResult scan = scanString(source);
return CompilerContext.runWithOptions(options, (CompilerContext c) {
KernelLibraryBuilder library = new KernelLibraryBuilder(
entryPoint,
entryPoint,
kernelTarget.loader,
null /* actualOrigin */,
null /* enclosingLibrary */,
);
List<KernelTypeVariableBuilder> typeVariableBuilders =
<KernelTypeVariableBuilder>[];
List<KernelFormalParameterBuilder> formalParameterBuilders =
<KernelFormalParameterBuilder>[];
KernelProcedureBuilder procedureBuilder = new KernelProcedureBuilder(
null /* metadata */,
Modifier.staticMask /* or Modifier.varMask */,
kernelTarget.dynamicType,
"analyzerTest",
typeVariableBuilders,
formalParameterBuilders,
kernel.ProcedureKind.Method,
library,
-1 /* charOffset */,
-1 /* charOpenParenOffset */,
-1 /* charEndOffset */);
TypeInferrerDisabled typeInferrer =
new TypeInferrerDisabled(new TypeSchemaEnvironment(
kernelTarget.loader.coreTypes,
kernelTarget.loader.hierarchy,
// TODO(danrubel): Enable strong mode.
false /* strong mode */,
));
BodyBuilder builder = new AstBodyBuilder(
library,
procedureBuilder,
library.scope,
procedureBuilder.computeFormalParameterScope(library.scope),
kernelTarget.loader.hierarchy,
kernelTarget.loader.coreTypes,
null /* classBuilder */,
false /* isInstanceMember */,
null /* uri */,
typeInferrer,
typeProvider,
)..constantContext = ConstantContext.none; // .inferred ?
Parser parser = new Parser(builder);
parseFunction(parser, parser.syntheticPreviousToken(scan.tokens));
return builder.pop();
});
}
}