Retain data flow info after assignment statements
#KT-2825 In Progress
This commit is contained in:
+25
-14
@@ -23,19 +23,22 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.*;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
|
import org.jetbrains.jet.lang.resolve.ModifiersChecker;
|
||||||
|
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
|
||||||
|
import org.jetbrains.jet.lang.resolve.TopDownAnalyzer;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
|
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsUtil;
|
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsUtil;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||||
import org.jetbrains.jet.lang.types.JetTypeInfo;
|
|
||||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
import org.jetbrains.jet.lang.types.JetTypeInfo;
|
||||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||||
|
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -182,16 +185,20 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
JetSimpleNameExpression operationSign = expression.getOperationReference();
|
JetSimpleNameExpression operationSign = expression.getOperationReference();
|
||||||
IElementType operationType = operationSign.getReferencedNameElementType();
|
IElementType operationType = operationSign.getReferencedNameElementType();
|
||||||
JetType result;
|
JetType result;
|
||||||
|
DataFlowInfo dataFlowInfo;
|
||||||
if (operationType == JetTokens.EQ) {
|
if (operationType == JetTokens.EQ) {
|
||||||
result = visitAssignment(expression, context);
|
JetTypeInfo typeInfo = visitAssignment(expression, context);
|
||||||
|
result = typeInfo.getType();
|
||||||
|
dataFlowInfo = typeInfo.getDataFlowInfo();
|
||||||
}
|
}
|
||||||
else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
|
else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
|
||||||
result = visitAssignmentOperation(expression, context);
|
result = visitAssignmentOperation(expression, context);
|
||||||
|
dataFlowInfo = context.dataFlowInfo;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return facade.getTypeInfo(expression, context);
|
return facade.getTypeInfo(expression, context);
|
||||||
}
|
}
|
||||||
return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo);
|
return DataFlowUtils.checkType(result, expression, context, dataFlowInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected JetType visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
protected JetType visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
||||||
@@ -263,25 +270,29 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
return checkAssignmentType(type, expression, contextWithExpectedType);
|
return checkAssignmentType(type, expression, contextWithExpectedType);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected JetType visitAssignment(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
@NotNull
|
||||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
protected JetTypeInfo visitAssignment(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
||||||
|
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceScope(scope);
|
||||||
JetExpression left = context.expressionTypingServices.deparenthesize(expression.getLeft(), context);
|
JetExpression left = context.expressionTypingServices.deparenthesize(expression.getLeft(), context);
|
||||||
JetExpression right = expression.getRight();
|
JetExpression right = expression.getRight();
|
||||||
if (left instanceof JetArrayAccessExpression) {
|
if (left instanceof JetArrayAccessExpression) {
|
||||||
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left;
|
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left;
|
||||||
if (right == null) return null;
|
if (right == null) return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||||
JetType assignmentType = basic.resolveArrayAccessSetMethod(arrayAccessExpression, right, context.replaceScope(scope), context.trace);
|
JetType assignmentType = basic.resolveArrayAccessSetMethod(arrayAccessExpression, right, context, context.trace);
|
||||||
basic.checkLValue(context.trace, arrayAccessExpression);
|
basic.checkLValue(context.trace, arrayAccessExpression);
|
||||||
return checkAssignmentType(assignmentType, expression, contextWithExpectedType);
|
return JetTypeInfo.create(checkAssignmentType(assignmentType, expression, contextWithExpectedType), context.dataFlowInfo);
|
||||||
}
|
}
|
||||||
JetType leftType = facade.getTypeInfo(expression.getLeft(), context.replaceScope(scope)).getType();
|
JetTypeInfo leftInfo = facade.getTypeInfo(expression.getLeft(), context);
|
||||||
|
JetType leftType = leftInfo.getType();
|
||||||
|
DataFlowInfo dataFlowInfo = leftInfo.getDataFlowInfo();
|
||||||
if (right != null) {
|
if (right != null) {
|
||||||
JetType rightType = facade.getTypeInfo(right, context.replaceExpectedType(leftType).replaceScope(scope)).getType();
|
JetTypeInfo rightInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo).replaceExpectedType(leftType));
|
||||||
|
dataFlowInfo = rightInfo.getDataFlowInfo();
|
||||||
}
|
}
|
||||||
if (leftType != null) { //if leftType == null, some another error has been generated
|
if (leftType != null) { //if leftType == null, some another error has been generated
|
||||||
basic.checkLValue(context.trace, expression.getLeft());
|
basic.checkLValue(context.trace, expression.getLeft());
|
||||||
}
|
}
|
||||||
return DataFlowUtils.checkStatementType(expression, contextWithExpectedType);
|
return DataFlowUtils.checkStatementType(expression, contextWithExpectedType, dataFlowInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
trait A
|
||||||
|
trait B : A {
|
||||||
|
fun foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bar1(a: A, var b: B) {
|
||||||
|
b = a as B
|
||||||
|
a.foo()
|
||||||
|
b.foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun id(b: B) = b
|
||||||
|
fun bar2(a: A, var b: B) {
|
||||||
|
b = id(a as B)
|
||||||
|
a.foo()
|
||||||
|
b.foo()
|
||||||
|
}
|
||||||
@@ -1141,6 +1141,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
|||||||
doTest("compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ArrayAccess.kt");
|
doTest("compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ArrayAccess.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Assignment.kt")
|
||||||
|
public void testAssignment() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/dataFlowInfoTraversal/Assignment.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("AssignmentInInitializer.kt")
|
@TestMetadata("AssignmentInInitializer.kt")
|
||||||
public void testAssignmentInInitializer() throws Exception {
|
public void testAssignmentInInitializer() throws Exception {
|
||||||
doTest("compiler/testData/diagnostics/tests/dataFlowInfoTraversal/AssignmentInInitializer.kt");
|
doTest("compiler/testData/diagnostics/tests/dataFlowInfoTraversal/AssignmentInInitializer.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user