mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
inline field: collect final field initializers in constructors (IDEA-130350)
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.refactoring.inline;
|
||||
|
||||
import com.intellij.codeInsight.PsiEquivalenceUtil;
|
||||
import com.intellij.codeInsight.TargetElementUtil;
|
||||
import com.intellij.lang.StdLanguages;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
@@ -23,12 +24,19 @@ import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.ProjectScope;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.refactoring.HelpID;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
@@ -46,7 +54,7 @@ public class InlineConstantFieldHandler extends JavaInlineActionHandler {
|
||||
final PsiElement navigationElement = element.getNavigationElement();
|
||||
final PsiField field = (PsiField)(navigationElement instanceof PsiField ? navigationElement : element);
|
||||
|
||||
if (!field.hasInitializer()) {
|
||||
if (getInitializer(field) == null) {
|
||||
String message = RefactoringBundle.message("no.initializer.present.for.the.field");
|
||||
CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_FIELD);
|
||||
return;
|
||||
@@ -97,4 +105,40 @@ public class InlineConstantFieldHandler extends JavaInlineActionHandler {
|
||||
InlineFieldDialog dialog = new InlineFieldDialog(project, field, refExpression);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected static PsiExpression getInitializer(PsiField field) {
|
||||
if (field.hasInitializer()) {
|
||||
return field.getInitializer();
|
||||
}
|
||||
|
||||
if (field.hasModifierProperty(PsiModifier.FINAL)) {
|
||||
PsiClass containingClass = field.getContainingClass();
|
||||
if (containingClass != null) {
|
||||
PsiMethod[] constructors = containingClass.getConstructors();
|
||||
final List<PsiExpression> result = new ArrayList<>();
|
||||
for (PsiReference reference : ReferencesSearch.search(field, new LocalSearchScope(constructors))) {
|
||||
final PsiElement element = reference.getElement();
|
||||
if (element instanceof PsiReferenceExpression && PsiUtil.isOnAssignmentLeftHand((PsiExpression)element)) {
|
||||
PsiAssignmentExpression assignmentExpression = PsiTreeUtil.getParentOfType(element, PsiAssignmentExpression.class);
|
||||
if (assignmentExpression != null) {
|
||||
ContainerUtil.addIfNotNull(assignmentExpression.getRExpression(), result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result.isEmpty()) return null;
|
||||
|
||||
PsiExpression first = result.get(0);
|
||||
for (PsiExpression expr : result) {
|
||||
if (!PsiEquivalenceUtil.areElementsEquivalent(expr, first)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+14
-4
@@ -137,7 +137,7 @@ public class InlineConstantFieldProcessor extends BaseRefactoringProcessor {
|
||||
|
||||
@Override
|
||||
protected void performRefactoring(@NotNull UsageInfo[] usages) {
|
||||
PsiExpression initializer = myField.getInitializer();
|
||||
PsiExpression initializer = InlineConstantFieldHandler.getInitializer(myField);
|
||||
LOG.assertTrue(initializer != null);
|
||||
|
||||
initializer = normalize ((PsiExpression)initializer.copy());
|
||||
@@ -190,13 +190,23 @@ public class InlineConstantFieldProcessor extends BaseRefactoringProcessor {
|
||||
if (myField.isWritable()) {
|
||||
myField.normalizeDeclaration();
|
||||
}
|
||||
|
||||
if (isAccessedForWriting(expr)) {
|
||||
PsiAssignmentExpression assignmentExpression = PsiTreeUtil.getParentOfType(expr, PsiAssignmentExpression.class);
|
||||
if (assignmentExpression != null) {
|
||||
assignmentExpression.delete();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (expr instanceof PsiReferenceExpression) {
|
||||
PsiExpression qExpression = ((PsiReferenceExpression)expr).getQualifierExpression();
|
||||
if (qExpression != null) {
|
||||
PsiReferenceExpression referenceExpression = null;
|
||||
if (initializer1 instanceof PsiReferenceExpression) {
|
||||
referenceExpression = (PsiReferenceExpression)initializer1;
|
||||
} else if (initializer1 instanceof PsiMethodCallExpression) {
|
||||
}
|
||||
else if (initializer1 instanceof PsiMethodCallExpression) {
|
||||
referenceExpression = ((PsiMethodCallExpression)initializer1).getMethodExpression();
|
||||
}
|
||||
if (referenceExpression != null &&
|
||||
@@ -242,7 +252,7 @@ public class InlineConstantFieldProcessor extends BaseRefactoringProcessor {
|
||||
MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();
|
||||
|
||||
ReferencedElementsCollector collector = new ReferencedElementsCollector();
|
||||
PsiExpression initializer = myField.getInitializer();
|
||||
PsiExpression initializer = InlineConstantFieldHandler.getInitializer(myField);
|
||||
LOG.assertTrue(initializer != null);
|
||||
initializer.accept(collector);
|
||||
HashSet<PsiMember> referencedWithVisibility = collector.myReferencedMembers;
|
||||
@@ -250,7 +260,7 @@ public class InlineConstantFieldProcessor extends BaseRefactoringProcessor {
|
||||
PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(myField.getProject()).getResolveHelper();
|
||||
for (UsageInfo info : usagesIn) {
|
||||
PsiElement element = info.getElement();
|
||||
if (element instanceof PsiExpression && isAccessedForWriting((PsiExpression)element)) {
|
||||
if (element instanceof PsiExpression && (!myField.hasModifierProperty(PsiModifier.FINAL) || myInlineThisOnly) && isAccessedForWriting((PsiExpression)element)) {
|
||||
String message = RefactoringBundle.message("0.is.used.for.writing.in.1", RefactoringUIUtil.getDescription(myField, true),
|
||||
RefactoringUIUtil.getDescription(ConflictsUtil.getContainer(element), true));
|
||||
conflicts.putValue(element, message);
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
class Test {
|
||||
private final int <caret>i;
|
||||
|
||||
public Test() {
|
||||
this.i = 0;
|
||||
}
|
||||
|
||||
public Test(String s) {
|
||||
this.i = 0;
|
||||
}
|
||||
|
||||
void foo() {
|
||||
System.out.println(i);
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
class Test {
|
||||
|
||||
public Test() {
|
||||
}
|
||||
|
||||
public Test(String s) {
|
||||
}
|
||||
|
||||
void foo() {
|
||||
System.out.println(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
class Test {
|
||||
private final int <caret>i;
|
||||
|
||||
public Test() {
|
||||
this.i = 0;
|
||||
}
|
||||
|
||||
public Test(String s) {
|
||||
this.i = s.length();
|
||||
}
|
||||
|
||||
void foo() {
|
||||
System.out.println(i);
|
||||
}
|
||||
}
|
||||
+13
-5
@@ -38,15 +38,22 @@ public class InlineConstantFieldTest extends LightRefactoringTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testFinalInitializedInConstructor() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testMultipleInitializers() throws Exception {
|
||||
configureByFile("/refactoring/inlineConstantField/" + getTestName(false) + ".java");
|
||||
PsiElement element = TargetElementUtil
|
||||
.findTargetElement(myEditor, TargetElementUtil.ELEMENT_NAME_ACCEPTED | TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED);
|
||||
assertTrue(element instanceof PsiField);
|
||||
assertNull(InlineConstantFieldHandler.getInitializer((PsiField)element));
|
||||
}
|
||||
|
||||
private void doTest() throws Exception {
|
||||
String name = getTestName(false);
|
||||
@NonNls String fileName = "/refactoring/inlineConstantField/" + name + ".java";
|
||||
configureByFile(fileName);
|
||||
performAction();
|
||||
checkResultByFile(fileName + ".after");
|
||||
}
|
||||
|
||||
private void performAction() {
|
||||
PsiElement element = TargetElementUtil
|
||||
.findTargetElement(myEditor, TargetElementUtil.ELEMENT_NAME_ACCEPTED | TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED);
|
||||
final PsiReference ref = myFile.findReferenceAt(myEditor.getCaretModel().getOffset());
|
||||
@@ -54,5 +61,6 @@ public class InlineConstantFieldTest extends LightRefactoringTestCase {
|
||||
assertTrue(element instanceof PsiField);
|
||||
PsiField field = (PsiField)element.getNavigationElement();
|
||||
new InlineConstantFieldProcessor(field, getProject(), refExpr, element instanceof PsiCompiledElement).run();
|
||||
checkResultByFile(fileName + ".after");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user