Type approximation factored out as an additional checker
This commit is contained in:
@@ -16,13 +16,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve
|
package org.jetbrains.kotlin.resolve
|
||||||
|
|
||||||
import org.jetbrains.annotations.ReadOnly
|
|
||||||
|
|
||||||
import java.util.Collections
|
|
||||||
import kotlin.properties.Delegates
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.checkers.*
|
import org.jetbrains.kotlin.resolve.calls.checkers.*
|
||||||
|
|
||||||
private val DEFAULT_CALL_CHECKERS = listOf(CapturingInClosureChecker(), InlineCheckerWrapper(), ReifiedTypeParameterSubstitutionChecker())
|
private val DEFAULT_CALL_CHECKERS = listOf(CapturingInClosureChecker(), InlineCheckerWrapper(), ReifiedTypeParameterSubstitutionChecker())
|
||||||
|
private val DEFAULT_TYPE_CHECKERS = listOf(TypeApproximator())
|
||||||
|
|
||||||
public abstract class AdditionalCheckerProvider(
|
public abstract class AdditionalCheckerProvider(
|
||||||
public val annotationCheckers: List<AnnotationChecker>,
|
public val annotationCheckers: List<AnnotationChecker>,
|
||||||
@@ -30,7 +27,7 @@ public abstract class AdditionalCheckerProvider(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
public val callCheckers: List<CallChecker> = DEFAULT_CALL_CHECKERS + additionalCallCheckers
|
public val callCheckers: List<CallChecker> = DEFAULT_CALL_CHECKERS + additionalCallCheckers
|
||||||
public val additionalTypeCheckers: List<AdditionalTypeChecker> = listOf()
|
public val additionalTypeCheckers: List<AdditionalTypeChecker> = DEFAULT_TYPE_CHECKERS
|
||||||
|
|
||||||
public object DefaultProvider : AdditionalCheckerProvider(listOf(), listOf()) {}
|
public object DefaultProvider : AdditionalCheckerProvider(listOf(), listOf()) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.resolve.calls.checkers
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.psi.JetExpression
|
||||||
|
import org.jetbrains.kotlin.types.JetType
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.types.TypeUtils.noExpectedType
|
||||||
|
import org.jetbrains.kotlin.types.getApproximationTo
|
||||||
|
import org.jetbrains.kotlin.types.Approximation
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability
|
||||||
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
|
public class TypeApproximator : AdditionalTypeChecker {
|
||||||
|
override fun checkType(expression: JetExpression, expressionType: JetType, c: ResolutionContext<*>) {
|
||||||
|
if (noExpectedType(c.expectedType)) return
|
||||||
|
|
||||||
|
val approximationInfo = expressionType.getApproximationTo(
|
||||||
|
c.expectedType,
|
||||||
|
object : Approximation.DataFlowExtras {
|
||||||
|
override val canBeNull: Boolean
|
||||||
|
get() = c.dataFlowInfo.getNullability(dataFlowValue).canBeNull()
|
||||||
|
override val possibleTypes: Set<JetType>
|
||||||
|
get() = c.dataFlowInfo.getPossibleTypes(dataFlowValue)
|
||||||
|
override val presentableText: String
|
||||||
|
get() = StringUtil.trimMiddle(expression.getText(), 50)
|
||||||
|
|
||||||
|
private val dataFlowValue =
|
||||||
|
DataFlowValueFactory.createDataFlowValue(expression, expressionType, c.trace.getBindingContext())
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (approximationInfo != null) {
|
||||||
|
c.trace.record(BindingContext.EXPRESSION_RESULT_APPROXIMATION, expression, approximationInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.types.expressions;
|
|||||||
|
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.intellij.openapi.util.Ref;
|
import com.intellij.openapi.util.Ref;
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
|
||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -37,11 +36,13 @@ import org.jetbrains.kotlin.resolve.constants.CompileTimeConstantChecker;
|
|||||||
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant;
|
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant;
|
||||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
||||||
import org.jetbrains.kotlin.resolve.constants.evaluate.EvaluatePackage;
|
import org.jetbrains.kotlin.resolve.constants.evaluate.EvaluatePackage;
|
||||||
import org.jetbrains.kotlin.types.*;
|
import org.jetbrains.kotlin.types.JetType;
|
||||||
|
import org.jetbrains.kotlin.types.JetTypeInfo;
|
||||||
|
import org.jetbrains.kotlin.types.TypeUtils;
|
||||||
|
import org.jetbrains.kotlin.types.TypesPackage;
|
||||||
import org.jetbrains.kotlin.types.checker.JetTypeChecker;
|
import org.jetbrains.kotlin.types.checker.JetTypeChecker;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
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;
|
||||||
@@ -161,50 +162,22 @@ public class DataFlowUtils {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static JetType checkType(
|
public static JetType checkType(
|
||||||
@Nullable final JetType expressionType,
|
@Nullable JetType expressionType,
|
||||||
@NotNull JetExpression expressionToCheck,
|
@NotNull JetExpression expressionToCheck,
|
||||||
@NotNull final ResolutionContext c,
|
@NotNull ResolutionContext c,
|
||||||
@Nullable Ref<Boolean> hasError
|
@Nullable Ref<Boolean> hasError
|
||||||
) {
|
) {
|
||||||
if (hasError != null) hasError.set(false);
|
if (hasError != null) hasError.set(false);
|
||||||
|
|
||||||
final JetExpression expression = JetPsiUtil.safeDeparenthesize(expressionToCheck, false);
|
JetExpression expression = JetPsiUtil.safeDeparenthesize(expressionToCheck, false);
|
||||||
recordExpectedType(c.trace, expression, c.expectedType);
|
recordExpectedType(c.trace, expression, c.expectedType);
|
||||||
|
|
||||||
if (expressionType == null) return null;
|
if (expressionType == null) return null;
|
||||||
|
|
||||||
|
c.additionalTypeChecker.checkType(expression, expressionType, c);
|
||||||
|
|
||||||
if (noExpectedType(c.expectedType) || !c.expectedType.getConstructor().isDenotable() ||
|
if (noExpectedType(c.expectedType) || !c.expectedType.getConstructor().isDenotable() ||
|
||||||
JetTypeChecker.DEFAULT.isSubtypeOf(expressionType, c.expectedType)) {
|
JetTypeChecker.DEFAULT.isSubtypeOf(expressionType, c.expectedType)) {
|
||||||
|
|
||||||
if (!noExpectedType(c.expectedType)) {
|
|
||||||
Approximation.Info approximationInfo = TypesPackage.getApproximationTo(expressionType, c.expectedType,
|
|
||||||
new Approximation.DataFlowExtras() {
|
|
||||||
private DataFlowValue getDataFlowValue() {
|
|
||||||
return DataFlowValueFactory.createDataFlowValue(expression, expressionType, c.trace.getBindingContext());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean getCanBeNull() {
|
|
||||||
return c.dataFlowInfo.getNullability(getDataFlowValue()).canBeNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<JetType> getPossibleTypes() {
|
|
||||||
return c.dataFlowInfo.getPossibleTypes(getDataFlowValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public String getPresentableText() {
|
|
||||||
return StringUtil.trimMiddle(expression.getText(), 50);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (approximationInfo != null) {
|
|
||||||
c.trace.record(BindingContext.EXPRESSION_RESULT_APPROXIMATION, expression, approximationInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return expressionType;
|
return expressionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user