Skip to content

Commit 847b2b1

Browse files
stereotype441commit-bot@chromium.org
authored andcommitted
Move "argument not assignable" checking to ResolverVisitor.
This should make it easier to implement "why not promoted" logic for arguments, since we'll be reporting the errors at a time when flow analysis information hasn't been discarded yet. Bug: #44898 Change-Id: I8499d711acc88b8397597b6116e5f6cfde43dc53 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/191805 Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Paul Berry <[email protected]>
1 parent 681d3e2 commit 847b2b1

File tree

3 files changed

+405
-379
lines changed

3 files changed

+405
-379
lines changed
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:analyzer/dart/ast/ast.dart';
6+
import 'package:analyzer/dart/element/element.dart';
7+
import 'package:analyzer/dart/element/type.dart';
8+
import 'package:analyzer/error/error.dart';
9+
import 'package:analyzer/error/listener.dart';
10+
import 'package:analyzer/src/dart/ast/extensions.dart';
11+
import 'package:analyzer/src/dart/element/type.dart';
12+
import 'package:analyzer/src/dart/element/type_system.dart';
13+
import 'package:analyzer/src/error/codes.dart';
14+
15+
/// Methods useful in detecting errors. This mixin exists to allow code to be
16+
/// more easily shared between the two visitors that do the majority of error
17+
/// reporting (ResolverVisitor and ErrorVerifier).
18+
mixin ErrorDetectionHelpers {
19+
ErrorReporter get errorReporter;
20+
21+
TypeSystemImpl get typeSystem;
22+
23+
/// Verify that the given [expression] can be assigned to its corresponding
24+
/// parameters. The [expectedStaticType] is the expected static type of the
25+
/// parameter. The [actualStaticType] is the actual static type of the
26+
/// argument.
27+
void checkForArgumentTypeNotAssignable(
28+
Expression expression,
29+
DartType? expectedStaticType,
30+
DartType actualStaticType,
31+
ErrorCode errorCode) {
32+
// Warning case: test static type information
33+
if (expectedStaticType != null) {
34+
if (!expectedStaticType.isVoid && checkForUseOfVoidResult(expression)) {
35+
return;
36+
}
37+
38+
checkForAssignableExpressionAtType(
39+
expression, actualStaticType, expectedStaticType, errorCode);
40+
}
41+
}
42+
43+
/// Verify that the given [argument] can be assigned to its corresponding
44+
/// parameter.
45+
///
46+
/// This method corresponds to
47+
/// [BestPracticesVerifier.checkForArgumentTypeNotAssignableForArgument].
48+
///
49+
/// See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE].
50+
void checkForArgumentTypeNotAssignableForArgument(Expression argument,
51+
{bool promoteParameterToNullable = false}) {
52+
checkForArgumentTypeNotAssignableForArgument2(
53+
argument: argument,
54+
parameter: argument.staticParameterElement,
55+
promoteParameterToNullable: promoteParameterToNullable,
56+
);
57+
}
58+
59+
void checkForArgumentTypeNotAssignableForArgument2({
60+
required Expression argument,
61+
required ParameterElement? parameter,
62+
required bool promoteParameterToNullable,
63+
}) {
64+
var staticParameterType = parameter?.type;
65+
if (promoteParameterToNullable && staticParameterType != null) {
66+
staticParameterType =
67+
typeSystem.makeNullable(staticParameterType as TypeImpl);
68+
}
69+
_checkForArgumentTypeNotAssignableWithExpectedTypes(argument,
70+
staticParameterType, CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE);
71+
}
72+
73+
bool checkForAssignableExpressionAtType(
74+
Expression expression,
75+
DartType actualStaticType,
76+
DartType expectedStaticType,
77+
ErrorCode errorCode) {
78+
if (!typeSystem.isAssignableTo(actualStaticType, expectedStaticType)) {
79+
AstNode getErrorNode(AstNode node) {
80+
if (node is CascadeExpression) {
81+
return getErrorNode(node.target);
82+
}
83+
if (node is ParenthesizedExpression) {
84+
return getErrorNode(node.expression);
85+
}
86+
return node;
87+
}
88+
89+
errorReporter.reportErrorForNode(
90+
errorCode,
91+
getErrorNode(expression),
92+
[actualStaticType, expectedStaticType],
93+
);
94+
return false;
95+
}
96+
return true;
97+
}
98+
99+
/// Check for situations where the result of a method or function is used,
100+
/// when it returns 'void'. Or, in rare cases, when other types of expressions
101+
/// are void, such as identifiers.
102+
///
103+
/// See [StaticWarningCode.USE_OF_VOID_RESULT].
104+
bool checkForUseOfVoidResult(Expression expression) {
105+
if (!identical(expression.staticType, VoidTypeImpl.instance)) {
106+
return false;
107+
}
108+
109+
if (expression is MethodInvocation) {
110+
SimpleIdentifier methodName = expression.methodName;
111+
errorReporter.reportErrorForNode(
112+
CompileTimeErrorCode.USE_OF_VOID_RESULT, methodName, []);
113+
} else {
114+
errorReporter.reportErrorForNode(
115+
CompileTimeErrorCode.USE_OF_VOID_RESULT, expression, []);
116+
}
117+
118+
return true;
119+
}
120+
121+
/// Verify that the given [expression] can be assigned to its corresponding
122+
/// parameters.
123+
///
124+
/// See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE],
125+
/// [CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE],
126+
/// [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE],
127+
/// [CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE],
128+
/// [CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE],
129+
/// [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], and
130+
/// [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE].
131+
void _checkForArgumentTypeNotAssignableWithExpectedTypes(
132+
Expression expression,
133+
DartType? expectedStaticType,
134+
ErrorCode errorCode) {
135+
checkForArgumentTypeNotAssignable(
136+
expression, expectedStaticType, expression.typeOrThrow, errorCode);
137+
}
138+
}

0 commit comments

Comments
 (0)