Verify the index of IndexExpression with both read and write elements.

Change-Id: Ie680d47c04469d0289b71026a5826a4cd3701ec3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/154440
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov 2020-07-15 17:21:54 +00:00 committed by commit-bot@chromium.org
parent 2fcdfbbd6c
commit 0f14f0e71f
2 changed files with 72 additions and 6 deletions

View file

@ -40,6 +40,7 @@ import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
import 'package:analyzer/src/generated/sdk.dart' show DartSdk, SdkLibrary;
import 'package:analyzer/src/task/strong/checker.dart';
import 'package:meta/meta.dart';
class EnclosingExecutableContext {
final ExecutableElement element;
@ -798,7 +799,22 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
@override
void visitIndexExpression(IndexExpression node) {
_checkForArgumentTypeNotAssignableForArgument(node.index);
void checkIndexExpression(MethodElement method) {
if (method != null) {
var parameters = method.parameters;
if (parameters.isNotEmpty) {
_checkForArgumentTypeNotAssignableForArgument2(
argument: node.index,
parameter: parameters[0],
promoteParameterToNullable: false,
);
}
}
}
checkIndexExpression(node.staticElement);
checkIndexExpression(node.auxiliaryElements?.staticElement);
if (node.isNullAware) {
var target = node.realTarget;
if (_isExpressionWithType(target)) {
@ -1455,12 +1471,24 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
/// See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE].
void _checkForArgumentTypeNotAssignableForArgument(Expression argument,
{bool promoteParameterToNullable = false}) {
// TODO(scheglov) probably cannot happen
if (argument == null) {
return;
}
ParameterElement staticParameterElement = argument.staticParameterElement;
DartType staticParameterType = staticParameterElement?.type;
_checkForArgumentTypeNotAssignableForArgument2(
argument: argument,
parameter: argument.staticParameterElement,
promoteParameterToNullable: promoteParameterToNullable,
);
}
void _checkForArgumentTypeNotAssignableForArgument2({
@required Expression argument,
@required ParameterElement parameter,
@required bool promoteParameterToNullable,
}) {
DartType staticParameterType = parameter?.type;
if (promoteParameterToNullable && staticParameterType != null) {
staticParameterType = _typeSystem.makeNullable(staticParameterType);
}

View file

@ -180,15 +180,53 @@ class A {
]);
}
test_index() async {
test_index_invalidRead() async {
await assertErrorsInCode('''
class A {
operator [](int index) {}
int operator [](int index) => 0;
}
f(A a) {
a['0'];
}''', [
error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 53, 3),
error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 60, 3),
]);
}
test_index_invalidRead_validWrite() async {
await assertErrorsInCode('''
class A {
int operator [](int index) => 0;
operator []=(String index, int value) {}
}
f(A a) {
a['0'] += 0;
}''', [
error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 103, 3),
]);
}
test_index_invalidWrite() async {
await assertErrorsInCode('''
class A {
operator []=(int index, int value) {}
}
f(A a) {
a['0'] = 0;
}''', [
error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 65, 3),
]);
}
test_index_validRead_invalidWrite() async {
await assertErrorsInCode('''
class A {
int operator [](String index) => 0;
operator []=(int index, int value) {}
}
f(A a) {
a['0'] += 0;
}''', [
error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 103, 3),
]);
}