mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[groovy] extract transformation-renaming logic to helper extension
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
<extensionPoint name="membersContributor" interface="org.jetbrains.plugins.groovy.lang.resolve.NonCodeMembersContributor"/>
|
||||
<extensionPoint name="importContributor" interface="org.jetbrains.plugins.groovy.lang.resolve.GrImportContributor"/>
|
||||
<extensionPoint name="astTransformationSupport" interface="org.jetbrains.plugins.groovy.transformations.AstTransformationSupport"/>
|
||||
<extensionPoint name="astTransformationRenameHelper" interface="org.jetbrains.plugins.groovy.transformations.AstTransformationRenameHelper"/>
|
||||
<extensionPoint name="closureMissingMethodContributor"
|
||||
interface="org.jetbrains.plugins.groovy.lang.resolve.ClosureMissingMethodContributor"/>
|
||||
<extensionPoint name="variableEnhancer" interface="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.GrVariableEnhancer"/>
|
||||
@@ -132,12 +133,14 @@
|
||||
<astTransformationSupport implementation="org.jetbrains.plugins.groovy.transformations.impl.BaseScriptTransformationSupport"/>
|
||||
<astTransformationSupport id="defaultSupport"
|
||||
implementation="org.jetbrains.plugins.groovy.transformations.impl.DefaultTransformationSupport"/>
|
||||
<astTransformationRenameHelper implementation="org.jetbrains.plugins.groovy.transformations.impl.DefaultRenameHelper"/>
|
||||
<astTransformationSupport order="after defaultSupport"
|
||||
implementation="org.jetbrains.plugins.groovy.transformations.impl.FieldScriptTransformationSupport"/>
|
||||
<astTransformationSupport id="delegateSupport" order="after defaultSupport"
|
||||
implementation="org.jetbrains.plugins.groovy.transformations.impl.DelegateTransformationSupport"/>
|
||||
<astTransformationSupport id="traitSupport" order="last"
|
||||
implementation="org.jetbrains.plugins.groovy.transformations.impl.TraitTransformationSupport"/>
|
||||
<astTransformationRenameHelper implementation="org.jetbrains.plugins.groovy.transformations.impl.TraitRenameHelper"/>
|
||||
|
||||
<positionManagerDelegate implementation="org.jetbrains.plugins.groovy.gant.GantPositionManagerHelper"/>
|
||||
|
||||
|
||||
+21
-138
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.refactoring.rename;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
@@ -36,13 +35,10 @@ import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrTraitField;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GrTraitUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||
@@ -54,13 +50,13 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.plugins.groovy.transformations.RenameHelperKt.getNewNameFromTransformations;
|
||||
|
||||
/**
|
||||
* @author ilyas
|
||||
*/
|
||||
public class RenameGrFieldProcessor extends RenameJavaVariableProcessor {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(RenameGrFieldProcessor.class);
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<PsiReference> findReferences(PsiElement element) {
|
||||
@@ -87,145 +83,34 @@ public class RenameGrFieldProcessor extends RenameJavaVariableProcessor {
|
||||
String newName,
|
||||
final UsageInfo[] usages,
|
||||
@Nullable RefactoringElementListener listener) throws IncorrectOperationException {
|
||||
final GrField field = (GrField)psiElement;
|
||||
String fieldName = field.getName();
|
||||
|
||||
NameProvider nameProvider = new NameProvider(field, newName);
|
||||
|
||||
MultiMap<PsiNamedElement, UsageInfo> propertyUsages = MultiMap.createLinked();
|
||||
MultiMap<PsiNamedElement, UsageInfo> simpleUsages = MultiMap.createLinked();
|
||||
|
||||
List<PsiReference> unknownUsages = new ArrayList<>();
|
||||
GrField field = (GrField)psiElement;
|
||||
Map<GrReferenceExpression, PsiElement> handled = ContainerUtil.newHashMap();
|
||||
|
||||
for (UsageInfo usage : usages) {
|
||||
final PsiReference ref = usage.getReference();
|
||||
if (ref instanceof GrReferenceExpression) {
|
||||
final GroovyResolveResult resolveResult = ((GrReferenceExpression)ref).advancedResolve();
|
||||
final PsiElement element = resolveResult.getElement();
|
||||
if (resolveResult.isInvokedOnProperty()) {
|
||||
propertyUsages.putValue((PsiNamedElement)element, usage);
|
||||
}
|
||||
else {
|
||||
simpleUsages.putValue((PsiNamedElement)element, usage);
|
||||
}
|
||||
PsiElement resolved = ref.resolve();
|
||||
ref.handleElementRename(getNewNameFromTransformations(resolved, newName));
|
||||
handled.put((GrReferenceExpression)ref, resolved);
|
||||
}
|
||||
else if (ref != null) {
|
||||
unknownUsages.add(ref);
|
||||
handleElementRename(newName, ref, field.getName());
|
||||
}
|
||||
}
|
||||
|
||||
for (PsiReference ref : unknownUsages) {
|
||||
handleElementRename(newName, ref, fieldName);
|
||||
}
|
||||
|
||||
field.setName(newName);
|
||||
|
||||
nameProvider.putNewElements(field);
|
||||
for (GrReferenceExpression expression : handled.keySet()) {
|
||||
PsiElement oldResolved = handled.get(expression);
|
||||
if (oldResolved == null) continue;
|
||||
PsiElement resolved = expression.resolve();
|
||||
if (resolved == null) continue;
|
||||
if (expression.getManager().areElementsEquivalent(oldResolved, resolved)) continue;
|
||||
qualify(field, expression);
|
||||
}
|
||||
|
||||
PsiManager manager = field.getManager();
|
||||
for (PsiNamedElement element : simpleUsages.keySet()) {
|
||||
for (UsageInfo info : simpleUsages.get(element)) {
|
||||
final String name = nameProvider.getNewName(element);
|
||||
rename(nameProvider.getNewElement(element), info, name == null ? newName : name, name != null, manager);
|
||||
}
|
||||
}
|
||||
for (PsiNamedElement element : propertyUsages.keySet()) {
|
||||
for (UsageInfo info : propertyUsages.get(element)) {
|
||||
rename(element, info, newName, true, manager);
|
||||
}
|
||||
}
|
||||
if (listener != null) {
|
||||
listener.elementRenamed(field);
|
||||
}
|
||||
}
|
||||
|
||||
private static class NameProvider {
|
||||
|
||||
private final Map<PsiElement, String> myNameMap = ContainerUtil.newHashMap();
|
||||
private final Map<String, PsiNamedElement> myNewElements = ContainerUtil.newHashMap();
|
||||
|
||||
|
||||
public NameProvider(GrField field, String newName) {
|
||||
myNameMap.put(field, newName);
|
||||
|
||||
if (field.isProperty()) {
|
||||
for (GrAccessorMethod getter : field.getGetters()) {
|
||||
myNameMap.put(getter, RenamePropertyUtil.getGetterNameByOldName(newName, getter.getName()));
|
||||
}
|
||||
final GrAccessorMethod setter = field.getSetter();
|
||||
if (setter != null) {
|
||||
myNameMap.put(setter, GroovyPropertyUtils.getSetterName(newName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String getNewName(@NotNull PsiElement element) {
|
||||
String name = myNameMap.get(element);
|
||||
if (name != null) {
|
||||
return name;
|
||||
}
|
||||
|
||||
if (element instanceof GrTraitField) {
|
||||
PsiField prototype = ((GrTraitField)element).getPrototype();
|
||||
String newPrototypeName = getNewName(prototype);
|
||||
return GrTraitUtil.getTraitFieldPrefix(prototype.getContainingClass()) + newPrototypeName;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void putNewElements(@NotNull GrField field) {
|
||||
myNewElements.put(field.getName(), field);
|
||||
|
||||
if (field.isProperty()) {
|
||||
for (GrAccessorMethod newGetter : field.getGetters()) {
|
||||
myNewElements.put(newGetter.getName(), newGetter);
|
||||
}
|
||||
|
||||
final GrAccessorMethod newSetter = field.getSetter();
|
||||
if (newSetter != null) {
|
||||
myNewElements.put(newSetter.getName(), newSetter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PsiNamedElement getNewElement(PsiNamedElement element) {
|
||||
String newName = getNewName(element);
|
||||
PsiNamedElement newElement = myNewElements.get(newName);
|
||||
if (newElement != null) {
|
||||
return newElement;
|
||||
}
|
||||
|
||||
if (element instanceof GrTraitField) {
|
||||
PsiField prototype = ((GrTraitField)element).getPrototype();
|
||||
return getNewElement(prototype);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void rename(PsiNamedElement element,
|
||||
UsageInfo info,
|
||||
String nameToUse,
|
||||
boolean shouldCheckForCorrectResolve,
|
||||
PsiManager manager) {
|
||||
final PsiReference ref = info.getReference();
|
||||
assert ref != null;
|
||||
final PsiElement renamed = ref.handleElementRename(nameToUse);
|
||||
PsiElement newly_resolved = ref.resolve();
|
||||
if (shouldCheckForCorrectResolve) {
|
||||
if (element instanceof GrAccessorMethod && newly_resolved instanceof GrAccessorMethod) {
|
||||
final GrAccessorMethod oldAccessor = (GrAccessorMethod)element;
|
||||
final GrAccessorMethod newAccessor = (GrAccessorMethod)newly_resolved;
|
||||
if (!manager.areElementsEquivalent(oldAccessor.getProperty(), newAccessor.getProperty()) &&
|
||||
oldAccessor.isSetter() == newAccessor.isSetter()) {
|
||||
qualify(oldAccessor, renamed, nameToUse);
|
||||
}
|
||||
}
|
||||
else if (!manager.areElementsEquivalent(element, newly_resolved)) {
|
||||
qualify((PsiMember)element, renamed, nameToUse);
|
||||
}
|
||||
listener.elementRenamed(psiElement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,13 +143,11 @@ public class RenameGrFieldProcessor extends RenameJavaVariableProcessor {
|
||||
ref.handleElementRename(toRename);
|
||||
}
|
||||
|
||||
private static void qualify(PsiMember member, PsiElement renamed, String name) {
|
||||
if (!(renamed instanceof GrReferenceExpression)) return;
|
||||
|
||||
private static void qualify(PsiMember member, GrReferenceExpression refExpr) {
|
||||
String name = refExpr.getReferenceName();
|
||||
final PsiClass clazz = member.getContainingClass();
|
||||
if (clazz == null) return;
|
||||
|
||||
final GrReferenceExpression refExpr = (GrReferenceExpression)renamed;
|
||||
if (refExpr.getQualifierExpression() != null) return;
|
||||
|
||||
final PsiElement replaced;
|
||||
@@ -274,7 +157,7 @@ public class RenameGrFieldProcessor extends RenameJavaVariableProcessor {
|
||||
replaced = refExpr.replace(newRefExpr);
|
||||
}
|
||||
else {
|
||||
final PsiClass containingClass = PsiTreeUtil.getParentOfType(renamed, PsiClass.class);
|
||||
final PsiClass containingClass = PsiTreeUtil.getParentOfType(refExpr, PsiClass.class);
|
||||
if (member.getManager().areElementsEquivalent(containingClass, clazz)) {
|
||||
final GrReferenceExpression newRefExpr = GroovyPsiElementFactory.getInstance(member.getProject())
|
||||
.createReferenceExpressionFromText("this." + name);
|
||||
@@ -291,7 +174,7 @@ public class RenameGrFieldProcessor extends RenameJavaVariableProcessor {
|
||||
|
||||
@Override
|
||||
public boolean canProcessElement(@NotNull final PsiElement element) {
|
||||
return element instanceof GrField /*&& ((GrField)element).isProperty()*/ || element instanceof GrAccessorMethod;
|
||||
return element instanceof GrField;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.transformations;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.psi.PsiMember;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.transformations.impl.DefaultRenameHelper;
|
||||
|
||||
public interface AstTransformationRenameHelper {
|
||||
|
||||
ExtensionPointName<AstTransformationRenameHelper> EP_NAME = ExtensionPointName.create(
|
||||
"org.intellij.groovy.astTransformationRenameHelper"
|
||||
);
|
||||
|
||||
/**
|
||||
* GrReferenceExpression may resolve to member generated by some AST Transformation from original member.
|
||||
* <p>
|
||||
* Example:
|
||||
* <pre>
|
||||
* class A {
|
||||
* def foo
|
||||
* }
|
||||
* new A().getFoo()
|
||||
* </pre>
|
||||
* {@code getFoo} references accessor method generated from original <i>foo</i> field.
|
||||
* Suppose we are renaming the field to <i>bar</i>.
|
||||
* Then {@code member} will be the referenced accessor method and {@code newOriginalName} is the new name of the field, i.e. <i>bar</i>.
|
||||
* Given this information {@link DefaultRenameHelper} returns the name of the new accessor
|
||||
* that will be generated after rename, i.e. <i>getBar</i>.
|
||||
*
|
||||
* @param member currently resolved member.
|
||||
* @param newOriginalName new name of original member.
|
||||
* @return name of new member which will be generated after original member changes its name to {@code newOriginalName}.
|
||||
* @see DefaultRenameHelper
|
||||
*/
|
||||
@Nullable
|
||||
String getNewMemberName(@NotNull PsiMember member, @NotNull String newOriginalName);
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.transformations.impl
|
||||
|
||||
import com.intellij.psi.PsiMember
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils.getAccessorName
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils.getSetterName
|
||||
import org.jetbrains.plugins.groovy.transformations.AstTransformationRenameHelper
|
||||
|
||||
class DefaultRenameHelper : AstTransformationRenameHelper {
|
||||
|
||||
override fun getNewMemberName(member: PsiMember, newOriginalName: String): String? {
|
||||
if (member !is GrAccessorMethod) return null
|
||||
return if (member.isSetter) {
|
||||
getSetterName(newOriginalName)
|
||||
}
|
||||
else {
|
||||
getAccessorName(if (member.name.startsWith("is")) "is" else "get", newOriginalName)
|
||||
}
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.transformations.impl
|
||||
|
||||
import com.intellij.psi.PsiMember
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrTraitField
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GrTraitUtil
|
||||
import org.jetbrains.plugins.groovy.transformations.AstTransformationRenameHelper
|
||||
|
||||
class TraitRenameHelper : AstTransformationRenameHelper {
|
||||
|
||||
override fun getNewMemberName(member: PsiMember, newOriginalName: String): String? {
|
||||
if (member !is GrTraitField) return null
|
||||
val prototype = member.prototype
|
||||
val containingClass = prototype.containingClass ?: return null
|
||||
return GrTraitUtil.getTraitFieldPrefix(containingClass) + newOriginalName
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.transformations
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiMember
|
||||
|
||||
fun PsiElement?.getNewNameFromTransformations(newName: String) = (this as? PsiMember)?.let {
|
||||
doGetNewNameFromTransformations(it, newName)
|
||||
} ?: newName
|
||||
|
||||
private fun doGetNewNameFromTransformations(member: PsiMember, newName: String): String? {
|
||||
@Suppress("LoopToCallChain")
|
||||
for (helper in AstTransformationRenameHelper.EP_NAME.extensions) {
|
||||
val newMemberName = helper.getNewMemberName(member, newName)
|
||||
if (newMemberName != null) return newMemberName
|
||||
}
|
||||
return null
|
||||
}
|
||||
Reference in New Issue
Block a user