| // 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/parser.dart' as analyzer; |
| 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/forest.dart' hide Identifier; |
| 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/async_modifier.dart'; |
| 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 'package:test/test.dart'; |
| |
| import '../../generated/parser_test.dart'; |
| import '../../generated/test_support.dart'; |
| |
| 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; |
| } |
| |
| class CompilerTestContext extends CompilerContext { |
| KernelTarget kernelTarget; |
| TypeProvider _typeProvider; |
| |
| CompilerTestContext(ProcessedOptions options) : super(options); |
| |
| Uri get entryPoint => options.inputs.single; |
| |
| static Future<T> runWithTestOptions<T>( |
| Future<T> action(CompilerTestContext c)) async { |
| // TODO(danrubel): Consider HybridFileSystem. |
| final MemoryFileSystem fs = |
| new MemoryFileSystem(Uri.parse("org-dartlang-test:///")); |
| |
| /// The custom URI used to locate the dill file in the MemoryFileSystem. |
| final Uri sdkSummary = fs.currentDirectory.resolve("vm_platform.dill"); |
| |
| /// The in memory test code URI |
| final Uri entryPoint = fs.currentDirectory.resolve("main.dart"); |
| |
| // 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); |
| }; |
| |
| final ProcessedOptions options = |
| new ProcessedOptions(optionBuilder, [entryPoint]); |
| |
| UriTranslatorImpl uriTranslator = await options.getUriTranslator(); |
| |
| return await new CompilerTestContext(options) |
| .runInContext<T>((CompilerContext _c) async { |
| CompilerTestContext c = _c; |
| DillTarget dillTarget = new DillTarget( |
| new Ticker(isVerbose: false), uriTranslator, options.target); |
| |
| c.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 c.kernelTarget.buildOutlines(); |
| c.kernelTarget.computeCoreTypes(); |
| assert(c.kernelTarget.loader.coreTypes != null); |
| |
| // Initialize the typeProvider if types should be resolved. |
| Map<String, Element> map = <String, Element>{}; |
| var coreTypes = c.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); |
| c._typeProvider = |
| new TypeProviderImpl.forNamespaces(namespace, namespace); |
| |
| T result; |
| Completer<T> completer = new Completer<T>(); |
| // Since we're using `package:test_reflective_loader`, we can't rely on |
| // normal async behavior, as `defineReflectiveSuite` doesn't return a |
| // future. However, since it's built on top of `package:test`, we can |
| // obtain a future that completes when all the tests are done using |
| // `tearDownAll`. This allows this function to complete no earlier than |
| // when the tests are done. This is important, as we don't want to call |
| // `CompilerContext.clear` before then. |
| tearDownAll(() => completer.complete(result)); |
| result = await action(c); |
| return completer.future; |
| }); |
| } |
| |
| static CompilerTestContext get current => CompilerContext.current; |
| } |
| |
| /// Implementation of [AbstractParserTestCase] specialized for testing building |
| /// Analyzer AST using the fasta [Forest] API. |
| class FastaBodyBuilderTestCase extends Object |
| with ParserTestHelpers |
| implements AbstractParserTestCase { |
| final bool resolveTypes; |
| |
| String content; |
| |
| /// The expected offset of the next token to be parsed after the parser has |
| /// finished parsing, or `null` (the default) if EOF is expected. |
| int expectedEndOffset; |
| |
| @override |
| void set enableGenericMethodComments(_) { |
| // Ignored. |
| } |
| |
| FastaBodyBuilderTestCase(this.resolveTypes); |
| |
| analyzer.Parser get parser => new ParserProxy(this); |
| |
| TypeProvider get typeProvider => CompilerTestContext.current._typeProvider; |
| |
| bool get usingFastaParser => true; |
| |
| @override |
| void assertNoErrors() { |
| // TODO(brianwilkerson) Implement this. |
| } |
| |
| void createParser(String content, {int expectedEndOffset}) { |
| this.content = content; |
| this.expectedEndOffset = expectedEndOffset; |
| } |
| |
| @override |
| void expectNotNullIfNoErrors(Object result) { |
| // TODO(brianwilkerson) Implement this. |
| } |
| |
| @override |
| ExpectedError expectedError(ErrorCode code, int offset, int length) { |
| return new ExpectedError(code, offset, length); |
| } |
| |
| 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, inAsync: true); |
| } |
| |
| @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>[]]) { |
| return parseCompilationUnit(content, codes: errorCodes); |
| } |
| |
| @override |
| BinaryExpression parseEqualityExpression(String code) { |
| return parseExpression(code); |
| } |
| |
| @override |
| Expression parseExpression(String source, |
| {List<ErrorCode> codes, |
| List<ExpectedError> errors, |
| int expectedEndOffset, |
| bool inAsync: false, |
| bool inCatchBlock: false}) { |
| // TODO(brianwilkerson) Check error codes. |
| Object result = _parse( |
| source, (parser, token) => parser.parseExpression(token), |
| inAsync: inAsync, inCatchBlock: inCatchBlock); |
| if (result is Generator) { |
| result = (result as Generator).buildForEffect(); |
| } |
| if (result is! Expression) { |
| throw new StateError('Expected Expression, found ${result.runtimeType}'); |
| } |
| return result; |
| } |
| |
| @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() { |
| CompilationUnit unit = parseCompilationUnit(content); |
| expect(unit.directives, hasLength(0)); |
| expect(unit.declarations, hasLength(1)); |
| return unit.declarations[0]; |
| } |
| |
| @override |
| Directive parseFullDirective() { |
| CompilationUnit unit = parseCompilationUnit(content); |
| expect(unit.directives, hasLength(1)); |
| expect(unit.declarations, hasLength(0)); |
| return unit.directives[0]; |
| } |
| |
| @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) { |
| StringBuffer buffer = new StringBuffer(); |
| if (token != null) { |
| buffer.write(token.lexeme); |
| buffer.write(' '); |
| } |
| if (typeArgumentsCode != null) { |
| buffer.write(typeArgumentsCode); |
| } |
| buffer.write(code); |
| return parseExpression(buffer.toString()); |
| } |
| |
| @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) { |
| StringBuffer buffer = new StringBuffer(); |
| if (token != null) { |
| buffer.write(token.lexeme); |
| buffer.write(' '); |
| } |
| if (typeArgumentsCode != null) { |
| buffer.write(typeArgumentsCode); |
| } |
| buffer.write(code); |
| return parseExpression(buffer.toString()); |
| } |
| |
| @override |
| MapLiteralEntry parseMapLiteralEntry(String code) { |
| Expression expression = parseExpression('{$code}'); |
| expect(expression, new isInstanceOf<MapLiteral>()); |
| MapLiteral literal = expression; |
| expect(literal.entries, hasLength(1)); |
| return literal.entries[0]; |
| } |
| |
| @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) { |
| Statement statement = parseStatement(code, inCatchBlock: true); |
| expect(statement, new isInstanceOf<ExpressionStatement>()); |
| Expression expression = (statement as ExpressionStatement).expression; |
| expect(expression, new isInstanceOf<RethrowExpression>()); |
| return expression; |
| } |
| |
| @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, |
| bool inCatchBlock: true}) { |
| // TODO(brianwilkerson) Check error codes. |
| return _parse(source, (parser, token) => parser.parseStatement(token), |
| inCatchBlock: inCatchBlock); |
| } |
| |
| @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) { |
| CompilationUnit unit = parseCompilationUnit(''' |
| f() { |
| $source; |
| } |
| '''); |
| FunctionDeclaration function = unit.declarations[0]; |
| BlockFunctionBody body = function.functionExpression.body; |
| VariableDeclarationStatement statement = body.block.statements[0]; |
| return statement.variables; |
| } |
| |
| T _parse<T>( |
| String source, void parseFunction(Parser parser, Token previousToken), |
| {bool inAsync: false, bool inCatchBlock: false}) { |
| ScannerResult scan = scanString(source); |
| |
| CompilerTestContext c = CompilerTestContext.current; |
| KernelLibraryBuilder library = new KernelLibraryBuilder( |
| c.entryPoint, |
| c.entryPoint, |
| c.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 */, |
| c.kernelTarget.dynamicType, |
| "analyzerTest", |
| typeVariableBuilders, |
| formalParameterBuilders, |
| kernel.ProcedureKind.Method, |
| library, |
| -1 /* charOffset */, |
| -1 /* charOpenParenOffset */, |
| -1 /* charEndOffset */); |
| |
| TypeInferrerDisabled typeInferrer = |
| new TypeInferrerDisabled(new TypeSchemaEnvironment( |
| c.kernelTarget.loader.coreTypes, |
| c.kernelTarget.loader.hierarchy, |
| // TODO(danrubel): Enable strong mode. |
| false /* strong mode */, |
| )); |
| |
| AstBodyBuilder builder = new AstBodyBuilder( |
| library, |
| procedureBuilder, |
| new UnlinkedScope(), |
| null, |
| c.kernelTarget.loader.hierarchy, |
| c.kernelTarget.loader.coreTypes, |
| null /* classBuilder */, |
| false /* isInstanceMember */, |
| null /* uri */, |
| typeInferrer, |
| typeProvider, |
| )..constantContext = ConstantContext.none; // .inferred ? |
| |
| Parser parser = new Parser(builder); |
| if (inAsync) { |
| parser.asyncState = AsyncModifier.Async; |
| } |
| if (inCatchBlock) { |
| builder.inCatchBlock = inCatchBlock; |
| } |
| parseFunction(parser, parser.syntheticPreviousToken(scan.tokens)); |
| // TODO(brianwilkerson) Check `expectedEndOffset` if it is not `null`. |
| return builder.pop(); |
| } |
| } |
| |
| /// A parser that can be used by [FastaBodyBuilderTestCase] to support the tests |
| /// that still call methods on the parser directly. |
| class ParserProxy implements analyzer.Parser { |
| final FastaBodyBuilderTestCase testCase; |
| |
| ParserProxy(this.testCase); |
| |
| @override |
| noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); |
| |
| @override |
| Annotation parseAnnotation() { |
| CompilationUnit unit = |
| testCase.parseCompilationUnit('${testCase.content} var v;'); |
| expect(unit.directives, hasLength(0)); |
| expect(unit.declarations, hasLength(1)); |
| expect( |
| unit.declarations[0], new isInstanceOf<TopLevelVariableDeclaration>()); |
| TopLevelVariableDeclaration declaration = unit.declarations[0]; |
| expect(declaration.metadata, hasLength(1)); |
| return declaration.metadata[0]; |
| } |
| |
| @override |
| ArgumentList parseArgumentList() { |
| Expression expression = testCase.parseExpression('f${testCase.content}'); |
| expect(expression, new isInstanceOf<MethodInvocation>()); |
| MethodInvocation invocation = expression; |
| return invocation.argumentList; |
| } |
| |
| @override |
| ClassMember parseClassMember(String className) { |
| CompilationUnit unit = testCase |
| .parseCompilationUnit('class $className { ${testCase.content} }'); |
| expect(unit.directives, hasLength(0)); |
| expect(unit.declarations, hasLength(1)); |
| expect(unit.declarations[0], new isInstanceOf<ClassDeclaration>()); |
| ClassDeclaration classDeclaration = unit.declarations[0]; |
| expect(classDeclaration.members, hasLength(1)); |
| return classDeclaration.members[0]; |
| } |
| |
| @override |
| List<Combinator> parseCombinators() { |
| CompilationUnit unit = testCase |
| .parseCompilationUnit('import "file.dart" ${testCase.content};'); |
| expect(unit.directives, hasLength(1)); |
| expect(unit.declarations, hasLength(0)); |
| expect(unit.directives[0], new isInstanceOf<LibraryDirective>()); |
| ImportDirective directive = unit.directives[0]; |
| return directive.combinators; |
| } |
| |
| @override |
| CommentReference parseCommentReference( |
| String referenceSource, int sourceOffset) { |
| // TODO(brianwilkerson) Implement this. |
| throw new UnimplementedError(); |
| } |
| |
| @override |
| CompilationUnit parseCompilationUnit2() { |
| return testCase.parseCompilationUnit(testCase.content); |
| } |
| |
| @override |
| Configuration parseConfiguration() { |
| CompilationUnit unit = testCase |
| .parseCompilationUnit('import "file.dart" ${testCase.content};'); |
| expect(unit.directives, hasLength(1)); |
| expect(unit.declarations, hasLength(0)); |
| expect(unit.directives[0], new isInstanceOf<LibraryDirective>()); |
| ImportDirective directive = unit.directives[0]; |
| expect(directive.configurations, hasLength(1)); |
| return directive.configurations[0]; |
| } |
| |
| @override |
| DottedName parseDottedName() { |
| CompilationUnit unit = testCase.parseCompilationUnit( |
| 'import "file.dart" if (${testCase.content}) "file2.dart";'); |
| expect(unit.directives, hasLength(1)); |
| expect(unit.declarations, hasLength(0)); |
| expect(unit.directives[0], new isInstanceOf<LibraryDirective>()); |
| ImportDirective directive = unit.directives[0]; |
| expect(directive.configurations, hasLength(1)); |
| return directive.configurations[0].name; |
| } |
| |
| @override |
| ExtendsClause parseExtendsClause() { |
| CompilationUnit unit = |
| testCase.parseCompilationUnit('class C ${testCase.content} {}'); |
| expect(unit.directives, hasLength(0)); |
| expect(unit.declarations, hasLength(1)); |
| expect(unit.declarations[0], new isInstanceOf<ClassDeclaration>()); |
| ClassDeclaration classDeclaration = unit.declarations[0]; |
| return classDeclaration.extendsClause; |
| } |
| |
| @override |
| analyzer.FinalConstVarOrType parseFinalConstVarOrType(bool optional, |
| {bool inFunctionType: false}) { |
| // TODO(brianwilkerson) Implement this or re-write the tests. |
| throw new UnimplementedError(); |
| } |
| |
| @override |
| FormalParameterList parseFormalParameterList({bool inFunctionType: false}) { |
| CompilationUnit unit = |
| testCase.parseCompilationUnit('f${testCase.content} {}'); |
| expect(unit.directives, hasLength(0)); |
| expect(unit.declarations, hasLength(1)); |
| expect(unit.declarations[0], new isInstanceOf<FunctionDeclaration>()); |
| FunctionDeclaration function = unit.declarations[0]; |
| return function.functionExpression.parameters; |
| } |
| |
| @override |
| FunctionBody parseFunctionBody(bool mayBeEmpty, |
| analyzer.ParserErrorCode emptyErrorCode, bool inExpression) { |
| CompilationUnit unit = |
| testCase.parseCompilationUnit('f() ${testCase.content}'); |
| expect(unit.directives, hasLength(0)); |
| expect(unit.declarations, hasLength(1)); |
| expect(unit.declarations[0], new isInstanceOf<FunctionDeclaration>()); |
| FunctionDeclaration declaration = unit.declarations[0]; |
| return declaration.functionExpression.body; |
| } |
| |
| @override |
| ImplementsClause parseImplementsClause() { |
| CompilationUnit unit = |
| testCase.parseCompilationUnit('class C ${testCase.content} {}'); |
| expect(unit.directives, hasLength(0)); |
| expect(unit.declarations, hasLength(1)); |
| expect(unit.declarations[0], new isInstanceOf<ClassDeclaration>()); |
| ClassDeclaration classDeclaration = unit.declarations[0]; |
| return classDeclaration.implementsClause; |
| } |
| |
| @override |
| analyzer.Modifiers parseModifiers() { |
| // TODO(brianwilkerson) Implement this or re-write the tests (this might |
| // need context to create the right kind of declaration for the modifiers). |
| throw new UnimplementedError(); |
| } |
| |
| @override |
| Expression parseMultiplicativeExpression() { |
| return testCase.parseExpression(testCase.content); |
| } |
| |
| @override |
| Expression parsePrimaryExpression() { |
| return testCase.parseExpression(testCase.content); |
| } |
| |
| @override |
| SimpleIdentifier parseSimpleIdentifier( |
| {bool allowKeyword: false, bool isDeclaration: false}) { |
| return testCase.parseExpression(testCase.content); |
| } |
| |
| @override |
| Statement parseStatement2() { |
| return testCase.parseStatement(testCase.content); |
| } |
| |
| @override |
| TypeAnnotation parseTypeAnnotation(bool inExpression) { |
| if (inExpression) { |
| // TODO(brianwilkerson) As far as I can see, this path is not used. |
| throw new UnimplementedError(); |
| } |
| CompilationUnit unit = |
| testCase.parseCompilationUnit('${testCase.content} x;'); |
| expect(unit.directives, hasLength(0)); |
| expect(unit.declarations, hasLength(1)); |
| expect( |
| unit.declarations[0], new isInstanceOf<TopLevelVariableDeclaration>()); |
| TopLevelVariableDeclaration variable = unit.declarations[0]; |
| return variable.variables.type; |
| } |
| |
| @override |
| TypeArgumentList parseTypeArgumentList() { |
| CompilationUnit unit = |
| testCase.parseCompilationUnit('C${testCase.content} c;'); |
| expect(unit.directives, hasLength(0)); |
| expect(unit.declarations, hasLength(1)); |
| expect( |
| unit.declarations[0], new isInstanceOf<TopLevelVariableDeclaration>()); |
| TopLevelVariableDeclaration variable = unit.declarations[0]; |
| return (variable.variables.type as TypeName).typeArguments; |
| } |
| |
| @override |
| TypeName parseTypeName(bool inExpression) { |
| return parseTypeAnnotation(inExpression) as TypeName; |
| } |
| |
| @override |
| TypeParameter parseTypeParameter() { |
| CompilationUnit unit = |
| testCase.parseCompilationUnit('class C<${testCase.content}> {}'); |
| expect(unit.directives, hasLength(0)); |
| expect(unit.declarations, hasLength(1)); |
| expect(unit.declarations[0], new isInstanceOf<ClassDeclaration>()); |
| ClassDeclaration classDeclaration = unit.declarations[0]; |
| return classDeclaration.typeParameters.typeParameters[0]; |
| } |
| |
| @override |
| Expression parseUnaryExpression() { |
| return testCase.parseExpression(testCase.content); |
| } |
| |
| @override |
| WithClause parseWithClause() { |
| CompilationUnit unit = |
| testCase.parseCompilationUnit('class C ${testCase.content} {}'); |
| expect(unit.directives, hasLength(0)); |
| expect(unit.declarations, hasLength(1)); |
| expect(unit.declarations[0], new isInstanceOf<ClassDeclaration>()); |
| ClassDeclaration classDeclaration = unit.declarations[0]; |
| return classDeclaration.withClause; |
| } |
| } |