inline constant: ensure generic inliners are checked during inline constant (IDEA-173345; IDEA-173475)

This commit is contained in:
Anna Kozlova
2017-05-26 17:52:45 +03:00
parent c5c4b4debc
commit 7bc32f51b0
3 changed files with 64 additions and 45 deletions
@@ -15,7 +15,10 @@
*/
package com.intellij.refactoring.inline;
import com.intellij.lang.Language;
import com.intellij.lang.findUsages.DescriptiveNameUtil;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.lang.refactoring.InlineHandler;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
@@ -51,6 +54,7 @@ public class InlineConstantFieldProcessor extends BaseRefactoringProcessor {
private final boolean mySearchInCommentsAndStrings;
private final boolean mySearchForTextOccurrences;
private final boolean myDeleteDeclaration;
private Map<Language, InlineHandler.Inliner> myInliners;
public InlineConstantFieldProcessor(PsiField field, Project project, PsiReferenceExpression ref, boolean isInlineThisOnly) {
this(field, project, ref, isInlineThisOnly, false, false, true);
@@ -102,8 +106,7 @@ public class InlineConstantFieldProcessor extends BaseRefactoringProcessor {
for (PsiReference ref : ReferencesSearch.search(myField, GlobalSearchScope.projectScope(myProject), false)) {
PsiElement element = ref.getElement();
UsageInfo info = new UsageInfo(element);
if (!(element instanceof PsiExpression) && PsiTreeUtil.getParentOfType(element, PsiImportStaticStatement.class) == null) {
if (element instanceof PsiDocMethodOrFieldRef) {
info = new UsageFromJavaDoc(element);
}
@@ -156,8 +159,12 @@ public class InlineConstantFieldProcessor extends BaseRefactoringProcessor {
}
else {
PsiImportStaticStatement importStaticStatement = PsiTreeUtil.getParentOfType(element, PsiImportStaticStatement.class);
LOG.assertTrue(importStaticStatement != null, element.getText());
importStaticStatement.delete();
if (importStaticStatement != null) {
importStaticStatement.delete();
}
else {
GenericInlineHandler.inlineReference(info, myField, myInliners);
}
}
}
catch (IncorrectOperationException e) {
@@ -285,12 +292,19 @@ public class InlineConstantFieldProcessor extends BaseRefactoringProcessor {
}
}
myInliners = GenericInlineHandler.initInliners(myField, usagesIn, new InlineHandler.Settings() {
@Override
public boolean isOnlyOneReferenceToInline() {
return myInlineThisOnly;
}
}, conflicts, JavaLanguage.INSTANCE);
if (!myInlineThisOnly) {
for (UsageInfo info : usagesIn) {
if (info instanceof UsageFromJavaDoc) {
final PsiElement element = info.getElement();
if (element instanceof PsiDocMethodOrFieldRef && !PsiTreeUtil.isAncestor(myField, element, false)) {
conflicts.putValue(element, "Inlined method is used in javadoc");
final PsiElement element = info.getElement();
if (element instanceof PsiDocMethodOrFieldRef) {
if (!PsiTreeUtil.isAncestor(myField, element, false)) {
conflicts.putValue(element, "Inlined field is used in javadoc");
}
}
}
@@ -234,37 +234,12 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
}
}
ArrayList<PsiReference> refs = convertUsagesToRefs(usagesIn);
myInliners = GenericInlineHandler.initializeInliners(myMethod, new InlineHandler.Settings() {
myInliners = GenericInlineHandler.initInliners(myMethod, usagesIn, new InlineHandler.Settings() {
@Override
public boolean isOnlyOneReferenceToInline() {
return myInlineThisOnly;
}
}, refs);
//hack to prevent conflicts 'Cannot inline reference from Java'
myInliners.put(JavaLanguage.INSTANCE, new InlineHandler.Inliner() {
@Nullable
@Override
public MultiMap<PsiElement, String> getConflicts(PsiReference reference, PsiElement referenced) {
return MultiMap.emptyInstance();
}
@Override
public void inlineUsage(@NotNull UsageInfo usage, @NotNull PsiElement referenced) {
if (usage instanceof NonCodeUsageInfo) return;
throw new UnsupportedOperationException(
"usage: " + usage.getClass().getName() +
", usage element: " + usage.getElement() +
", referenced: " + referenced.getClass().getName() +
", text: " + referenced.getText());
}
});
for (PsiReference ref : refs) {
GenericInlineHandler.collectConflicts(ref, myMethod, myInliners, conflicts);
}
}, conflicts, JavaLanguage.INSTANCE);
final PsiReturnStatement[] returnStatements = PsiUtil.findReturnStatements(myMethod);
for (PsiReturnStatement statement : returnStatements) {
@@ -290,16 +265,6 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
return showConflicts(conflicts, usagesIn);
}
private static ArrayList<PsiReference> convertUsagesToRefs(UsageInfo[] usagesIn) {
ArrayList<PsiReference> refs = new ArrayList<>();
for (UsageInfo info : usagesIn) {
final PsiReference ref = info.getReference();
if (ref != null) { //ref can be null if it is conflict usage info
refs.add(ref);
}
}
return refs;
}
private boolean checkReadOnly() {
return myMethod.isWritable() || myMethod instanceof PsiCompiledElement;
@@ -36,10 +36,12 @@ import com.intellij.refactoring.BaseRefactoringProcessor;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.ui.ConflictsDialog;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.refactoring.util.NonCodeUsageInfo;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -155,6 +157,44 @@ public class GenericInlineHandler {
return inliners;
}
public static Map<Language, InlineHandler.Inliner> initInliners(PsiElement elementToInline,
UsageInfo[] usagesIn,
InlineHandler.Settings settings,
MultiMap<PsiElement, String> conflicts,
Language... emptyInliners) {
ArrayList<PsiReference> refs = new ArrayList<>();
for (UsageInfo info : usagesIn) {
if (info instanceof NonCodeUsageInfo) continue;
PsiElement element = info.getElement();
if (element != null) {
PsiReference[] references = element.getReferences();
if (references.length > 0) {
refs.add(references[0]);
}
}
}
Map<Language, InlineHandler.Inliner> inliners = initializeInliners(elementToInline, settings, refs);
for (Language language : emptyInliners) {
inliners.put(language, new InlineHandler.Inliner() {
@Nullable
@Override
public MultiMap<PsiElement, String> getConflicts(@NotNull PsiReference reference, @NotNull PsiElement referenced) {
return null;
}
@Override
public void inlineUsage(@NotNull UsageInfo usage, @NotNull PsiElement referenced) { }
});
}
for (PsiReference ref : refs) {
collectConflicts(ref, elementToInline, inliners, conflicts);
}
return inliners;
}
public static void collectConflicts(final PsiReference reference,
final PsiElement element,
final Map<Language, InlineHandler.Inliner> inliners,