Preserve code block when variable from lambda body conflicts with later declaration

Fixes IDEA-196540 TrivialFunctionalExpressionUsageInspection produces code with variable redefinitions
This commit is contained in:
Tagir Valeev
2018-08-01 20:49:03 +07:00
parent aa9efdf94c
commit b3325f5116
3 changed files with 45 additions and 5 deletions

View File

@@ -0,0 +1,10 @@
// "Replace call with method body" "true"
class Test {
void test() {
{
int a = 6;
}
int a =5;
}
}

View File

@@ -0,0 +1,13 @@
// "Replace call with method body" "true"
class Test {
void test() {
new Runnable() {
@Override
public void run() {
int a =6;
}
}.r<caret>un();
int a =5;
}
}

View File

@@ -4,6 +4,7 @@ package com.intellij.codeInspection;
import com.intellij.codeInsight.BlockUtils;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.MethodSignatureUtil;
import com.intellij.psi.util.PsiTreeUtil;
@@ -14,6 +15,7 @@ import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ObjectUtils;
import com.siyeh.ig.psiutils.*;
import one.util.streamex.StreamEx;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -220,13 +222,18 @@ public class TrivialFunctionalExpressionUsageInspection extends AbstractBaseJava
final PsiStatement[] statements = ((PsiCodeBlock)body).getStatements();
PsiReturnStatement statement = null;
if (statements.length > 0) {
final PsiStatement anchor = PsiTreeUtil.getParentOfType(parent, PsiStatement.class, false);
PsiElement anchor = PsiTreeUtil.getParentOfType(parent, PsiStatement.class, false);
statement = ObjectUtils.tryCast(statements[statements.length - 1], PsiReturnStatement.class);
if (anchor != null) {
final PsiElement gParent = anchor.getParent();
for (PsiElement child : body.getChildren()) {
if (child != statement && !(child instanceof PsiJavaToken)) {
gParent.addBefore(ct.markUnchanged(child), anchor);
PsiElement gParent = anchor.getParent();
if (hasNameConflict(statements, anchor)) {
gParent.addBefore(JavaPsiFacade.getElementFactory(element.getProject()).createStatementFromText(ct.text(body), anchor), anchor);
}
else {
for (PsiElement child : body.getChildren()) {
if (child != statement && !(child instanceof PsiJavaToken)) {
gParent.addBefore(ct.markUnchanged(child), anchor);
}
}
}
}
@@ -240,6 +247,16 @@ public class TrivialFunctionalExpressionUsageInspection extends AbstractBaseJava
}
}
private static boolean hasNameConflict(PsiStatement[] statements, PsiElement anchor) {
JavaCodeStyleManager manager = JavaCodeStyleManager.getInstance(anchor.getProject());
return StreamEx.of(statements).select(PsiDeclarationStatement.class)
.flatArray(PsiDeclarationStatement::getDeclaredElements)
.select(PsiNamedElement.class)
.map(PsiNamedElement::getName)
.nonNull()
.anyMatch(name -> !name.equals(manager.suggestUniqueVariableName(name, anchor, true)));
}
private static void inlineCallArguments(PsiMethodCallExpression callExpression,
PsiLambdaExpression element,
CommentTracker ct) {