diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AdditionalCheckerProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AdditionalCheckerProvider.kt index 94e6af59a08..b4758c7cd06 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AdditionalCheckerProvider.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AdditionalCheckerProvider.kt @@ -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, @@ -30,7 +27,7 @@ public abstract class AdditionalCheckerProvider( ) { public val callCheckers: List = DEFAULT_CALL_CHECKERS + additionalCallCheckers - public val additionalTypeCheckers: List = listOf() + public val additionalTypeCheckers: List = DEFAULT_TYPE_CHECKERS public object DefaultProvider : AdditionalCheckerProvider(listOf(), listOf()) {} } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/TypeApproximator.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/TypeApproximator.kt new file mode 100644 index 00000000000..4a679f6bdf8 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/TypeApproximator.kt @@ -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 + 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) + } + } +} \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowUtils.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowUtils.java index 525b87c060b..afd1da8866b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowUtils.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowUtils.java @@ -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 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 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; }