Refactoring: checkType && checkImplicitCast returned to DataFlowUtils, PROCESSED unboxing returned, StringTemplateVisitor made local
This commit is contained in:
@@ -157,8 +157,9 @@ public class BindingContextUtils {
|
||||
|
||||
@Nullable
|
||||
public static JetTypeInfo getRecordedTypeInfo(@NotNull JetExpression expression, @NotNull BindingContext context) {
|
||||
// noinspection ConstantConditions
|
||||
if (!context.get(BindingContext.PROCESSED, expression)) return null;
|
||||
// NB: should never return null if expression is already processed
|
||||
if (!Boolean.TRUE.equals(context.get(BindingContext.PROCESSED, expression))) return null;
|
||||
JetTypeInfo result = context.get(BindingContext.EXPRESSION_TYPE_INFO, expression);
|
||||
return result != null ? result : TypeInfoFactoryPackage.noTypeInfo(DataFlowInfo.EMPTY);
|
||||
}
|
||||
|
||||
+34
-41
@@ -104,7 +104,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
// TODO : type substitutions???
|
||||
CallExpressionResolver callExpressionResolver = components.expressionTypingServices.getCallExpressionResolver();
|
||||
JetTypeInfo typeInfo = callExpressionResolver.getSimpleNameExpressionTypeInfo(expression, NO_RECEIVER, null, context);
|
||||
return typeInfo.checkType(expression, context); // TODO : Extensions to this
|
||||
return DataFlowUtils.checkType(typeInfo, expression, context); // TODO : Extensions to this
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -158,7 +158,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
|
||||
JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType.replaceExpectedType(targetType));
|
||||
checkBinaryWithTypeRHS(expression, context, targetType, typeInfo.getType());
|
||||
return typeInfo.replaceType(targetType).checkType(expression, context);
|
||||
return DataFlowUtils.checkType(typeInfo.replaceType(targetType), expression, context);
|
||||
}
|
||||
|
||||
JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType);
|
||||
@@ -176,7 +176,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
JetType result = operationType == AS_SAFE ? TypeUtils.makeNullable(targetType) : targetType;
|
||||
return typeInfo.replaceType(result).checkType(expression, context);
|
||||
return DataFlowUtils.checkType(typeInfo.replaceType(result), expression, context);
|
||||
}
|
||||
|
||||
private void checkBinaryWithTypeRHS(
|
||||
@@ -582,7 +582,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
});
|
||||
result[0] = defaultType;
|
||||
if (Boolean.FALSE.equals(context.trace.get(PROCESSED, expression))) {
|
||||
// noinspection ConstantConditions
|
||||
if (!context.trace.get(PROCESSED, expression)) {
|
||||
temporaryTrace.recordType(expression, defaultType);
|
||||
temporaryTrace.record(PROCESSED, expression);
|
||||
}
|
||||
@@ -887,7 +888,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
return createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
|
||||
}
|
||||
|
||||
return typeInfo.replaceType(result).checkType(expression, contextWithExpectedType);
|
||||
return DataFlowUtils.checkType(typeInfo.replaceType(result), expression, contextWithExpectedType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -936,7 +937,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
// The call to checkType() is only needed here to execute additionalTypeCheckers, hence the NO_EXPECTED_TYPE
|
||||
return baseTypeInfo.replaceType(resultingType).checkType(expression, context.replaceExpectedType(NO_EXPECTED_TYPE));
|
||||
return DataFlowUtils.checkType(baseTypeInfo.replaceType(resultingType), expression, context.replaceExpectedType(NO_EXPECTED_TYPE));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1087,7 +1088,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
if (value != null) {
|
||||
return createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
|
||||
}
|
||||
return result.checkType(expression, contextWithExpectedType);
|
||||
return DataFlowUtils.checkType(result, expression, contextWithExpectedType);
|
||||
}
|
||||
|
||||
private JetTypeInfo visitEquality(
|
||||
@@ -1357,7 +1358,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
|
||||
@Override
|
||||
public JetTypeInfo visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression, ExpressionTypingContext context) {
|
||||
return resolveArrayAccessGetMethod(expression, context).checkType(expression, context);
|
||||
return DataFlowUtils.checkType(resolveArrayAccessGetMethod(expression, context), expression, context);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -1409,45 +1410,37 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
return TypeInfoFactoryPackage.noTypeInfo(context);
|
||||
}
|
||||
|
||||
private class StringTemplateVisitor extends JetVisitorVoid {
|
||||
|
||||
final ExpressionTypingContext context;
|
||||
|
||||
JetTypeInfo typeInfo;
|
||||
|
||||
StringTemplateVisitor(ExpressionTypingContext context) {
|
||||
this.context = context;
|
||||
this.typeInfo = TypeInfoFactoryPackage.noTypeInfo(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitStringTemplateEntryWithExpression(@NotNull JetStringTemplateEntryWithExpression entry) {
|
||||
JetExpression entryExpression = entry.getExpression();
|
||||
if (entryExpression != null) {
|
||||
typeInfo = facade.getTypeInfo(entryExpression, context.replaceDataFlowInfo(typeInfo.getDataFlowInfo()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEscapeStringTemplateEntry(@NotNull JetEscapeStringTemplateEntry entry) {
|
||||
CompileTimeConstantChecker.CharacterWithDiagnostic value = CompileTimeConstantChecker.escapedStringToCharacter(entry.getText(), entry);
|
||||
Diagnostic diagnostic = value.getDiagnostic();
|
||||
if (diagnostic != null) {
|
||||
context.trace.report(diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetTypeInfo visitStringTemplateExpression(@NotNull JetStringTemplateExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
|
||||
StringTemplateVisitor visitor = new StringTemplateVisitor(context);
|
||||
final ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
|
||||
class StringTemplateVisitor extends JetVisitorVoid {
|
||||
private JetTypeInfo typeInfo = TypeInfoFactoryPackage.noTypeInfo(context);
|
||||
|
||||
@Override
|
||||
public void visitStringTemplateEntryWithExpression(@NotNull JetStringTemplateEntryWithExpression entry) {
|
||||
JetExpression entryExpression = entry.getExpression();
|
||||
if (entryExpression != null) {
|
||||
typeInfo = facade.getTypeInfo(entryExpression, context.replaceDataFlowInfo(typeInfo.getDataFlowInfo()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEscapeStringTemplateEntry(@NotNull JetEscapeStringTemplateEntry entry) {
|
||||
CompileTimeConstantChecker.CharacterWithDiagnostic value = CompileTimeConstantChecker.escapedStringToCharacter(entry.getText(), entry);
|
||||
Diagnostic diagnostic = value.getDiagnostic();
|
||||
if (diagnostic != null) {
|
||||
context.trace.report(diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
StringTemplateVisitor visitor = new StringTemplateVisitor();
|
||||
for (JetStringTemplateEntry entry : expression.getEntries()) {
|
||||
entry.accept(visitor);
|
||||
}
|
||||
ConstantExpressionEvaluator.evaluate(expression, context.trace, contextWithExpectedType.expectedType);
|
||||
return visitor.typeInfo.replaceType(components.builtIns.getStringType()).checkType(expression, contextWithExpectedType);
|
||||
return DataFlowUtils.checkType(visitor.typeInfo.replaceType(components.builtIns.getStringType()),
|
||||
expression,
|
||||
contextWithExpectedType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+17
-8
@@ -189,8 +189,12 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
} else {
|
||||
dataFlowInfo = typeInfo.getDataFlowInfo().or(otherInfo);
|
||||
}
|
||||
return typeInfo.replaceType(components.builtIns.getUnitType()).checkType(ifExpression, context).
|
||||
checkImplicitCast(ifExpression, context, isStatement).replaceDataFlowInfo(dataFlowInfo);
|
||||
return DataFlowUtils.checkImplicitCast(DataFlowUtils.checkType(typeInfo.replaceType(components.builtIns.getUnitType()),
|
||||
ifExpression,
|
||||
context),
|
||||
ifExpression,
|
||||
context,
|
||||
isStatement).replaceDataFlowInfo(dataFlowInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -240,8 +244,9 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
// but without affecting changing variables
|
||||
dataFlowInfo = dataFlowInfo.and(loopVisitor.clearDataFlowInfoForAssignedLocalVariables(bodyTypeInfo.getJumpFlowInfo()));
|
||||
}
|
||||
return bodyTypeInfo.replaceType(components.builtIns.getUnitType()).checkType(expression, contextWithExpectedType).replaceDataFlowInfo(
|
||||
dataFlowInfo);
|
||||
return DataFlowUtils
|
||||
.checkType(bodyTypeInfo.replaceType(components.builtIns.getUnitType()), expression, contextWithExpectedType)
|
||||
.replaceDataFlowInfo(dataFlowInfo);
|
||||
}
|
||||
|
||||
private boolean containsJumpOutOfLoop(final JetLoopExpression loopExpression, final ExpressionTypingContext context) {
|
||||
@@ -337,13 +342,16 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
// Here we must record data flow information at the end of the body (or at the first jump, to be precise) and
|
||||
// .and it with entrance data flow information, because do-while body is executed at least once
|
||||
// See KT-6283
|
||||
// NB: it's really important to do it for non-empty body which is not a function literal
|
||||
// If it's a function literal, it appears always unused so it's no matter what we do at this point
|
||||
if (body != null) {
|
||||
// We should take data flow info from the first jump point,
|
||||
// but without affecting changing variables
|
||||
dataFlowInfo = dataFlowInfo.and(loopVisitor.clearDataFlowInfoForAssignedLocalVariables(bodyTypeInfo.getJumpFlowInfo()));
|
||||
}
|
||||
return bodyTypeInfo.replaceType(components.builtIns.getUnitType()).checkType(expression, contextWithExpectedType).replaceDataFlowInfo(
|
||||
dataFlowInfo);
|
||||
return DataFlowUtils
|
||||
.checkType(bodyTypeInfo.replaceType(components.builtIns.getUnitType()), expression, contextWithExpectedType)
|
||||
.replaceDataFlowInfo(dataFlowInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -402,8 +410,9 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
bodyTypeInfo = loopRangeInfo;
|
||||
}
|
||||
|
||||
return bodyTypeInfo.replaceType(components.builtIns.getUnitType()).checkType(expression, contextWithExpectedType).replaceDataFlowInfo(
|
||||
loopRangeInfo.getDataFlowInfo());
|
||||
return DataFlowUtils
|
||||
.checkType(bodyTypeInfo.replaceType(components.builtIns.getUnitType()), expression, contextWithExpectedType)
|
||||
.replaceDataFlowInfo(loopRangeInfo.getDataFlowInfo());
|
||||
}
|
||||
|
||||
private VariableDescriptor createLoopParameterDescriptor(
|
||||
|
||||
@@ -149,6 +149,11 @@ public class DataFlowUtils {
|
||||
return checkType(expressionType, expression, context, null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JetTypeInfo checkType(@NotNull JetTypeInfo typeInfo, @NotNull JetExpression expression, @NotNull ResolutionContext context) {
|
||||
return typeInfo.replaceType(checkType(typeInfo.getType(), expression, context));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static JetType checkType(
|
||||
@Nullable JetType expressionType,
|
||||
@@ -220,6 +225,11 @@ public class DataFlowUtils {
|
||||
return expressionType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JetTypeInfo checkImplicitCast(@NotNull JetTypeInfo typeInfo, @NotNull JetExpression expression, @NotNull ResolutionContext context, boolean isStatement) {
|
||||
return typeInfo.replaceType(checkImplicitCast(typeInfo.getType(), expression, context, isStatement));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JetTypeInfo illegalStatementType(@NotNull JetExpression expression, @NotNull ExpressionTypingContext context, @NotNull ExpressionTypingInternals facade) {
|
||||
facade.checkStatementType(
|
||||
|
||||
+1
-1
@@ -228,7 +228,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
else {
|
||||
return facade.getTypeInfo(expression, context);
|
||||
}
|
||||
return result.checkType(expression, context);
|
||||
return DataFlowUtils.checkType(result, expression, context);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -42,12 +42,6 @@ import org.jetbrains.kotlin.types.JetType
|
||||
|
||||
fun clearType() = replaceType(null)
|
||||
|
||||
fun checkType(expression: JetExpression, context: ResolutionContext<*>) =
|
||||
replaceType(DataFlowUtils.checkType(type, expression, context))
|
||||
|
||||
fun checkImplicitCast(expression: JetExpression, context: ResolutionContext<*>, isStatement: Boolean) =
|
||||
replaceType(DataFlowUtils.checkImplicitCast(type, expression, context, isStatement))
|
||||
|
||||
// NB: do not compare type with this.type because this comparison is complex and unstabld
|
||||
fun replaceType(type: JetType?) = JetTypeInfo(type, dataFlowInfo, jumpOutPossible, jumpFlowInfo)
|
||||
|
||||
@@ -57,10 +51,12 @@ import org.jetbrains.kotlin.types.JetType
|
||||
fun replaceJumpFlowInfo(jumpFlowInfo: DataFlowInfo) =
|
||||
if (jumpFlowInfo == this.jumpFlowInfo) this else JetTypeInfo(type, dataFlowInfo, jumpOutPossible, jumpFlowInfo)
|
||||
|
||||
fun replaceDataFlowInfo(dataFlowInfo: DataFlowInfo) =
|
||||
if (dataFlowInfo == this.dataFlowInfo) this
|
||||
// If jump flow information was the same, it should be changed together
|
||||
else if (this.dataFlowInfo == jumpFlowInfo) JetTypeInfo(type, dataFlowInfo, jumpOutPossible, dataFlowInfo)
|
||||
// Otherwise they are changed separately
|
||||
else JetTypeInfo(type, dataFlowInfo, jumpOutPossible, jumpFlowInfo)
|
||||
fun replaceDataFlowInfo(dataFlowInfo: DataFlowInfo) = when (this.dataFlowInfo) {
|
||||
// Nothing changed
|
||||
dataFlowInfo -> this
|
||||
// Jump info is the same as data flow info: change both
|
||||
jumpFlowInfo -> JetTypeInfo(type, dataFlowInfo, jumpOutPossible, dataFlowInfo)
|
||||
// Jump info is not the same: change data flow info only
|
||||
else -> JetTypeInfo(type, dataFlowInfo, jumpOutPossible, jumpFlowInfo)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -63,7 +63,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
DataFlowInfo newDataFlowInfo = conditionInfo.and(typeInfo.getDataFlowInfo());
|
||||
context.trace.record(BindingContext.DATAFLOW_INFO_AFTER_CONDITION, expression, newDataFlowInfo);
|
||||
}
|
||||
return typeInfo.replaceType(KotlinBuiltIns.getInstance().getBooleanType()).checkType(expression, contextWithExpectedType);
|
||||
return DataFlowUtils.checkType(typeInfo.replaceType(KotlinBuiltIns.getInstance().getBooleanType()), expression, contextWithExpectedType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.psi.JetExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.types.JetType
|
||||
import org.jetbrains.kotlin.types.expressions.DataFlowUtils
|
||||
import org.jetbrains.kotlin.types.expressions.JetTypeInfo
|
||||
|
||||
/*
|
||||
@@ -40,4 +41,4 @@ public fun noTypeInfo(dataFlowInfo: DataFlowInfo): JetTypeInfo = createTypeInfo(
|
||||
public fun noTypeInfo(context: ResolutionContext<*>): JetTypeInfo = noTypeInfo(context.dataFlowInfo)
|
||||
|
||||
public fun createCheckedTypeInfo(type: JetType?, context: ResolutionContext<*>, expression: JetExpression): JetTypeInfo =
|
||||
createTypeInfo(type, context).checkType(expression, context)
|
||||
DataFlowUtils.checkType(createTypeInfo(type, context), expression, context)
|
||||
|
||||
@@ -3,7 +3,9 @@ fun bar(): Boolean { return true }
|
||||
public fun foo(x: String?): Int {
|
||||
var y: Any
|
||||
do {
|
||||
y = ""
|
||||
// This and hashCode() below are needed just to prevent
|
||||
// UNINITIALIZED_VARIABLE, UNUSED_VALUE, ...
|
||||
y = ""
|
||||
y = if (x == null) break else <!DEBUG_INFO_SMARTCAST!>x<!>
|
||||
} while (bar())
|
||||
y.hashCode()
|
||||
|
||||
Reference in New Issue
Block a user