mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 12:24:24 +00:00
Suppress redundant tearoff errors when constructor tearoffs not enabled
Fixes https://github.com/dart-lang/sdk/issues/47035 Change-Id: I745da785d80744f84e3582727e423e4caed866c0 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/211720 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Samuel Rawlins <srawlins@google.com>
This commit is contained in:
parent
b12724b7c6
commit
873ecfd8fd
7 changed files with 76 additions and 10 deletions
|
@ -39,11 +39,16 @@ class ConstructorReferenceResolver {
|
|||
);
|
||||
}
|
||||
var name = node.constructorName.name;
|
||||
if (element == null && name != null) {
|
||||
if (element == null &&
|
||||
name != null &&
|
||||
_resolver.isConstructorTearoffsEnabled) {
|
||||
// The illegal construction, which looks like a type-instantiated
|
||||
// constructor tearoff, may be an attempt to reference a member on
|
||||
// [enclosingElement]. Try to provide a helpful error, and fall back to
|
||||
// "unknown constructor."
|
||||
//
|
||||
// Only report errors when the constructor tearoff feature is enabled,
|
||||
// to avoid reporting redundant errors.
|
||||
var enclosingElement = node.constructorName.type.name.staticElement;
|
||||
if (enclosingElement is TypeAliasElement) {
|
||||
enclosingElement = enclosingElement.aliasedType.element;
|
||||
|
|
|
@ -186,11 +186,15 @@ class FunctionReferenceResolver {
|
|||
/// with what the user may be intending.
|
||||
void _resolveDisallowedExpression(
|
||||
FunctionReferenceImpl node, DartType? rawType) {
|
||||
_errorReporter.reportErrorForNode(
|
||||
CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION,
|
||||
node.function,
|
||||
[],
|
||||
);
|
||||
if (_resolver.isConstructorTearoffsEnabled) {
|
||||
// Only report constructor tearoff-related errors if the constructor
|
||||
// tearoff feature is enabled.
|
||||
_errorReporter.reportErrorForNode(
|
||||
CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION,
|
||||
node.function,
|
||||
[],
|
||||
);
|
||||
}
|
||||
_resolve(node: node, rawType: rawType);
|
||||
}
|
||||
|
||||
|
|
|
@ -761,6 +761,20 @@ class ResolutionVisitor extends RecursiveAstVisitor<void> {
|
|||
void visitInstanceCreationExpression(InstanceCreationExpression node) {
|
||||
var newNode = _astRewriter.instanceCreationExpression(_nameScope, node);
|
||||
if (newNode != node) {
|
||||
if (node.constructorName.type.typeArguments != null &&
|
||||
newNode is MethodInvocation &&
|
||||
newNode.target is FunctionReference &&
|
||||
!_libraryElement.featureSet.isEnabled(Feature.constructor_tearoffs)) {
|
||||
// A function reference with explicit type arguments (an expression of
|
||||
// the form `a<...>.m(...)` or `p.a<...>.m(...)` where `a` does not
|
||||
// refer to a class name, nor a type alias), is illegal without the
|
||||
// constructor tearoff feature.
|
||||
//
|
||||
// This is a case where the parser does not report an error, because the
|
||||
// parser thinks this could be an InstanceCreationExpression.
|
||||
_errorReporter.reportErrorForNode(
|
||||
HintCode.SDK_VERSION_CONSTRUCTOR_TEAROFFS, node, []);
|
||||
}
|
||||
return newNode.accept(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -805,6 +805,29 @@ bar() {
|
|||
@reflectiveTest
|
||||
class ConstructorReferenceResolutionWithoutConstructorTearoffsTest
|
||||
extends PubPackageResolutionTest with WithoutConstructorTearoffsMixin {
|
||||
test_class_generic_nonConstructor() async {
|
||||
await assertErrorsInCode('''
|
||||
class A<T> {
|
||||
static int i = 1;
|
||||
}
|
||||
|
||||
void bar() {
|
||||
A<int>.i;
|
||||
}
|
||||
''', [
|
||||
error(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 52, 5),
|
||||
]);
|
||||
|
||||
var classElement = findElement.class_('A');
|
||||
assertConstructorReference(
|
||||
findNode.constructorReference('A<int>.i;'),
|
||||
null,
|
||||
classElement,
|
||||
'dynamic',
|
||||
expectedTypeNameType: 'A<int>',
|
||||
);
|
||||
}
|
||||
|
||||
test_constructorTearoff() async {
|
||||
await assertErrorsInCode('''
|
||||
class A {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// 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:analyzer/src/dart/error/syntactic_errors.dart';
|
||||
import 'package:analyzer/src/error/codes.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
|
@ -10,6 +11,8 @@ import 'context_collection_resolution.dart';
|
|||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(FunctionReferenceResolutionTest);
|
||||
defineReflectiveTests(
|
||||
FunctionReferenceResolutionWithoutConstructorTearoffsTest);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -996,3 +999,24 @@ void bar() {
|
|||
findNode.functionReference('foo<int>;'), null, 'dynamic');
|
||||
}
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class FunctionReferenceResolutionWithoutConstructorTearoffsTest
|
||||
extends PubPackageResolutionTest with WithoutConstructorTearoffsMixin {
|
||||
test_localVariable() async {
|
||||
// This code includes a disallowed type instantiation (local variable),
|
||||
// but in the case that the experiment is not enabled, we suppress the
|
||||
// associated error.
|
||||
await assertErrorsInCode('''
|
||||
void bar(void Function<T>(T a) foo) {
|
||||
foo<int>;
|
||||
}
|
||||
''', [
|
||||
error(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 43, 5),
|
||||
]);
|
||||
|
||||
var reference = findNode.functionReference('foo<int>;');
|
||||
assertFunctionReference(
|
||||
reference, findElement.parameter('foo'), 'void Function(int)');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,8 +100,6 @@ main() {
|
|||
// ^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR
|
||||
Foo.bar<int>.baz();
|
||||
//^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION
|
||||
// ^
|
||||
// [cfe] Couldn't find constructor 'bar'.
|
||||
// ^^^
|
||||
|
|
|
@ -102,8 +102,6 @@ main() {
|
|||
// ^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR
|
||||
Foo.bar<int>.baz();
|
||||
//^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION
|
||||
// ^
|
||||
// [cfe] Couldn't find constructor 'bar'.
|
||||
// ^^^
|
||||
|
|
Loading…
Reference in a new issue