DataFlowUtils -> DataFlowAnalyzer and make it a component
This commit is contained in:
@@ -41,13 +41,14 @@ import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator
|
|||||||
import org.jetbrains.kotlin.types.ErrorUtils
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
import org.jetbrains.kotlin.types.JetType
|
import org.jetbrains.kotlin.types.JetType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.expressions.DataFlowUtils
|
import org.jetbrains.kotlin.types.expressions.DataFlowAnalyzer
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
|
||||||
public class CallCompleter(
|
public class CallCompleter(
|
||||||
private val argumentTypeResolver: ArgumentTypeResolver,
|
private val argumentTypeResolver: ArgumentTypeResolver,
|
||||||
private val candidateResolver: CandidateResolver,
|
private val candidateResolver: CandidateResolver,
|
||||||
private val symbolUsageValidator: SymbolUsageValidator,
|
private val symbolUsageValidator: SymbolUsageValidator,
|
||||||
|
private val dataFlowAnalyzer: DataFlowAnalyzer,
|
||||||
private val builtIns: KotlinBuiltIns
|
private val builtIns: KotlinBuiltIns
|
||||||
) {
|
) {
|
||||||
fun <D : CallableDescriptor> completeCall(
|
fun <D : CallableDescriptor> completeCall(
|
||||||
@@ -260,7 +261,7 @@ public class CallCompleter(
|
|||||||
argumentTypeResolver.getCallableReferenceTypeInfo(expression, callableReferenceArgument, context, RESOLVE_FUNCTION_ARGUMENTS)
|
argumentTypeResolver.getCallableReferenceTypeInfo(expression, callableReferenceArgument, context, RESOLVE_FUNCTION_ARGUMENTS)
|
||||||
}
|
}
|
||||||
|
|
||||||
DataFlowUtils.checkType(updatedType, deparenthesized, context)
|
dataFlowAnalyzer.checkType(updatedType, deparenthesized, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun completeCallForArgument(
|
private fun completeCallForArgument(
|
||||||
|
|||||||
+11
-5
@@ -45,7 +45,10 @@ import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator;
|
|||||||
import org.jetbrains.kotlin.types.ErrorUtils;
|
import org.jetbrains.kotlin.types.ErrorUtils;
|
||||||
import org.jetbrains.kotlin.types.JetType;
|
import org.jetbrains.kotlin.types.JetType;
|
||||||
import org.jetbrains.kotlin.types.TypeUtils;
|
import org.jetbrains.kotlin.types.TypeUtils;
|
||||||
import org.jetbrains.kotlin.types.expressions.*;
|
import org.jetbrains.kotlin.types.expressions.DataFlowAnalyzer;
|
||||||
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
|
||||||
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
|
||||||
|
import org.jetbrains.kotlin.types.expressions.JetTypeInfo;
|
||||||
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryPackage;
|
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryPackage;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -63,15 +66,18 @@ public class CallExpressionResolver {
|
|||||||
private final CallResolver callResolver;
|
private final CallResolver callResolver;
|
||||||
private final ConstantExpressionEvaluator constantExpressionEvaluator;
|
private final ConstantExpressionEvaluator constantExpressionEvaluator;
|
||||||
private final SymbolUsageValidator symbolUsageValidator;
|
private final SymbolUsageValidator symbolUsageValidator;
|
||||||
|
private final DataFlowAnalyzer dataFlowAnalyzer;
|
||||||
|
|
||||||
public CallExpressionResolver(
|
public CallExpressionResolver(
|
||||||
@NotNull CallResolver callResolver,
|
@NotNull CallResolver callResolver,
|
||||||
@NotNull ConstantExpressionEvaluator constantExpressionEvaluator,
|
@NotNull ConstantExpressionEvaluator constantExpressionEvaluator,
|
||||||
@NotNull SymbolUsageValidator symbolUsageValidator
|
@NotNull SymbolUsageValidator symbolUsageValidator,
|
||||||
|
@NotNull DataFlowAnalyzer dataFlowAnalyzer
|
||||||
) {
|
) {
|
||||||
this.callResolver = callResolver;
|
this.callResolver = callResolver;
|
||||||
this.constantExpressionEvaluator = constantExpressionEvaluator;
|
this.constantExpressionEvaluator = constantExpressionEvaluator;
|
||||||
this.symbolUsageValidator = symbolUsageValidator;
|
this.symbolUsageValidator = symbolUsageValidator;
|
||||||
|
this.dataFlowAnalyzer = dataFlowAnalyzer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExpressionTypingServices expressionTypingServices;
|
private ExpressionTypingServices expressionTypingServices;
|
||||||
@@ -182,7 +188,7 @@ public class CallExpressionResolver {
|
|||||||
) {
|
) {
|
||||||
JetTypeInfo typeInfo = getCallExpressionTypeInfoWithoutFinalTypeCheck(callExpression, receiver, callOperationNode, context);
|
JetTypeInfo typeInfo = getCallExpressionTypeInfoWithoutFinalTypeCheck(callExpression, receiver, callOperationNode, context);
|
||||||
if (context.contextDependency == INDEPENDENT) {
|
if (context.contextDependency == INDEPENDENT) {
|
||||||
DataFlowUtils.checkType(typeInfo.getType(), callExpression, context);
|
dataFlowAnalyzer.checkType(typeInfo.getType(), callExpression, context);
|
||||||
}
|
}
|
||||||
return typeInfo;
|
return typeInfo;
|
||||||
}
|
}
|
||||||
@@ -379,7 +385,7 @@ public class CallExpressionResolver {
|
|||||||
|
|
||||||
CompileTimeConstant<?> value = constantExpressionEvaluator.evaluateExpression(expression, context.trace, context.expectedType);
|
CompileTimeConstant<?> value = constantExpressionEvaluator.evaluateExpression(expression, context.trace, context.expectedType);
|
||||||
if (value != null && value.getIsPure()) {
|
if (value != null && value.getIsPure()) {
|
||||||
return ExpressionTypingUtils.createCompileTimeConstantTypeInfo(value, expression, context);
|
return dataFlowAnalyzer.createCompileTimeConstantTypeInfo(value, expression, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
JetTypeInfo typeInfo;
|
JetTypeInfo typeInfo;
|
||||||
@@ -424,7 +430,7 @@ public class CallExpressionResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (context.contextDependency == INDEPENDENT) {
|
if (context.contextDependency == INDEPENDENT) {
|
||||||
DataFlowUtils.checkType(typeInfo.getType(), expression, context);
|
dataFlowAnalyzer.checkType(typeInfo.getType(), expression, context);
|
||||||
}
|
}
|
||||||
return typeInfo;
|
return typeInfo;
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-29
@@ -96,7 +96,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
// TODO : type substitutions???
|
// TODO : type substitutions???
|
||||||
CallExpressionResolver callExpressionResolver = components.callExpressionResolver;
|
CallExpressionResolver callExpressionResolver = components.callExpressionResolver;
|
||||||
JetTypeInfo typeInfo = callExpressionResolver.getSimpleNameExpressionTypeInfo(expression, NO_RECEIVER, null, context);
|
JetTypeInfo typeInfo = callExpressionResolver.getSimpleNameExpressionTypeInfo(expression, NO_RECEIVER, null, context);
|
||||||
return DataFlowUtils.checkType(typeInfo, expression, context); // TODO : Extensions to this
|
return components.dataFlowAnalyzer.checkType(typeInfo, expression, context); // TODO : Extensions to this
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -125,7 +125,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert compileTimeConstant != null : "CompileTimeConstant should be evaluated for constant expression or an error should be recorded " + expression.getText();
|
assert compileTimeConstant != null : "CompileTimeConstant should be evaluated for constant expression or an error should be recorded " + expression.getText();
|
||||||
return createCompileTimeConstantTypeInfo(compileTimeConstant, expression, context);
|
return components.dataFlowAnalyzer.createCompileTimeConstantTypeInfo(compileTimeConstant, expression, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -175,7 +175,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
|
|
||||||
JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType.replaceExpectedType(targetType));
|
JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType.replaceExpectedType(targetType));
|
||||||
checkBinaryWithTypeRHS(expression, context, targetType, typeInfo.getType());
|
checkBinaryWithTypeRHS(expression, context, targetType, typeInfo.getType());
|
||||||
return DataFlowUtils.checkType(typeInfo.replaceType(targetType), expression, context);
|
return components.dataFlowAnalyzer.checkType(typeInfo.replaceType(targetType), expression, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType);
|
JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType);
|
||||||
@@ -193,7 +193,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JetType result = operationType == AS_SAFE ? TypeUtils.makeNullable(targetType) : targetType;
|
JetType result = operationType == AS_SAFE ? TypeUtils.makeNullable(targetType) : targetType;
|
||||||
return DataFlowUtils.checkType(typeInfo.replaceType(result), expression, context);
|
return components.dataFlowAnalyzer.checkType(typeInfo.replaceType(result), expression, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkBinaryWithTypeRHS(
|
private void checkBinaryWithTypeRHS(
|
||||||
@@ -241,7 +241,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
context.trace.report(USELESS_CAST.on(expression));
|
context.trace.report(USELESS_CAST.on(expression));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Collection<JetType> possibleTypes = DataFlowUtils.getAllPossibleTypes(
|
Collection<JetType> possibleTypes = components.dataFlowAnalyzer.getAllPossibleTypes(
|
||||||
expression.getLeft(), context.dataFlowInfo, actualType, context);
|
expression.getLeft(), context.dataFlowInfo, actualType, context);
|
||||||
|
|
||||||
boolean checkExactType = checkExactTypeForUselessCast(expression);
|
boolean checkExactType = checkExactTypeForUselessCast(expression);
|
||||||
@@ -295,7 +295,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
context.trace.recordType(expression.getInstanceReference(), result);
|
context.trace.recordType(expression.getInstanceReference(), result);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return TypeInfoFactoryPackage.createCheckedTypeInfo(result, context, expression);
|
return components.dataFlowAnalyzer.createCheckedTypeInfo(result, context, expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -319,7 +319,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
if (result != null) {
|
if (result != null) {
|
||||||
context.trace.recordType(expression.getInstanceReference(), result);
|
context.trace.recordType(expression.getInstanceReference(), result);
|
||||||
}
|
}
|
||||||
return TypeInfoFactoryPackage.createCheckedTypeInfo(result, context, expression);
|
return components.dataFlowAnalyzer.createCheckedTypeInfo(result, context, expression);
|
||||||
}
|
}
|
||||||
throw new IllegalStateException("Unknown code: " + resolutionResult.getCode());
|
throw new IllegalStateException("Unknown code: " + resolutionResult.getCode());
|
||||||
}
|
}
|
||||||
@@ -509,7 +509,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
public JetTypeInfo visitClassLiteralExpression(@NotNull JetClassLiteralExpression expression, ExpressionTypingContext c) {
|
public JetTypeInfo visitClassLiteralExpression(@NotNull JetClassLiteralExpression expression, ExpressionTypingContext c) {
|
||||||
JetType type = resolveClassLiteral(expression, c);
|
JetType type = resolveClassLiteral(expression, c);
|
||||||
if (type != null && !type.isError()) {
|
if (type != null && !type.isError()) {
|
||||||
return TypeInfoFactoryPackage.createCheckedTypeInfo(
|
return components.dataFlowAnalyzer.createCheckedTypeInfo(
|
||||||
components.reflectionTypes.getKClassType(Annotations.EMPTY, type), c, expression
|
components.reflectionTypes.getKClassType(Annotations.EMPTY, type), c, expression
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -604,11 +604,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
if (callableReference.getReferencedName().isEmpty()) {
|
if (callableReference.getReferencedName().isEmpty()) {
|
||||||
c.trace.report(UNRESOLVED_REFERENCE.on(callableReference, callableReference));
|
c.trace.report(UNRESOLVED_REFERENCE.on(callableReference, callableReference));
|
||||||
JetType errorType = ErrorUtils.createErrorType("Empty callable reference");
|
JetType errorType = ErrorUtils.createErrorType("Empty callable reference");
|
||||||
return TypeInfoFactoryPackage.createCheckedTypeInfo(errorType, c, expression);
|
return components.dataFlowAnalyzer.createCheckedTypeInfo(errorType, c, expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
JetType result = getCallableReferenceType(expression, receiverType, c);
|
JetType result = getCallableReferenceType(expression, receiverType, c);
|
||||||
return TypeInfoFactoryPackage.createCheckedTypeInfo(result, c, expression);
|
return components.dataFlowAnalyzer.createCheckedTypeInfo(result, c, expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -651,9 +651,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Breaks are not possible inside constructor arguments, so jumpPossible or jumpFlowInfo are not necessary here
|
// Breaks are not possible inside constructor arguments, so jumpPossible or jumpFlowInfo are not necessary here
|
||||||
JetTypeInfo resultTypeInfo = DataFlowUtils.checkType(TypeInfoFactoryPackage.createTypeInfo(result[0], resultFlowInfo),
|
JetTypeInfo resultTypeInfo = components.dataFlowAnalyzer.checkType(TypeInfoFactoryPackage.createTypeInfo(result[0], resultFlowInfo),
|
||||||
expression,
|
expression,
|
||||||
context);
|
context);
|
||||||
// We have to record it here,
|
// We have to record it here,
|
||||||
// otherwise ExpressionTypingVisitorDispatcher records wrong information
|
// otherwise ExpressionTypingVisitorDispatcher records wrong information
|
||||||
context.trace.record(EXPRESSION_TYPE_INFO, expression, resultTypeInfo);
|
context.trace.record(EXPRESSION_TYPE_INFO, expression, resultTypeInfo);
|
||||||
@@ -781,12 +781,12 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
expression, contextWithExpectedType.trace, contextWithExpectedType.expectedType
|
expression, contextWithExpectedType.trace, contextWithExpectedType.expectedType
|
||||||
);
|
);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
return createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
|
return components.dataFlowAnalyzer.createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
|
||||||
}
|
}
|
||||||
|
|
||||||
return DataFlowUtils.checkType(typeInfo.replaceType(result),
|
return components.dataFlowAnalyzer.checkType(typeInfo.replaceType(result),
|
||||||
expression,
|
expression,
|
||||||
contextWithExpectedType.replaceDataFlowInfo(typeInfo.getDataFlowInfo()));
|
contextWithExpectedType.replaceDataFlowInfo(typeInfo.getDataFlowInfo()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private JetTypeInfo visitExclExclExpression(@NotNull JetUnaryExpression expression, @NotNull ExpressionTypingContext context) {
|
private JetTypeInfo visitExclExclExpression(@NotNull JetUnaryExpression expression, @NotNull ExpressionTypingContext context) {
|
||||||
@@ -820,7 +820,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The call to checkType() is only needed here to execute additionalTypeCheckers, hence the NO_EXPECTED_TYPE
|
// The call to checkType() is only needed here to execute additionalTypeCheckers, hence the NO_EXPECTED_TYPE
|
||||||
return DataFlowUtils.checkType(baseTypeInfo.replaceType(resultingType), expression, context.replaceExpectedType(NO_EXPECTED_TYPE));
|
return components.dataFlowAnalyzer.checkType(baseTypeInfo.replaceType(resultingType), expression, context.replaceExpectedType(NO_EXPECTED_TYPE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -977,9 +977,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
expression, contextWithExpectedType.trace, contextWithExpectedType.expectedType
|
expression, contextWithExpectedType.trace, contextWithExpectedType.expectedType
|
||||||
);
|
);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
return createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
|
return components.dataFlowAnalyzer.createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
|
||||||
}
|
}
|
||||||
return DataFlowUtils.checkType(result, expression, contextWithExpectedType);
|
return components.dataFlowAnalyzer.checkType(result, expression, contextWithExpectedType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private JetTypeInfo visitEquality(
|
private JetTypeInfo visitEquality(
|
||||||
@@ -1092,7 +1092,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
WritableScopeImpl leftScope = newWritableScopeImpl(context, "Left scope of && or ||");
|
WritableScopeImpl leftScope = newWritableScopeImpl(context, "Left scope of && or ||");
|
||||||
// TODO: This gets computed twice: here and in extractDataFlowInfoFromCondition() for the whole condition
|
// TODO: This gets computed twice: here and in extractDataFlowInfoFromCondition() for the whole condition
|
||||||
boolean isAnd = operationType == JetTokens.ANDAND;
|
boolean isAnd = operationType == JetTokens.ANDAND;
|
||||||
DataFlowInfo flowInfoLeft = DataFlowUtils.extractDataFlowInfoFromCondition(left, isAnd, context).and(dataFlowInfo);
|
DataFlowInfo flowInfoLeft = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(left, isAnd, context).and(dataFlowInfo);
|
||||||
WritableScopeImpl rightScope = isAnd ? leftScope : newWritableScopeImpl(context, "Right scope of && or ||");
|
WritableScopeImpl rightScope = isAnd ? leftScope : newWritableScopeImpl(context, "Right scope of && or ||");
|
||||||
|
|
||||||
ExpressionTypingContext contextForRightExpr =
|
ExpressionTypingContext contextForRightExpr =
|
||||||
@@ -1149,10 +1149,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If break or continue was possible, take condition check info as the jump info
|
// If break or continue was possible, take condition check info as the jump info
|
||||||
return TypeInfoFactoryPackage.createTypeInfo(DataFlowUtils.checkType(type, expression, contextWithExpectedType),
|
return TypeInfoFactoryPackage.createTypeInfo(components.dataFlowAnalyzer.checkType(type, expression, contextWithExpectedType),
|
||||||
dataFlowInfo,
|
dataFlowInfo,
|
||||||
loopBreakContinuePossible,
|
loopBreakContinuePossible,
|
||||||
context.dataFlowInfo);
|
context.dataFlowInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -1265,7 +1265,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JetTypeInfo visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression, ExpressionTypingContext context) {
|
public JetTypeInfo visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression, ExpressionTypingContext context) {
|
||||||
return DataFlowUtils.checkType(resolveArrayAccessGetMethod(expression, context), expression, context);
|
return components.dataFlowAnalyzer.checkType(resolveArrayAccessGetMethod(expression, context), expression, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -1345,9 +1345,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
entry.accept(visitor);
|
entry.accept(visitor);
|
||||||
}
|
}
|
||||||
components.constantExpressionEvaluator.evaluateExpression(expression, context.trace, contextWithExpectedType.expectedType);
|
components.constantExpressionEvaluator.evaluateExpression(expression, context.trace, contextWithExpectedType.expectedType);
|
||||||
return DataFlowUtils.checkType(visitor.typeInfo.replaceType(components.builtIns.getStringType()),
|
return components.dataFlowAnalyzer.checkType(visitor.typeInfo.replaceType(components.builtIns.getStringType()),
|
||||||
expression,
|
expression,
|
||||||
contextWithExpectedType);
|
contextWithExpectedType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+8
-3
@@ -60,9 +60,14 @@ public class ControlStructureTypingUtils {
|
|||||||
private static final Logger LOG = Logger.getInstance(ControlStructureTypingUtils.class);
|
private static final Logger LOG = Logger.getInstance(ControlStructureTypingUtils.class);
|
||||||
|
|
||||||
private final CallResolver callResolver;
|
private final CallResolver callResolver;
|
||||||
|
private final DataFlowAnalyzer dataFlowAnalyzer;
|
||||||
|
|
||||||
public ControlStructureTypingUtils(@NotNull CallResolver callResolver) {
|
public ControlStructureTypingUtils(
|
||||||
|
@NotNull CallResolver callResolver,
|
||||||
|
@NotNull DataFlowAnalyzer dataFlowAnalyzer
|
||||||
|
) {
|
||||||
this.callResolver = callResolver;
|
this.callResolver = callResolver;
|
||||||
|
this.dataFlowAnalyzer = dataFlowAnalyzer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ ResolvedCall<FunctionDescriptor> resolveSpecialConstructionAsCall(
|
/*package*/ ResolvedCall<FunctionDescriptor> resolveSpecialConstructionAsCall(
|
||||||
@@ -245,7 +250,7 @@ public class ControlStructureTypingUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
/*package*/ static TracingStrategy createTracingForSpecialConstruction(
|
/*package*/ TracingStrategy createTracingForSpecialConstruction(
|
||||||
final @NotNull Call call,
|
final @NotNull Call call,
|
||||||
@NotNull String constructionName,
|
@NotNull String constructionName,
|
||||||
final @NotNull ExpressionTypingContext context
|
final @NotNull ExpressionTypingContext context
|
||||||
@@ -272,7 +277,7 @@ public class ControlStructureTypingUtils {
|
|||||||
if (typeInfo == null) return false;
|
if (typeInfo == null) return false;
|
||||||
|
|
||||||
Ref<Boolean> hasError = Ref.create();
|
Ref<Boolean> hasError = Ref.create();
|
||||||
DataFlowUtils.checkType(
|
dataFlowAnalyzer.checkType(
|
||||||
typeInfo.getType(),
|
typeInfo.getType(),
|
||||||
expression,
|
expression,
|
||||||
context
|
context
|
||||||
|
|||||||
+32
-25
@@ -26,7 +26,10 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
|||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
import org.jetbrains.kotlin.resolve.*;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||||
|
import org.jetbrains.kotlin.resolve.ModifiersChecker;
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
|
import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
||||||
@@ -99,8 +102,8 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
|
|
||||||
WritableScopeImpl thenScope = newWritableScopeImpl(context, "Then scope");
|
WritableScopeImpl thenScope = newWritableScopeImpl(context, "Then scope");
|
||||||
WritableScopeImpl elseScope = newWritableScopeImpl(context, "Else scope");
|
WritableScopeImpl elseScope = newWritableScopeImpl(context, "Else scope");
|
||||||
DataFlowInfo thenInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, true, context).and(conditionDataFlowInfo);
|
DataFlowInfo thenInfo = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(condition, true, context).and(conditionDataFlowInfo);
|
||||||
DataFlowInfo elseInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, context).and(conditionDataFlowInfo);
|
DataFlowInfo elseInfo = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(condition, false, context).and(conditionDataFlowInfo);
|
||||||
|
|
||||||
if (elseBranch == null) {
|
if (elseBranch == null) {
|
||||||
if (thenBranch != null) {
|
if (thenBranch != null) {
|
||||||
@@ -111,7 +114,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
? result.replaceJumpOutPossible(true).replaceJumpFlowInfo(conditionDataFlowInfo)
|
? result.replaceJumpOutPossible(true).replaceJumpFlowInfo(conditionDataFlowInfo)
|
||||||
: result;
|
: result;
|
||||||
}
|
}
|
||||||
return TypeInfoFactoryPackage.createTypeInfo(DataFlowUtils.checkImplicitCast(
|
return TypeInfoFactoryPackage.createTypeInfo(components.dataFlowAnalyzer.checkImplicitCast(
|
||||||
components.builtIns.getUnitType(), ifExpression,
|
components.builtIns.getUnitType(), ifExpression,
|
||||||
contextWithExpectedType, isStatement
|
contextWithExpectedType, isStatement
|
||||||
),
|
),
|
||||||
@@ -165,7 +168,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
JetType resultType = resolvedCall.getResultingDescriptor().getReturnType();
|
JetType resultType = resolvedCall.getResultingDescriptor().getReturnType();
|
||||||
// If break or continue was possible, take condition check info as the jump info
|
// If break or continue was possible, take condition check info as the jump info
|
||||||
return TypeInfoFactoryPackage
|
return TypeInfoFactoryPackage
|
||||||
.createTypeInfo(DataFlowUtils.checkImplicitCast(resultType, ifExpression, contextWithExpectedType, isStatement),
|
.createTypeInfo(components.dataFlowAnalyzer.checkImplicitCast(resultType, ifExpression, contextWithExpectedType, isStatement),
|
||||||
resultDataFlowInfo, loopBreakContinuePossible, conditionDataFlowInfo);
|
resultDataFlowInfo, loopBreakContinuePossible, conditionDataFlowInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,12 +193,16 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
} else {
|
} else {
|
||||||
dataFlowInfo = typeInfo.getDataFlowInfo().or(otherInfo);
|
dataFlowInfo = typeInfo.getDataFlowInfo().or(otherInfo);
|
||||||
}
|
}
|
||||||
return DataFlowUtils.checkImplicitCast(DataFlowUtils.checkType(typeInfo.replaceType(components.builtIns.getUnitType()),
|
return components.dataFlowAnalyzer.checkImplicitCast(
|
||||||
ifExpression,
|
components.dataFlowAnalyzer.checkType(
|
||||||
context),
|
typeInfo.replaceType(components.builtIns.getUnitType()),
|
||||||
ifExpression,
|
ifExpression,
|
||||||
context,
|
context
|
||||||
isStatement).replaceDataFlowInfo(dataFlowInfo);
|
),
|
||||||
|
ifExpression,
|
||||||
|
context,
|
||||||
|
isStatement
|
||||||
|
).replaceDataFlowInfo(dataFlowInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -204,7 +211,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public JetTypeInfo visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
public JetTypeInfo visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||||
if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade);
|
if (!isStatement) return components.dataFlowAnalyzer.illegalStatementType(expression, contextWithExpectedType, facade);
|
||||||
|
|
||||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(
|
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(
|
||||||
INDEPENDENT);
|
INDEPENDENT);
|
||||||
@@ -220,7 +227,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
|
|
||||||
JetExpression body = expression.getBody();
|
JetExpression body = expression.getBody();
|
||||||
JetTypeInfo bodyTypeInfo;
|
JetTypeInfo bodyTypeInfo;
|
||||||
DataFlowInfo conditionInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, true, context).and(dataFlowInfo);
|
DataFlowInfo conditionInfo = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(condition, true, context).and(dataFlowInfo);
|
||||||
if (body != null) {
|
if (body != null) {
|
||||||
WritableScopeImpl scopeToExtend = newWritableScopeImpl(context, "Scope extended in while's condition");
|
WritableScopeImpl scopeToExtend = newWritableScopeImpl(context, "Scope extended in while's condition");
|
||||||
bodyTypeInfo = components.expressionTypingServices.getBlockReturnedTypeWithWritableScope(
|
bodyTypeInfo = components.expressionTypingServices.getBlockReturnedTypeWithWritableScope(
|
||||||
@@ -233,7 +240,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
|
|
||||||
// Condition is false at this point only if there is no jumps outside
|
// Condition is false at this point only if there is no jumps outside
|
||||||
if (!containsJumpOutOfLoop(expression, context)) {
|
if (!containsJumpOutOfLoop(expression, context)) {
|
||||||
dataFlowInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, context).and(dataFlowInfo);
|
dataFlowInfo = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(condition, false, context).and(dataFlowInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case: while (true)
|
// Special case: while (true)
|
||||||
@@ -245,7 +252,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
// but without affecting changing variables
|
// but without affecting changing variables
|
||||||
dataFlowInfo = dataFlowInfo.and(loopVisitor.clearDataFlowInfoForAssignedLocalVariables(bodyTypeInfo.getJumpFlowInfo()));
|
dataFlowInfo = dataFlowInfo.and(loopVisitor.clearDataFlowInfoForAssignedLocalVariables(bodyTypeInfo.getJumpFlowInfo()));
|
||||||
}
|
}
|
||||||
return DataFlowUtils
|
return components.dataFlowAnalyzer
|
||||||
.checkType(bodyTypeInfo.replaceType(components.builtIns.getUnitType()), expression, contextWithExpectedType)
|
.checkType(bodyTypeInfo.replaceType(components.builtIns.getUnitType()), expression, contextWithExpectedType)
|
||||||
.replaceDataFlowInfo(dataFlowInfo);
|
.replaceDataFlowInfo(dataFlowInfo);
|
||||||
}
|
}
|
||||||
@@ -295,7 +302,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public JetTypeInfo visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
public JetTypeInfo visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||||
if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade);
|
if (!isStatement) return components.dataFlowAnalyzer.illegalStatementType(expression, contextWithExpectedType, facade);
|
||||||
|
|
||||||
ExpressionTypingContext context =
|
ExpressionTypingContext context =
|
||||||
contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
|
contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
|
||||||
@@ -335,7 +342,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
DataFlowInfo dataFlowInfo;
|
DataFlowInfo dataFlowInfo;
|
||||||
// Without jumps out, condition is entered and false, with jumps out, we know nothing about it
|
// Without jumps out, condition is entered and false, with jumps out, we know nothing about it
|
||||||
if (!containsJumpOutOfLoop(expression, context)) {
|
if (!containsJumpOutOfLoop(expression, context)) {
|
||||||
dataFlowInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, context).and(conditionDataFlowInfo);
|
dataFlowInfo = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(condition, false, context).and(conditionDataFlowInfo);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dataFlowInfo = context.dataFlowInfo;
|
dataFlowInfo = context.dataFlowInfo;
|
||||||
@@ -350,7 +357,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
// but without affecting changing variables
|
// but without affecting changing variables
|
||||||
dataFlowInfo = dataFlowInfo.and(loopVisitor.clearDataFlowInfoForAssignedLocalVariables(bodyTypeInfo.getJumpFlowInfo()));
|
dataFlowInfo = dataFlowInfo.and(loopVisitor.clearDataFlowInfoForAssignedLocalVariables(bodyTypeInfo.getJumpFlowInfo()));
|
||||||
}
|
}
|
||||||
return DataFlowUtils
|
return components.dataFlowAnalyzer
|
||||||
.checkType(bodyTypeInfo.replaceType(components.builtIns.getUnitType()), expression, contextWithExpectedType)
|
.checkType(bodyTypeInfo.replaceType(components.builtIns.getUnitType()), expression, contextWithExpectedType)
|
||||||
.replaceDataFlowInfo(dataFlowInfo);
|
.replaceDataFlowInfo(dataFlowInfo);
|
||||||
}
|
}
|
||||||
@@ -361,7 +368,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public JetTypeInfo visitForExpression(JetForExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
public JetTypeInfo visitForExpression(JetForExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||||
if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade);
|
if (!isStatement) return components.dataFlowAnalyzer.illegalStatementType(expression, contextWithExpectedType, facade);
|
||||||
|
|
||||||
ExpressionTypingContext context =
|
ExpressionTypingContext context =
|
||||||
contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
|
contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
|
||||||
@@ -413,7 +420,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
bodyTypeInfo = loopRangeInfo;
|
bodyTypeInfo = loopRangeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DataFlowUtils
|
return components.dataFlowAnalyzer
|
||||||
.checkType(bodyTypeInfo.replaceType(components.builtIns.getUnitType()), expression, contextWithExpectedType)
|
.checkType(bodyTypeInfo.replaceType(components.builtIns.getUnitType()), expression, contextWithExpectedType)
|
||||||
.replaceDataFlowInfo(loopRangeInfo.getDataFlowInfo());
|
.replaceDataFlowInfo(loopRangeInfo.getDataFlowInfo());
|
||||||
}
|
}
|
||||||
@@ -472,7 +479,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
VariableDescriptor variableDescriptor = components.descriptorResolver.resolveLocalVariableDescriptor(
|
VariableDescriptor variableDescriptor = components.descriptorResolver.resolveLocalVariableDescriptor(
|
||||||
context.scope, catchParameter, context.trace);
|
context.scope, catchParameter, context.trace);
|
||||||
JetType throwableType = components.builtIns.getThrowable().getDefaultType();
|
JetType throwableType = components.builtIns.getThrowable().getDefaultType();
|
||||||
DataFlowUtils.checkType(variableDescriptor.getType(), catchParameter, context.replaceExpectedType(throwableType));
|
components.dataFlowAnalyzer.checkType(variableDescriptor.getType(), catchParameter, context.replaceExpectedType(throwableType));
|
||||||
if (catchBody != null) {
|
if (catchBody != null) {
|
||||||
WritableScope catchScope = newWritableScopeImpl(context, "Catch scope");
|
WritableScope catchScope = newWritableScopeImpl(context, "Catch scope");
|
||||||
catchScope.addVariableDescriptor(variableDescriptor);
|
catchScope.addVariableDescriptor(variableDescriptor);
|
||||||
@@ -510,7 +517,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
facade.getTypeInfo(thrownExpression, context
|
facade.getTypeInfo(thrownExpression, context
|
||||||
.replaceExpectedType(throwableType).replaceScope(context.scope).replaceContextDependency(INDEPENDENT));
|
.replaceExpectedType(throwableType).replaceScope(context.scope).replaceContextDependency(INDEPENDENT));
|
||||||
}
|
}
|
||||||
return TypeInfoFactoryPackage.createCheckedTypeInfo(components.builtIns.getNothingType(), context, expression);
|
return components.dataFlowAnalyzer.createCheckedTypeInfo(components.builtIns.getNothingType(), context, expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -583,7 +590,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
context.trace.report(RETURN_TYPE_MISMATCH.on(expression, expectedType));
|
context.trace.report(RETURN_TYPE_MISMATCH.on(expression, expectedType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return TypeInfoFactoryPackage.createCheckedTypeInfo(resultType, context, expression);
|
return components.dataFlowAnalyzer.createCheckedTypeInfo(resultType, context, expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isClassInitializer(@NotNull Pair<FunctionDescriptor, PsiElement> containingFunInfo) {
|
private static boolean isClassInitializer(@NotNull Pair<FunctionDescriptor, PsiElement> containingFunInfo) {
|
||||||
@@ -594,14 +601,14 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
@Override
|
@Override
|
||||||
public JetTypeInfo visitBreakExpression(@NotNull JetBreakExpression expression, ExpressionTypingContext context) {
|
public JetTypeInfo visitBreakExpression(@NotNull JetBreakExpression expression, ExpressionTypingContext context) {
|
||||||
LabelResolver.INSTANCE.resolveControlLabel(expression, context);
|
LabelResolver.INSTANCE.resolveControlLabel(expression, context);
|
||||||
return TypeInfoFactoryPackage.createCheckedTypeInfo(components.builtIns.getNothingType(), context, expression).
|
return components.dataFlowAnalyzer.createCheckedTypeInfo(components.builtIns.getNothingType(), context, expression).
|
||||||
replaceJumpOutPossible(true);
|
replaceJumpOutPossible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JetTypeInfo visitContinueExpression(@NotNull JetContinueExpression expression, ExpressionTypingContext context) {
|
public JetTypeInfo visitContinueExpression(@NotNull JetContinueExpression expression, ExpressionTypingContext context) {
|
||||||
LabelResolver.INSTANCE.resolveControlLabel(expression, context);
|
LabelResolver.INSTANCE.resolveControlLabel(expression, context);
|
||||||
return TypeInfoFactoryPackage.createCheckedTypeInfo(components.builtIns.getNothingType(), context, expression).
|
return components.dataFlowAnalyzer.createCheckedTypeInfo(components.builtIns.getNothingType(), context, expression).
|
||||||
replaceJumpOutPossible(true);
|
replaceJumpOutPossible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+47
-16
@@ -26,13 +26,13 @@ import org.jetbrains.kotlin.lexer.JetTokens;
|
|||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver;
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
|
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue;
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue;
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastUtils;
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastUtils;
|
||||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstantChecker;
|
import org.jetbrains.kotlin.resolve.constants.*;
|
||||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
|
||||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
||||||
import org.jetbrains.kotlin.types.JetType;
|
import org.jetbrains.kotlin.types.JetType;
|
||||||
import org.jetbrains.kotlin.types.TypeUtils;
|
import org.jetbrains.kotlin.types.TypeUtils;
|
||||||
@@ -46,12 +46,10 @@ import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
|||||||
import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT;
|
import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT;
|
||||||
import static org.jetbrains.kotlin.types.TypeUtils.*;
|
import static org.jetbrains.kotlin.types.TypeUtils.*;
|
||||||
|
|
||||||
public class DataFlowUtils {
|
public class DataFlowAnalyzer {
|
||||||
private DataFlowUtils() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static DataFlowInfo extractDataFlowInfoFromCondition(
|
public DataFlowInfo extractDataFlowInfoFromCondition(
|
||||||
@Nullable JetExpression condition,
|
@Nullable JetExpression condition,
|
||||||
final boolean conditionValue,
|
final boolean conditionValue,
|
||||||
final ExpressionTypingContext context
|
final ExpressionTypingContext context
|
||||||
@@ -143,17 +141,17 @@ public class DataFlowUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static JetType checkType(@Nullable JetType expressionType, @NotNull JetExpression expression, @NotNull ResolutionContext context) {
|
public JetType checkType(@Nullable JetType expressionType, @NotNull JetExpression expression, @NotNull ResolutionContext context) {
|
||||||
return checkType(expressionType, expression, context, null);
|
return checkType(expressionType, expression, context, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JetTypeInfo checkType(@NotNull JetTypeInfo typeInfo, @NotNull JetExpression expression, @NotNull ResolutionContext context) {
|
public JetTypeInfo checkType(@NotNull JetTypeInfo typeInfo, @NotNull JetExpression expression, @NotNull ResolutionContext context) {
|
||||||
return typeInfo.replaceType(checkType(typeInfo.getType(), expression, context));
|
return typeInfo.replaceType(checkType(typeInfo.getType(), expression, context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static JetType checkType(
|
public JetType checkType(
|
||||||
@Nullable JetType expressionType,
|
@Nullable JetType expressionType,
|
||||||
@NotNull JetExpression expressionToCheck,
|
@NotNull JetExpression expressionToCheck,
|
||||||
@NotNull ResolutionContext c,
|
@NotNull ResolutionContext c,
|
||||||
@@ -195,7 +193,7 @@ public class DataFlowUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static JetType checkPossibleCast(
|
public JetType checkPossibleCast(
|
||||||
@NotNull JetType expressionType,
|
@NotNull JetType expressionType,
|
||||||
@NotNull JetExpression expression,
|
@NotNull JetExpression expression,
|
||||||
@NotNull ResolutionContext c
|
@NotNull ResolutionContext c
|
||||||
@@ -212,7 +210,7 @@ public class DataFlowUtils {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void recordExpectedType(@NotNull BindingTrace trace, @NotNull JetExpression expression, @NotNull JetType expectedType) {
|
public void recordExpectedType(@NotNull BindingTrace trace, @NotNull JetExpression expression, @NotNull JetType expectedType) {
|
||||||
if (expectedType != NO_EXPECTED_TYPE) {
|
if (expectedType != NO_EXPECTED_TYPE) {
|
||||||
JetType normalizeExpectedType = expectedType == UNIT_EXPECTED_TYPE ? KotlinBuiltIns.getInstance().getUnitType() : expectedType;
|
JetType normalizeExpectedType = expectedType == UNIT_EXPECTED_TYPE ? KotlinBuiltIns.getInstance().getUnitType() : expectedType;
|
||||||
trace.record(BindingContext.EXPECTED_EXPRESSION_TYPE, expression, normalizeExpectedType);
|
trace.record(BindingContext.EXPECTED_EXPRESSION_TYPE, expression, normalizeExpectedType);
|
||||||
@@ -220,7 +218,7 @@ public class DataFlowUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static JetType checkStatementType(@NotNull JetExpression expression, @NotNull ResolutionContext context) {
|
public JetType checkStatementType(@NotNull JetExpression expression, @NotNull ResolutionContext context) {
|
||||||
if (!noExpectedType(context.expectedType) && !KotlinBuiltIns.isUnit(context.expectedType) && !context.expectedType.isError()) {
|
if (!noExpectedType(context.expectedType) && !KotlinBuiltIns.isUnit(context.expectedType) && !context.expectedType.isError()) {
|
||||||
context.trace.report(EXPECTED_TYPE_MISMATCH.on(expression, context.expectedType));
|
context.trace.report(EXPECTED_TYPE_MISMATCH.on(expression, context.expectedType));
|
||||||
return null;
|
return null;
|
||||||
@@ -229,7 +227,7 @@ public class DataFlowUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static JetType checkImplicitCast(@Nullable JetType expressionType, @NotNull JetExpression expression, @NotNull ResolutionContext context, boolean isStatement) {
|
public JetType checkImplicitCast(@Nullable JetType expressionType, @NotNull JetExpression expression, @NotNull ResolutionContext context, boolean isStatement) {
|
||||||
if (expressionType != null && context.expectedType == NO_EXPECTED_TYPE && context.contextDependency == INDEPENDENT && !isStatement
|
if (expressionType != null && context.expectedType == NO_EXPECTED_TYPE && context.contextDependency == INDEPENDENT && !isStatement
|
||||||
&& (KotlinBuiltIns.isUnit(expressionType) || KotlinBuiltIns.isAnyOrNullableAny(expressionType))
|
&& (KotlinBuiltIns.isUnit(expressionType) || KotlinBuiltIns.isAnyOrNullableAny(expressionType))
|
||||||
&& !TypesPackage.isDynamic(expressionType)) {
|
&& !TypesPackage.isDynamic(expressionType)) {
|
||||||
@@ -239,12 +237,12 @@ public class DataFlowUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JetTypeInfo checkImplicitCast(@NotNull JetTypeInfo typeInfo, @NotNull JetExpression expression, @NotNull ResolutionContext context, boolean isStatement) {
|
public JetTypeInfo checkImplicitCast(@NotNull JetTypeInfo typeInfo, @NotNull JetExpression expression, @NotNull ResolutionContext context, boolean isStatement) {
|
||||||
return typeInfo.replaceType(checkImplicitCast(typeInfo.getType(), expression, context, isStatement));
|
return typeInfo.replaceType(checkImplicitCast(typeInfo.getType(), expression, context, isStatement));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JetTypeInfo illegalStatementType(@NotNull JetExpression expression, @NotNull ExpressionTypingContext context, @NotNull ExpressionTypingInternals facade) {
|
public JetTypeInfo illegalStatementType(@NotNull JetExpression expression, @NotNull ExpressionTypingContext context, @NotNull ExpressionTypingInternals facade) {
|
||||||
facade.checkStatementType(
|
facade.checkStatementType(
|
||||||
expression, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT));
|
expression, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT));
|
||||||
context.trace.report(EXPRESSION_EXPECTED.on(expression, expression));
|
context.trace.report(EXPRESSION_EXPECTED.on(expression, expression));
|
||||||
@@ -252,7 +250,7 @@ public class DataFlowUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static Collection<JetType> getAllPossibleTypes(
|
public Collection<JetType> getAllPossibleTypes(
|
||||||
@NotNull JetExpression expression,
|
@NotNull JetExpression expression,
|
||||||
@NotNull DataFlowInfo dataFlowInfo,
|
@NotNull DataFlowInfo dataFlowInfo,
|
||||||
@NotNull JetType type,
|
@NotNull JetType type,
|
||||||
@@ -265,4 +263,37 @@ public class DataFlowUtils {
|
|||||||
}
|
}
|
||||||
return possibleTypes;
|
return possibleTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JetTypeInfo createCheckedTypeInfo(
|
||||||
|
@Nullable JetType type,
|
||||||
|
@NotNull ResolutionContext<?> context,
|
||||||
|
@NotNull JetExpression expression
|
||||||
|
) {
|
||||||
|
return checkType(TypeInfoFactoryPackage.createTypeInfo(type, context), expression, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JetTypeInfo createCompileTimeConstantTypeInfo(
|
||||||
|
@NotNull CompileTimeConstant<?> value,
|
||||||
|
@NotNull JetExpression expression,
|
||||||
|
@NotNull ExpressionTypingContext context
|
||||||
|
) {
|
||||||
|
JetType expressionType;
|
||||||
|
if (value instanceof IntegerValueTypeConstant) {
|
||||||
|
IntegerValueTypeConstant integerValueTypeConstant = (IntegerValueTypeConstant) value;
|
||||||
|
if (context.contextDependency == INDEPENDENT) {
|
||||||
|
expressionType = integerValueTypeConstant.getType(context.expectedType);
|
||||||
|
ArgumentTypeResolver.updateNumberType(expressionType, expression, context.statementFilter, context.trace);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
expressionType = integerValueTypeConstant.getUnknownIntegerType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
expressionType = ((TypedCompileTimeConstant<?>) value).getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
return createCheckedTypeInfo(expressionType, context, expression);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+7
-1
@@ -52,6 +52,7 @@ public class ExpressionTypingComponents {
|
|||||||
/*package*/ MultiDeclarationResolver multiDeclarationResolver;
|
/*package*/ MultiDeclarationResolver multiDeclarationResolver;
|
||||||
/*package*/ ConstantExpressionEvaluator constantExpressionEvaluator;
|
/*package*/ ConstantExpressionEvaluator constantExpressionEvaluator;
|
||||||
/*package*/ ModifiersChecker modifiersChecker;
|
/*package*/ ModifiersChecker modifiersChecker;
|
||||||
|
/*package*/ DataFlowAnalyzer dataFlowAnalyzer;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public void setGlobalContext(@NotNull GlobalContext globalContext) {
|
public void setGlobalContext(@NotNull GlobalContext globalContext) {
|
||||||
@@ -164,7 +165,12 @@ public class ExpressionTypingComponents {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public void setModifiersChecker(ModifiersChecker modifiersChecker) {
|
public void setModifiersChecker(@NotNull ModifiersChecker modifiersChecker) {
|
||||||
this.modifiersChecker = modifiersChecker;
|
this.modifiersChecker = modifiersChecker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public void setDataFlowAnalyzer(@NotNull DataFlowAnalyzer dataFlowAnalyzer) {
|
||||||
|
this.dataFlowAnalyzer = dataFlowAnalyzer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-5
@@ -21,18 +21,14 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.analyzer.AnalyzerPackage;
|
import org.jetbrains.kotlin.analyzer.AnalyzerPackage;
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
|
import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
|
||||||
import org.jetbrains.kotlin.lexer.JetTokens;
|
import org.jetbrains.kotlin.lexer.JetTokens;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
import org.jetbrains.kotlin.resolve.*;
|
import org.jetbrains.kotlin.resolve.*;
|
||||||
import org.jetbrains.kotlin.resolve.callableReferences.CallableReferencesPackage;
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode;
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency;
|
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency;
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
|
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.JetScope;
|
import org.jetbrains.kotlin.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.WritableScope;
|
import org.jetbrains.kotlin.resolve.scopes.WritableScope;
|
||||||
@@ -174,7 +170,8 @@ public class ExpressionTypingServices {
|
|||||||
|
|
||||||
JetTypeInfo r;
|
JetTypeInfo r;
|
||||||
if (block.isEmpty()) {
|
if (block.isEmpty()) {
|
||||||
r = TypeInfoFactoryPackage.createCheckedTypeInfo(expressionTypingComponents.builtIns.getUnitType(), context, expression);
|
r = expressionTypingComponents.dataFlowAnalyzer
|
||||||
|
.createCheckedTypeInfo(expressionTypingComponents.builtIns.getUnitType(), context, expression);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
r = getBlockReturnedTypeWithWritableScope(scope, block, coercionStrategyForLastExpression,
|
r = getBlockReturnedTypeWithWritableScope(scope, block, coercionStrategyForLastExpression,
|
||||||
|
|||||||
-23
@@ -242,27 +242,4 @@ public class ExpressionTypingUtils {
|
|||||||
private ExpressionTypingUtils() {
|
private ExpressionTypingUtils() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static JetTypeInfo createCompileTimeConstantTypeInfo(
|
|
||||||
@NotNull CompileTimeConstant<?> value,
|
|
||||||
@NotNull JetExpression expression,
|
|
||||||
@NotNull ExpressionTypingContext context
|
|
||||||
) {
|
|
||||||
JetType expressionType;
|
|
||||||
if (value instanceof IntegerValueTypeConstant) {
|
|
||||||
IntegerValueTypeConstant integerValueTypeConstant = (IntegerValueTypeConstant) value;
|
|
||||||
if (context.contextDependency == INDEPENDENT) {
|
|
||||||
expressionType = integerValueTypeConstant.getType(context.expectedType);
|
|
||||||
ArgumentTypeResolver.updateNumberType(expressionType, expression, context.statementFilter, context.trace);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
expressionType = integerValueTypeConstant.getUnknownIntegerType();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
expressionType = ((TypedCompileTimeConstant<?>) value).getType();
|
|
||||||
}
|
|
||||||
|
|
||||||
return TypeInfoFactoryPackage.createCheckedTypeInfo(expressionType, context, expression);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-11
@@ -29,7 +29,9 @@ import org.jetbrains.kotlin.diagnostics.Errors;
|
|||||||
import org.jetbrains.kotlin.lexer.JetTokens;
|
import org.jetbrains.kotlin.lexer.JetTokens;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
import org.jetbrains.kotlin.resolve.*;
|
import org.jetbrains.kotlin.resolve.AnnotationResolver;
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
|
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace;
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache;
|
import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache;
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
|
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
|
||||||
@@ -80,7 +82,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static JetType checkAssignmentType(
|
private JetType checkAssignmentType(
|
||||||
@Nullable JetType assignmentType,
|
@Nullable JetType assignmentType,
|
||||||
@NotNull JetBinaryExpression expression,
|
@NotNull JetBinaryExpression expression,
|
||||||
@NotNull ExpressionTypingContext context
|
@NotNull ExpressionTypingContext context
|
||||||
@@ -90,7 +92,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
context.trace.report(Errors.ASSIGNMENT_TYPE_MISMATCH.on(expression, context.expectedType));
|
context.trace.report(Errors.ASSIGNMENT_TYPE_MISMATCH.on(expression, context.expectedType));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return DataFlowUtils.checkStatementType(expression, context);
|
return components.dataFlowAnalyzer.checkStatementType(expression, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -99,7 +101,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
scope, context.replaceScope(scope).replaceContextDependency(INDEPENDENT),
|
scope, context.replaceScope(scope).replaceContextDependency(INDEPENDENT),
|
||||||
scope.getContainingDeclaration(),
|
scope.getContainingDeclaration(),
|
||||||
declaration);
|
declaration);
|
||||||
return TypeInfoFactoryPackage.createTypeInfo(DataFlowUtils.checkStatementType(declaration, context), context);
|
return TypeInfoFactoryPackage.createTypeInfo(components.dataFlowAnalyzer.checkStatementType(declaration, context), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -163,7 +165,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
|
|
||||||
scope.addVariableDescriptor(propertyDescriptor);
|
scope.addVariableDescriptor(propertyDescriptor);
|
||||||
components.modifiersChecker.withTrace(context.trace).checkModifiersForLocalDeclaration(property, propertyDescriptor);
|
components.modifiersChecker.withTrace(context.trace).checkModifiersForLocalDeclaration(property, propertyDescriptor);
|
||||||
return typeInfo.replaceType(DataFlowUtils.checkStatementType(property, context));
|
return typeInfo.replaceType(components.dataFlowAnalyzer.checkStatementType(property, context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -183,7 +185,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
return TypeInfoFactoryPackage.noTypeInfo(context);
|
return TypeInfoFactoryPackage.noTypeInfo(context);
|
||||||
}
|
}
|
||||||
components.multiDeclarationResolver.defineLocalVariablesFromMultiDeclaration(scope, multiDeclaration, expressionReceiver, initializer, context);
|
components.multiDeclarationResolver.defineLocalVariablesFromMultiDeclaration(scope, multiDeclaration, expressionReceiver, initializer, context);
|
||||||
return typeInfo.replaceType(DataFlowUtils.checkStatementType(multiDeclaration, context));
|
return typeInfo.replaceType(components.dataFlowAnalyzer.checkStatementType(multiDeclaration, context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -197,7 +199,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
scope, context.replaceScope(scope).replaceContextDependency(INDEPENDENT),
|
scope, context.replaceScope(scope).replaceContextDependency(INDEPENDENT),
|
||||||
scope.getContainingDeclaration(),
|
scope.getContainingDeclaration(),
|
||||||
klass);
|
klass);
|
||||||
return TypeInfoFactoryPackage.createTypeInfo(DataFlowUtils.checkStatementType(klass, context), context);
|
return TypeInfoFactoryPackage.createTypeInfo(components.dataFlowAnalyzer.checkStatementType(klass, context), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -208,7 +210,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JetTypeInfo visitDeclaration(@NotNull JetDeclaration dcl, ExpressionTypingContext context) {
|
public JetTypeInfo visitDeclaration(@NotNull JetDeclaration dcl, ExpressionTypingContext context) {
|
||||||
return TypeInfoFactoryPackage.createTypeInfo(DataFlowUtils.checkStatementType(dcl, context), context);
|
return TypeInfoFactoryPackage.createTypeInfo(components.dataFlowAnalyzer.checkStatementType(dcl, context), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -225,7 +227,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
else {
|
else {
|
||||||
return facade.getTypeInfo(expression, context);
|
return facade.getTypeInfo(expression, context);
|
||||||
}
|
}
|
||||||
return DataFlowUtils.checkType(result, expression, context);
|
return components.dataFlowAnalyzer.checkType(result, expression, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -320,7 +322,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
basic.resolveArrayAccessSetMethod((JetArrayAccessExpression) left, right, contextForResolve, context.trace);
|
basic.resolveArrayAccessSetMethod((JetArrayAccessExpression) left, right, contextForResolve, context.trace);
|
||||||
}
|
}
|
||||||
rightInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(leftInfo.getDataFlowInfo()));
|
rightInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(leftInfo.getDataFlowInfo()));
|
||||||
DataFlowUtils.checkType(binaryOperationType, expression, context.replaceExpectedType(leftType).replaceDataFlowInfo(rightInfo.getDataFlowInfo()));
|
components.dataFlowAnalyzer.checkType(binaryOperationType, expression, context.replaceExpectedType(leftType).replaceDataFlowInfo(rightInfo.getDataFlowInfo()));
|
||||||
basic.checkLValue(context.trace, context, leftOperand, right);
|
basic.checkLValue(context.trace, context, leftOperand, right);
|
||||||
}
|
}
|
||||||
temporary.commit();
|
temporary.commit();
|
||||||
@@ -368,7 +370,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
|
||||||
basic.checkLValue(context.trace, context, leftOperand, right);
|
basic.checkLValue(context.trace, context, leftOperand, right);
|
||||||
}
|
}
|
||||||
return resultInfo.replaceType(DataFlowUtils.checkStatementType(expression, contextWithExpectedType));
|
return resultInfo.replaceType(components.dataFlowAnalyzer.checkStatementType(expression, contextWithExpectedType));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+7
-6
@@ -27,8 +27,11 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
|
|||||||
import org.jetbrains.kotlin.diagnostics.Errors.*
|
import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getAnnotationEntries
|
import org.jetbrains.kotlin.psi.psiUtil.getAnnotationEntries
|
||||||
import org.jetbrains.kotlin.resolve.*
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext.EXPECTED_RETURN_TYPE
|
import org.jetbrains.kotlin.resolve.BindingContext.EXPECTED_RETURN_TYPE
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContextUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||||
|
import org.jetbrains.kotlin.resolve.FunctionDescriptorUtil
|
||||||
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
|
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
|
||||||
import org.jetbrains.kotlin.resolve.scopes.WritableScope
|
import org.jetbrains.kotlin.resolve.scopes.WritableScope
|
||||||
import org.jetbrains.kotlin.resolve.source.toSourceElement
|
import org.jetbrains.kotlin.resolve.source.toSourceElement
|
||||||
@@ -39,9 +42,7 @@ import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE
|
|||||||
import org.jetbrains.kotlin.types.TypeUtils.noExpectedType
|
import org.jetbrains.kotlin.types.TypeUtils.noExpectedType
|
||||||
import org.jetbrains.kotlin.types.checker.JetTypeChecker
|
import org.jetbrains.kotlin.types.checker.JetTypeChecker
|
||||||
import org.jetbrains.kotlin.types.expressions.CoercionStrategy.COERCION_TO_UNIT
|
import org.jetbrains.kotlin.types.expressions.CoercionStrategy.COERCION_TO_UNIT
|
||||||
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createCheckedTypeInfo
|
|
||||||
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo
|
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo
|
||||||
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.noTypeInfo
|
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
|
||||||
public class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : ExpressionTypingVisitor(facade) {
|
public class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : ExpressionTypingVisitor(facade) {
|
||||||
@@ -109,10 +110,10 @@ public class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Express
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isStatement) {
|
if (isStatement) {
|
||||||
return createTypeInfo(DataFlowUtils.checkStatementType(function, context), context)
|
return createTypeInfo(components.dataFlowAnalyzer.checkStatementType(function, context), context)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return createCheckedTypeInfo(createFunctionType(functionDescriptor), context, function)
|
return components.dataFlowAnalyzer.createCheckedTypeInfo(createFunctionType(functionDescriptor), context, function)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,7 +152,7 @@ public class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Express
|
|||||||
return createTypeInfo(resultType, context)
|
return createTypeInfo(resultType, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
return createCheckedTypeInfo(resultType, context, expression)
|
return components.dataFlowAnalyzer.createCheckedTypeInfo(resultType, context, expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createFunctionLiteralDescriptor(
|
private fun createFunctionLiteralDescriptor(
|
||||||
|
|||||||
+7
-7
@@ -67,7 +67,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
DataFlowInfo newDataFlowInfo = conditionInfo.and(typeInfo.getDataFlowInfo());
|
DataFlowInfo newDataFlowInfo = conditionInfo.and(typeInfo.getDataFlowInfo());
|
||||||
context.trace.record(BindingContext.DATAFLOW_INFO_AFTER_CONDITION, expression, newDataFlowInfo);
|
context.trace.record(BindingContext.DATAFLOW_INFO_AFTER_CONDITION, expression, newDataFlowInfo);
|
||||||
}
|
}
|
||||||
return DataFlowUtils.checkType(typeInfo.replaceType(components.builtIns.getBooleanType()), expression, contextWithExpectedType);
|
return components.dataFlowAnalyzer.checkType(typeInfo.replaceType(components.builtIns.getBooleanType()), expression, contextWithExpectedType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -76,7 +76,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public JetTypeInfo visitWhenExpression(JetWhenExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
public JetTypeInfo visitWhenExpression(JetWhenExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||||
DataFlowUtils.recordExpectedType(contextWithExpectedType.trace, expression, contextWithExpectedType.expectedType);
|
components.dataFlowAnalyzer.recordExpectedType(contextWithExpectedType.trace, expression, contextWithExpectedType.expectedType);
|
||||||
|
|
||||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
|
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
|
||||||
// TODO :change scope according to the bound value in the when header
|
// TODO :change scope according to the bound value in the when header
|
||||||
@@ -94,7 +94,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
assert subjectType != null;
|
assert subjectType != null;
|
||||||
if (TypeUtils.isNullableType(subjectType) && !WhenChecker.containsNullCase(expression, context.trace)) {
|
if (TypeUtils.isNullableType(subjectType) && !WhenChecker.containsNullCase(expression, context.trace)) {
|
||||||
ExpressionTypingContext subjectContext = context.replaceExpectedType(TypeUtils.makeNotNullable(subjectType));
|
ExpressionTypingContext subjectContext = context.replaceExpectedType(TypeUtils.makeNotNullable(subjectType));
|
||||||
DataFlowUtils.checkPossibleCast(subjectType, JetPsiUtil.safeDeparenthesize(subjectExpression, false), subjectContext);
|
components.dataFlowAnalyzer.checkPossibleCast(subjectType, JetPsiUtil.safeDeparenthesize(subjectExpression, false), subjectContext);
|
||||||
}
|
}
|
||||||
context = context.replaceDataFlowInfo(typeInfo.getDataFlowInfo());
|
context = context.replaceDataFlowInfo(typeInfo.getDataFlowInfo());
|
||||||
}
|
}
|
||||||
@@ -143,8 +143,8 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
commonDataFlowInfo = commonDataFlowInfo.or(context.dataFlowInfo);
|
commonDataFlowInfo = commonDataFlowInfo.or(context.dataFlowInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TypeInfoFactoryPackage.createTypeInfo(expressionTypes.isEmpty() ? null : DataFlowUtils.checkType(
|
return TypeInfoFactoryPackage.createTypeInfo(expressionTypes.isEmpty() ? null : components.dataFlowAnalyzer.checkType(
|
||||||
DataFlowUtils.checkImplicitCast(
|
components.dataFlowAnalyzer.checkImplicitCast(
|
||||||
CommonSupertypes.commonSupertype(expressionTypes), expression,
|
CommonSupertypes.commonSupertype(expressionTypes), expression,
|
||||||
contextWithExpectedType, isStatement),
|
contextWithExpectedType, isStatement),
|
||||||
expression, contextWithExpectedType),
|
expression, contextWithExpectedType),
|
||||||
@@ -280,8 +280,8 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
context.trace.report(TYPE_MISMATCH_IN_CONDITION.on(expression, type));
|
context.trace.report(TYPE_MISMATCH_IN_CONDITION.on(expression, type));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DataFlowInfo ifInfo = DataFlowUtils.extractDataFlowInfoFromCondition(expression, true, context);
|
DataFlowInfo ifInfo = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(expression, true, context);
|
||||||
DataFlowInfo elseInfo = DataFlowUtils.extractDataFlowInfoFromCondition(expression, false, context);
|
DataFlowInfo elseInfo = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(expression, false, context);
|
||||||
return new DataFlowInfos(ifInfo, elseInfo);
|
return new DataFlowInfos(ifInfo, elseInfo);
|
||||||
}
|
}
|
||||||
return noChange(context);
|
return noChange(context);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.psi.JetExpression
|
|||||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||||
import org.jetbrains.kotlin.types.JetType
|
import org.jetbrains.kotlin.types.JetType
|
||||||
import org.jetbrains.kotlin.types.expressions.DataFlowUtils
|
import org.jetbrains.kotlin.types.expressions.DataFlowAnalyzer
|
||||||
import org.jetbrains.kotlin.types.expressions.JetTypeInfo
|
import org.jetbrains.kotlin.types.expressions.JetTypeInfo
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -39,6 +39,3 @@ public fun createTypeInfo(type: JetType?, context: ResolutionContext<*>): JetTyp
|
|||||||
public fun noTypeInfo(dataFlowInfo: DataFlowInfo): JetTypeInfo = createTypeInfo(null, dataFlowInfo)
|
public fun noTypeInfo(dataFlowInfo: DataFlowInfo): JetTypeInfo = createTypeInfo(null, dataFlowInfo)
|
||||||
|
|
||||||
public fun noTypeInfo(context: ResolutionContext<*>): JetTypeInfo = noTypeInfo(context.dataFlowInfo)
|
public fun noTypeInfo(context: ResolutionContext<*>): JetTypeInfo = noTypeInfo(context.dataFlowInfo)
|
||||||
|
|
||||||
public fun createCheckedTypeInfo(type: JetType?, context: ResolutionContext<*>, expression: JetExpression): JetTypeInfo =
|
|
||||||
DataFlowUtils.checkType(createTypeInfo(type, context), expression, context)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user