Type approximation factored out as an additional checker
This commit is contained in:
@@ -16,13 +16,10 @@
|
||||
|
||||
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.*
|
||||
|
||||
private val DEFAULT_CALL_CHECKERS = listOf(CapturingInClosureChecker(), InlineCheckerWrapper(), ReifiedTypeParameterSubstitutionChecker())
|
||||
private val DEFAULT_TYPE_CHECKERS = listOf(TypeApproximator())
|
||||
|
||||
public abstract class AdditionalCheckerProvider(
|
||||
public val annotationCheckers: List<AnnotationChecker>,
|
||||
@@ -30,7 +27,7 @@ public abstract class AdditionalCheckerProvider(
|
||||
) {
|
||||
|
||||
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()) {}
|
||||
}
|
||||
|
||||
@@ -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.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
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.evaluate.ConstantExpressionEvaluator;
|
||||
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 java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
||||
import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT;
|
||||
@@ -161,50 +162,22 @@ public class DataFlowUtils {
|
||||
|
||||
@Nullable
|
||||
public static JetType checkType(
|
||||
@Nullable final JetType expressionType,
|
||||
@Nullable JetType expressionType,
|
||||
@NotNull JetExpression expressionToCheck,
|
||||
@NotNull final ResolutionContext c,
|
||||
@NotNull ResolutionContext c,
|
||||
@Nullable Ref<Boolean> hasError
|
||||
) {
|
||||
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);
|
||||
|
||||
if (expressionType == null) return null;
|
||||
|
||||
c.additionalTypeChecker.checkType(expression, expressionType, c);
|
||||
|
||||
if (noExpectedType(c.expectedType) || !c.expectedType.getConstructor().isDenotable() ||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user