rename records components (IDEA-228462)

GitOrigin-RevId: f673a1841f9f8ca454a73b9f2a38b3e7edacbf65
This commit is contained in:
Anna.Kozlova
2020-01-29 19:34:36 +00:00
committed by intellij-monorepo-bot
parent c936621849
commit 90d15bfaf0
11 changed files with 108 additions and 2 deletions
@@ -5,6 +5,8 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.*;
import com.intellij.psi.impl.light.LightRecordCanonicalConstructor;
import com.intellij.psi.impl.light.LightRecordMember;
import com.intellij.psi.javadoc.PsiDocTag;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.SearchScope;
@@ -148,6 +150,14 @@ public class JavaTargetElementEvaluator extends TargetElementEvaluatorEx2 implem
return JavaPsiFacade.getInstance(refElement.getProject()).findClass(qualifiedName, refElement.getResolveScope());
}
}
if (refElement instanceof LightRecordMember) {
return ((LightRecordMember)refElement).getRecordComponent();
}
if (refElement instanceof LightRecordCanonicalConstructor) {
return ((LightRecordCanonicalConstructor)refElement).getContainingClass();
}
}
return super.adjustReferenceOrReferencedElement(file, editor, offset, flags, refElement);
}
@@ -8,6 +8,7 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Pass;
import com.intellij.psi.*;
import com.intellij.psi.impl.light.LightRecordMethod;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
@@ -137,6 +138,7 @@ public class RenameJavaMethodProcessor extends RenameJavaMemberProcessor {
if (elem instanceof PsiMethod) {
PsiMethod actualMethod = (PsiMethod) elem;
if (actualMethod instanceof LightRecordMethod) return;
if (!methodAndOverriders.contains(actualMethod)) {
PsiClass outerClass = PsiTreeUtil.getParentOfType(element, PsiClass.class);
while (outerClass != null) {
@@ -327,6 +329,10 @@ public class RenameJavaMethodProcessor extends RenameJavaMemberProcessor {
return element;
}
}
PsiRecordComponent recordComponent = JavaPsiRecordUtil.getRecordComponentForAccessor(psiMethod);
if (recordComponent != null) {
return recordComponent;
}
return SuperMethodWarningUtil.checkSuperMethod(psiMethod, RefactoringBundle.message("to.rename"));
}
@@ -345,6 +351,11 @@ public class RenameJavaMethodProcessor extends RenameJavaMemberProcessor {
super.substituteElementToRename(element, editor, renameCallback);
}
else {
PsiRecordComponent recordComponent = JavaPsiRecordUtil.getRecordComponentForAccessor(psiMethod);
if (recordComponent != null) {
renameCallback.pass(recordComponent);
return;
}
SuperMethodWarningUtil.checkSuperMethod(psiMethod, "Rename", new PsiElementProcessor<PsiMethod>() {
@Override
public boolean execute(@NotNull PsiMethod method) {
@@ -27,6 +27,7 @@ import com.intellij.refactoring.util.RefactoringMessageUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -129,6 +130,17 @@ public class RenameJavaVariableProcessor extends RenameJavaMemberProcessor {
if (element instanceof PsiField && JavaLanguage.INSTANCE.equals(element.getLanguage())) {
prepareFieldRenaming((PsiField)element, newName, allRenames);
}
if (element instanceof PsiRecordComponent) {
PsiClass containingClass = ((PsiRecordComponent)element).getContainingClass();
if (containingClass != null) {
PsiMethod explicitGetter = ContainerUtil
.find(containingClass.findMethodsByName(((PsiRecordComponent)element).getName(), false), m -> m.getParameters().length == 0);
if (explicitGetter != null) {
addOverriddenAndImplemented(explicitGetter, newName, null, newName, JavaCodeStyleManager.getInstance(element.getProject()), allRenames);
}
}
}
}
private static void prepareFieldRenaming(PsiField field, String newName, final Map<PsiElement, String> allRenames) {
@@ -7,8 +7,11 @@ import com.intellij.psi.*;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.SearchRequestCollector;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.JavaPsiRecordUtil;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class JavaRecordComponentSearcher extends QueryExecutorBase<PsiReference, ReferencesSearch.SearchParameters> {
@Override
@@ -23,10 +26,19 @@ public class JavaRecordComponentSearcher extends QueryExecutorBase<PsiReference,
queryParameters.getEffectiveSearchScope(),
false,
info.myLightMethod);
optimizer.searchWord(info.myName,
new LocalSearchScope(info.myClass),
true,
info.myLightField);
PsiParameter parameter = info.myLightCompactConstructorParameter;
if (parameter != null) {
optimizer.searchWord(info.myName,
new LocalSearchScope(parameter.getDeclarationScope()),
true,
parameter);
}
}
}
}
@@ -37,27 +49,36 @@ public class JavaRecordComponentSearcher extends QueryExecutorBase<PsiReference,
if (name == null) return null;
PsiClass containingClass = recordComponent.getContainingClass();
if (containingClass == null) return null;
PsiMethod[] methods = containingClass.findMethodsByName(name, false);
if (methods.length != 1) return null;
PsiField field = containingClass.findFieldByName(name, false);
if (field == null) return null;
PsiMethod method = methods[0];
return new RecordNavigationInfo(method, field, name, recordComponent.getContainingClass());
PsiMethod compactConstructor = ContainerUtil.find(containingClass.getConstructors(), JavaPsiRecordUtil::isCompactConstructor);
PsiParameter parameter = compactConstructor != null
? ContainerUtil.find(compactConstructor.getParameterList().getParameters(), p -> name.equals(p.getName()))
: null;
return new RecordNavigationInfo(methods[0], field, parameter, name, recordComponent.getContainingClass());
});
}
private static class RecordNavigationInfo {
@NotNull final PsiMethod myLightMethod;
@NotNull final PsiField myLightField;
@Nullable final PsiParameter myLightCompactConstructorParameter;
@NotNull final String myName;
@NotNull final PsiClass myClass;
private RecordNavigationInfo(@NotNull PsiMethod lightMethod,
@NotNull PsiField lightField,
@Nullable PsiParameter parameter,
@NotNull String name,
@NotNull PsiClass aClass) {
myLightMethod = lightMethod;
myLightField = lightField;
myLightCompactConstructorParameter = parameter;
myName = name;
myClass = aClass;
}
@@ -0,0 +1,8 @@
interface IBar {
int bar();
}
record Foo(int bar) implements IBar{
public Foo { this.bar = b<caret>ar; }
public int bar() { return bar; }
public int test() { return bar(); }
}
@@ -0,0 +1,8 @@
interface IBar {
int baz();
}
record Foo(int baz) implements IBar{
public Foo { this.baz = b<caret>az; }
public int baz() { return baz; }
public int test() { return baz(); }
}
@@ -0,0 +1,5 @@
record Foo(int bar) {
public Foo { this.bar = bar; }
public int b<caret>ar() { return bar; }
public int test() { return bar(); }
}
@@ -0,0 +1,5 @@
record Foo(int baz) {
public Foo { this.baz = baz; }
public int b<caret>az() { return baz; }
public int test() { return baz(); }
}
@@ -0,0 +1,4 @@
record Foo(int b<caret>ar) {
public Foo { this.bar = bar; }
public int test() { return bar(); }
}
@@ -0,0 +1,4 @@
record Foo(int b<caret>az) {
public Foo { this.baz = baz; }
public int test() { return baz(); }
}
@@ -34,6 +34,24 @@ public class LightRecordsHighlightingTest extends LightJavaCodeInsightFixtureTes
doTest();
}
public void testRenameOnRecordComponent() {
doTestRename();
}
public void testRenameOnCompactConstructorReference() {
doTestRename();
}
public void testRenameOnExplicitGetter() {
doTestRename();
}
private void doTestRename() {
doTest();
myFixture.renameElementAtCaret("baz");
myFixture.checkResultByFile(getTestName(false) + "_after.java");
}
private void doTest() {
myFixture.addClass("package java.lang; public abstract class Record {" +
"public abstract boolean equals(Object obj);" +