| Index: pkg/front_end/lib/src/fasta/kernel/body_builder.dart
|
| 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 221e89fc7008066ac1eb74f6db65938c97a0b50a..3cf478a342bbb7390d05af478d3cb63e8bcd7232 100644
|
| --- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
|
| +++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
|
| @@ -280,7 +280,9 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
| Uri get uri => library.fileUri ?? library.uri;
|
|
|
| @override
|
| - JumpTarget createJumpTarget(JumpTargetKind kind) => new JumpTarget(kind);
|
| + JumpTarget createJumpTarget(JumpTargetKind kind, int charOffset) {
|
| + return new JumpTarget(kind, member, charOffset);
|
| + }
|
|
|
| @override
|
| void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
|
| @@ -706,9 +708,10 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
| isFirstIdentifier = true;
|
| }
|
|
|
| - Builder computeSetter(Builder builder, Scope scope, String name) {
|
| + Builder computeSetter(
|
| + Builder builder, Scope scope, String name, int charOffset) {
|
| if (builder.isSetter) return builder;
|
| - if (builder.isGetter) return scope.lookupSetter(name);
|
| + if (builder.isGetter) return scope.lookupSetter(name, charOffset, uri);
|
| return builder.isField ? (builder.isFinal ? null : builder) : null;
|
| }
|
|
|
| @@ -721,7 +724,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
| this.scope.parent == enclosingScope);
|
| // This deals with this kind of initializer: `C(a) : a = a;`
|
| Scope scope = inInitializer ? enclosingScope : this.scope;
|
| - Builder builder = scope.lookup(name);
|
| + Builder builder = scope.lookup(name, token.charOffset, uri);
|
| push(builderToFirstExpression(builder, name, token.charOffset));
|
| } else {
|
| push(new Identifier(name)..fileOffset = token.charOffset);
|
| @@ -733,7 +736,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
| {bool isPrefix: false}) {
|
| if (builder == null || (!isInstanceContext && builder.isInstanceMember)) {
|
| if (!isPrefix && identical(name, "dynamic") && builder == null) {
|
| - return new KernelNamedTypeBuilder(name, null);
|
| + return new KernelNamedTypeBuilder(name, null, charOffset, uri);
|
| }
|
| Name n = new Name(name, library.library);
|
| if (!isPrefix && isInstanceContext) {
|
| @@ -768,7 +771,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
| }
|
| Member getter = builder.target.hasGetter ? builder.target : null;
|
| Member setter = builder.target.hasSetter ? builder.target : null;
|
| - setter ??= computeSetter(builder, scope, name)?.target;
|
| + setter ??= computeSetter(builder, scope, name, charOffset)?.target;
|
| return
|
| new StaticAccessor(this, charOffset, getter, setter);
|
| }
|
| @@ -907,7 +910,10 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
| internalError("unhandled identifier: ${node.runtimeType}");
|
| }
|
| push(variable);
|
| - scope[variable.name] = new KernelVariableBuilder(variable);
|
| + scope[variable.name] = new KernelVariableBuilder(variable,
|
| + // TODO(ahe): This should be `member ?? classBuilder ?? part`, but we
|
| + // don't have an object representing the current part.
|
| + member ?? classBuilder);
|
| }
|
|
|
| @override
|
| @@ -959,14 +965,14 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
| }
|
|
|
| @override
|
| - void enterLoop() {
|
| + void enterLoop(int charOffset) {
|
| if (peek() is LabelTarget) {
|
| LabelTarget target = peek();
|
| - enterBreakTarget(target.breakTarget);
|
| - enterContinueTarget(target.continueTarget);
|
| + enterBreakTarget(charOffset, target.breakTarget);
|
| + enterContinueTarget(charOffset, target.continueTarget);
|
| } else{
|
| - enterBreakTarget();
|
| - enterContinueTarget();
|
| + enterBreakTarget(charOffset);
|
| + enterContinueTarget(charOffset);
|
| }
|
| }
|
|
|
| @@ -1140,10 +1146,10 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
| push(new SymbolLiteral(value));
|
| }
|
|
|
| - DartType toKernelType(String name, List<DartType> arguments) {
|
| + DartType toKernelType(String name, List<DartType> arguments, int charOffset) {
|
| if (identical(name, "void")) return const VoidType();
|
| if (identical(name, "dynamic")) return const DynamicType();
|
| - Builder builder = scope.lookup(name);
|
| + Builder builder = scope.lookup(name, charOffset, uri);
|
| if (builder is TypeDeclarationBuilder) {
|
| return builder.buildTypesWithBuiltArguments(arguments);
|
| }
|
| @@ -1178,7 +1184,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
| if (prefix is Builder) {
|
| builder = prefix;
|
| } else {
|
| - builder = scope.lookup(prefix);
|
| + builder = scope.lookup(prefix, beginToken.charOffset, uri);
|
| }
|
| if (builder is PrefixBuilder) {
|
| name = builder.exports[suffix];
|
| @@ -1204,7 +1210,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
| } else if (name is TypeBuilder) {
|
| push(name.build());
|
| } else {
|
| - push(toKernelType(name, arguments));
|
| + push(toKernelType(name, arguments, beginToken.charOffset));
|
| }
|
| if (peek() is TypeParameterType) {
|
| TypeParameterType type = peek();
|
| @@ -1263,6 +1269,8 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
| @override
|
| void endFormalParameter(Token thisKeyword) {
|
| debugEvent("FormalParameter");
|
| + // TODO(ahe): Need beginToken here.
|
| + int charOffset = thisKeyword?.charOffset;
|
| if (thisKeyword != null) {
|
| if (!inConstructor) {
|
| return inputError("'this' parameters can only be used on constructors.",
|
| @@ -1275,7 +1283,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
| ignore(Unhandled.Metadata);
|
| VariableDeclaration variable;
|
| if (!inCatchClause && functionNestingLevel == 0) {
|
| - var builder = formalParameterScope.lookup(name.name);
|
| + var builder = formalParameterScope.lookup(name.name, charOffset, uri);
|
| if (builder == null) {
|
| return inputError("'${name.name}' isn't a field in this class.",
|
| name.fileOffset);
|
| @@ -1353,7 +1361,8 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
| popList(count) ?? <VariableDeclaration>[], optional);
|
| push(formals);
|
| if (inCatchClause || functionNestingLevel != 0) {
|
| - enterLocalScope(formals.computeFormalParameterScope(scope));
|
| + enterLocalScope(formals.computeFormalParameterScope(
|
| + scope, member ?? classBuilder ?? library));
|
| }
|
| }
|
|
|
| @@ -1718,7 +1727,10 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
| name.name, isFinal: true);
|
| push(new FunctionDeclaration(variable,
|
| new FunctionNode(new InvalidStatement())));
|
| - scope[variable.name] = new KernelVariableBuilder(variable);
|
| + scope[variable.name] = new KernelVariableBuilder(variable,
|
| + // TODO(ahe): This should be `member ?? classBuilder ?? part`, but we
|
| + // don't have an object representing the current part.
|
| + member ?? classBuilder);
|
| enterLocalScope();
|
| }
|
|
|
| @@ -1868,7 +1880,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
| debugEvent("beginLabeledStatement");
|
| List<Label> labels = popList(labelCount);
|
| enterLocalScope();
|
| - LabelTarget target = new LabelTarget();
|
| + LabelTarget target = new LabelTarget(member, token.charOffset);
|
| for (Label label in labels) {
|
| scope[label.name] = target;
|
| }
|
| @@ -1953,7 +1965,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
| debugEvent("beginSwitchBlock");
|
| enterLocalScope();
|
| enterSwitchScope();
|
| - enterBreakTarget();
|
| + enterBreakTarget(token.charOffset);
|
| }
|
|
|
| @override
|
| @@ -1975,7 +1987,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
| for (Label label in labels) {
|
| Builder existing = scope.local[label.name];
|
| if (existing == null) {
|
| - scope[label.name] = createGotoTarget();
|
| + scope[label.name] = createGotoTarget(firstToken.charOffset);
|
| } else {
|
| // TODO(ahe): Should validate this is a goto target and not duplicated.
|
| }
|
| @@ -2017,7 +2029,8 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
| List<Label> labels = pop();
|
| SwitchCase current = cases[i] = pop();
|
| for (Label label in labels) {
|
| - JumpTarget target = switchScope.lookup(label.name);
|
| + JumpTarget target =
|
| + switchScope.lookup(label.name, label.fileOffset, uri);
|
| if (target != null) {
|
| target.resolveGotos(current);
|
| }
|
| @@ -2051,7 +2064,8 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
| if (hasTarget) {
|
| Identifier identifier = pop();
|
| name = identifier.name;
|
| - target = scope.lookup(identifier.name);
|
| + target = scope.lookup(
|
| + identifier.name, breakKeyword.next.charOffset, uri);
|
| }
|
| if (target == null && name == null) {
|
| push(compileTimeErrorInLoopOrSwitch =
|
| @@ -2078,7 +2092,8 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
| if (hasTarget) {
|
| Identifier identifier = pop();
|
| name = identifier.name;
|
| - target = scope.lookup(identifier.name);
|
| + target = scope.lookup(
|
| + identifier.name, continueKeyword.next.charOffset, uri);
|
| if (target != null && target is! JumpTarget) {
|
| push(compileTimeErrorInLoopOrSwitch =
|
| buildCompileTimeErrorStatement(
|
| @@ -2092,7 +2107,8 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
| continueKeyword.next.charOffset));
|
| return;
|
| }
|
| - switchScope[identifier.name] = target = createGotoTarget();
|
| + switchScope[identifier.name] = target =
|
| + createGotoTarget(identifier.fileOffset);
|
| }
|
| if (target.isGotoTarget) {
|
| ContinueSwitchStatement statement = new ContinueSwitchStatement(null);
|
| @@ -2485,7 +2501,8 @@ class JumpTarget extends Builder {
|
|
|
| final JumpTargetKind kind;
|
|
|
| - JumpTarget(this.kind);
|
| + JumpTarget(this.kind, MemberBuilder member, int charOffset)
|
| + : super(member, charOffset, member.fileUri);
|
|
|
| bool get isBreakTarget => kind == JumpTargetKind.Break;
|
|
|
| @@ -2536,11 +2553,15 @@ class JumpTarget extends Builder {
|
| }
|
|
|
| class LabelTarget extends Builder implements JumpTarget {
|
| - final JumpTarget breakTarget = new JumpTarget(JumpTargetKind.Break);
|
| + final JumpTarget breakTarget;
|
|
|
| - final JumpTarget continueTarget = new JumpTarget(JumpTargetKind.Continue);
|
| + final JumpTarget continueTarget;
|
|
|
| - LabelTarget();
|
| + LabelTarget(MemberBuilder member, int charOffset)
|
| + : breakTarget = new JumpTarget(JumpTargetKind.Break, member, charOffset),
|
| + continueTarget =
|
| + new JumpTarget(JumpTargetKind.Continue, member, charOffset),
|
| + super(member, charOffset, member.fileUri);
|
|
|
| bool get hasUsers => breakTarget.hasUsers || continueTarget.hasUsers;
|
|
|
| @@ -2634,15 +2655,15 @@ class FormalParameters {
|
| requiredParameterCount: requiredParameterCount);
|
| }
|
|
|
| - Scope computeFormalParameterScope(Scope parent) {
|
| + Scope computeFormalParameterScope(Scope parent, Builder builder) {
|
| if (required.length == 0 && optional == null) return parent;
|
| Map<String, Builder> local = <String, Builder>{};
|
| for (VariableDeclaration parameter in required) {
|
| - local[parameter.name] = new KernelVariableBuilder(parameter);
|
| + local[parameter.name] = new KernelVariableBuilder(parameter, builder);
|
| }
|
| if (optional != null) {
|
| for (VariableDeclaration parameter in optional.formals) {
|
| - local[parameter.name] = new KernelVariableBuilder(parameter);
|
| + local[parameter.name] = new KernelVariableBuilder(parameter, builder);
|
| }
|
| }
|
| return new Scope(local, parent, isModifiable: false);
|
|
|