Skip to content

[Analyzer] Cause CompileTimeError in analyzer when use 'Function' as a type: #45735

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion pkg/analyzer/lib/error/error.dart
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,6 @@ const List<ErrorCode> errorCodeValues = [
HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH,
HintCode.DEAD_CODE_ON_CATCH_SUBTYPE,
HintCode.DEPRECATED_EXTENDS_FUNCTION,
HintCode.DEPRECATED_FUNCTION_CLASS_DECLARATION,
HintCode.DEPRECATED_MEMBER_USE,
HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE,
HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE_WITH_MESSAGE,
Expand Down
1 change: 0 additions & 1 deletion pkg/analyzer/lib/src/error/codes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13720,7 +13720,6 @@ class CompileTimeErrorCode extends AnalyzerErrorCode {
"The type '{0}' implied by the 'yield' expression must be assignable "
"to '{1}'.",
hasPublishedDocs: true);

/**
* Initialize a newly created error code to have the given [name]. The message
* associated with the error will be created from the given [message]
Expand Down
79 changes: 75 additions & 4 deletions pkg/analyzer/lib/src/generated/error_verifier.dart
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,7 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
_checkForBuiltInIdentifierAsName(
name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_EXTENSION_NAME);
}
_checkExtensionBadFunctionUse(node);
super.visitExtensionDeclaration(node);
_enclosingExtension = null;
}
Expand Down Expand Up @@ -959,6 +960,7 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
_checkForMainFunction(node.name);
_checkForWrongTypeParameterVarianceInSuperinterfaces();
// _checkForBadFunctionUse(node);
_checkMixinBasFunctionUse(node);
super.visitMixinDeclaration(node);
} finally {
_enclosingClass = outerClass;
Expand Down Expand Up @@ -1575,20 +1577,89 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
}
}

/// Verifies that the mixin is not named `Function` and that its type
/// parameters don't named `Function`.
void _checkMixinBasFunctionUse(MixinDeclaration node) {
final functionToken = "Function";
var typeParams = node.typeParameters;
var onClause = node.onClause;
if (node.name.name == functionToken) {
errorReporter.reportErrorForNode(
CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME, node.name,
[functionToken]);
}
if (typeParams != null) {
for (TypeParameter parameter in typeParams.typeParameters) {
if (parameter.name.name == functionToken) {
errorReporter.reportErrorForNode(
CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME,
parameter, [functionToken]);
}
}
}
// Check Mixin OnClause
if (onClause != null) {
for (TypeName type in onClause.superclassConstraints) {
var mixinElement = type.name.staticElement;
if (mixinElement != null && mixinElement.name == functionToken) {
errorReporter.reportErrorForNode(
CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, type,
[type.name],
);
}
}
}
}

/// Verifies that the extension is not named `Function` and that its type
/// parameters don't named `Function`.
void _checkExtensionBadFunctionUse(ExtensionDeclaration node) {
final functionToken = "Function";
var typeParams = node.typeParameters;
if (node.name != null && node.name?.name == functionToken) {
errorReporter.reportErrorForNode(
CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_EXTENSION_NAME, node.name
!, [functionToken]);
}
if (typeParams != null) {
for (TypeParameter parameter in typeParams.typeParameters) {
if (parameter.name.name == functionToken) {
errorReporter.reportErrorForNode(
CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME,
parameter, [functionToken]);
}
}
}
}

/// Verifies that the class is not named `Function` and that it doesn't
/// extends/implements/mixes in `Function`.
/// Also Verifies that the class's type parameters is not named `Function`.
void _checkForBadFunctionUse(ClassDeclaration node) {
var extendsClause = node.extendsClause;
var withClause = node.withClause;
var typeParams = node.typeParameters;
final functionToken = "Function";

if (node.name.name == "Function") {
if (node.name.name == functionToken) {
errorReporter.reportErrorForNode(
HintCode.DEPRECATED_FUNCTION_CLASS_DECLARATION, node.name);
CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME, node.name,
[functionToken]);
}

if (typeParams != null) {
for (TypeParameter parameter in typeParams.typeParameters) {
if (parameter.name.name == functionToken) {
errorReporter.reportErrorForNode(
CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME,
parameter, [functionToken]);
}
}
}

if (extendsClause != null) {
var superElement = extendsClause.superclass.name.staticElement;
if (superElement != null && superElement.name == "Function") {
if (superElement != null && superElement.name == functionToken) {
errorReporter.reportErrorForNode(
HintCode.DEPRECATED_EXTENDS_FUNCTION, extendsClause.superclass);
}
Expand All @@ -1597,7 +1668,7 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
if (withClause != null) {
for (TypeName type in withClause.mixinTypes) {
var mixinElement = type.name.staticElement;
if (mixinElement != null && mixinElement.name == "Function") {
if (mixinElement != null && mixinElement.name == functionToken) {
errorReporter.reportErrorForNode(
HintCode.DEPRECATED_MIXIN_FUNCTION, type);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.

import 'package:analyzer/src/dart/error/hint_codes.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../dart/resolution/context_collection_resolution.dart';
Expand All @@ -28,7 +29,7 @@ class A extends Function {}
class Function {}
class A extends Function {}
''', [
error(HintCode.DEPRECATED_FUNCTION_CLASS_DECLARATION, 6, 8),
error(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME, 6, 8),
error(HintCode.DEPRECATED_EXTENDS_FUNCTION, 34, 8),
]);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) 2021, 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:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../dart/resolution/context_collection_resolution.dart';

main() {
defineReflectiveSuite(() {
defineReflectiveTests(DeprecatedFunctionAsTypeIdentifierTest);
});
}

@reflectiveTest
class DeprecatedFunctionAsTypeIdentifierTest extends PubPackageResolutionTest {
test_typedef() async {
await assertErrorsInCode('''
typedef Function = int;
typedef F<Function> = int;
''', [
error(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 8, 8),
]);
}

test_extension() async {
await assertErrorsInCode('''
extension Function on List {}
extension E<Function> on List<Function> {}
''', [
error(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_EXTENSION_NAME, 10, 8),
error(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME, 42, 8),
]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +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/hint_codes.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../dart/resolution/context_collection_resolution.dart';
Expand All @@ -19,7 +19,17 @@ class DeprecatedFunctionClassDeclarationTest extends PubPackageResolutionTest {
await assertErrorsInCode('''
class Function {}
''', [
error(HintCode.DEPRECATED_FUNCTION_CLASS_DECLARATION, 6, 8),
error(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME, 6, 8),
]);
}

test_typeparameter() async {
await assertErrorsInCode('''
class Function {}
class C<Function> {}
''', [
error(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME, 6, 8),
error(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME, 26, 8),
]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.

import 'package:analyzer/src/dart/error/hint_codes.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../dart/resolution/context_collection_resolution.dart';
Expand All @@ -28,8 +29,26 @@ class A extends Object with Function {}
class Function {}
class A extends Object with Function {}
''', [
error(HintCode.DEPRECATED_FUNCTION_CLASS_DECLARATION, 6, 8),
error(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME, 6, 8),
error(HintCode.DEPRECATED_MIXIN_FUNCTION, 46, 8),
]);
}

test_mixin() async {
await assertErrorsInCode('''
mixin Function {}
mixin M<Function> implements List<Function> {}
''', [
error(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME, 6, 8),
error(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME, 26, 8),
]);
}

test_mixin_onclause() async {
await assertErrorsInCode('''
mixin A on Function {}
''', [
error(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 11, 8),
]);
}
}
3 changes: 3 additions & 0 deletions pkg/analyzer/test/src/diagnostics/test_all.dart
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ import 'deferred_import_of_extension_test.dart' as deferred_import_of_extension;
import 'definitely_unassigned_late_local_variable_test.dart'
as definitely_unassigned_late_local_variable;
import 'deprecated_extends_function_test.dart' as deprecated_extends_function;
import 'deprecated_function_as_type_identifier_test.dart'
as deprecated_function_as_type_identifier;
import 'deprecated_function_class_declaration_test.dart'
as deprecated_function_class_declaration;
import 'deprecated_member_use_test.dart' as deprecated_member_use;
Expand Down Expand Up @@ -766,6 +768,7 @@ main() {
deferred_import_of_extension.main();
definitely_unassigned_late_local_variable.main();
deprecated_extends_function.main();
deprecated_function_as_type_identifier.main();
deprecated_function_class_declaration.main();
deprecated_member_use.main();
deprecated_mixin_function.main();
Expand Down