mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
introduce parameter object: extract change signature part to start under the same progress
This commit is contained in:
+46
-12
@@ -38,6 +38,8 @@ import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.refactoring.MoveDestination;
|
||||
import com.intellij.refactoring.RefactorJBundle;
|
||||
import com.intellij.refactoring.changeSignature.ChangeInfo;
|
||||
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessorBase;
|
||||
import com.intellij.refactoring.introduceparameterobject.usageInfo.*;
|
||||
import com.intellij.refactoring.util.FixableUsageInfo;
|
||||
import com.intellij.refactoring.util.FixableUsagesRefactoringProcessor;
|
||||
@@ -77,6 +79,7 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
private final Set<PsiParameter> paramsNeedingGetters = new HashSet<PsiParameter>();
|
||||
private final PsiClass existingClass;
|
||||
private PsiMethod myExistingClassCompatibleConstructor;
|
||||
private ChangeInfo myChangeInfo;
|
||||
|
||||
public IntroduceParameterObjectProcessor(String className,
|
||||
String packageName,
|
||||
@@ -179,7 +182,24 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
if (myUseExistingClass && existingClass != null) {
|
||||
myExistingClassCompatibleConstructor = existingClassIsCompatible(existingClass, parameters);
|
||||
}
|
||||
findUsagesForMethod(method, usages, true);
|
||||
|
||||
final PsiCodeBlock body = method.getBody();
|
||||
final String baseParameterName = StringUtil.decapitalize(className);
|
||||
|
||||
final String fixedParamName =
|
||||
body != null
|
||||
? JavaCodeStyleManager.getInstance(myProject).suggestUniqueVariableName(baseParameterName, body.getLBrace(), true)
|
||||
: JavaCodeStyleManager.getInstance(myProject).propertyNameToVariableName(baseParameterName, VariableKind.PARAMETER);
|
||||
|
||||
myChangeInfo =
|
||||
new MergeMethodArguments(method, className, packageName, fixedParamName, paramsToMerge, typeParams, keepMethodAsDelegate,
|
||||
myCreateInnerClass ? method.getContainingClass() : null).createChangeInfo();
|
||||
|
||||
for (UsageInfo info : ChangeSignatureProcessorBase.findUsages(myChangeInfo)) {
|
||||
usages.add(new ChangeSignatureUsageWrapper(info));
|
||||
}
|
||||
|
||||
findUsagesForMethod(method, usages, fixedParamName);
|
||||
|
||||
if (myUseExistingClass && existingClass != null && !(paramsNeedingGetters.isEmpty() && paramsNeedingSetters.isEmpty())) {
|
||||
usages.add(new AppendAccessorsUsageInfo(existingClass, myGenerateAccessors, paramsNeedingGetters, paramsNeedingSetters, parameters));
|
||||
@@ -187,7 +207,7 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
|
||||
final PsiMethod[] overridingMethods = OverridingMethodsSearch.search(method, true).toArray(PsiMethod.EMPTY_ARRAY);
|
||||
for (PsiMethod siblingMethod : overridingMethods) {
|
||||
findUsagesForMethod(siblingMethod, usages, false);
|
||||
findUsagesForMethod(siblingMethod, usages, fixedParamName);
|
||||
}
|
||||
|
||||
if (myNewVisibility != null) {
|
||||
@@ -195,16 +215,7 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
}
|
||||
}
|
||||
|
||||
private void findUsagesForMethod(PsiMethod overridingMethod, List<FixableUsageInfo> usages, boolean changeSignature) {
|
||||
final PsiCodeBlock body = overridingMethod.getBody();
|
||||
final String baseParameterName = StringUtil.decapitalize(className);
|
||||
final String fixedParamName =
|
||||
body != null
|
||||
? JavaCodeStyleManager.getInstance(myProject).suggestUniqueVariableName(baseParameterName, body.getLBrace(), true)
|
||||
: JavaCodeStyleManager.getInstance(myProject).propertyNameToVariableName(baseParameterName, VariableKind.PARAMETER);
|
||||
|
||||
usages.add(new MergeMethodArguments(overridingMethod, className, packageName, fixedParamName, paramsToMerge, typeParams, keepMethodAsDelegate, myCreateInnerClass ? method.getContainingClass() : null, changeSignature));
|
||||
|
||||
private void findUsagesForMethod(PsiMethod overridingMethod, List<FixableUsageInfo> usages, String fixedParamName) {
|
||||
final ParamUsageVisitor visitor = new ParamUsageVisitor(overridingMethod, paramsToMerge);
|
||||
overridingMethod.accept(visitor);
|
||||
final Set<PsiReferenceExpression> values = visitor.getParameterUsages();
|
||||
@@ -261,6 +272,13 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
}
|
||||
}
|
||||
}
|
||||
List<UsageInfo> changeSignatureUsages = new ArrayList<>();
|
||||
for (UsageInfo info : usageInfos) {
|
||||
if (info instanceof ChangeSignatureUsageWrapper) {
|
||||
changeSignatureUsages.add(((ChangeSignatureUsageWrapper)info).getInfo());
|
||||
}
|
||||
}
|
||||
ChangeSignatureProcessorBase.doChangeSignature(myChangeInfo, changeSignatureUsages.toArray(new UsageInfo[changeSignatureUsages.size()]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -537,4 +555,20 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class ChangeSignatureUsageWrapper extends FixableUsageInfo {
|
||||
private final UsageInfo myInfo;
|
||||
|
||||
public ChangeSignatureUsageWrapper(UsageInfo info) {
|
||||
super(info.getElement());
|
||||
myInfo = info;
|
||||
}
|
||||
|
||||
public UsageInfo getInfo() {
|
||||
return myInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fixUsage() throws IncorrectOperationException {}
|
||||
}
|
||||
}
|
||||
|
||||
+43
-68
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -13,32 +13,29 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.refactoring.introduceparameterobject.usageInfo;
|
||||
package com.intellij.refactoring.introduceparameterobject;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.impl.source.PsiImmediateClassType;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor;
|
||||
import com.intellij.refactoring.changeSignature.ChangeInfo;
|
||||
import com.intellij.refactoring.changeSignature.JavaChangeInfoImpl;
|
||||
import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
|
||||
import com.intellij.refactoring.util.FixableUsageInfo;
|
||||
import com.intellij.refactoring.util.CanonicalTypes;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.VisibilityUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@SuppressWarnings({"MethodWithTooManyParameters"})
|
||||
public class MergeMethodArguments extends FixableUsageInfo {
|
||||
public class MergeMethodArguments {
|
||||
private final PsiMethod method;
|
||||
private final PsiClass myContainingClass;
|
||||
private final boolean myChangeSignature;
|
||||
private final boolean myKeepMethodAsDelegate;
|
||||
private final List<PsiTypeParameter> typeParams;
|
||||
private final String className;
|
||||
@@ -53,50 +50,45 @@ public class MergeMethodArguments extends FixableUsageInfo {
|
||||
String parameterName,
|
||||
int[] paramsToMerge,
|
||||
List<PsiTypeParameter> typeParams,
|
||||
final boolean keepMethodAsDelegate, final PsiClass containingClass, boolean changeSignature) {
|
||||
super(method);
|
||||
final boolean keepMethodAsDelegate,
|
||||
final PsiClass containingClass) {
|
||||
this.paramsToMerge = paramsToMerge;
|
||||
this.packageName = packageName;
|
||||
this.className = className;
|
||||
this.parameterName = parameterName;
|
||||
this.method = method;
|
||||
myContainingClass = containingClass;
|
||||
myChangeSignature = changeSignature;
|
||||
lastParamIsVararg = method.isVarArgs() && isParameterToMerge(method.getParameterList().getParametersCount() - 1);
|
||||
myKeepMethodAsDelegate = keepMethodAsDelegate;
|
||||
this.typeParams = new ArrayList<PsiTypeParameter>(typeParams);
|
||||
}
|
||||
|
||||
public void fixUsage() throws IncorrectOperationException {
|
||||
public ChangeInfo createChangeInfo() {
|
||||
final Project project = method.getProject();
|
||||
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
|
||||
final PsiMethod deepestSuperMethod = method.findDeepestSuperMethod();
|
||||
final PsiClass psiClass;
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
||||
String packageName;
|
||||
if (myContainingClass != null) {
|
||||
psiClass = myContainingClass.findInnerClassByName(className, false);
|
||||
}
|
||||
else {
|
||||
psiClass = psiFacade.findClass(StringUtil.getQualifiedName(packageName, className), GlobalSearchScope.allScope(project));
|
||||
}
|
||||
assert psiClass != null;
|
||||
PsiSubstitutor subst = PsiSubstitutor.EMPTY;
|
||||
if (deepestSuperMethod != null) {
|
||||
final PsiClass parentClass = deepestSuperMethod.getContainingClass();
|
||||
final PsiSubstitutor parentSubstitutor =
|
||||
TypeConversionUtil.getSuperClassSubstitutor(parentClass, method.getContainingClass(), PsiSubstitutor.EMPTY);
|
||||
for (int i1 = 0; i1 < psiClass.getTypeParameters().length; i1++) {
|
||||
final PsiTypeParameter typeParameter = psiClass.getTypeParameters()[i1];
|
||||
for (PsiTypeParameter parameter : parentClass.getTypeParameters()) {
|
||||
if (Comparing.strEqual(typeParameter.getName(), parameter.getName())) {
|
||||
subst = subst.put(typeParameter, parentSubstitutor.substitute(
|
||||
new PsiImmediateClassType(parameter, PsiSubstitutor.EMPTY)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
packageName = myContainingClass.getQualifiedName();
|
||||
if (packageName == null) {
|
||||
packageName = myContainingClass.getName();
|
||||
}
|
||||
}
|
||||
else {
|
||||
packageName = this.packageName;
|
||||
}
|
||||
|
||||
String text = StringUtil.getQualifiedName(packageName, className);
|
||||
if (!typeParams.isEmpty()) {
|
||||
text += "<" + StringUtil.join(typeParams, new Function<PsiTypeParameter, String>() {
|
||||
@Override
|
||||
public String fun(PsiTypeParameter parameter) {
|
||||
return parameter.getName();
|
||||
}
|
||||
}, ", ") + ">";
|
||||
}
|
||||
final PsiType classType = factory.createTypeFromText(text, method);
|
||||
final List<ParameterInfoImpl> parametersInfo = new ArrayList<ParameterInfoImpl>();
|
||||
final PsiClassType classType = JavaPsiFacade.getElementFactory(project).createType(psiClass, subst);
|
||||
|
||||
final ParameterInfoImpl mergedParamInfo = new ParameterInfoImpl(-1, parameterName, classType, null) {
|
||||
@Override
|
||||
@@ -117,33 +109,16 @@ public class MergeMethodArguments extends FixableUsageInfo {
|
||||
}
|
||||
|
||||
parametersInfo.add(firstIncludedIdx == -1 ? 0 : firstIncludedIdx, mergedParamInfo);
|
||||
final SmartPsiElementPointer<PsiMethod> meth = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(method);
|
||||
|
||||
final Runnable performChangeSignatureRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final PsiMethod psiMethod = meth.getElement();
|
||||
if (psiMethod == null) return;
|
||||
if (myChangeSignature) {
|
||||
final ChangeSignatureProcessor changeSignatureProcessor =
|
||||
new ChangeSignatureProcessor(psiMethod.getProject(), psiMethod,
|
||||
myKeepMethodAsDelegate, null, psiMethod.getName(),
|
||||
psiMethod.getReturnType(),
|
||||
parametersInfo.toArray(new ParameterInfoImpl[parametersInfo.size()]));
|
||||
changeSignatureProcessor.run();
|
||||
}
|
||||
}
|
||||
};
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
performChangeSignatureRunnable.run();
|
||||
} else {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
CommandProcessor.getInstance().runUndoTransparentAction(performChangeSignatureRunnable);
|
||||
}
|
||||
});
|
||||
}
|
||||
PsiType returnType = method.getReturnType();
|
||||
return new JavaChangeInfoImpl(VisibilityUtil.getVisibilityModifier(method.getModifierList()),
|
||||
method,
|
||||
method.getName(),
|
||||
returnType != null ? CanonicalTypes.createTypeWrapper(returnType) : null,
|
||||
parametersInfo.toArray(new ParameterInfoImpl[parametersInfo.size()]),
|
||||
null,
|
||||
myKeepMethodAsDelegate,
|
||||
Collections.emptySet(),
|
||||
Collections.emptySet());
|
||||
}
|
||||
|
||||
private boolean isParameterToMerge(int index) {
|
||||
+53
-44
@@ -71,23 +71,27 @@ public abstract class ChangeSignatureProcessorBase extends BaseRefactoringProces
|
||||
@Override
|
||||
@NotNull
|
||||
protected UsageInfo[] findUsages() {
|
||||
List<UsageInfo> infos = new ArrayList<UsageInfo>();
|
||||
return findUsages(myChangeInfo);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static UsageInfo[] findUsages(ChangeInfo changeInfo) {
|
||||
List<UsageInfo> infos = new ArrayList<UsageInfo>();
|
||||
final ChangeSignatureUsageProcessor[] processors = ChangeSignatureUsageProcessor.EP_NAME.getExtensions();
|
||||
for (ChangeSignatureUsageProcessor processor : processors) {
|
||||
ContainerUtil.addAll(infos, processor.findUsages(myChangeInfo));
|
||||
ContainerUtil.addAll(infos, processor.findUsages(changeInfo));
|
||||
}
|
||||
infos = filterUsages(infos);
|
||||
return infos.toArray(new UsageInfo[infos.size()]);
|
||||
}
|
||||
|
||||
protected List<UsageInfo> filterUsages(List<UsageInfo> infos) {
|
||||
protected static List<UsageInfo> filterUsages(List<UsageInfo> infos) {
|
||||
Map<PsiElement, MoveRenameUsageInfo> moveRenameInfos = new HashMap<PsiElement, MoveRenameUsageInfo>();
|
||||
Set<PsiElement> usedElements = new HashSet<PsiElement>();
|
||||
|
||||
List<UsageInfo> result = new ArrayList<UsageInfo>(infos.size() / 2);
|
||||
for (UsageInfo info : infos) {
|
||||
LOG.assertTrue(info != null, getClass());
|
||||
LOG.assertTrue(info != null);
|
||||
PsiElement element = info.getElement();
|
||||
if (info instanceof MoveRenameUsageInfo) {
|
||||
if (usedElements.contains(element)) continue;
|
||||
@@ -139,14 +143,15 @@ public abstract class ChangeSignatureProcessorBase extends BaseRefactoringProces
|
||||
@Override
|
||||
protected void performRefactoring(@NotNull UsageInfo[] usages) {
|
||||
RefactoringTransaction transaction = getTransaction();
|
||||
final RefactoringElementListener elementListener = transaction == null ? null : transaction.getElementListener(myChangeInfo.getMethod());
|
||||
final String fqn = CopyReferenceAction.elementToFqn(myChangeInfo.getMethod());
|
||||
final ChangeInfo changeInfo = myChangeInfo;
|
||||
final RefactoringElementListener elementListener = transaction == null ? null : transaction.getElementListener(changeInfo.getMethod());
|
||||
final String fqn = CopyReferenceAction.elementToFqn(changeInfo.getMethod());
|
||||
if (fqn != null) {
|
||||
UndoableAction action = new BasicUndoableAction() {
|
||||
@Override
|
||||
public void undo() {
|
||||
if (elementListener instanceof UndoRefactoringElementListener) {
|
||||
((UndoRefactoringElementListener)elementListener).undoElementMovedOrRenamed(myChangeInfo.getMethod(), fqn);
|
||||
((UndoRefactoringElementListener)elementListener).undoElementMovedOrRenamed(changeInfo.getMethod(), fqn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,44 +162,10 @@ public abstract class ChangeSignatureProcessorBase extends BaseRefactoringProces
|
||||
UndoManager.getInstance(myProject).undoableActionPerformed(action);
|
||||
}
|
||||
try {
|
||||
final ChangeSignatureUsageProcessor[] processors = ChangeSignatureUsageProcessor.EP_NAME.getExtensions();
|
||||
|
||||
final ResolveSnapshotProvider resolveSnapshotProvider = myChangeInfo.isParameterNamesChanged() ?
|
||||
VariableInplaceRenamer.INSTANCE.forLanguage(myChangeInfo.getMethod().getLanguage()) : null;
|
||||
final List<ResolveSnapshotProvider.ResolveSnapshot> snapshots = new ArrayList<ResolveSnapshotProvider.ResolveSnapshot>();
|
||||
for (ChangeSignatureUsageProcessor processor : processors) {
|
||||
if (resolveSnapshotProvider != null) {
|
||||
processor.registerConflictResolvers(snapshots, resolveSnapshotProvider, usages, myChangeInfo);
|
||||
}
|
||||
}
|
||||
|
||||
for (UsageInfo usage : usages) {
|
||||
for (ChangeSignatureUsageProcessor processor : processors) {
|
||||
if (processor.processUsage(myChangeInfo, usage, true, usages)) break;
|
||||
}
|
||||
}
|
||||
|
||||
LOG.assertTrue(myChangeInfo.getMethod().isValid());
|
||||
for (ChangeSignatureUsageProcessor processor : processors) {
|
||||
if (processor.processPrimaryMethod(myChangeInfo)) break;
|
||||
}
|
||||
|
||||
for (UsageInfo usage : usages) {
|
||||
for (ChangeSignatureUsageProcessor processor : processors) {
|
||||
if (processor.processUsage(myChangeInfo, usage, false, usages)) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!snapshots.isEmpty()) {
|
||||
for (ParameterInfo parameterInfo : myChangeInfo.getNewParameters()) {
|
||||
for (ResolveSnapshotProvider.ResolveSnapshot snapshot : snapshots) {
|
||||
snapshot.apply(parameterInfo.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
final PsiElement method = myChangeInfo.getMethod();
|
||||
doChangeSignature(changeInfo, usages);
|
||||
final PsiElement method = changeInfo.getMethod();
|
||||
LOG.assertTrue(method.isValid());
|
||||
if (elementListener != null && myChangeInfo.isNameChanged()) {
|
||||
if (elementListener != null && changeInfo.isNameChanged()) {
|
||||
elementListener.elementRenamed(method);
|
||||
}
|
||||
}
|
||||
@@ -203,6 +174,44 @@ public abstract class ChangeSignatureProcessorBase extends BaseRefactoringProces
|
||||
}
|
||||
}
|
||||
|
||||
public static void doChangeSignature(ChangeInfo changeInfo, @NotNull UsageInfo[] usages) {
|
||||
final ChangeSignatureUsageProcessor[] processors = ChangeSignatureUsageProcessor.EP_NAME.getExtensions();
|
||||
|
||||
final ResolveSnapshotProvider resolveSnapshotProvider = changeInfo.isParameterNamesChanged() ?
|
||||
VariableInplaceRenamer.INSTANCE.forLanguage(changeInfo.getMethod().getLanguage()) : null;
|
||||
final List<ResolveSnapshotProvider.ResolveSnapshot> snapshots = new ArrayList<ResolveSnapshotProvider.ResolveSnapshot>();
|
||||
for (ChangeSignatureUsageProcessor processor : processors) {
|
||||
if (resolveSnapshotProvider != null) {
|
||||
processor.registerConflictResolvers(snapshots, resolveSnapshotProvider, usages, changeInfo);
|
||||
}
|
||||
}
|
||||
|
||||
for (UsageInfo usage : usages) {
|
||||
for (ChangeSignatureUsageProcessor processor : processors) {
|
||||
if (processor.processUsage(changeInfo, usage, true, usages)) break;
|
||||
}
|
||||
}
|
||||
|
||||
LOG.assertTrue(changeInfo.getMethod().isValid());
|
||||
for (ChangeSignatureUsageProcessor processor : processors) {
|
||||
if (processor.processPrimaryMethod(changeInfo)) break;
|
||||
}
|
||||
|
||||
for (UsageInfo usage : usages) {
|
||||
for (ChangeSignatureUsageProcessor processor : processors) {
|
||||
if (processor.processUsage(changeInfo, usage, false, usages)) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!snapshots.isEmpty()) {
|
||||
for (ParameterInfo parameterInfo : changeInfo.getNewParameters()) {
|
||||
for (ResolveSnapshotProvider.ResolveSnapshot snapshot : snapshots) {
|
||||
snapshot.apply(parameterInfo.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCommandName() {
|
||||
return RefactoringBundle.message("changing.signature.of.0", DescriptiveNameUtil.getDescriptiveName(myChangeInfo.getMethod()));
|
||||
|
||||
Reference in New Issue
Block a user