Refactor getKotlinTypeWithPossibleSmartCastToFP and related parts
This commit is contained in:
@@ -10,13 +10,12 @@ import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactoryImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.getKotlinTypeForComparison
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.getKotlinTypeWithPossibleSmartCastToFP
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
class TypeAndNullability(@JvmField val type: Type, @JvmField val isNullable: Boolean)
|
||||
@@ -35,60 +34,31 @@ fun calcProperTypeForIeee754ArithmeticIfNeeded(
|
||||
return TypeAndNullability(asmType, isNullable)
|
||||
}
|
||||
|
||||
private fun KotlinType.isFloatingPointOrNullable() =
|
||||
KotlinBuiltIns.isDoubleOrNullableDouble(this) || KotlinBuiltIns.isFloatOrNullableFloat(this)
|
||||
|
||||
fun KtExpression.getKotlinTypeForComparison(bindingContext: BindingContext): KotlinType? =
|
||||
when {
|
||||
this is KtProperty -> bindingContext[BindingContext.VARIABLE, this]?.type
|
||||
else -> kotlinType(bindingContext)
|
||||
}
|
||||
|
||||
fun legacyCalcTypeForIeee754ArithmeticIfNeeded(
|
||||
expression: KtExpression?,
|
||||
bindingContext: BindingContext,
|
||||
descriptor: DeclarationDescriptor,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
): TypeAndNullability? {
|
||||
val ktType = expression?.getKotlinTypeForComparison(bindingContext) ?: return null
|
||||
|
||||
if (KotlinBuiltIns.isDoubleOrNullableDouble(ktType)) {
|
||||
return TypeAndNullability(
|
||||
Type.DOUBLE_TYPE,
|
||||
TypeUtils.isNullableType(ktType)
|
||||
)
|
||||
}
|
||||
|
||||
if (KotlinBuiltIns.isFloatOrNullableFloat(ktType)) {
|
||||
return TypeAndNullability(
|
||||
Type.FLOAT_TYPE,
|
||||
TypeUtils.isNullableType(ktType)
|
||||
)
|
||||
}
|
||||
|
||||
// NB. Using DataFlowValueFactoryImpl is a hack, but it is ok for 'legacy'
|
||||
val dataFlow = DataFlowValueFactoryImpl(languageVersionSettings).createDataFlowValue(
|
||||
expression,
|
||||
ktType,
|
||||
bindingContext,
|
||||
descriptor
|
||||
val ktType = expression.getKotlinTypeWithPossibleSmartCastToFP(
|
||||
// NB. Using DataFlowValueFactoryImpl is a hack, but it is ok for 'legacy'
|
||||
bindingContext, descriptor, languageVersionSettings, DataFlowValueFactoryImpl(languageVersionSettings)
|
||||
)
|
||||
val stableTypes = bindingContext.getDataFlowInfoBefore(expression).getStableTypes(dataFlow, languageVersionSettings)
|
||||
return stableTypes.firstNotNullResult {
|
||||
when {
|
||||
KotlinBuiltIns.isDoubleOrNullableDouble(it) -> TypeAndNullability(
|
||||
|
||||
if (ktType != null) {
|
||||
if (KotlinBuiltIns.isDoubleOrNullableDouble(ktType)) {
|
||||
return TypeAndNullability(
|
||||
Type.DOUBLE_TYPE,
|
||||
TypeUtils.isNullableType(
|
||||
it
|
||||
)
|
||||
TypeUtils.isNullableType(ktType)
|
||||
)
|
||||
KotlinBuiltIns.isFloatOrNullableFloat(it) -> TypeAndNullability(
|
||||
}
|
||||
|
||||
if (KotlinBuiltIns.isFloatOrNullableFloat(ktType)) {
|
||||
return TypeAndNullability(
|
||||
Type.FLOAT_TYPE,
|
||||
TypeUtils.isNullableType(
|
||||
it
|
||||
)
|
||||
TypeUtils.isNullableType(ktType)
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.smartcasts
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
|
||||
fun KtExpression.getKotlinTypeForComparison(bindingContext: BindingContext): KotlinType? =
|
||||
when {
|
||||
this is KtProperty -> bindingContext[BindingContext.VARIABLE, this]?.type
|
||||
else -> bindingContext.getType(this)
|
||||
}
|
||||
|
||||
fun KtExpression?.getKotlinTypeWithPossibleSmartCastToFP(
|
||||
bindingContext: BindingContext,
|
||||
descriptor: DeclarationDescriptor?,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
dataFlowValueFactory: DataFlowValueFactory
|
||||
): KotlinType? {
|
||||
val givenType = this?.getKotlinTypeForComparison(bindingContext) ?: return null
|
||||
|
||||
if (KotlinBuiltIns.isDoubleOrNullableDouble(givenType)) {
|
||||
return givenType
|
||||
}
|
||||
|
||||
if (KotlinBuiltIns.isFloatOrNullableFloat(givenType)) {
|
||||
return givenType
|
||||
}
|
||||
|
||||
if (descriptor != null) {
|
||||
val dataFlow = dataFlowValueFactory.createDataFlowValue(this, givenType, bindingContext, descriptor)
|
||||
val stableTypes = bindingContext.getDataFlowInfoBefore(this).getStableTypes(dataFlow, languageVersionSettings)
|
||||
stableTypes.firstNotNullResult {
|
||||
when {
|
||||
KotlinBuiltIns.isDoubleOrNullableDouble(it) -> it
|
||||
KotlinBuiltIns.isFloatOrNullableFloat(it) -> it
|
||||
else -> null
|
||||
}
|
||||
}?.let { return it }
|
||||
}
|
||||
return givenType
|
||||
}
|
||||
+4
-38
@@ -21,10 +21,7 @@ import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.containingDeclarationForPseudocode
|
||||
import org.jetbrains.kotlin.codegen.getKotlinTypeForComparison
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
|
||||
@@ -38,19 +35,17 @@ import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getLastParentOfTypeInRow
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getFirstArgumentExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getReceiverExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
|
||||
import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.getKotlinTypeWithPossibleSmartCastToFP
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
import org.jetbrains.kotlin.types.typeUtil.*
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
|
||||
class ReplaceCallWithBinaryOperatorInspection : AbstractApplicabilityBasedInspection<KtDotQualifiedExpression>(
|
||||
KtDotQualifiedExpression::class.java
|
||||
@@ -172,46 +167,17 @@ class ReplaceCallWithBinaryOperatorInspection : AbstractApplicabilityBasedInspec
|
||||
private fun KtDotQualifiedExpression.isFloatingPointNumberEquals(): Boolean {
|
||||
val resolvedCall = resolveToCall() ?: return false
|
||||
val context = analyze(BodyResolveMode.PARTIAL)
|
||||
val calcDescriptor = {
|
||||
this.containingDeclarationForPseudocode?.resolveToDescriptorIfAny()
|
||||
}
|
||||
val dataFlowValueFactory = getResolutionFacade().getFrontendService(DataFlowValueFactory::class.java)
|
||||
val receiverType = resolvedCall.getReceiverExpression()?.getKotlinTypeWithPossibleSmartCastToFP(
|
||||
context, calcDescriptor
|
||||
context, containingDeclarationForPseudocode?.resolveToDescriptorIfAny(), languageVersionSettings, dataFlowValueFactory
|
||||
) ?: return false
|
||||
val argumentType = resolvedCall.getFirstArgumentExpression()?.getKotlinTypeWithPossibleSmartCastToFP(
|
||||
context, calcDescriptor
|
||||
context, containingDeclarationForPseudocode?.resolveToDescriptorIfAny(), languageVersionSettings, dataFlowValueFactory
|
||||
) ?: return false
|
||||
return receiverType.isFpType() && argumentType.isNumericType() ||
|
||||
argumentType.isFpType() && receiverType.isNumericType()
|
||||
}
|
||||
|
||||
private fun KtExpression.getKotlinTypeWithPossibleSmartCastToFP(
|
||||
context: BindingContext,
|
||||
calcDescriptor: () -> DeclarationDescriptor?
|
||||
): KotlinType? {
|
||||
val givenType = getKotlinTypeForComparison(context) ?: return null
|
||||
|
||||
if (KotlinBuiltIns.isDoubleOrNullableDouble(givenType) || KotlinBuiltIns.isFloatOrNullableFloat(givenType)) {
|
||||
return givenType
|
||||
}
|
||||
|
||||
val dataFlowValueFactory = getResolutionFacade().getFrontendService(DataFlowValueFactory::class.java)
|
||||
val dataFlow = dataFlowValueFactory.createDataFlowValue(
|
||||
this,
|
||||
givenType,
|
||||
context,
|
||||
calcDescriptor() ?: return givenType
|
||||
)
|
||||
val stableTypes = context.getDataFlowInfoBefore(this).getStableTypes(dataFlow, languageVersionSettings)
|
||||
return stableTypes.firstNotNullResult {
|
||||
when {
|
||||
KotlinBuiltIns.isDoubleOrNullableDouble(it) -> it
|
||||
KotlinBuiltIns.isFloatOrNullableFloat(it) -> it
|
||||
else -> null
|
||||
}
|
||||
} ?: givenType
|
||||
}
|
||||
|
||||
private fun KtSimpleNameExpression.isFloatingPointNumberEquals(): Boolean {
|
||||
val dotQualified = parent.parent as? KtDotQualifiedExpression ?: return false
|
||||
return dotQualified.isFloatingPointNumberEquals()
|
||||
|
||||
Reference in New Issue
Block a user