[cfe] Use original name in extension method errors.

Previously the errors were reported using the synthesized name, like
`Extension|method` instead of `method`.

+ Report errors on invalid uses of explicit extension application as
an expression or lvalue.

Change-Id: I6d85430be4ab3966ee94131b37aa365265c07eac
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/118383
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
This commit is contained in:
Johnni Winther 2019-09-24 07:55:45 +00:00
parent b7ad248209
commit 175fc6edff
11 changed files with 255 additions and 42 deletions

View file

@ -3317,6 +3317,26 @@ const MessageCode messageExplicitExtensionArgumentMismatch = const MessageCode(
message:
r"""Explicit extension application requires exactly 1 positional argument.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeExplicitExtensionAsExpression =
messageExplicitExtensionAsExpression;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageExplicitExtensionAsExpression = const MessageCode(
"ExplicitExtensionAsExpression",
message:
r"""Explicit extension application cannot be used as an expression.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeExplicitExtensionAsLvalue =
messageExplicitExtensionAsLvalue;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageExplicitExtensionAsLvalue = const MessageCode(
"ExplicitExtensionAsLvalue",
message:
r"""Explicit extension application cannot be a target for assignment.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(

View file

@ -1859,11 +1859,12 @@ class BodyBuilder extends ScopeListener<JumpTarget>
Builder setter =
_getCorrespondingSetterBuilder(scope, declaration, name, charOffset);
// TODO(johnniwinther): Check for constantContext like below?
return new ExtensionInstanceAccessGenerator.fromBuilder(this,
return new ExtensionInstanceAccessGenerator.fromBuilder(this, name,
extensionThis, extensionTypeParameters, declaration, token, setter);
} else if (declaration.isRegularMethod) {
assert(declaration.isStatic || declaration.isTopLevel);
return new StaticAccessGenerator(this, token, declaration.target, null);
return new StaticAccessGenerator(
this, token, name, declaration.target, null);
} else if (declaration is PrefixBuilder) {
assert(prefix == null);
return new PrefixUseGenerator(this, token, declaration);
@ -1875,7 +1876,7 @@ class BodyBuilder extends ScopeListener<JumpTarget>
Builder setter =
_getCorrespondingSetterBuilder(scope, declaration, name, charOffset);
StaticAccessGenerator generator = new StaticAccessGenerator.fromBuilder(
this, declaration, token, setter);
this, name, declaration, token, setter);
if (constantContext != ConstantContext.none) {
Member readTarget = generator.readTarget;
if (!(readTarget is Field && readTarget.isConst ||

View file

@ -1367,6 +1367,9 @@ class SuperIndexedAccessGenerator extends Generator {
/// }
///
class StaticAccessGenerator extends Generator {
/// The name of the original target;
final String targetName;
/// The static [Member] used for performing a read or invocation on this
/// subexpression.
///
@ -1383,12 +1386,17 @@ class StaticAccessGenerator extends Generator {
final Member writeTarget;
StaticAccessGenerator(ExpressionGeneratorHelper helper, Token token,
this.readTarget, this.writeTarget)
: assert(readTarget != null || writeTarget != null),
this.targetName, this.readTarget, this.writeTarget)
: assert(targetName != null),
assert(readTarget != null || writeTarget != null),
super(helper, token);
factory StaticAccessGenerator.fromBuilder(ExpressionGeneratorHelper helper,
Builder declaration, Token token, Builder builderSetter) {
factory StaticAccessGenerator.fromBuilder(
ExpressionGeneratorHelper helper,
String targetName,
Builder declaration,
Token token,
Builder builderSetter) {
if (declaration is AccessErrorBuilder) {
AccessErrorBuilder error = declaration;
declaration = error.builder;
@ -1409,14 +1417,14 @@ class StaticAccessGenerator extends Generator {
setter = builderSetter.target;
}
}
return new StaticAccessGenerator(helper, token, getter, setter);
return new StaticAccessGenerator(helper, token, targetName, getter, setter);
}
@override
String get _debugName => "StaticAccessGenerator";
@override
String get _plainNameForRead => (readTarget ?? writeTarget).name.name;
String get _plainNameForRead => targetName;
@override
Expression buildSimpleRead() {
@ -1524,6 +1532,8 @@ class StaticAccessGenerator extends Generator {
@override
void printOn(StringSink sink) {
NameSystem syntheticNames = new NameSystem();
sink.write(", targetName: ");
sink.write(targetName);
sink.write(", readTarget: ");
printQualifiedNameOn(readTarget, sink, syntheticNames: syntheticNames);
sink.write(", writeTarget: ");
@ -1550,6 +1560,9 @@ class StaticAccessGenerator extends Generator {
///
/// These can only occur within an extension instance member.
class ExtensionInstanceAccessGenerator extends Generator {
/// The original name of the target.
final String targetName;
/// The static [Member] generated for an instance extension member which is
/// used for performing a read on this subexpression.
///
@ -1586,17 +1599,20 @@ class ExtensionInstanceAccessGenerator extends Generator {
ExtensionInstanceAccessGenerator(
ExpressionGeneratorHelper helper,
Token token,
this.targetName,
this.readTarget,
this.invokeTarget,
this.writeTarget,
this.extensionThis,
this.extensionTypeParameters)
: assert(readTarget != null || writeTarget != null),
: assert(targetName != null),
assert(readTarget != null || writeTarget != null),
assert(extensionThis != null),
super(helper, token);
factory ExtensionInstanceAccessGenerator.fromBuilder(
ExpressionGeneratorHelper helper,
String targetName,
VariableDeclaration extensionThis,
List<TypeParameter> extensionTypeParameters,
Builder declaration,
@ -1628,15 +1644,22 @@ class ExtensionInstanceAccessGenerator extends Generator {
if (builderSetter != null && builderSetter.isSetter) {
writeTarget = builderSetter.target;
}
return new ExtensionInstanceAccessGenerator(helper, token, readTarget,
invokeTarget, writeTarget, extensionThis, extensionTypeParameters);
return new ExtensionInstanceAccessGenerator(
helper,
token,
targetName,
readTarget,
invokeTarget,
writeTarget,
extensionThis,
extensionTypeParameters);
}
@override
String get _debugName => "InstanceExtensionAccessGenerator";
@override
String get _plainNameForRead => (readTarget ?? writeTarget).name.name;
String get _plainNameForRead => targetName;
int get _extensionTypeParameterCount => extensionTypeParameters?.length ?? 0;
@ -1785,6 +1808,8 @@ class ExtensionInstanceAccessGenerator extends Generator {
@override
void printOn(StringSink sink) {
NameSystem syntheticNames = new NameSystem();
sink.write(", targetName: ");
sink.write(targetName);
sink.write(", readTarget: ");
printQualifiedNameOn(readTarget, sink, syntheticNames: syntheticNames);
sink.write(", writeTarget: ");
@ -1814,6 +1839,9 @@ class ExtensionInstanceAccessGenerator extends Generator {
/// }
///
class ExplicitExtensionInstanceAccessGenerator extends Generator {
/// The name of the original target;
final String targetName;
/// The static [Member] generated for an instance extension member which is
/// used for performing a read on this subexpression.
///
@ -1850,13 +1878,15 @@ class ExplicitExtensionInstanceAccessGenerator extends Generator {
ExplicitExtensionInstanceAccessGenerator(
ExpressionGeneratorHelper helper,
Token token,
this.targetName,
this.readTarget,
this.invokeTarget,
this.writeTarget,
this.receiver,
this.explicitTypeArguments,
this.extensionTypeParameterCount)
: assert(readTarget != null || writeTarget != null),
: assert(targetName != null),
assert(readTarget != null || writeTarget != null),
assert(receiver != null),
super(helper, token);
@ -1868,6 +1898,7 @@ class ExplicitExtensionInstanceAccessGenerator extends Generator {
Expression receiver,
List<DartType> explicitTypeArguments,
int extensionTypeParameterCount) {
String targetName;
Procedure readTarget;
Procedure invokeTarget;
if (getterBuilder != null) {
@ -1878,11 +1909,14 @@ class ExplicitExtensionInstanceAccessGenerator extends Generator {
// when not explicitly looking for a setter.
assert(getterBuilder.isSetter);
} else if (getterBuilder.isGetter) {
readTarget = getterBuilder.target;
MemberBuilder memberBuilder = getterBuilder;
readTarget = memberBuilder.member;
targetName = memberBuilder.name;
} else if (getterBuilder.isRegularMethod) {
MemberBuilder procedureBuilder = getterBuilder;
readTarget = procedureBuilder.extensionTearOff;
invokeTarget = procedureBuilder.procedure;
targetName = procedureBuilder.name;
} else {
return unhandled(
"${getterBuilder.runtimeType}",
@ -1892,12 +1926,17 @@ class ExplicitExtensionInstanceAccessGenerator extends Generator {
}
}
Procedure writeTarget;
if (setterBuilder != null && setterBuilder.isSetter) {
writeTarget = setterBuilder.target;
if (setterBuilder is AccessErrorBuilder) {
targetName ??= setterBuilder.name;
} else if (setterBuilder != null && setterBuilder.isSetter) {
MemberBuilder memberBuilder = setterBuilder;
writeTarget = memberBuilder.member;
targetName ??= memberBuilder.name;
}
return new ExplicitExtensionInstanceAccessGenerator(
helper,
token,
targetName,
readTarget,
invokeTarget,
writeTarget,
@ -1910,7 +1949,7 @@ class ExplicitExtensionInstanceAccessGenerator extends Generator {
String get _debugName => "InstanceExtensionAccessGenerator";
@override
String get _plainNameForRead => (readTarget ?? writeTarget).name.name;
String get _plainNameForRead => targetName;
List<DartType> _createExtensionTypeArguments() {
return explicitTypeArguments ?? const <DartType>[];
@ -2065,6 +2104,8 @@ class ExplicitExtensionInstanceAccessGenerator extends Generator {
@override
void printOn(StringSink sink) {
NameSystem syntheticNames = new NameSystem();
sink.write(", targetName: ");
sink.write(targetName);
sink.write(", readTarget: ");
printQualifiedNameOn(readTarget, sink, syntheticNames: syntheticNames);
sink.write(", writeTarget: ");
@ -2183,6 +2224,18 @@ class ExplicitExtensionAccessGenerator extends Generator {
"ExplicitExtensionAccessGenerator.doInvocation", fileOffset, _uri);
}
@override
Expression _makeInvalidRead() {
return _helper.buildProblem(messageExplicitExtensionAsExpression,
fileOffset, lengthForToken(token));
}
@override
Expression _makeInvalidWrite(Expression value) {
return _helper.buildProblem(
messageExplicitExtensionAsLvalue, fileOffset, lengthForToken(token));
}
@override
void printOn(StringSink sink) {
sink.write(", extensionBuilder: ");
@ -2445,8 +2498,8 @@ class TypeUseGenerator extends ReadOnlyAccessGenerator {
final TypeDeclarationBuilder declaration;
TypeUseGenerator(ExpressionGeneratorHelper helper, Token token,
this.declaration, String plainNameForRead)
: super(helper, token, null, plainNameForRead);
this.declaration, String targetName)
: super(helper, token, null, targetName);
@override
String get _debugName => "TypeUseGenerator";
@ -2489,7 +2542,7 @@ class TypeUseGenerator extends ReadOnlyAccessGenerator {
}
}
return new NamedTypeBuilder(
_plainNameForRead, nullabilityBuilder, argumentBuilders)
targetName, nullabilityBuilder, argumentBuilders)
..bind(declaration);
}
@ -2542,16 +2595,6 @@ class TypeUseGenerator extends ReadOnlyAccessGenerator {
return super.expression;
}
@override
Expression _makeInvalidWrite(Expression value) {
return _helper.throwNoSuchMethodError(
_forest.createNullLiteral(fileOffset),
_plainNameForRead,
_forest.createArguments(fileOffset, <Expression>[value]),
fileOffset,
isSetter: true);
}
@override
buildPropertyAccess(
IncompleteSendGenerator send, int operatorOffset, bool isNullAware) {
@ -2604,7 +2647,7 @@ class TypeUseGenerator extends ReadOnlyAccessGenerator {
}
}
generator = new StaticAccessGenerator.fromBuilder(
_helper, member, send.token, setter);
_helper, name.name, member, send.token, setter);
}
return arguments == null
@ -2673,20 +2716,22 @@ class TypeUseGenerator extends ReadOnlyAccessGenerator {
/// }
///
class ReadOnlyAccessGenerator extends Generator {
@override
final String _plainNameForRead;
final String targetName;
Expression expression;
VariableDeclaration value;
ReadOnlyAccessGenerator(ExpressionGeneratorHelper helper, Token token,
this.expression, this._plainNameForRead)
this.expression, this.targetName)
: super(helper, token);
@override
String get _debugName => "ReadOnlyAccessGenerator";
@override
String get _plainNameForRead => targetName;
@override
Expression buildSimpleRead() => expression;
@ -2736,7 +2781,7 @@ class ReadOnlyAccessGenerator extends Generator {
@override
doInvocation(int offset, Arguments arguments) {
return _helper.buildMethodInvocation(buildSimpleRead(), callName, arguments,
adjustForImplicitCall(_plainNameForRead, offset),
adjustForImplicitCall(targetName, offset),
isImplicitCall: true);
}
@ -2746,7 +2791,7 @@ class ReadOnlyAccessGenerator extends Generator {
sink.write(", expression: ");
printNodeOn(expression, sink, syntheticNames: syntheticNames);
sink.write(", plainNameForRead: ");
sink.write(_plainNameForRead);
sink.write(targetName);
sink.write(", value: ");
printNodeOn(value, sink, syntheticNames: syntheticNames);
}
@ -3380,9 +3425,8 @@ class UnexpectedQualifiedUseGenerator extends Generator {
: super(helper, token);
@override
String get _plainNameForRead {
return "${prefixGenerator._plainNameForRead}.${token.lexeme}";
}
String get _plainNameForRead =>
"${prefixGenerator._plainNameForRead}.${token.lexeme}";
@override
String get _debugName => "UnexpectedQualifiedUseGenerator";

View file

@ -197,6 +197,10 @@ ExplicitExtensionArgumentMismatch/analyzerCode: Fail
ExplicitExtensionArgumentMismatch/example: Fail
ExplicitExtensionTypeArgumentMismatch/analyzerCode: Fail
ExplicitExtensionTypeArgumentMismatch/example: Fail
ExplicitExtensionAsExpression/analyzerCode: Fail
ExplicitExtensionAsExpression/example: Fail
ExplicitExtensionAsLvalue/analyzerCode: Fail
ExplicitExtensionAsLvalue/example: Fail
ExportAfterPart/part_wrapped_script1: Fail
ExportAfterPart/script1: Fail
ExpressionNotMetadata/analyzerCode: Fail

View file

@ -3706,3 +3706,9 @@ ExplicitExtensionArgumentMismatch:
ExplicitExtensionTypeArgumentMismatch:
template: "Explicit extension application of extension '#name' takes '#count' type argument(s)."
ExplicitExtensionAsExpression:
template: "Explicit extension application cannot be used as an expression."
ExplicitExtensionAsLvalue:
template: "Explicit extension application cannot be a target for assignment."

View file

@ -161,9 +161,10 @@ main() {
" getter: $uri::myGetter, setter: $uri::mySetter)",
new SuperIndexedAccessGenerator(helper, token, index, getter, setter));
check(
"StaticAccessGenerator(offset: 4, readTarget: $uri::myGetter,"
"StaticAccessGenerator(offset: 4, targetName: foo,"
" readTarget: $uri::myGetter,"
" writeTarget: $uri::mySetter)",
new StaticAccessGenerator(helper, token, getter, setter));
new StaticAccessGenerator(helper, token, 'foo', getter, setter));
check(
"LoadLibraryGenerator(offset: 4,"
" builder: Instance of 'LoadLibraryBuilder')",

View file

@ -0,0 +1,18 @@
// Copyright (c) 2019, 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.
class Class {}
extension Extension on Class {}
errors(Class c) {
Extension(c);
Extension(c) = 42;
Extension(c) += 42;
Extension(c)++;
++Extension(c);
}
main() {
}

View file

@ -0,0 +1,14 @@
library;
import self as self;
import "dart:core" as core;
class Class extends core::Object {
synthetic constructor •() → self::Class*
;
}
extension Extension on self::Class* {
}
static method errors(self::Class* c) → dynamic
;
static method main() → dynamic
;

View file

@ -0,0 +1,52 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/extensions/explicit_invalid_access.dart:10:3: Error: Explicit extension application cannot be used as an expression.
// Extension(c);
// ^^^^^^^^^
//
// pkg/front_end/testcases/extensions/explicit_invalid_access.dart:11:3: Error: Explicit extension application cannot be a target for assignment.
// Extension(c) = 42;
// ^^^^^^^^^
//
// pkg/front_end/testcases/extensions/explicit_invalid_access.dart:12:3: Error: Explicit extension application cannot be used as an expression.
// Extension(c) += 42;
// ^^^^^^^^^
//
// pkg/front_end/testcases/extensions/explicit_invalid_access.dart:13:3: Error: Explicit extension application cannot be used as an expression.
// Extension(c)++;
// ^^^^^^^^^
//
// pkg/front_end/testcases/extensions/explicit_invalid_access.dart:14:5: Error: Explicit extension application cannot be used as an expression.
// ++Extension(c);
// ^^^^^^^^^
//
import self as self;
import "dart:core" as core;
class Class extends core::Object {
synthetic constructor •() → self::Class*
: super core::Object::•()
;
}
extension Extension on self::Class* {
}
static method errors(self::Class* c) → dynamic {
invalid-expression "pkg/front_end/testcases/extensions/explicit_invalid_access.dart:10:3: Error: Explicit extension application cannot be used as an expression.
Extension(c);
^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/explicit_invalid_access.dart:11:3: Error: Explicit extension application cannot be a target for assignment.
Extension(c) = 42;
^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/explicit_invalid_access.dart:12:3: Error: Explicit extension application cannot be used as an expression.
Extension(c) += 42;
^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/explicit_invalid_access.dart:13:3: Error: Explicit extension application cannot be used as an expression.
Extension(c)++;
^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/explicit_invalid_access.dart:14:5: Error: Explicit extension application cannot be used as an expression.
++Extension(c);
^^^^^^^^^";
}
static method main() → dynamic {}

View file

@ -0,0 +1,52 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/extensions/explicit_invalid_access.dart:10:3: Error: Explicit extension application cannot be used as an expression.
// Extension(c);
// ^^^^^^^^^
//
// pkg/front_end/testcases/extensions/explicit_invalid_access.dart:11:3: Error: Explicit extension application cannot be a target for assignment.
// Extension(c) = 42;
// ^^^^^^^^^
//
// pkg/front_end/testcases/extensions/explicit_invalid_access.dart:12:3: Error: Explicit extension application cannot be used as an expression.
// Extension(c) += 42;
// ^^^^^^^^^
//
// pkg/front_end/testcases/extensions/explicit_invalid_access.dart:13:3: Error: Explicit extension application cannot be used as an expression.
// Extension(c)++;
// ^^^^^^^^^
//
// pkg/front_end/testcases/extensions/explicit_invalid_access.dart:14:5: Error: Explicit extension application cannot be used as an expression.
// ++Extension(c);
// ^^^^^^^^^
//
import self as self;
import "dart:core" as core;
class Class extends core::Object {
synthetic constructor •() → self::Class*
: super core::Object::•()
;
}
extension Extension on self::Class* {
}
static method errors(self::Class* c) → dynamic {
invalid-expression "pkg/front_end/testcases/extensions/explicit_invalid_access.dart:10:3: Error: Explicit extension application cannot be used as an expression.
Extension(c);
^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/explicit_invalid_access.dart:11:3: Error: Explicit extension application cannot be a target for assignment.
Extension(c) = 42;
^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/explicit_invalid_access.dart:12:3: Error: Explicit extension application cannot be used as an expression.
Extension(c) += 42;
^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/explicit_invalid_access.dart:13:3: Error: Explicit extension application cannot be used as an expression.
Extension(c)++;
^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/explicit_invalid_access.dart:14:5: Error: Explicit extension application cannot be used as an expression.
++Extension(c);
^^^^^^^^^";
}
static method main() → dynamic {}

View file

@ -18,6 +18,7 @@ extensions/dynamic_invoke: TextSerializationFailure
extensions/explicit_extension_access: TextSerializationFailure
extensions/explicit_extension_inference: TextSerializationFailure
extensions/explicit_generic_extension_access: TextSerializationFailure
extensions/explicit_invalid_access: TextSerializationFailure
extensions/explicit_this: TextSerializationFailure
extensions/extension_methods: TextSerializationFailure
extensions/extension_setter: TextSerializationFailure