[java] inline local: incorporate CFG specifics with inner classes/lambdas in api

GitOrigin-RevId: efeb9380a0f158bca548b582a09da5fea033854e
This commit is contained in:
Anna Kozlova
2021-09-30 08:05:54 +00:00
committed by intellij-monorepo-bot
parent 3e5bab3b79
commit d8dd7e904c
4 changed files with 32 additions and 45 deletions
@@ -172,6 +172,23 @@ public class InlineLocalHandler extends JavaInlineActionHandler {
final String localName = local.getName();
final List<PsiElement> innerClassesWithUsages = new ArrayList<>();
final List<PsiElement> innerClassUsages = new ArrayList<>();
final PsiElement containingClass = PsiTreeUtil.getParentOfType(local, PsiClass.class, PsiLambdaExpression.class);
for (PsiElement element : allRefs) {
PsiElement innerClass = element;
while (innerClass != null) {
final PsiElement parentPsiClass = PsiTreeUtil.getParentOfType(innerClass.getParent(), PsiClass.class, PsiLambdaExpression.class);
if (parentPsiClass == containingClass) {
if (innerClass != element) {
innerClassesWithUsages.add(innerClass);
innerClassUsages.add(element);
}
break;
}
innerClass = parentPsiClass;
}
}
final PsiCodeBlock containerBlock = PsiTreeUtil.getParentOfType(local, PsiCodeBlock.class);
if (containerBlock == null) {
final String message = RefactoringBundle.getCannotRefactorMessage(
@@ -179,16 +196,10 @@ public class InlineLocalHandler extends JavaInlineActionHandler {
CommonRefactoringUtil.showErrorHint(project, editor, message, getRefactoringName(local), HelpID.INLINE_VARIABLE);
return null;
}
final List<PsiElement> innerClassUsages = Collections.synchronizedList(new ArrayList<>());
final PsiElement containingClass = PsiTreeUtil.getParentOfType(local, PsiClass.class, PsiLambdaExpression.class);
final PsiExpression defToInline;
try {
PsiElement refToInline = getRefToInline(local, allRefs, innerClassUsages, containingClass);
defToInline = getDefToInline(local,
refToInline != null ? refToInline : refExpr,
containerBlock, true);
defToInline = getDefToInline(local, innerClassesWithUsages.isEmpty() ? refExpr : innerClassesWithUsages.get(0), containerBlock, true);
if (defToInline == null) {
final String key = refExpr == null ? "variable.has.no.initializer" : "variable.has.no.dominating.definition";
String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message(key, localName));
@@ -349,33 +360,6 @@ public class InlineLocalHandler extends JavaInlineActionHandler {
};
}
@Nullable
static PsiElement getRefToInline(@NotNull PsiLocalVariable local,
@NotNull Collection<PsiElement> allRefs,
List<PsiElement> innerClassUsages,
PsiElement containingClass) {
final List<PsiElement> innerClassesWithUsages = Collections.synchronizedList(new ArrayList<>());
for (PsiElement element : allRefs) {
PsiElement innerClass = PsiTreeUtil.getParentOfType(element, PsiClass.class, PsiLambdaExpression.class);
while (innerClass != containingClass && innerClass != null) {
final PsiElement parentPsiClass = PsiTreeUtil.getParentOfType(innerClass.getParent(), PsiClass.class, PsiLambdaExpression.class);
if (parentPsiClass == containingClass) {
if (innerClass instanceof PsiLambdaExpression) {
if (PsiTreeUtil.isAncestor(innerClass, local, false)) {
innerClassesWithUsages.add(element);
innerClass = parentPsiClass;
continue;
}
}
innerClassesWithUsages.add(innerClass);
innerClassUsages.add(element);
}
innerClass = parentPsiClass;
}
}
return innerClassesWithUsages.isEmpty() ? null : innerClassesWithUsages.get(0);
}
@NotNull
static List<SmartPsiElementPointer<PsiExpression>> inlineOccurrences(@NotNull Project project,
@NotNull PsiVariable local,
@@ -26,7 +26,6 @@ import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewDescriptor;
import com.intellij.usageView.UsageViewUtil;
import com.intellij.util.JavaPsiConstructorUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.VisibilityUtil;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
@@ -108,12 +107,7 @@ public class InlineParameterExpressionProcessor extends BaseRefactoringProcessor
final PsiElement element = expression.resolve();
if (element instanceof PsiLocalVariable) {
final PsiLocalVariable localVariable = (PsiLocalVariable)element;
final List<PsiElement> innerClassUsages = Collections.synchronizedList(new ArrayList<>());
final PsiElement containingClass = PsiTreeUtil.getParentOfType(localVariable, PsiClass.class, PsiLambdaExpression.class);
PsiElement refToInline = InlineLocalHandler.getRefToInline(localVariable,
Collections.singletonList(expression),
innerClassUsages, containingClass);
final PsiElement[] elements = DefUseUtil.getDefs(myCallingBlock, localVariable, ObjectUtils.notNull(refToInline, expression));
final PsiElement[] elements = DefUseUtil.getDefs(myCallingBlock, localVariable, expression);
if (elements.length == 1) {
PsiExpression localInitializer = null;
if (elements[0] instanceof PsiLocalVariable) {
@@ -1,4 +1,4 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.psi.controlFlow;
import com.intellij.openapi.diagnostic.Logger;
@@ -257,6 +257,15 @@ public final class DefUseUtil {
}
public static PsiElement @NotNull [] getDefs(@NotNull PsiCodeBlock body, @NotNull PsiVariable def, @NotNull PsiElement ref, boolean rethrow) {
if (def instanceof PsiLocalVariable && ref instanceof PsiReferenceExpression && ((PsiReferenceExpression)ref).resolve() == def) {
final PsiElement containingClass = PsiTreeUtil.getParentOfType(def, PsiClass.class, PsiLambdaExpression.class);
PsiElement refContainer = PsiTreeUtil.getParentOfType(ref, PsiClass.class, PsiLambdaExpression.class);
while (containingClass != refContainer && refContainer != null) {
ref = refContainer;
refContainer = PsiTreeUtil.getParentOfType(refContainer.getParent(), PsiClass.class, PsiLambdaExpression.class);
}
}
try {
RefsDefs refsDefs = new RefsDefs(body) {
final PsiManager psiManager = def.getManager();
@@ -3,8 +3,8 @@ class Foo {
}
void bar() {
final String <flown11>res;
res = <flown111>"a";
final String res;
res = <flown11>"a";
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {