Refactoring: improve isApplicable methods in surrounders

This commit is contained in:
Nikolay Krasko
2017-09-12 13:17:07 +03:00
parent b925df0e14
commit 32c02161cd
10 changed files with 33 additions and 33 deletions
@@ -21,8 +21,13 @@ import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.idea.KotlinBundle;
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils;
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils;
import org.jetbrains.kotlin.psi.KtBlockExpression;
import org.jetbrains.kotlin.psi.KtExpression;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode;
public class KotlinSurrounderUtils {
public static String SURROUND_WITH = KotlinBundle.message("surround.with");
@@ -42,4 +47,14 @@ public class KotlinSurrounderUtils {
public static void showErrorHint(@NotNull Project project, @NotNull Editor editor, @NotNull String message) {
CodeInsightUtils.showErrorHint(project, editor, message, SURROUND_WITH, null);
}
public static boolean isUsedAsStatement(@NotNull KtExpression expression) {
BindingContext context = ResolutionUtils.analyze(expression, BodyResolveMode.PARTIAL);
return BindingContextUtilsKt.isUsedAsStatement(expression, context);
}
public static boolean isUsedAsExpression(@NotNull KtExpression expression) {
BindingContext context = ResolutionUtils.analyze(expression, BodyResolveMode.PARTIAL);
return BindingContextUtilsKt.isUsedAsExpression(expression, context);
}
}
@@ -26,8 +26,6 @@ import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.createExpressionByPattern
abstract class KotlinControlFlowExpressionSurrounderBase : KotlinExpressionSurrounder() {
override fun isApplicable(expression: KtExpression) = true
override fun isApplicableToStatements() = false
override fun surroundExpression(project: Project, editor: Editor, expression: KtExpression): TextRange? {
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode;
import org.jetbrains.kotlin.types.KotlinType;
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isUnit;
import static org.jetbrains.kotlin.idea.codeInsight.surroundWith.KotlinSurrounderUtils.isUsedAsStatement;
public abstract class KotlinExpressionSurrounder implements Surrounder {
@@ -45,26 +46,28 @@ public abstract class KotlinExpressionSurrounder implements Surrounder {
if (expression instanceof KtCallExpression && expression.getParent() instanceof KtQualifiedExpression) {
return false;
}
return isApplicable(expression);
}
protected boolean isApplicable(@NotNull KtExpression expression) {
BindingContext context = ResolutionUtils.analyze(expression, BodyResolveMode.PARTIAL);
KotlinType type = context.getType(expression);
if (type == null || (isUnit(type) && isApplicableToStatements())) {
return false;
}
boolean usedAsExpression = Boolean.TRUE.equals(context.get(BindingContext.USED_AS_EXPRESSION, expression));
if (!isApplicableToStatements() && !usedAsExpression) {
if (!isApplicableToStatements() && isUsedAsStatement(expression)) {
return false;
}
return isApplicable(expression);
return true;
}
protected boolean isApplicableToStatements() {
return true;
}
protected abstract boolean isApplicable(@NotNull KtExpression expression);
@Nullable
@Override
public TextRange surroundElements(@NotNull Project project, @NotNull Editor editor, @NotNull PsiElement[] elements) {
@@ -40,6 +40,7 @@ public class KotlinNotSurrounder extends KotlinExpressionSurrounder {
@Override
public boolean isApplicable(@NotNull KtExpression expression) {
if (!super.isApplicable(expression)) return false;
KotlinType type = ResolutionUtils.analyze(expression, BodyResolveMode.PARTIAL).getType(expression);
return type != null && KotlinBuiltIns.isBoolean(type);
}
@@ -33,11 +33,6 @@ public class KotlinParenthesesSurrounder extends KotlinExpressionSurrounder {
return CodeInsightBundle.message("surround.with.parenthesis.template");
}
@Override
public boolean isApplicable(@NotNull KtExpression expression) {
return true;
}
@Nullable
@Override
public TextRange surroundExpression( @NotNull Project project, @NotNull Editor editor, @NotNull KtExpression expression) {
@@ -31,8 +31,8 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.util.TextRange
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinRuntimeTypeEvaluator
import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinRuntimeTypeEvaluator
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
@@ -43,6 +43,8 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
class KotlinRuntimeTypeCastSurrounder: KotlinExpressionSurrounder() {
override fun isApplicable(expression: KtExpression): Boolean {
if (!super.isApplicable(expression)) return false
if (!expression.isPhysical) return false
val file = expression.containingFile
if (file !is KtCodeFragment) return false
@@ -33,7 +33,7 @@ public class KotlinStringTemplateSurrounder extends KotlinExpressionSurrounder {
@Override
public boolean isApplicable(@NotNull KtExpression expression) {
return !(expression instanceof KtStringTemplateExpression);
return !(expression instanceof KtStringTemplateExpression) && super.isApplicable(expression);
}
@Nullable
@@ -37,11 +37,6 @@ public class KotlinWhenSurrounder extends KotlinExpressionSurrounder {
return KotlinBundle.message("surround.with.when.template");
}
@Override
public boolean isApplicable(@NotNull KtExpression expression) {
return true;
}
@Nullable
@Override
public TextRange surroundExpression(@NotNull Project project, @NotNull Editor editor, @NotNull KtExpression expression) {
@@ -32,7 +32,7 @@ import org.jetbrains.kotlin.utils.sure
class KotlinWithIfExpressionSurrounder(val withElse: Boolean) : KotlinExpressionSurrounder() {
override fun isApplicable(expression: KtExpression) =
expression.analyze(BodyResolveMode.PARTIAL).getType(expression)?.isBoolean() ?: false
super.isApplicable(expression) && (expression.analyze(BodyResolveMode.PARTIAL).getType(expression)?.isBoolean() ?: false)
override fun surroundExpression(project: Project, editor: Editor, expression: KtExpression): TextRange? {
val factory = KtPsiFactory(project)
@@ -24,11 +24,8 @@ import com.intellij.psi.PsiElement;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils;
import org.jetbrains.kotlin.psi.KtElement;
import org.jetbrains.kotlin.idea.codeInsight.surroundWith.KotlinSurrounderUtils;
import org.jetbrains.kotlin.psi.KtExpression;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode;
public abstract class KotlinStatementsSurrounder implements Surrounder {
@@ -38,13 +35,8 @@ public abstract class KotlinStatementsSurrounder implements Surrounder {
return false;
}
if (elements.length == 1 || !(elements[0] instanceof KtExpression) && !isApplicableWhenUsedAsExpression()) {
KtElement expression = (KtElement) elements[0];
Boolean usedAsExpression = ResolutionUtils.analyze(expression, BodyResolveMode.PARTIAL)
.get(BindingContext.USED_AS_EXPRESSION, expression);
if (usedAsExpression != null && usedAsExpression) {
if (elements.length == 1 || elements[0] instanceof KtExpression) {
if (!isApplicableWhenUsedAsExpression() && KotlinSurrounderUtils.isUsedAsExpression((KtExpression) elements[0])) {
return false;
}
}
@@ -61,8 +53,7 @@ public abstract class KotlinStatementsSurrounder implements Surrounder {
public TextRange surroundElements(
@NotNull Project project,
@NotNull Editor editor,
@NotNull PsiElement[] elements
) throws IncorrectOperationException {
@NotNull PsiElement[] elements) throws IncorrectOperationException {
PsiElement container = elements[0].getParent();
if (container == null) return null;
return surroundStatements(project, editor, container, elements);