| Index: pkg/fasta/lib/src/source/outline_builder.dart
|
| diff --git a/pkg/fasta/lib/src/source/outline_builder.dart b/pkg/fasta/lib/src/source/outline_builder.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..7a51e55bc964d1f6f8dad0d835f0aee3b0cba39a
|
| --- /dev/null
|
| +++ b/pkg/fasta/lib/src/source/outline_builder.dart
|
| @@ -0,0 +1,477 @@
|
| +// Copyright (c) 2016, 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.
|
| +
|
| +library fasta.outline_builder;
|
| +
|
| +import 'package:kernel/ast.dart' show
|
| + AsyncMarker,
|
| + ProcedureKind;
|
| +
|
| +import 'package:dart_parser/src/parser.dart' show
|
| + FormalParameterType,
|
| + optional;
|
| +
|
| +import 'package:dart_scanner/src/token.dart' show
|
| + Token;
|
| +
|
| +import '../combinator.dart' show
|
| + Combinator;
|
| +
|
| +import '../errors.dart' show
|
| + internalError;
|
| +
|
| +import '../builder/builder.dart';
|
| +
|
| +import '../modifier.dart' show
|
| + Modifier;
|
| +
|
| +import 'source_library_builder.dart' show
|
| + SourceLibraryBuilder;
|
| +
|
| +import 'unhandled_listener.dart' show
|
| + NullValue,
|
| + Unhandled,
|
| + UnhandledListener;
|
| +
|
| +enum MethodBody {
|
| + Abstract,
|
| + Regular,
|
| + RedirectingFactoryBody,
|
| +}
|
| +
|
| +AsyncMarker asyncMarkerFromTokens(Token asyncToken, Token starToken) {
|
| + if (asyncToken == null || identical(asyncToken.stringValue, "sync")) {
|
| + if (starToken == null) {
|
| + return AsyncMarker.Sync;
|
| + } else {
|
| + assert(identical(starToken.stringValue, "*"));
|
| + return AsyncMarker.SyncStar;
|
| + }
|
| + } else if (identical(asyncToken.stringValue, "async")) {
|
| + if (starToken == null) {
|
| + return AsyncMarker.Async;
|
| + } else {
|
| + assert(identical(starToken.stringValue, "*"));
|
| + return AsyncMarker.AsyncStar;
|
| + }
|
| + } else {
|
| + return internalError("Unknown async modifier: $asyncToken");
|
| + }
|
| +}
|
| +
|
| +class OutlineBuilder extends UnhandledListener {
|
| + final SourceLibraryBuilder library;
|
| +
|
| + OutlineBuilder(this.library);
|
| +
|
| + Uri get uri => library.uri;
|
| +
|
| + void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
|
| + debugEvent("Metadata");
|
| + List arguments = pop();
|
| + String postfix = popIfNotNull(periodBeforeName);
|
| + List<TypeBuilder> typeArguments = pop();
|
| + if (arguments == null) {
|
| + String expression = pop();
|
| + push(new MetadataBuilder.fromExpression(expression, postfix));
|
| + } else {
|
| + String typeName = pop();
|
| + push(new MetadataBuilder.fromConstructor(
|
| + library.addConstructorReference(
|
| + typeName, typeArguments, postfix), arguments));
|
| + }
|
| + }
|
| +
|
| + void endHide(Token hideKeyword) {
|
| + debugEvent("Hide");
|
| + List<String> names = pop();
|
| + push(new Combinator.hide(names));
|
| + }
|
| +
|
| + void endShow(Token showKeyword) {
|
| + debugEvent("Show");
|
| + List<String> names = pop();
|
| + push(new Combinator.show(names));
|
| + }
|
| +
|
| + void endCombinators(int count) {
|
| + debugEvent("Combinators");
|
| + push(popList(count) ?? NullValue.Combinators);
|
| + }
|
| +
|
| + void endExport(Token exportKeyword, Token semicolon) {
|
| + debugEvent("Export");
|
| + List<Combinator> combinators = pop();
|
| + Unhandled conditionalUris = pop();
|
| + String uri = pop();
|
| + List<MetadataBuilder> metadata = pop();
|
| + library.addExport(metadata, uri, conditionalUris, combinators);
|
| + checkEmpty();
|
| + }
|
| +
|
| + void endImport(Token importKeyword, Token deferredKeyword, Token asKeyword,
|
| + Token semicolon) {
|
| + debugEvent("endImport");
|
| + List<Combinator> combinators = pop();
|
| + String prefix = popIfNotNull(asKeyword);
|
| + Unhandled conditionalUris = pop();
|
| + String uri = pop();
|
| + List<MetadataBuilder> metadata = pop();
|
| + library.addImport(metadata, uri, conditionalUris, prefix, combinators,
|
| + deferredKeyword != null);
|
| + checkEmpty();
|
| + }
|
| +
|
| + void endPart(Token partKeyword, Token semicolon) {
|
| + debugEvent("Part");
|
| + String uri = pop();
|
| + List<MetadataBuilder> metadata = pop();
|
| + library.addPart(metadata, uri);
|
| + checkEmpty();
|
| + }
|
| +
|
| + void handleOperatorName(Token operatorKeyword, Token token) {
|
| + debugEvent("OperatorName");
|
| + push(token.stringValue);
|
| + }
|
| +
|
| + void endIdentifierList(int count) {
|
| + debugEvent("endIdentifierList");
|
| + push(popList(count) ?? NullValue.IdentifierList);
|
| + }
|
| +
|
| + void handleQualified(Token period) {
|
| + debugEvent("handleQualified");
|
| + String name = pop();
|
| + String receiver = pop();
|
| + push("$receiver.$name");
|
| + }
|
| +
|
| + void endLibraryName(Token libraryKeyword, Token semicolon) {
|
| + debugEvent("endLibraryName");
|
| + String name = pop();
|
| + List<MetadataBuilder> metadata = pop();
|
| + library.name = name;
|
| + library.metadata = metadata;
|
| + }
|
| +
|
| + void beginClassDeclaration(Token token) {
|
| + library.beginNestedScope();
|
| + }
|
| +
|
| + void endClassDeclaration(int interfacesCount, Token beginToken,
|
| + Token extendsKeyword, Token implementsKeyword, Token endToken) {
|
| + debugEvent("endClassDeclaration");
|
| + List<TypeBuilder> interfaces = popList(interfacesCount);
|
| + TypeBuilder supertype = pop();
|
| + List<TypeVariableBuilder> typeVariables = pop();
|
| + String name = pop();
|
| + int modifiers = Modifier.validate(pop());
|
| + List<MetadataBuilder> metadata = pop();
|
| + library.addClass(
|
| + metadata, modifiers, name, typeVariables, supertype, interfaces);
|
| + checkEmpty();
|
| + }
|
| +
|
| + ProcedureKind computeProcedureKind(Token token) {
|
| + if (token == null) return ProcedureKind.Method;
|
| + if (optional("get", token)) return ProcedureKind.Getter;
|
| + if (optional("set", token)) return ProcedureKind.Setter;
|
| + return internalError("Unhandled: ${token.value}");
|
| + }
|
| +
|
| + ProcedureBuilder endTopLevelMethod(
|
| + Token beginToken, Token getOrSet, Token endToken) {
|
| + debugEvent("endTopLevelMethod");
|
| + MethodBody kind = pop();
|
| + AsyncMarker asyncModifier = pop();
|
| + List<FormalParameterBuilder> formals = pop();
|
| + List<TypeVariableBuilder> typeVariables = pop();
|
| + String name = pop();
|
| + TypeBuilder returnType = pop();
|
| + int modifiers = Modifier.validate(pop(),
|
| + isAbstract: kind == MethodBody.Abstract);
|
| + List<MetadataBuilder> metadata = pop();
|
| + checkEmpty();
|
| + return library.addProcedure(metadata, modifiers, returnType, name,
|
| + typeVariables, formals, asyncModifier, computeProcedureKind(getOrSet));
|
| + }
|
| +
|
| + void handleNoFunctionBody(Token token) {
|
| + debugEvent("NoFunctionBody");
|
| + push(MethodBody.Abstract);
|
| + }
|
| +
|
| + void skippedFunctionBody(Token token) {
|
| + debugEvent("skippedFunctionBody");
|
| + push(MethodBody.Regular);
|
| + }
|
| +
|
| + void endMethod(Token getOrSet, Token beginToken, Token endToken) {
|
| + debugEvent("Method");
|
| + MethodBody kind = pop();
|
| + if (kind == MethodBody.RedirectingFactoryBody) {
|
| + // This will cause an error later.
|
| + pop();
|
| + }
|
| + AsyncMarker asyncModifier = pop();
|
| + List<FormalParameterBuilder> formals = pop();
|
| + List<TypeVariableBuilder> typeVariables = pop();
|
| + String name = pop();
|
| + if (identical("-", name) && formals == null) {
|
| + name = "unary-";
|
| + }
|
| + TypeBuilder returnType = pop();
|
| + int modifiers = Modifier.validate(pop(),
|
| + isAbstract: kind == MethodBody.Abstract);
|
| + List<MetadataBuilder> metadata = pop();
|
| + library.addProcedure(metadata, modifiers, returnType, name, typeVariables,
|
| + formals, asyncModifier, computeProcedureKind(getOrSet));
|
| + }
|
| +
|
| + void endMixinApplication() {
|
| + debugEvent("MixinApplication");
|
| + List<TypeBuilder> mixins = pop();
|
| + TypeBuilder supertype = pop();
|
| + push(library.addMixinApplication(supertype, mixins));
|
| + }
|
| +
|
| + void beginNamedMixinApplication(Token token) {
|
| + library.beginNestedScope();
|
| + }
|
| +
|
| + void endNamedMixinApplication(
|
| + Token classKeyword, Token implementsKeyword, Token endToken) {
|
| + debugEvent("endNamedMixinApplication");
|
| + List<TypeBuilder> interfaces = popIfNotNull(implementsKeyword);
|
| + TypeBuilder mixinApplication = pop();
|
| + int modifiers = Modifier.validate(pop());
|
| + List<TypeVariableBuilder> typeVariables = pop();
|
| + String name = pop();
|
| + List<MetadataBuilder> metadata = pop();
|
| + library.addNamedMixinApplication(
|
| + metadata, name, typeVariables, modifiers, mixinApplication, interfaces);
|
| + checkEmpty();
|
| + }
|
| +
|
| + void endTypeArguments(int count, Token beginToken, Token endToken) {
|
| + debugEvent("TypeArguments");
|
| + push(popList(count) ?? NullValue.TypeArguments);
|
| + }
|
| +
|
| + void endType(Token beginToken, Token endToken) {
|
| + debugEvent("Type");
|
| + List<TypeBuilder> arguments = pop();
|
| + String name = pop();
|
| + push(library.addInterfaceType(name, arguments));
|
| + }
|
| +
|
| + void endTypeList(int count) {
|
| + debugEvent("TypeList");
|
| + push(popList(count) ?? NullValue.TypeList);
|
| + }
|
| +
|
| + void endTypeVariables(int count, Token beginToken, Token endToken) {
|
| + debugEvent("TypeVariables");
|
| + push(popList(count) ?? NullValue.TypeVariables);
|
| + }
|
| +
|
| + void handleVoidKeyword(Token token) {
|
| + debugEvent("VoidKeyword");
|
| + push(library.addVoidType());
|
| + }
|
| +
|
| + void endFormalParameter(Token thisKeyword) {
|
| + debugEvent("FormalParameter");
|
| + String name = pop();
|
| + TypeBuilder type = pop();
|
| + int modifiers = Modifier.validate(pop());
|
| + List<MetadataBuilder> metadata = pop();
|
| + push(library.addFormalParameter(metadata, modifiers, type, name,
|
| + thisKeyword != null));
|
| + }
|
| +
|
| + void handleValuedFormalParameter(Token equals, Token token) {
|
| + debugEvent("ValuedFormalParameter");
|
| + // Ignored for now.
|
| + }
|
| +
|
| + void handleFunctionTypedFormalParameter(Token token) {
|
| + debugEvent("FunctionTypedFormalParameter");
|
| + pop(); // Function type parameters.
|
| + pop(); // Type variables.
|
| + String name = pop();
|
| + pop(); // Return type.
|
| + push(NullValue.Type);
|
| + push(name);
|
| + }
|
| +
|
| + void endOptionalFormalParameters(
|
| + int count, Token beginToken, Token endToken) {
|
| + debugEvent("OptionalFormalParameters");
|
| + FormalParameterType kind = optional("{", beginToken)
|
| + ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL;
|
| + List parameters = popList(count);
|
| + for (FormalParameterBuilder parameter in parameters) {
|
| + parameter.kind = kind;
|
| + }
|
| + push(parameters);
|
| + }
|
| +
|
| + void endFormalParameters(int count, Token beginToken, Token endToken) {
|
| + debugEvent("FormalParameters");
|
| + List formals = popList(count);
|
| + if (formals != null && formals.isNotEmpty) {
|
| + var last = formals.last;
|
| + if (last is List) {
|
| + var newList =
|
| + new List<FormalParameterBuilder>(formals.length - 1 + last.length);
|
| + newList.setRange(0, formals.length - 1, formals);
|
| + newList.setRange(formals.length - 1, newList.length, last);
|
| + for (int i = 0; i < last.length; i++) {
|
| + newList[i + formals.length - 1] = last[i];
|
| + }
|
| + formals = newList;
|
| + }
|
| + }
|
| + if (formals != null) {
|
| + for (var formal in formals) {
|
| + if (formal is! FormalParameterBuilder) {
|
| + internalError(formals);
|
| + }
|
| + }
|
| + formals = new List<FormalParameterBuilder>.from(formals);
|
| + }
|
| + push(formals ?? NullValue.FormalParameters);
|
| + }
|
| +
|
| + void endEnum(Token enumKeyword, Token endBrace, int count) {
|
| + List<String> constants = popList(count);
|
| + String name = pop();
|
| + List<MetadataBuilder> metadata = pop();
|
| + library.addEnum(metadata, name, constants);
|
| + checkEmpty();
|
| + }
|
| +
|
| + void beginFunctionTypeAlias(Token token) {
|
| + library.beginNestedScope();
|
| + }
|
| +
|
| + void endFunctionTypeAlias(Token typedefKeyword, Token endToken) {
|
| + debugEvent("endFunctionTypeAlias");
|
| + List<FormalParameterBuilder> formals = pop();
|
| + List<TypeVariableBuilder> typeVariables = pop();
|
| + String name = pop();
|
| + TypeBuilder returnType = pop();
|
| + List<MetadataBuilder> metadata = pop();
|
| + library.addFunctionTypeAlias(
|
| + metadata, returnType, name, typeVariables, formals);
|
| + checkEmpty();
|
| + }
|
| +
|
| + void endTopLevelFields(int count, Token beginToken, Token endToken) {
|
| + debugEvent("endTopLevelFields");
|
| + List<String> names = popList(count);
|
| + TypeBuilder type = pop();
|
| + int modifiers = Modifier.validate(pop());
|
| + List<MetadataBuilder> metadata = pop();
|
| + library.addFields(metadata, modifiers, type, names);
|
| + checkEmpty();
|
| + }
|
| +
|
| + void endFields(int count, Token beginToken, Token endToken) {
|
| + debugEvent("Fields");
|
| + List<String> names = popList(count);
|
| + TypeBuilder type = pop();
|
| + int modifiers = Modifier.validate(pop());
|
| + List<MetadataBuilder> metadata = pop();
|
| + library.addFields(metadata, modifiers, type, names);
|
| + }
|
| +
|
| + void endTypeVariable(Token token, Token extendsOrSuper) {
|
| + debugEvent("endTypeVariable");
|
| + TypeBuilder bound = pop();
|
| + String name = pop();
|
| + push(library.addTypeVariable(name, bound));
|
| + }
|
| +
|
| + void endPartOf(Token partKeyword, Token semicolon) {
|
| + debugEvent("endPartOf");
|
| + String name = pop();
|
| + List<MetadataBuilder> metadata = pop();
|
| + library.addPartOf(metadata, name);
|
| + }
|
| +
|
| + void endConstructorReference(
|
| + Token start, Token periodBeforeName, Token endToken) {
|
| + debugEvent("ConstructorReference");
|
| + String suffix = popIfNotNull(periodBeforeName);
|
| + List<TypeBuilder> typeArguments = pop();
|
| + String name = pop();
|
| + push(library.addConstructorReference(name, typeArguments, suffix));
|
| + }
|
| +
|
| + void endFactoryMethod(Token beginToken, Token endToken) {
|
| + debugEvent("FactoryMethod");
|
| + MethodBody kind = pop();
|
| + ConstructorReferenceBuilder redirectionTarget;
|
| + if (kind == MethodBody.RedirectingFactoryBody) {
|
| + redirectionTarget = pop();
|
| + }
|
| + AsyncMarker asyncModifier = pop();
|
| + List<FormalParameterBuilder> formals = pop();
|
| + var name = pop();
|
| + List<MetadataBuilder> metadata = pop();
|
| + library.addFactoryMethod(metadata, name, formals, asyncModifier,
|
| + redirectionTarget);
|
| + }
|
| +
|
| + void endRedirectingFactoryBody(Token beginToken, Token endToken) {
|
| + debugEvent("RedirectingFactoryBody");
|
| + push(MethodBody.RedirectingFactoryBody);
|
| + }
|
| +
|
| + void endInitializer(Token assignmentOperator) {
|
| + debugEvent("Initializer");
|
| + // This is a variable initializer and it's ignored for now. May also be
|
| + // constructor initializer.
|
| + }
|
| +
|
| + void endInitializers(int count, Token beginToken, Token endToken) {
|
| + debugEvent("Initializers");
|
| + // Ignored for now.
|
| + }
|
| +
|
| + void handleNoInitializers() {
|
| + debugEvent("NoInitializers");
|
| + // This is a constructor initializer and it's ignored for now.
|
| + }
|
| +
|
| + void endMember() {
|
| + debugEvent("Member");
|
| + }
|
| +
|
| + void endClassBody(int memberCount, Token beginToken, Token endToken) {
|
| + debugEvent("ClassBody");
|
| + }
|
| +
|
| + void handleAsyncModifier(Token asyncToken, Token starToken) {
|
| + debugEvent("AsyncModifier");
|
| + push(asyncMarkerFromTokens(asyncToken, starToken));
|
| + }
|
| +
|
| + void handleModifier(Token token) {
|
| + debugEvent("Modifier");
|
| + push(new Modifier.fromString(token.stringValue));
|
| + }
|
| +
|
| + void handleModifiers(int count) {
|
| + debugEvent("Modifiers");
|
| + push(popList(count) ?? NullValue.Modifiers);
|
| + }
|
| +
|
| + void debugEvent(String name) {
|
| + // printEvent(name);
|
| + }
|
| +}
|
|
|