checkLValue for array indexing expression should resolve set method #KT-7218 Fixed
This commit is contained in:
+23
-7
@@ -835,8 +835,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression);
|
context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression);
|
||||||
|
JetExpression stubExpression = ExpressionTypingUtils.createFakeExpressionOfType(baseExpression.getProject(), context.trace, "$e", type);
|
||||||
checkLValue(context.trace, baseExpression);
|
checkLValue(context.trace, context, baseExpression, stubExpression);
|
||||||
}
|
}
|
||||||
// TODO : Maybe returnType?
|
// TODO : Maybe returnType?
|
||||||
result = receiverType;
|
result = receiverType;
|
||||||
@@ -939,18 +939,34 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
/**
|
/**
|
||||||
* @return {@code true} iff expression can be assigned to
|
* @return {@code true} iff expression can be assigned to
|
||||||
*/
|
*/
|
||||||
public static boolean checkLValue(@NotNull BindingTrace trace, @NotNull JetExpression expression) {
|
public boolean checkLValue(
|
||||||
return checkLValue(trace, expression, false);
|
@NotNull BindingTrace trace,
|
||||||
|
@NotNull ExpressionTypingContext context,
|
||||||
|
@NotNull JetExpression expression,
|
||||||
|
@NotNull JetExpression rightHandSide
|
||||||
|
) {
|
||||||
|
return checkLValue(trace, context, expression, rightHandSide, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean checkLValue(@NotNull BindingTrace trace, @NotNull JetExpression expressionWithParenthesis, boolean canBeThis) {
|
private boolean checkLValue(
|
||||||
|
@NotNull BindingTrace trace,
|
||||||
|
@NotNull ExpressionTypingContext context,
|
||||||
|
@NotNull JetExpression expressionWithParenthesis,
|
||||||
|
@NotNull JetExpression rightHandSide,
|
||||||
|
boolean canBeThis
|
||||||
|
) {
|
||||||
JetExpression expression = JetPsiUtil.deparenthesize(expressionWithParenthesis);
|
JetExpression expression = JetPsiUtil.deparenthesize(expressionWithParenthesis);
|
||||||
if (expression instanceof JetArrayAccessExpression) {
|
if (expression instanceof JetArrayAccessExpression) {
|
||||||
JetExpression arrayExpression = ((JetArrayAccessExpression) expression).getArrayExpression();
|
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) expression;
|
||||||
|
JetExpression arrayExpression = arrayAccessExpression.getArrayExpression();
|
||||||
if (arrayExpression == null) return false;
|
if (arrayExpression == null) return false;
|
||||||
|
|
||||||
return checkLValue(trace, arrayExpression, true);
|
TemporaryBindingTrace ignoreReportsTrace = TemporaryBindingTrace.create(trace, "Trace for checking set function");
|
||||||
|
ExpressionTypingContext findSetterContext = context.replaceBindingTrace(ignoreReportsTrace);
|
||||||
|
JetTypeInfo info = resolveArrayAccessSetMethod(arrayAccessExpression, rightHandSide, findSetterContext, ignoreReportsTrace);
|
||||||
|
return info.getType() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canBeThis && expression instanceof JetThisExpression) return true;
|
if (canBeThis && expression instanceof JetThisExpression) return true;
|
||||||
VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), expression, true);
|
VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), expression, true);
|
||||||
|
|
||||||
|
|||||||
+5
-4
@@ -269,7 +269,8 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
JetType binaryOperationType;
|
JetType binaryOperationType;
|
||||||
TemporaryTraceAndCache temporaryForBinaryOperation = TemporaryTraceAndCache.create(
|
TemporaryTraceAndCache temporaryForBinaryOperation = TemporaryTraceAndCache.create(
|
||||||
context, "trace to check binary operation like '+' for", expression);
|
context, "trace to check binary operation like '+' for", expression);
|
||||||
boolean lhsAssignable = BasicExpressionTypingVisitor.checkLValue(TemporaryBindingTrace.create(context.trace, "Trace for checking assignability"), left);
|
TemporaryBindingTrace ignoreReportsTrace = TemporaryBindingTrace.create(context.trace, "Trace for checking assignability");
|
||||||
|
boolean lhsAssignable = basic.checkLValue(ignoreReportsTrace, context, left, right);
|
||||||
if (assignmentOperationType == null || lhsAssignable) {
|
if (assignmentOperationType == null || lhsAssignable) {
|
||||||
// Check for '+'
|
// Check for '+'
|
||||||
Name counterpartName = OperatorConventions.BINARY_OPERATION_NAMES.get(OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(operationType));
|
Name counterpartName = OperatorConventions.BINARY_OPERATION_NAMES.get(OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(operationType));
|
||||||
@@ -314,7 +315,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
}
|
}
|
||||||
dataFlowInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
|
dataFlowInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
|
||||||
DataFlowUtils.checkType(binaryOperationType, expression, context.replaceExpectedType(leftType).replaceDataFlowInfo(dataFlowInfo));
|
DataFlowUtils.checkType(binaryOperationType, expression, context.replaceExpectedType(leftType).replaceDataFlowInfo(dataFlowInfo));
|
||||||
BasicExpressionTypingVisitor.checkLValue(context.trace, leftOperand);
|
basic.checkLValue(context.trace, context, leftOperand, right);
|
||||||
}
|
}
|
||||||
temporary.commit();
|
temporary.commit();
|
||||||
return JetTypeInfo.create(checkAssignmentType(type, expression, contextWithExpectedType), dataFlowInfo);
|
return JetTypeInfo.create(checkAssignmentType(type, expression, contextWithExpectedType), dataFlowInfo);
|
||||||
@@ -331,7 +332,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left;
|
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left;
|
||||||
if (right == null) return JetTypeInfo.create(null, context.dataFlowInfo);
|
if (right == null) return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||||
JetTypeInfo typeInfo = basic.resolveArrayAccessSetMethod(arrayAccessExpression, right, context, context.trace);
|
JetTypeInfo typeInfo = basic.resolveArrayAccessSetMethod(arrayAccessExpression, right, context, context.trace);
|
||||||
BasicExpressionTypingVisitor.checkLValue(context.trace, arrayAccessExpression);
|
basic.checkLValue(context.trace, context, arrayAccessExpression, right);
|
||||||
return JetTypeInfo.create(checkAssignmentType(typeInfo.getType(), expression, contextWithExpectedType),
|
return JetTypeInfo.create(checkAssignmentType(typeInfo.getType(), expression, contextWithExpectedType),
|
||||||
typeInfo.getDataFlowInfo());
|
typeInfo.getDataFlowInfo());
|
||||||
}
|
}
|
||||||
@@ -349,7 +350,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (leftType != null && leftOperand != null) { //if leftType == null, some other error has been generated
|
if (leftType != null && leftOperand != null) { //if leftType == null, some other error has been generated
|
||||||
BasicExpressionTypingVisitor.checkLValue(context.trace, leftOperand);
|
basic.checkLValue(context.trace, context, leftOperand, right);
|
||||||
}
|
}
|
||||||
return DataFlowUtils.checkStatementType(expression, contextWithExpectedType, dataFlowInfo);
|
return DataFlowUtils.checkStatementType(expression, contextWithExpectedType, dataFlowInfo);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
fun getArray(): Array<Int> = throw Exception()
|
||||||
|
fun getList(): MutableList<Int> = throw Exception()
|
||||||
|
fun fn() {
|
||||||
|
getArray()[1] = 2
|
||||||
|
getList()[1] = 2
|
||||||
|
getArray()[1]++
|
||||||
|
getList()[1]++
|
||||||
|
getArray()[1] += 2
|
||||||
|
getList()[1] += 2
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
internal fun fn(): kotlin.Unit
|
||||||
|
internal fun getArray(): kotlin.Array<kotlin.Int>
|
||||||
|
internal fun getList(): kotlin.MutableList<kotlin.Int>
|
||||||
@@ -127,12 +127,12 @@ class Test() {
|
|||||||
a[4]++
|
a[4]++
|
||||||
a[6] += 43
|
a[6] += 43
|
||||||
|
|
||||||
<!VARIABLE_EXPECTED!>ab.getArray()<!>[54] = 23
|
ab.getArray()[54] = 23
|
||||||
<!VARIABLE_EXPECTED!>ab.getArray()<!>[54]++
|
ab.getArray()[54]++
|
||||||
|
|
||||||
(@f a)[3] = 4
|
(@f a)[3] = 4
|
||||||
(a : Array<Int>)[4]++
|
(a : Array<Int>)[4]++
|
||||||
(<!VARIABLE_EXPECTED!>ab.getArray()<!> : Array<Int>)[54] += 43
|
(ab.getArray() : Array<Int>)[54] += 43
|
||||||
|
|
||||||
this<!NO_SET_METHOD!><!UNRESOLVED_REFERENCE!>[<!>54<!UNRESOLVED_REFERENCE!>]<!><!> = 34
|
this<!NO_SET_METHOD!><!UNRESOLVED_REFERENCE!>[<!>54<!UNRESOLVED_REFERENCE!>]<!><!> = 34
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,6 +144,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("AssignToArrayElement.kt")
|
||||||
|
public void testAssignToArrayElement() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/AssignToArrayElement.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("AutoCreatedIt.kt")
|
@TestMetadata("AutoCreatedIt.kt")
|
||||||
public void testAutoCreatedIt() throws Exception {
|
public void testAutoCreatedIt() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/AutoCreatedIt.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/AutoCreatedIt.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user