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 {
|
||||
context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression);
|
||||
|
||||
checkLValue(context.trace, baseExpression);
|
||||
JetExpression stubExpression = ExpressionTypingUtils.createFakeExpressionOfType(baseExpression.getProject(), context.trace, "$e", type);
|
||||
checkLValue(context.trace, context, baseExpression, stubExpression);
|
||||
}
|
||||
// TODO : Maybe returnType?
|
||||
result = receiverType;
|
||||
@@ -939,18 +939,34 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
/**
|
||||
* @return {@code true} iff expression can be assigned to
|
||||
*/
|
||||
public static boolean checkLValue(@NotNull BindingTrace trace, @NotNull JetExpression expression) {
|
||||
return checkLValue(trace, expression, false);
|
||||
public boolean checkLValue(
|
||||
@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);
|
||||
if (expression instanceof JetArrayAccessExpression) {
|
||||
JetExpression arrayExpression = ((JetArrayAccessExpression) expression).getArrayExpression();
|
||||
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) expression;
|
||||
JetExpression arrayExpression = arrayAccessExpression.getArrayExpression();
|
||||
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;
|
||||
VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), expression, true);
|
||||
|
||||
|
||||
+5
-4
@@ -269,7 +269,8 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
JetType binaryOperationType;
|
||||
TemporaryTraceAndCache temporaryForBinaryOperation = TemporaryTraceAndCache.create(
|
||||
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) {
|
||||
// Check for '+'
|
||||
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();
|
||||
DataFlowUtils.checkType(binaryOperationType, expression, context.replaceExpectedType(leftType).replaceDataFlowInfo(dataFlowInfo));
|
||||
BasicExpressionTypingVisitor.checkLValue(context.trace, leftOperand);
|
||||
basic.checkLValue(context.trace, context, leftOperand, right);
|
||||
}
|
||||
temporary.commit();
|
||||
return JetTypeInfo.create(checkAssignmentType(type, expression, contextWithExpectedType), dataFlowInfo);
|
||||
@@ -331,7 +332,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left;
|
||||
if (right == null) return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
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),
|
||||
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
|
||||
BasicExpressionTypingVisitor.checkLValue(context.trace, leftOperand);
|
||||
basic.checkLValue(context.trace, context, leftOperand, right);
|
||||
}
|
||||
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[6] += 43
|
||||
|
||||
<!VARIABLE_EXPECTED!>ab.getArray()<!>[54] = 23
|
||||
<!VARIABLE_EXPECTED!>ab.getArray()<!>[54]++
|
||||
ab.getArray()[54] = 23
|
||||
ab.getArray()[54]++
|
||||
|
||||
(@f a)[3] = 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
|
||||
}
|
||||
|
||||
@@ -144,6 +144,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
||||
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")
|
||||
public void testAutoCreatedIt() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/AutoCreatedIt.kt");
|
||||
|
||||
Reference in New Issue
Block a user