Refactoring: use isUsedAsExpression instead of USED_AS_EXPRESSION slice

This commit is contained in:
Mikhail Glukhikh
2019-07-09 11:43:36 +03:00
parent 5afa5de1d7
commit 5e94f537ef
6 changed files with 13 additions and 8 deletions
@@ -168,6 +168,8 @@ public interface BindingContext {
* Has type of current expression has been already resolved
*/
WritableSlice<KtExpression, Boolean> PROCESSED = Slices.createSimpleSlice();
// Please do not use this slice (USED_AS_EXPRESSION) directly,
// use extension element.isUsedAsExpression() instead
WritableSlice<KtElement, Boolean> USED_AS_EXPRESSION = Slices.createSimpleSetSlice();
WritableSlice<KtElement, Boolean> USED_AS_RESULT_OF_LAMBDA = Slices.createSimpleSetSlice();
WritableSlice<KtElement, Boolean> UNREACHABLE_CODE = Slices.createSimpleSetSlice();
@@ -39,6 +39,7 @@ import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.renderer.RenderingFormat
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getParameterForArgument
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
@@ -90,7 +91,7 @@ class KotlinExpressionTypeProvider : ExpressionTypeProvider<KtExpression>() {
private fun KtExpression.shouldShowStatementType(): Boolean {
if (parent !is KtBlockExpression) return true
if (parent.children.lastOrNull() == this) {
return analyze(BodyResolveMode.PARTIAL_WITH_CFA)[BindingContext.USED_AS_EXPRESSION, this] ?: false
return isUsedAsExpression(analyze(BodyResolveMode.PARTIAL_WITH_CFA))
}
return false
}
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.idea.refactoring.getLineNumber
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
import org.jetbrains.kotlin.types.typeUtil.isNothing
class RedundantElseInIfInspection : AbstractKotlinInspection() {
@@ -87,7 +88,7 @@ private fun KtIfExpression.lastSingleElseKeyword(): PsiElement? {
private fun KtIfExpression.hasRedundantElse(): Boolean {
val context = analyze()
if (context[BindingContext.USED_AS_EXPRESSION, this] == true) return false
if (isUsedAsExpression(context)) return false
var ifExpression = this
while (true) {
if ((ifExpression.then)?.isReturnOrNothing(context) != true) return false
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
@@ -34,7 +35,7 @@ class RedundantWithInspection : AbstractKotlinInspection() {
val lambdaBody = lambda.bodyExpression ?: return
val context = callExpression.analyze(BodyResolveMode.PARTIAL_WITH_CFA)
if (lambdaBody.statements.size > 1 && context[BindingContext.USED_AS_EXPRESSION, callExpression] == true) return
if (lambdaBody.statements.size > 1 && callExpression.isUsedAsExpression(context)) return
if (callExpression.getResolvedCall(context)?.resultingDescriptor?.fqNameSafe != FqName("kotlin.with")) return
val lambdaDescriptor = context[BindingContext.FUNCTION, lambda.functionLiteral] ?: return
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
class SafeCastWithReturnInspection : AbstractKotlinInspection() {
@@ -30,11 +31,11 @@ class SafeCastWithReturnInspection : AbstractKotlinInspection() {
if (KtPsiUtil.deparenthesize(parent.right) !is KtReturnExpression) return
val context = expression.analyze(BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS)
if (context[BindingContext.USED_AS_EXPRESSION, parent] == true) {
if (parent.isUsedAsExpression(context)) {
val lambda = expression.getStrictParentOfType<KtLambdaExpression>() ?: return
if (lambda.functionLiteral.bodyExpression?.statements?.lastOrNull() != parent) return
val call = lambda.getStrictParentOfType<KtCallExpression>() ?: return
if (context[BindingContext.USED_AS_EXPRESSION, call] == true) return
if (call.isUsedAsExpression(context)) return
}
if (context.diagnostics.forElement(expression.operationReference).any { it.factory == Errors.CAST_NEVER_SUCCEEDS }) return
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.kotlin.psi.callExpressionVisitor
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl
import org.jetbrains.kotlin.resolve.calls.tower.NewVariableAsFunctionResolvedCallImpl
@@ -31,7 +32,7 @@ class UnusedLambdaExpressionBodyInspection : AbstractKotlinInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return callExpressionVisitor(fun(expression) {
val context = expression.analyze(BodyResolveMode.PARTIAL_WITH_CFA)
if (expression.used(context)) {
if (expression.isUsedAsExpression(context)) {
return
}
@@ -54,8 +55,6 @@ class UnusedLambdaExpressionBodyInspection : AbstractKotlinInspection() {
})
}
private fun KtExpression.used(context: BindingContext): Boolean = context[BindingContext.USED_AS_EXPRESSION, this] ?: true
private fun CallableDescriptor.returnsFunction() = returnType?.isFunctionType ?: false
class RemoveEqTokenFromFunctionDeclarationFix(function: KtFunction) : LocalQuickFixOnPsiElement(function) {