-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
@mustBeConst
annotation for parameters which should be
constant. As const-only parameters are not planned, see dart-lang/language#1684, an annotation with analyzer support could help a bit at least, see #29381. The motivation is to enforce const arguments for methods annotated with `@ResourceIdentifier`, to be able to record the argument values at build time, see https://dart-review.googlesource.com/c/sdk/+/329961. Tested: pkg/analyzer/test/src/diagnostics/const_argument_test.dart Change-Id: I2b8d2dce0c899fc0caa4985d892a5d031c747521 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/357701 Reviewed-by: Phil Quitslund <[email protected]> Reviewed-by: Lasse Nielsen <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Moritz Sümmermann <[email protected]> Reviewed-by: Marya Belanger <[email protected]>
- Loading branch information
Showing
15 changed files
with
904 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
118 changes: 118 additions & 0 deletions
118
pkg/analyzer/lib/src/error/const_argument_verifier.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
// Copyright (c) 2024, 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/dart/ast/ast.dart'; | ||
import 'package:analyzer/dart/ast/syntactic_entity.dart'; | ||
import 'package:analyzer/dart/ast/token.dart'; | ||
import 'package:analyzer/dart/ast/visitor.dart'; | ||
import 'package:analyzer/dart/element/type.dart'; | ||
import 'package:analyzer/error/listener.dart'; | ||
import 'package:analyzer/src/dart/ast/utilities.dart'; | ||
import 'package:analyzer/src/dart/element/element.dart'; | ||
import 'package:analyzer/src/error/codes.dart'; | ||
|
||
/// Checks if the arguments for a parameter label as `@mustBeConst` are actually | ||
/// constant. | ||
class ConstArgumentsVerifier extends SimpleAstVisitor<void> { | ||
final ErrorReporter _errorReporter; | ||
|
||
final ConstantEvaluator _constantEvaluator; | ||
|
||
ConstArgumentsVerifier(this._errorReporter) | ||
: _constantEvaluator = ConstantEvaluator(); | ||
|
||
@override | ||
void visitAssignmentExpression(AssignmentExpression node) { | ||
if (node.operator.type == TokenType.EQ) { | ||
_check( | ||
arguments: [node.rightHandSide], | ||
errorNode: node.operator, | ||
); | ||
} else if (node.rightHandSide.staticParameterElement?.hasMustBeConst ?? | ||
false) { | ||
// If the operator is not `=`, then the argument cannot be const, as it | ||
// depends on the value of the left hand side. | ||
_errorReporter.atNode( | ||
node.rightHandSide, | ||
WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, | ||
arguments: [node.rightHandSide], | ||
); | ||
} | ||
} | ||
|
||
@override | ||
void visitBinaryExpression(BinaryExpression node) { | ||
_check( | ||
arguments: [node.rightOperand], | ||
errorNode: node.operator, | ||
); | ||
} | ||
|
||
@override | ||
void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { | ||
if (node.staticInvokeType is FunctionType) { | ||
_check( | ||
arguments: node.argumentList.arguments, | ||
errorNode: node, | ||
); | ||
} | ||
} | ||
|
||
@override | ||
void visitIndexExpression(IndexExpression node) { | ||
_check( | ||
arguments: [node.index], | ||
errorNode: node.leftBracket, | ||
); | ||
} | ||
|
||
@override | ||
void visitInstanceCreationExpression(InstanceCreationExpression node) { | ||
if (node.inConstantContext) return; | ||
_check( | ||
arguments: node.argumentList.arguments, | ||
errorNode: node.constructorName, | ||
); | ||
} | ||
|
||
@override | ||
void visitMethodInvocation(MethodInvocation node) { | ||
_check( | ||
arguments: node.argumentList.arguments, | ||
errorNode: node.methodName, | ||
); | ||
} | ||
|
||
void _check({ | ||
required List<Expression> arguments, | ||
required SyntacticEntity errorNode, | ||
}) { | ||
for (final argument in arguments) { | ||
final parameter = argument.staticParameterElement; | ||
if (parameter != null && parameter.hasMustBeConst) { | ||
Expression resolvedArgument; | ||
if (parameter.isNamed) { | ||
resolvedArgument = (argument as NamedExpression).expression; | ||
} else { | ||
resolvedArgument = argument; | ||
} | ||
if (resolvedArgument is Identifier) { | ||
final staticElement = resolvedArgument.staticElement; | ||
if (staticElement != null && | ||
staticElement.nonSynthetic is ConstVariableElement) { | ||
return; | ||
} | ||
} | ||
if (resolvedArgument.accept(_constantEvaluator) == | ||
ConstantEvaluator.NOT_A_CONSTANT) { | ||
_errorReporter.atNode( | ||
argument, | ||
WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, | ||
arguments: [parameter.name], | ||
); | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.