Add UnlinkedScope
This scope is for use when building an AST before building the outline.
Change-Id: I90786449fb4e7d755e64d40f91c4cb67a02a6082
Reviewed-on: https://dart-review.googlesource.com/57581
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/src/fasta/ast_body_builder.dart b/pkg/analyzer/lib/src/fasta/ast_body_builder.dart
index 4c4d6ec6..92c95b7 100644
--- a/pkg/analyzer/lib/src/fasta/ast_body_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_body_builder.dart
@@ -14,6 +14,9 @@
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/core_types.dart' show CoreTypes;
+export 'package:front_end/src/fasta/kernel/unlinked_scope.dart'
+ show UnlinkedScope;
+
class AstBodyBuilder extends BodyBuilder<Expression, Statement, dynamic> {
@override
final AstBuildingForest forest;
@@ -38,4 +41,9 @@
void enterThenForTypePromotion(Expression condition) {
// Do nothing.
}
+
+ @override
+ void logEvent(String name) {
+ throw "Parser event '$name' not implemented";
+ }
}
diff --git a/pkg/analyzer/lib/src/fasta/ast_building_factory.dart b/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
index e2f5c56..d794f10 100644
--- a/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
@@ -602,6 +602,15 @@
}
@override
+ Generator<Expression, Statement, _Arguments> unlinkedGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+ Token token,
+ UnlinkedDeclaration declaration) {
+ // TODO(brianwilkerson) Implement this.
+ throw new UnimplementedError();
+ }
+
+ @override
Generator<Expression, Statement, _Arguments> unresolvedNameGenerator(
ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
Token token,
diff --git a/pkg/analyzer/test/src/fasta/body_builder_test_helper.dart b/pkg/analyzer/test/src/fasta/body_builder_test_helper.dart
index 74c0314..aaf8164 100644
--- a/pkg/analyzer/test/src/fasta/body_builder_test_helper.dart
+++ b/pkg/analyzer/test/src/fasta/body_builder_test_helper.dart
@@ -516,8 +516,8 @@
AstBodyBuilder builder = new AstBodyBuilder(
library,
procedureBuilder,
- library.scope,
- procedureBuilder.computeFormalParameterScope(library.scope),
+ new UnlinkedScope(),
+ null,
kernelTarget.loader.hierarchy,
kernelTarget.loader.coreTypes,
null /* classBuilder */,
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index c72e5ab..350f96f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -90,6 +90,7 @@
ThisAccessGenerator,
ThisPropertyAccessGenerator,
TypeUseGenerator,
+ UnlinkedGenerator,
UnresolvedNameGenerator,
VariableUseGenerator,
buildIsNull;
@@ -1391,6 +1392,9 @@
{bool isQualified: false, PrefixBuilder prefix}) {
int charOffset = offsetForToken(token);
Declaration declaration = scope.lookup(name, charOffset, uri);
+ if (declaration is UnlinkedDeclaration) {
+ return new UnlinkedGenerator(this, token, declaration);
+ }
if (declaration == null &&
prefix == null &&
(classBuilder?.isPatch ?? false)) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index ab4d78d..c69b304 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -32,7 +32,8 @@
Identifier,
LoadLibraryBuilder,
PrefixBuilder,
- TypeDeclarationBuilder;
+ TypeDeclarationBuilder,
+ UnlinkedDeclaration;
import 'kernel_ast_api.dart'
show
@@ -837,3 +838,27 @@
isSetter: isSetter);
}
}
+
+abstract class UnlinkedGenerator<Expression, Statement, Arguments>
+ implements Generator<Expression, Statement, Arguments> {
+ factory UnlinkedGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token,
+ UnlinkedDeclaration declaration) {
+ return helper.forest.unlinkedGenerator(helper, token, declaration);
+ }
+
+ UnlinkedDeclaration get declaration;
+
+ @override
+ String get plainNameForRead => declaration.name;
+
+ @override
+ String get debugName => "UnlinkedGenerator";
+
+ @override
+ void printOn(StringSink sink) {
+ sink.write(", name: ");
+ sink.write(declaration.name);
+ }
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
index cfc6ad9..a976f3b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
@@ -58,6 +58,7 @@
KernelThisIndexedAccessGenerator,
KernelThisPropertyAccessGenerator,
KernelTypeUseGenerator,
+ KernelUnlinkedGenerator,
KernelUnresolvedNameGenerator,
KernelVariableUseGenerator;
@@ -109,7 +110,8 @@
Generator,
LoadLibraryBuilder,
PrefixBuilder,
- TypeDeclarationBuilder;
+ TypeDeclarationBuilder,
+ UnlinkedDeclaration;
/// A shadow tree factory.
class Fangorn extends Forest<Expression, Statement, Token, Arguments> {
@@ -765,6 +767,14 @@
Name name) {
return new KernelUnresolvedNameGenerator(helper, token, name);
}
+
+ @override
+ KernelUnlinkedGenerator unlinkedGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token,
+ UnlinkedDeclaration declaration) {
+ return new KernelUnlinkedGenerator(helper, token, declaration);
+ }
}
class _VariablesDeclaration extends Statement {
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index 0aeec3d..ac39797 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -19,7 +19,11 @@
import 'expression_generator_helper.dart' show ExpressionGeneratorHelper;
import 'kernel_builder.dart'
- show LoadLibraryBuilder, PrefixBuilder, TypeDeclarationBuilder;
+ show
+ LoadLibraryBuilder,
+ PrefixBuilder,
+ TypeDeclarationBuilder,
+ UnlinkedDeclaration;
export 'body_builder.dart' show Identifier, Operator;
@@ -28,7 +32,11 @@
export 'expression_generator_helper.dart' show ExpressionGeneratorHelper;
export 'kernel_builder.dart'
- show LoadLibraryBuilder, PrefixBuilder, TypeDeclarationBuilder;
+ show
+ LoadLibraryBuilder,
+ PrefixBuilder,
+ TypeDeclarationBuilder,
+ UnlinkedDeclaration;
/// A tree factory.
///
@@ -459,6 +467,11 @@
Location location,
kernel.Name name);
+ Generator<Expression, Statement, Arguments> unlinkedGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Location location,
+ UnlinkedDeclaration declaration);
+
// TODO(ahe): Remove this method when all users are moved here.
kernel.Arguments castArguments(Arguments arguments) {
dynamic a = arguments;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
index aa4860e..a2fbeca 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
@@ -4,6 +4,18 @@
library fasta.kernel_builder;
+import 'package:kernel/ast.dart'
+ show
+ Combinator,
+ Constructor,
+ Initializer,
+ Procedure,
+ RedirectingInitializer;
+
+import '../combinator.dart' as fasta;
+
+export '../builder/builder.dart';
+
export 'kernel_class_builder.dart' show KernelClassBuilder;
export 'kernel_enum_builder.dart' show KernelEnumBuilder;
@@ -12,20 +24,22 @@
export 'kernel_formal_parameter_builder.dart' show KernelFormalParameterBuilder;
-export 'kernel_function_type_builder.dart' show KernelFunctionTypeBuilder;
-
export 'kernel_function_type_alias_builder.dart'
show KernelFunctionTypeAliasBuilder;
-export 'kernel_prefix_builder.dart' show KernelPrefixBuilder;
+export 'kernel_function_type_builder.dart' show KernelFunctionTypeBuilder;
-export 'kernel_named_type_builder.dart' show KernelNamedTypeBuilder;
+export 'kernel_invalid_type_builder.dart' show KernelInvalidTypeBuilder;
export 'kernel_library_builder.dart' show KernelLibraryBuilder;
export 'kernel_mixin_application_builder.dart'
show KernelMixinApplicationBuilder;
+export 'kernel_named_type_builder.dart' show KernelNamedTypeBuilder;
+
+export 'kernel_prefix_builder.dart' show KernelPrefixBuilder;
+
export 'kernel_procedure_builder.dart'
show
KernelConstructorBuilder,
@@ -37,23 +51,11 @@
export 'kernel_type_variable_builder.dart' show KernelTypeVariableBuilder;
-export '../builder/builder.dart';
-
export 'kernel_variable_builder.dart' show KernelVariableBuilder;
-export 'kernel_invalid_type_builder.dart' show KernelInvalidTypeBuilder;
-
export 'load_library_builder.dart' show LoadLibraryBuilder;
-import 'package:kernel/ast.dart'
- show
- Combinator,
- Constructor,
- Initializer,
- Procedure,
- RedirectingInitializer;
-
-import '../combinator.dart' as fasta;
+export 'unlinked_scope.dart' show UnlinkedDeclaration;
int compareProcedures(Procedure a, Procedure b) {
int i = "${a.fileUri}".compareTo("${b.fileUri}");
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
index 97d3930..bc2d940 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
@@ -2,7 +2,8 @@
// 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 'package:kernel/ast.dart' show Arguments, Expression, Node, Statement;
+import 'package:kernel/ast.dart'
+ show Arguments, Expression, InvalidExpression, Node, Statement;
import '../../scanner/token.dart' show Token;
@@ -61,6 +62,7 @@
ThisIndexedAccessGenerator,
ThisPropertyAccessGenerator,
TypeUseGenerator,
+ UnlinkedGenerator,
UnresolvedNameGenerator,
VariableUseGenerator;
@@ -68,7 +70,8 @@
import 'forest.dart' show Forest;
-import 'kernel_builder.dart' show LoadLibraryBuilder, PrefixBuilder;
+import 'kernel_builder.dart'
+ show LoadLibraryBuilder, PrefixBuilder, UnlinkedDeclaration;
import 'kernel_api.dart' show NameSystem, printNodeOn, printQualifiedNameOn;
@@ -1462,6 +1465,53 @@
}
}
+class KernelUnlinkedGenerator extends KernelGenerator
+ with UnlinkedGenerator<Expression, Statement, Arguments> {
+ @override
+ final UnlinkedDeclaration declaration;
+
+ final Expression receiver;
+
+ final Name name;
+
+ KernelUnlinkedGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token,
+ this.declaration)
+ : name = new Name(declaration.name, helper.library.target),
+ receiver = new InvalidExpression(declaration.name)
+ ..fileOffset = offsetForToken(token),
+ super(helper, token);
+
+ @override
+ Expression _makeRead(ShadowComplexAssignment complexAssignment) {
+ return unsupported("_makeRead", offsetForToken(token), uri);
+ }
+
+ @override
+ Expression _makeWrite(Expression value, bool voidContext,
+ ShadowComplexAssignment complexAssignment) {
+ return unsupported("_makeWrite", offsetForToken(token), uri);
+ }
+
+ @override
+ Expression buildAssignment(Expression value, {bool voidContext}) {
+ return new PropertySet(receiver, name, value)
+ ..fileOffset = offsetForToken(token);
+ }
+
+ @override
+ Expression buildSimpleRead() {
+ return new ShadowPropertyGet(receiver, name)
+ ..fileOffset = offsetForToken(token);
+ }
+
+ @override
+ Expression doInvocation(int offset, Arguments arguments) {
+ return unsupported("doInvocation", offset, uri);
+ }
+}
+
Expression makeLet(VariableDeclaration variable, Expression body) {
if (variable == null) return body;
return new Let(variable, body);
diff --git a/pkg/front_end/lib/src/fasta/kernel/unlinked_scope.dart b/pkg/front_end/lib/src/fasta/kernel/unlinked_scope.dart
new file mode 100644
index 0000000..6949064
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/kernel/unlinked_scope.dart
@@ -0,0 +1,38 @@
+// 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 'kernel_builder.dart' show Declaration, Scope;
+
+/// Scope that returns an [UnlinkedDeclaration] if a name can't be resolved.
+/// This is intended to be used as the `enclosingScope` in `BodyBuilder` to
+/// create ASTs with building outlines.
+class UnlinkedScope extends Scope {
+ UnlinkedScope() : super.top(isModifiable: false);
+
+ Declaration lookupIn(String name, int charOffset, Uri fileUri,
+ Map<String, Declaration> map, bool isInstanceScope) {
+ return new UnlinkedDeclaration(name, isInstanceScope, charOffset, fileUri);
+ }
+}
+
+class UnlinkedDeclaration extends Declaration {
+ final String name;
+
+ final bool isInstanceScope;
+
+ @override
+ final int charOffset;
+
+ @override
+ final Uri fileUri;
+
+ UnlinkedDeclaration(
+ this.name, this.isInstanceScope, this.charOffset, this.fileUri);
+
+ @override
+ Declaration get parent => null;
+
+ @override
+ String get fullNameForErrors => name;
+}
diff --git a/pkg/front_end/test/fasta/generator_to_string_test.dart b/pkg/front_end/test/fasta/generator_to_string_test.dart
index 1aa4ce9..8d1dad4 100644
--- a/pkg/front_end/test/fasta/generator_to_string_test.dart
+++ b/pkg/front_end/test/fasta/generator_to_string_test.dart
@@ -37,7 +37,8 @@
KernelTypeVariableBuilder,
LoadLibraryBuilder,
PrefixBuilder,
- TypeDeclarationBuilder;
+ TypeDeclarationBuilder,
+ UnlinkedDeclaration;
import 'package:front_end/src/fasta/kernel/kernel_target.dart'
show KernelTarget;
@@ -70,11 +71,12 @@
KernelThisIndexedAccessGenerator,
KernelThisPropertyAccessGenerator,
KernelTypeUseGenerator,
+ KernelUnlinkedGenerator,
+ KernelUnresolvedNameGenerator,
KernelVariableUseGenerator,
ParenthesizedExpressionGenerator,
SendAccessGenerator,
- ThisAccessGenerator,
- KernelUnresolvedNameGenerator;
+ ThisAccessGenerator;
import 'package:front_end/src/fasta/scanner.dart' show Token, scanString;
@@ -229,5 +231,9 @@
helper, token, prefixBuilder, -1, declaration, "foo"));
check("UnresolvedNameGenerator(offset: 4, name: bar)",
new KernelUnresolvedNameGenerator(helper, token, name));
+ check(
+ "UnlinkedGenerator(offset: 4, name: foo)",
+ new KernelUnlinkedGenerator(
+ helper, token, new UnlinkedDeclaration("foo", false, -1, null)));
});
}
diff --git a/pkg/front_end/test/fasta/unlinked_scope_test.dart b/pkg/front_end/test/fasta/unlinked_scope_test.dart
new file mode 100644
index 0000000..1f6c28f
--- /dev/null
+++ b/pkg/front_end/test/fasta/unlinked_scope_test.dart
@@ -0,0 +1,113 @@
+// 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 'package:expect/expect.dart' show Expect;
+
+import 'package:kernel/ast.dart' show Expression, ProcedureKind;
+
+import 'package:kernel/target/targets.dart' show NoneTarget, TargetFlags;
+
+import 'package:front_end/src/api_prototype/compiler_options.dart'
+ show CompilerOptions, FormattedMessage, ProblemHandler;
+
+import 'package:front_end/src/base/processed_options.dart'
+ show ProcessedOptions;
+
+import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;
+
+import 'package:front_end/src/fasta/dill/dill_target.dart' show DillTarget;
+
+import 'package:front_end/src/fasta/kernel/kernel_body_builder.dart'
+ show KernelBodyBuilder;
+
+import 'package:front_end/src/fasta/kernel/kernel_builder.dart'
+ show KernelLibraryBuilder, KernelProcedureBuilder;
+
+import 'package:front_end/src/fasta/kernel/kernel_target.dart'
+ show KernelTarget;
+
+import 'package:front_end/src/fasta/kernel/unlinked_scope.dart'
+ show UnlinkedScope;
+
+import 'package:front_end/src/fasta/parser.dart' show Parser;
+
+import 'package:front_end/src/fasta/scanner.dart' show Token, scanString;
+
+import 'package:front_end/src/fasta/scope.dart' show Scope;
+
+import 'package:front_end/src/fasta/severity.dart' show Severity;
+
+ProblemHandler handler;
+
+class MockLibraryBuilder extends KernelLibraryBuilder {
+ MockLibraryBuilder(Uri uri)
+ : super(
+ uri,
+ uri,
+ new KernelTarget(
+ null,
+ false,
+ new DillTarget(
+ null, null, new NoneTarget(new TargetFlags())),
+ null)
+ .loader,
+ null,
+ null);
+
+ KernelProcedureBuilder mockProcedure(String name) {
+ return new KernelProcedureBuilder(null, 0, null, name, null, null,
+ ProcedureKind.Getter, this, -1, -1, -1);
+ }
+}
+
+class MockBodyBuilder extends KernelBodyBuilder {
+ MockBodyBuilder.internal(
+ MockLibraryBuilder libraryBuilder, String name, Scope scope)
+ : super(libraryBuilder, libraryBuilder.mockProcedure(name), scope, scope,
+ null, null, null, false, libraryBuilder.uri, null);
+
+ MockBodyBuilder(Uri uri, String name, Scope scope)
+ : this.internal(new MockLibraryBuilder(uri), name, scope);
+}
+
+Expression compileExpression(String source) {
+ KernelBodyBuilder listener = new MockBodyBuilder(
+ Uri.parse("org-dartlang-test:my_library.dart"),
+ "<test>",
+ new UnlinkedScope());
+
+ handler = (FormattedMessage problem, Severity severity,
+ List<FormattedMessage> context) {
+ throw problem.formatted;
+ };
+
+ Token token = scanString(source).tokens;
+ Parser parser = new Parser(listener);
+ parser.parseExpression(parser.syntheticPreviousToken(token));
+ Expression e = listener.popForValue();
+ listener.checkEmpty(-1);
+ return e;
+}
+
+void testExpression(String source, [String expected]) {
+ Expression e = compileExpression(source);
+ String actual =
+ "$e".replaceAll(new RegExp(r'invalid-expression "[^"]*"\.'), "");
+ Expect.stringEquals(expected ?? source, actual);
+ print(e);
+}
+
+main() {
+ CompilerContext context = new CompilerContext(new ProcessedOptions(
+ new CompilerOptions()
+ ..onProblem = (FormattedMessage problem, Severity severity,
+ List<FormattedMessage> context) {
+ handler(problem, severity, context);
+ }));
+ context.runInContext((_) {
+ testExpression("unresolved");
+ testExpression("a + b", "a.+(b)");
+ testExpression("a = b");
+ });
+}