mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-08 15:09:39 +07:00
[java] inline parameter: find defs of local variables used inside lambda parameter initializer (IDEA-278368)
GitOrigin-RevId: eac35d3e7067592031f483a6ca7fe29ce26e56db
This commit is contained in:
committed by
intellij-monorepo-bot
parent
04daf179e3
commit
b09b860649
@@ -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.refactoring.inline;
|
||||
|
||||
import com.intellij.codeInsight.ExceptionUtil;
|
||||
@@ -42,7 +42,6 @@ import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import com.intellij.refactoring.util.InlineUtil;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -173,27 +172,6 @@ public class InlineLocalHandler extends JavaInlineActionHandler {
|
||||
|
||||
final String localName = local.getName();
|
||||
|
||||
final List<PsiElement> innerClassesWithUsages = Collections.synchronizedList(new ArrayList<>());
|
||||
final List<PsiElement> innerClassUsages = Collections.synchronizedList(new ArrayList<>());
|
||||
final PsiElement containingClass = PsiTreeUtil.getParentOfType(local, PsiClass.class, PsiLambdaExpression.class);
|
||||
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;
|
||||
}
|
||||
}
|
||||
final PsiCodeBlock containerBlock = PsiTreeUtil.getParentOfType(local, PsiCodeBlock.class);
|
||||
if (containerBlock == null) {
|
||||
final String message = RefactoringBundle.getCannotRefactorMessage(
|
||||
@@ -201,10 +179,16 @@ 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 {
|
||||
defToInline = getDefToInline(local, innerClassesWithUsages.isEmpty() ? refExpr : innerClassesWithUsages.get(0), containerBlock, true);
|
||||
PsiElement refToInline = getRefToInline(local, allRefs, innerClassUsages, containingClass);
|
||||
defToInline = getDefToInline(local,
|
||||
refToInline != null ? refToInline : refExpr,
|
||||
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));
|
||||
@@ -365,6 +349,33 @@ 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,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2021 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.refactoring.inline;
|
||||
|
||||
import com.intellij.codeInsight.ExceptionUtil;
|
||||
@@ -26,6 +26,7 @@ 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;
|
||||
@@ -107,7 +108,12 @@ public class InlineParameterExpressionProcessor extends BaseRefactoringProcessor
|
||||
final PsiElement element = expression.resolve();
|
||||
if (element instanceof PsiLocalVariable) {
|
||||
final PsiLocalVariable localVariable = (PsiLocalVariable)element;
|
||||
final PsiElement[] elements = DefUseUtil.getDefs(myCallingBlock, localVariable, expression);
|
||||
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));
|
||||
if (elements.length == 1) {
|
||||
PsiExpression localInitializer = null;
|
||||
if (elements[0] instanceof PsiLocalVariable) {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
interface A {
|
||||
void foo(int i);
|
||||
}
|
||||
class B {
|
||||
B(A <caret>a) {
|
||||
System.out.println(a);
|
||||
}
|
||||
}
|
||||
class C {
|
||||
{
|
||||
int k = 42;
|
||||
B b = new B(i1 -> i1 + k);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
interface A {
|
||||
void foo(int i);
|
||||
}
|
||||
class B {
|
||||
B() {
|
||||
System.out.println((A) i1 -> i1 + 42);
|
||||
}
|
||||
}
|
||||
class C {
|
||||
{
|
||||
B b = new B();
|
||||
}
|
||||
}
|
||||
@@ -98,6 +98,10 @@ public class InlineParameterTest extends LightRefactoringTestCase {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
public void testInlineLambdaWithOuterRef() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
public void testRefThis() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user