mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
introduce parameter object: initial
This commit is contained in:
@@ -170,9 +170,6 @@ extracted.class.command.name=Extracted class {0}
|
||||
method.to.extract.parameters.from.label=Method to extract parameters from
|
||||
name.for.new.parameter.label=Name for new parameter:
|
||||
method.selected.has.no.parameters=Method selected has no parameters.
|
||||
introduced.parameter.class.command.name=Introduced parameter class {0} for {1}.{2}()
|
||||
method.whose.parameters.are.to.wrapped=Method whose parameters are to wrapped
|
||||
references.to.be.modified=References to be modified
|
||||
parameters.to.extract.border=Parameters to Extract
|
||||
parameter=Parameter
|
||||
your.evaluation.license.for.refactor.j.will.expire.in.less.than.n.days=Your evaluation license for Refactor-J will expire in less than {0} days.\n
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* @author ven
|
||||
*/
|
||||
public class OverriderUsageInfo extends UsageInfo {
|
||||
public class OverriderUsageInfo extends UsageInfo implements OverriderMethodUsageInfo<PsiMethod> {
|
||||
private final PsiMethod myBaseMethod;
|
||||
private final boolean myToInsertArgs;
|
||||
private final boolean myToCatchExceptions;
|
||||
@@ -44,6 +44,7 @@ public class OverriderUsageInfo extends UsageInfo {
|
||||
return myBaseMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiMethod getOverridingMethod() {
|
||||
return myOverridingMethod;
|
||||
}
|
||||
|
||||
+20
-6
@@ -28,6 +28,9 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PsiFormatUtil;
|
||||
import com.intellij.refactoring.*;
|
||||
import com.intellij.refactoring.changeSignature.JavaMethodDescriptor;
|
||||
import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
|
||||
import com.intellij.refactoring.introduceParameterObject.IntroduceParameterObjectProcessor;
|
||||
import com.intellij.refactoring.move.moveClassesOrPackages.DestinationFolderComboBox;
|
||||
import com.intellij.refactoring.ui.PackageNameReferenceEditorCombo;
|
||||
import com.intellij.refactoring.ui.RefactoringDialog;
|
||||
@@ -166,20 +169,31 @@ public class IntroduceParameterObjectDialog extends RefactoringDialog {
|
||||
packageName = getPackageName();
|
||||
className = getClassName();
|
||||
}
|
||||
List<VariableData> parameters = new ArrayList<VariableData>();
|
||||
final PsiParameterList parameterList = sourceMethod.getParameterList();
|
||||
final List<ParameterInfoImpl> parameters = new ArrayList<>();
|
||||
for (VariableData data : parameterInfo) {
|
||||
if (data.passAsParameter) {
|
||||
parameters.add(data);
|
||||
parameters.add(new ParameterInfoImpl(parameterList.getParameterIndex((PsiParameter)data.variable), data.name, data.type));
|
||||
}
|
||||
}
|
||||
final ParameterInfoImpl[] infos = parameters.toArray(new ParameterInfoImpl[parameters.size()]);
|
||||
final String newVisibility =
|
||||
myEscalateVisibilityCheckBox.isEnabled() && myEscalateVisibilityCheckBox.isSelected() ? VisibilityUtil.ESCALATE_VISIBILITY : null;
|
||||
final MoveDestination moveDestination = ((DestinationFolderComboBox)myDestinationCb)
|
||||
.selectDirectory(new PackageWrapper(PsiManager.getInstance(myProject), packageName), false);
|
||||
invokeRefactoring(new IntroduceParameterObjectProcessor(className, packageName, moveDestination, sourceMethod,
|
||||
parameters.toArray(new VariableData[parameters.size()]),
|
||||
keepMethod, useExistingClass,
|
||||
createInnerClass, newVisibility, myGenerateAccessorsCheckBox.isSelected()));
|
||||
final JavaIntroduceParameterObjectClassDescriptor classDescriptor =
|
||||
new JavaIntroduceParameterObjectClassDescriptor(className, packageName, moveDestination, useExistingClass, createInnerClass,
|
||||
newVisibility, infos, sourceMethod,
|
||||
myGenerateAccessorsCheckBox.isSelected());
|
||||
invokeRefactoring(
|
||||
new IntroduceParameterObjectProcessor<PsiMethod, ParameterInfoImpl, JavaIntroduceParameterObjectClassDescriptor>(getProject(),
|
||||
classDescriptor,
|
||||
sourceMethod,
|
||||
infos,
|
||||
new JavaMethodDescriptor(
|
||||
sourceMethod)
|
||||
.getParameters(),
|
||||
keepMethod));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
-412
@@ -1,412 +0,0 @@
|
||||
/*
|
||||
* 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 com.intellij.refactoring.introduceparameterobject;
|
||||
|
||||
import com.intellij.ide.highlighter.JavaFileType;
|
||||
import com.intellij.ide.util.PackageUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtil;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.impl.source.javadoc.PsiDocParamRef;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.javadoc.PsiDocTag;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.searches.OverridingMethodsSearch;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
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;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.refactoring.util.VariableData;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usageView.UsageViewDescriptor;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.VisibilityUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringProcessor {
|
||||
private static final Logger logger = Logger.getInstance("com.siyeh.rpp.introduceparameterobject.IntroduceParameterObjectProcessor");
|
||||
|
||||
private final MoveDestination myMoveDestination;
|
||||
private final PsiMethod method;
|
||||
private final String className;
|
||||
private final String packageName;
|
||||
private final boolean myUseExistingClass;
|
||||
private final boolean myCreateInnerClass;
|
||||
private final String myNewVisibility;
|
||||
private final boolean myGenerateAccessors;
|
||||
private final List<ParameterChunk> parameters;
|
||||
private final int[] paramsToMerge;
|
||||
private final List<PsiTypeParameter> typeParams;
|
||||
private final PsiClass existingClass;
|
||||
private PsiMethod myExistingClassCompatibleConstructor;
|
||||
private ChangeInfo myChangeInfo;
|
||||
private final String fixedParamName;
|
||||
|
||||
public IntroduceParameterObjectProcessor(String className,
|
||||
String packageName,
|
||||
MoveDestination moveDestination,
|
||||
PsiMethod method,
|
||||
VariableData[] parameters, boolean keepMethodAsDelegate, final boolean useExistingClass,
|
||||
final boolean createInnerClass,
|
||||
String newVisibility,
|
||||
boolean generateAccessors) {
|
||||
super(method.getProject());
|
||||
myMoveDestination = moveDestination;
|
||||
this.method = method;
|
||||
this.className = className;
|
||||
this.packageName = packageName;
|
||||
myUseExistingClass = useExistingClass;
|
||||
myCreateInnerClass = createInnerClass;
|
||||
myNewVisibility = newVisibility;
|
||||
myGenerateAccessors = generateAccessors;
|
||||
this.parameters = new ArrayList<ParameterChunk>();
|
||||
for (VariableData parameter : parameters) {
|
||||
this.parameters.add(new ParameterChunk(parameter));
|
||||
}
|
||||
final PsiParameterList parameterList = method.getParameterList();
|
||||
final PsiParameter[] methodParams = parameterList.getParameters();
|
||||
paramsToMerge = new int[parameters.length];
|
||||
for (int p = 0; p < parameters.length; p++) {
|
||||
VariableData parameter = parameters[p];
|
||||
for (int i = 0; i < methodParams.length; i++) {
|
||||
final PsiParameter methodParam = methodParams[i];
|
||||
if (parameter.variable.equals(methodParam)) {
|
||||
paramsToMerge[p] = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
final Set<PsiTypeParameter> typeParamSet = new HashSet<PsiTypeParameter>();
|
||||
final PsiTypeVisitor<Object> typeParametersVisitor = new PsiTypeVisitor<Object>() {
|
||||
@Override
|
||||
public Object visitClassType(PsiClassType classType) {
|
||||
final PsiClass referent = classType.resolve();
|
||||
if (referent instanceof PsiTypeParameter) {
|
||||
typeParamSet.add((PsiTypeParameter)referent);
|
||||
}
|
||||
return super.visitClassType(classType);
|
||||
}
|
||||
};
|
||||
for (VariableData parameter : parameters) {
|
||||
parameter.type.accept(typeParametersVisitor);
|
||||
}
|
||||
typeParams = new ArrayList<PsiTypeParameter>(typeParamSet);
|
||||
|
||||
final String qualifiedName = StringUtil.getQualifiedName(packageName, className);
|
||||
final GlobalSearchScope scope = GlobalSearchScope.allScope(myProject);
|
||||
existingClass = JavaPsiFacade.getInstance(myProject).findClass(qualifiedName, scope);
|
||||
|
||||
final PsiCodeBlock body = method.getBody();
|
||||
final String baseParameterName = StringUtil.decapitalize(className);
|
||||
|
||||
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();
|
||||
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected UsageViewDescriptor createUsageViewDescriptor(@NotNull UsageInfo[] usageInfos) {
|
||||
return new IntroduceParameterObjectUsageViewDescriptor(method);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean preprocessUsages(@NotNull final Ref<UsageInfo[]> refUsages) {
|
||||
MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();
|
||||
if (myUseExistingClass) {
|
||||
if (existingClass == null) {
|
||||
conflicts.putValue(null, RefactorJBundle.message("cannot.perform.the.refactoring") + "Could not find the selected class");
|
||||
}
|
||||
if (myExistingClassCompatibleConstructor == null) {
|
||||
conflicts.putValue(existingClass, RefactorJBundle.message("cannot.perform.the.refactoring") + "Selected class has no compatible constructors");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (existingClass != null) {
|
||||
conflicts.putValue(existingClass,
|
||||
RefactorJBundle.message("cannot.perform.the.refactoring") +
|
||||
RefactorJBundle.message("there.already.exists.a.class.with.the.chosen.name"));
|
||||
}
|
||||
if (myMoveDestination != null) {
|
||||
if (!myMoveDestination.isTargetAccessible(myProject, method.getContainingFile().getVirtualFile())) {
|
||||
conflicts.putValue(method, "Created class won't be accessible");
|
||||
}
|
||||
}
|
||||
}
|
||||
List<UsageInfo> changeSignatureUsages = new ArrayList<>();
|
||||
for (UsageInfo usageInfo : refUsages.get()) {
|
||||
if (usageInfo instanceof FixableUsageInfo) {
|
||||
final String conflictMessage = ((FixableUsageInfo)usageInfo).getConflictMessage();
|
||||
if (conflictMessage != null) {
|
||||
conflicts.putValue(usageInfo.getElement(), conflictMessage);
|
||||
}
|
||||
}
|
||||
else {
|
||||
changeSignatureUsages.add(usageInfo);
|
||||
}
|
||||
}
|
||||
|
||||
ChangeSignatureProcessorBase.collectConflictsFromExtensions(new Ref<>(changeSignatureUsages.toArray(new UsageInfo[changeSignatureUsages.size()])), conflicts, myChangeInfo);
|
||||
|
||||
return showConflicts(conflicts, refUsages.get());
|
||||
}
|
||||
|
||||
public void findUsages(@NotNull List<FixableUsageInfo> usages) {
|
||||
if (myUseExistingClass && existingClass != null) {
|
||||
myExistingClassCompatibleConstructor = JavaIntroduceParameterObjectDelegate.existingClassIsCompatible(existingClass, parameters);
|
||||
}
|
||||
|
||||
for (UsageInfo info : ChangeSignatureProcessorBase.findUsages(myChangeInfo)) {
|
||||
usages.add(new ChangeSignatureUsageWrapper(info));
|
||||
}
|
||||
|
||||
final PsiMethod[] overridingMethods = OverridingMethodsSearch.search(method).toArray(PsiMethod.EMPTY_ARRAY);
|
||||
for (int i : paramsToMerge) {
|
||||
final PsiParameter parameterInBase = method.getParameterList().getParameters()[i];
|
||||
ParameterChunk parameterChunk = ParameterChunk.getChunkByParameter(parameterInBase, parameters);
|
||||
assert parameterChunk != null;
|
||||
@NonNls String getter = parameterChunk.getGetterName(myProject);
|
||||
@NonNls String setter = parameterChunk.getSetterName(myProject);
|
||||
|
||||
final boolean[] needAccessors = {false, false};
|
||||
findUsagesForMethod(method, usages, fixedParamName, i, needAccessors, getter, setter);
|
||||
|
||||
for (PsiMethod siblingMethod : overridingMethods) {
|
||||
findUsagesForMethod(siblingMethod, usages, fixedParamName, i, needAccessors, getter, setter);
|
||||
}
|
||||
|
||||
final boolean useExisting = myUseExistingClass && existingClass != null;
|
||||
|
||||
if (needAccessors[0] && parameterChunk.getGetter() == null) {
|
||||
usages.add(new AppendAccessorsUsageInfo(existingClass, myGenerateAccessors || !useExisting, parameterInBase, true, parameters));
|
||||
}
|
||||
if (needAccessors[1] && parameterChunk.getSetter() == null) {
|
||||
usages.add(new AppendAccessorsUsageInfo(existingClass, myGenerateAccessors || !useExisting, parameterInBase, false, parameters));
|
||||
}
|
||||
}
|
||||
|
||||
if (myNewVisibility != null) {
|
||||
usages.add(new BeanClassVisibilityUsageInfo(existingClass, usages.toArray(new UsageInfo[usages.size()]), myNewVisibility, myExistingClassCompatibleConstructor));
|
||||
}
|
||||
}
|
||||
|
||||
private static void findUsagesForMethod(PsiMethod overridingMethod,
|
||||
List<FixableUsageInfo> usages,
|
||||
String fixedParamName,
|
||||
int i,
|
||||
final boolean[] needAccessors, String getter, String setter) {
|
||||
final LocalSearchScope localSearchScope = new LocalSearchScope(overridingMethod);
|
||||
final PsiParameter[] params = overridingMethod.getParameterList().getParameters();
|
||||
final PsiParameter parameter = params[i];
|
||||
ReferencesSearch.search(parameter, localSearchScope).forEach(new Processor<PsiReference>() {
|
||||
@Override
|
||||
public boolean process(PsiReference reference) {
|
||||
final PsiElement refElement = reference.getElement();
|
||||
if (refElement instanceof PsiReferenceExpression) {
|
||||
final PsiReferenceExpression paramUsage = (PsiReferenceExpression)refElement;
|
||||
needAccessors[0] = true;
|
||||
if (RefactoringUtil.isPlusPlusOrMinusMinus(paramUsage.getParent())) {
|
||||
usages.add(new ReplaceParameterIncrementDecrement(paramUsage, fixedParamName, setter, getter));
|
||||
needAccessors[1] = true;
|
||||
}
|
||||
else if (RefactoringUtil.isAssignmentLHS(paramUsage)) {
|
||||
usages.add(new ReplaceParameterAssignmentWithCall(paramUsage, fixedParamName, setter, getter));
|
||||
needAccessors[1] = true;
|
||||
}
|
||||
else {
|
||||
usages.add(new ReplaceParameterReferenceWithCall(paramUsage, fixedParamName, getter));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void performRefactoring(@NotNull UsageInfo[] usageInfos) {
|
||||
final PsiClass psiClass = buildClass(usageInfos);
|
||||
if (psiClass != null) {
|
||||
fixJavadocForConstructor(psiClass);
|
||||
super.performRefactoring(usageInfos);
|
||||
if (!myUseExistingClass) {
|
||||
for (PsiReference reference : ReferencesSearch.search(method)) {
|
||||
final PsiElement place = reference.getElement();
|
||||
VisibilityUtil.escalateVisibility(psiClass, place);
|
||||
for (PsiMethod constructor : psiClass.getConstructors()) {
|
||||
VisibilityUtil.escalateVisibility(constructor, place);
|
||||
}
|
||||
}
|
||||
}
|
||||
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()]));
|
||||
}
|
||||
}
|
||||
|
||||
private PsiClass buildClass(UsageInfo[] usageInfos) {
|
||||
if (existingClass != null) {
|
||||
return existingClass;
|
||||
}
|
||||
|
||||
Set<PsiParameter> paramsWithSetters = new HashSet<>();
|
||||
for (UsageInfo info : usageInfos) {
|
||||
if (info instanceof AppendAccessorsUsageInfo && !((AppendAccessorsUsageInfo)info).isGetter()) {
|
||||
paramsWithSetters.add(((AppendAccessorsUsageInfo)info).getParameter());
|
||||
}
|
||||
}
|
||||
|
||||
final ParameterObjectBuilder beanClassBuilder = new ParameterObjectBuilder();
|
||||
beanClassBuilder.setVisibility(myCreateInnerClass ? PsiModifier.PRIVATE : PsiModifier.PUBLIC);
|
||||
beanClassBuilder.setProject(myProject);
|
||||
beanClassBuilder.setTypeArguments(typeParams);
|
||||
beanClassBuilder.setClassName(className);
|
||||
beanClassBuilder.setPackageName(packageName);
|
||||
for (ParameterChunk parameterChunk : parameters) {
|
||||
final VariableData parameter = parameterChunk.getParameter();
|
||||
final boolean setterRequired = paramsWithSetters.contains(parameter.variable);
|
||||
beanClassBuilder.addField((PsiParameter)parameter.variable, parameter.name, parameter.type, setterRequired);
|
||||
}
|
||||
final String classString = beanClassBuilder.buildBeanClass();
|
||||
|
||||
try {
|
||||
final PsiFileFactory factory = PsiFileFactory.getInstance(method.getProject());
|
||||
final PsiJavaFile newFile = (PsiJavaFile)factory.createFileFromText(className + ".java", JavaFileType.INSTANCE, classString);
|
||||
if (myCreateInnerClass) {
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
final PsiClass[] classes = newFile.getClasses();
|
||||
assert classes.length > 0 : classString;
|
||||
final PsiClass innerClass = (PsiClass)containingClass.add(classes[0]);
|
||||
PsiUtil.setModifierProperty(innerClass, PsiModifier.STATIC, true);
|
||||
return (PsiClass)JavaCodeStyleManager.getInstance(newFile.getProject()).shortenClassReferences(innerClass);
|
||||
} else {
|
||||
final PsiFile containingFile = method.getContainingFile();
|
||||
final PsiDirectory containingDirectory = containingFile.getContainingDirectory();
|
||||
final PsiDirectory directory;
|
||||
if (myMoveDestination != null) {
|
||||
directory = myMoveDestination.getTargetDirectory(containingDirectory);
|
||||
} else {
|
||||
final Module module = ModuleUtil.findModuleForPsiElement(containingFile);
|
||||
directory = PackageUtil.findOrCreateDirectoryForPackage(module, packageName, containingDirectory, true, true);
|
||||
}
|
||||
|
||||
if (directory != null) {
|
||||
|
||||
final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(method.getManager().getProject());
|
||||
final PsiElement shortenedFile = JavaCodeStyleManager.getInstance(newFile.getProject()).shortenClassReferences(newFile);
|
||||
final PsiElement reformattedFile = codeStyleManager.reformat(shortenedFile);
|
||||
return ((PsiJavaFile)directory.add(reformattedFile)).getClasses()[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
logger.info(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void fixJavadocForConstructor(PsiClass psiClass) {
|
||||
final PsiDocComment docComment = method.getDocComment();
|
||||
if (docComment != null) {
|
||||
final List<PsiDocTag> mergedTags = new ArrayList<PsiDocTag>();
|
||||
final PsiDocTag[] paramTags = docComment.findTagsByName("param");
|
||||
for (PsiDocTag paramTag : paramTags) {
|
||||
final PsiElement[] dataElements = paramTag.getDataElements();
|
||||
if (dataElements.length > 0) {
|
||||
if (dataElements[0] instanceof PsiDocParamRef) {
|
||||
final PsiReference reference = dataElements[0].getReference();
|
||||
if (reference != null) {
|
||||
final PsiElement resolve = reference.resolve();
|
||||
if (resolve instanceof PsiParameter) {
|
||||
final int parameterIndex = method.getParameterList().getParameterIndex((PsiParameter)resolve);
|
||||
if (ArrayUtil.find(paramsToMerge, parameterIndex) < 0) continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
mergedTags.add((PsiDocTag)paramTag.copy());
|
||||
}
|
||||
}
|
||||
|
||||
PsiMethod compatibleParamObjectConstructor = null;
|
||||
if (myExistingClassCompatibleConstructor != null && myExistingClassCompatibleConstructor.getDocComment() == null) {
|
||||
compatibleParamObjectConstructor = myExistingClassCompatibleConstructor;
|
||||
} else if (!myUseExistingClass){
|
||||
compatibleParamObjectConstructor = psiClass.getConstructors()[0];
|
||||
}
|
||||
|
||||
if (compatibleParamObjectConstructor != null) {
|
||||
PsiDocComment psiDocComment = JavaPsiFacade.getElementFactory(myProject).createDocCommentFromText("/**\n*/");
|
||||
psiDocComment = (PsiDocComment)compatibleParamObjectConstructor.addBefore(psiDocComment, compatibleParamObjectConstructor.getFirstChild());
|
||||
|
||||
for (PsiDocTag tag : mergedTags) {
|
||||
psiDocComment.add(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected String getCommandName() {
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
return RefactorJBundle.message("introduced.parameter.class.command.name", className, containingClass.getName(), method.getName());
|
||||
}
|
||||
|
||||
|
||||
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 {}
|
||||
}
|
||||
}
|
||||
-45
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2013 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 com.intellij.refactoring.introduceparameterobject;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.refactoring.RefactorJBundle;
|
||||
import com.intellij.refactoring.psi.MyUsageViewUtil;
|
||||
import com.intellij.refactoring.ui.UsageViewDescriptorAdapter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
class IntroduceParameterObjectUsageViewDescriptor extends UsageViewDescriptorAdapter {
|
||||
|
||||
private final PsiMethod method;
|
||||
|
||||
IntroduceParameterObjectUsageViewDescriptor(PsiMethod method) {
|
||||
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiElement[] getElements() {
|
||||
return new PsiElement[]{method};
|
||||
}
|
||||
public String getProcessedElementsHeader() {
|
||||
return RefactorJBundle.message("method.whose.parameters.are.to.wrapped");
|
||||
}
|
||||
|
||||
public String getCodeReferencesText(int usagesCount, int filesCount) {
|
||||
return RefactorJBundle.message("references.to.be.modified") + MyUsageViewUtil.getUsageCountInfo(usagesCount, filesCount, "reference");
|
||||
}
|
||||
}
|
||||
+403
@@ -0,0 +1,403 @@
|
||||
/*
|
||||
* 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 com.intellij.refactoring.introduceparameterobject;
|
||||
|
||||
import com.intellij.codeInsight.generation.GenerateMembersUtil;
|
||||
import com.intellij.ide.highlighter.JavaFileType;
|
||||
import com.intellij.ide.util.PackageUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.refactoring.MoveDestination;
|
||||
import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
|
||||
import com.intellij.refactoring.introduceParameterObject.IntroduceParameterObjectClassDescriptor;
|
||||
import com.intellij.refactoring.introduceParameterObject.IntroduceParameterObjectDelegate;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class JavaIntroduceParameterObjectClassDescriptor extends IntroduceParameterObjectClassDescriptor<PsiMethod, ParameterInfoImpl> {
|
||||
private static final Logger LOG = Logger.getInstance("#" + JavaIntroduceParameterObjectClassDescriptor.class.getName());
|
||||
private final Set<PsiTypeParameter> myTypeParameters = new HashSet<>();
|
||||
private final Map<ParameterInfoImpl, ParameterBean> myExistingClassProperties = new HashMap<>();
|
||||
private final MoveDestination myMoveDestination;
|
||||
|
||||
private PsiMethod myExistingClassCompatibleConstructor;
|
||||
|
||||
public JavaIntroduceParameterObjectClassDescriptor(String className,
|
||||
String packageName,
|
||||
MoveDestination moveDestination,
|
||||
boolean useExistingClass,
|
||||
boolean createInnerClass,
|
||||
String newVisibility,
|
||||
ParameterInfoImpl[] paramsToMerge,
|
||||
PsiMethod method, boolean generateAccessors) {
|
||||
super(className, calcPackageName(packageName, createInnerClass, method), useExistingClass, createInnerClass,
|
||||
newVisibility, generateAccessors, paramsToMerge);
|
||||
myMoveDestination = moveDestination;
|
||||
final PsiTypeVisitor<Object> typeParametersVisitor = new PsiTypeVisitor<Object>() {
|
||||
@Override
|
||||
public Object visitClassType(PsiClassType classType) {
|
||||
final PsiClass referent = classType.resolve();
|
||||
if (referent instanceof PsiTypeParameter) {
|
||||
myTypeParameters.add((PsiTypeParameter)referent);
|
||||
}
|
||||
for (PsiType type : classType.getParameters()) {
|
||||
type.accept(this);
|
||||
}
|
||||
|
||||
return super.visitClassType(classType);
|
||||
}
|
||||
};
|
||||
for (ParameterInfoImpl parameterInfo : paramsToMerge) {
|
||||
parameterInfo.getTypeWrapper().getType(method, method.getManager()).accept(typeParametersVisitor);
|
||||
}
|
||||
}
|
||||
|
||||
private static String calcPackageName(String packageName, boolean createInnerClass, PsiMethod method) {
|
||||
if (createInnerClass) {
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass != null) {
|
||||
final String qualifiedName = containingClass.getQualifiedName();
|
||||
return qualifiedName != null ? qualifiedName : "";
|
||||
}
|
||||
else {
|
||||
return packageName;
|
||||
}
|
||||
}
|
||||
return packageName;
|
||||
}
|
||||
|
||||
public Set<PsiTypeParameter> getTypeParameters() {
|
||||
return myTypeParameters;
|
||||
}
|
||||
|
||||
public MoveDestination getMoveDestination() {
|
||||
return myMoveDestination;
|
||||
}
|
||||
|
||||
public String createFakeClassTypeText() {
|
||||
String text = StringUtil.getQualifiedName(getPackageName(), getClassName());
|
||||
if (!myTypeParameters.isEmpty()) {
|
||||
text += "<" + StringUtil.join(myTypeParameters, new Function<PsiTypeParameter, String>() {
|
||||
@Override
|
||||
public String fun(PsiTypeParameter parameter) {
|
||||
return parameter.getName();
|
||||
}
|
||||
}, ", ") + ">";
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
public PsiMethod getExistingClassCompatibleConstructor() {
|
||||
return myExistingClassCompatibleConstructor;
|
||||
}
|
||||
|
||||
public void setExistingClassCompatibleConstructor(PsiMethod existingClassCompatibleConstructor) {
|
||||
myExistingClassCompatibleConstructor = existingClassCompatibleConstructor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiClass getExistingClass() {
|
||||
return (PsiClass)super.getExistingClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExistingClass(PsiElement existingClass) {
|
||||
super.setExistingClass(existingClass);
|
||||
if (isUseExistingClass()) {
|
||||
setExistingClassCompatibleConstructor(existingClassIsCompatible((PsiClass)existingClass));
|
||||
}
|
||||
}
|
||||
|
||||
public String getGetter(ParameterInfoImpl param) {
|
||||
final ParameterBean bean = getBean(param);
|
||||
return bean != null ? bean.getGetter() : null;
|
||||
}
|
||||
|
||||
public String getSetter(ParameterInfoImpl param) {
|
||||
final ParameterBean bean = getBean(param);
|
||||
return bean != null ? bean.getSetter() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSetterName(ParameterInfoImpl parameterInfo, PsiElement context) {
|
||||
final ParameterBean bean = getBean(parameterInfo);
|
||||
@NonNls String setter = bean != null ? bean.getSetter() : null;
|
||||
if (setter == null) {
|
||||
setter = bean != null && bean.getField() != null
|
||||
? GenerateMembersUtil.suggestSetterName(bean.getField())
|
||||
: GenerateMembersUtil
|
||||
.suggestSetterName(parameterInfo.getName(), parameterInfo.getTypeWrapper().getType(context, context.getManager()),
|
||||
context.getProject());
|
||||
}
|
||||
|
||||
return setter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGetterName(ParameterInfoImpl paramInfo, PsiElement context) {
|
||||
final ParameterBean bean = getBean(paramInfo);
|
||||
@NonNls String getter = bean != null ? bean.getGetter() : null;
|
||||
if (getter == null) {
|
||||
getter = bean != null && bean.getField() != null ? GenerateMembersUtil.suggestGetterName(bean.getField())
|
||||
: GenerateMembersUtil
|
||||
.suggestGetterName(paramInfo.getName(), paramInfo.getTypeWrapper().getType(context, context.getManager()),
|
||||
context.getProject());
|
||||
}
|
||||
return getter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initExistingClass(PsiMethod method) {
|
||||
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(method.getProject());
|
||||
final String qualifiedName = StringUtil.getQualifiedName(getPackageName(), getClassName());
|
||||
final PsiClass existingClass = psiFacade.findClass(qualifiedName, method.getResolveScope());
|
||||
setExistingClass(existingClass);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiField getField(ParameterInfoImpl parameter) {
|
||||
final ParameterBean bean = getBean(parameter);
|
||||
return bean != null ? bean.getField() : null;
|
||||
}
|
||||
|
||||
private ParameterBean getBean(ParameterInfoImpl param) {
|
||||
return myExistingClassProperties.get(param);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiMethod existingClassIsCompatible(@NotNull PsiClass aClass) {
|
||||
ParameterInfoImpl[] paramsToMerge = getParamsToMerge();
|
||||
if (paramsToMerge.length == 1) {
|
||||
final ParameterInfoImpl parameterInfo = paramsToMerge[0];
|
||||
final PsiType paramType = parameterInfo.getTypeWrapper().getType(aClass, aClass.getManager());
|
||||
if (TypeConversionUtil.isPrimitiveWrapper(aClass.getQualifiedName())) {
|
||||
ParameterBean bean = new ParameterBean();
|
||||
bean.setField(aClass.findFieldByName("value", false));
|
||||
bean.setGetter(paramType.getCanonicalText() + "Value");
|
||||
myExistingClassProperties.put(parameterInfo, bean);
|
||||
for (PsiMethod constructor : aClass.getConstructors()) {
|
||||
if (constructorIsCompatible(constructor, new ParameterInfoImpl[]{parameterInfo}, aClass)) return constructor;
|
||||
}
|
||||
}
|
||||
}
|
||||
final PsiMethod[] constructors = aClass.getConstructors();
|
||||
PsiMethod compatibleConstructor = null;
|
||||
for (PsiMethod constructor : constructors) {
|
||||
if (constructorIsCompatible(constructor, paramsToMerge, aClass)) {
|
||||
compatibleConstructor = constructor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (compatibleConstructor == null) {
|
||||
return null;
|
||||
}
|
||||
final PsiParameterList parameterList = compatibleConstructor.getParameterList();
|
||||
final PsiParameter[] constructorParams = parameterList.getParameters();
|
||||
for (int i = 0; i < constructorParams.length; i++) {
|
||||
final PsiParameter param = constructorParams[i];
|
||||
final ParameterInfoImpl methodParam = getParameterInfo(i);
|
||||
final ParameterBean bean = new ParameterBean();
|
||||
myExistingClassProperties.put(methodParam, bean);
|
||||
|
||||
final PsiField field = findFieldAssigned(param, compatibleConstructor);
|
||||
if (field == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
bean.setField(field);
|
||||
|
||||
final PsiMethod getterForField = PropertyUtil.findGetterForField(field);
|
||||
if (getterForField != null) {
|
||||
bean.setGetter(getterForField.getName());
|
||||
}
|
||||
|
||||
final PsiMethod setterForField = PropertyUtil.findSetterForField(field);
|
||||
if (setterForField != null) {
|
||||
bean.setSetter(setterForField.getName());
|
||||
}
|
||||
}
|
||||
return compatibleConstructor;
|
||||
}
|
||||
|
||||
private boolean constructorIsCompatible(PsiMethod constructor, ParameterInfoImpl[] paramsToMerge, PsiElement context) {
|
||||
final PsiParameterList parameterList = constructor.getParameterList();
|
||||
final PsiParameter[] constructorParams = parameterList.getParameters();
|
||||
if (constructorParams.length != paramsToMerge.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < constructorParams.length; i++) {
|
||||
if (!TypeConversionUtil.isAssignable(constructorParams[i].getType(),
|
||||
getParameterInfo(i).getTypeWrapper().getType(context, context.getManager()))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static PsiField findFieldAssigned(PsiParameter param, PsiMethod constructor) {
|
||||
final ParamAssignmentFinder visitor = new ParamAssignmentFinder(param);
|
||||
constructor.accept(visitor);
|
||||
return visitor.getFieldAssigned();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiClass createClass(PsiMethod method, IntroduceParameterObjectDelegate.Accessor[] accessors) {
|
||||
if (isUseExistingClass()) {
|
||||
return getExistingClass();
|
||||
}
|
||||
|
||||
final ParameterObjectBuilder beanClassBuilder = new ParameterObjectBuilder();
|
||||
beanClassBuilder.setVisibility(isCreateInnerClass() ? PsiModifier.PRIVATE : PsiModifier.PUBLIC);
|
||||
beanClassBuilder.setProject(method.getProject());
|
||||
beanClassBuilder.setTypeArguments(getTypeParameters());
|
||||
beanClassBuilder.setClassName(getClassName());
|
||||
beanClassBuilder.setPackageName(getPackageName());
|
||||
PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
final ParameterInfoImpl[] parameterInfos = getParamsToMerge();
|
||||
for (int i = 0; i < parameterInfos.length; i++) {
|
||||
PsiParameter parameter = parameters[parameterInfos[i].getOldIndex()];
|
||||
final boolean setterRequired = accessors[i] == IntroduceParameterObjectDelegate.Accessor.Setter;
|
||||
final String newName = parameterInfos[i].getName();
|
||||
beanClassBuilder
|
||||
.addField(parameter, newName, parameterInfos[i].getTypeWrapper().getType(method, method.getManager()), setterRequired);
|
||||
}
|
||||
|
||||
final String classString = beanClassBuilder.buildBeanClass();
|
||||
|
||||
try {
|
||||
final PsiFileFactory factory = PsiFileFactory.getInstance(method.getProject());
|
||||
final PsiJavaFile newFile =
|
||||
(PsiJavaFile)factory.createFileFromText(getClassName() + ".java", JavaFileType.INSTANCE, classString);
|
||||
if (isCreateInnerClass()) {
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
final PsiClass[] classes = newFile.getClasses();
|
||||
assert classes.length > 0 : classString;
|
||||
final PsiClass innerClass = (PsiClass)containingClass.add(classes[0]);
|
||||
PsiUtil.setModifierProperty(innerClass, PsiModifier.STATIC, true);
|
||||
return (PsiClass)JavaCodeStyleManager.getInstance(newFile.getProject()).shortenClassReferences(innerClass);
|
||||
}
|
||||
else {
|
||||
final PsiFile containingFile = method.getContainingFile();
|
||||
final PsiDirectory containingDirectory = containingFile.getContainingDirectory();
|
||||
final PsiDirectory directory;
|
||||
final MoveDestination moveDestination = getMoveDestination();
|
||||
if (moveDestination != null) {
|
||||
directory = moveDestination.getTargetDirectory(containingDirectory);
|
||||
}
|
||||
else {
|
||||
final Module module = ModuleUtilCore.findModuleForPsiElement(containingFile);
|
||||
directory =
|
||||
PackageUtil.findOrCreateDirectoryForPackage(module, getPackageName(), containingDirectory, true, true);
|
||||
}
|
||||
|
||||
if (directory != null) {
|
||||
|
||||
final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(method.getManager().getProject());
|
||||
final PsiElement shortenedFile = JavaCodeStyleManager.getInstance(newFile.getProject()).shortenClassReferences(newFile);
|
||||
final PsiElement reformattedFile = codeStyleManager.reformat(shortenedFile);
|
||||
return ((PsiJavaFile)directory.add(reformattedFile)).getClasses()[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.info(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static class ParamAssignmentFinder extends JavaRecursiveElementWalkingVisitor {
|
||||
|
||||
private final PsiParameter param;
|
||||
|
||||
private PsiField fieldAssigned = null;
|
||||
|
||||
ParamAssignmentFinder(PsiParameter param) {
|
||||
this.param = param;
|
||||
}
|
||||
|
||||
public void visitAssignmentExpression(PsiAssignmentExpression assignment) {
|
||||
super.visitAssignmentExpression(assignment);
|
||||
final PsiExpression lhs = assignment.getLExpression();
|
||||
final PsiExpression rhs = assignment.getRExpression();
|
||||
if (!(lhs instanceof PsiReferenceExpression)) {
|
||||
return;
|
||||
}
|
||||
if (!(rhs instanceof PsiReferenceExpression)) {
|
||||
return;
|
||||
}
|
||||
final PsiElement referent = ((PsiReference)rhs).resolve();
|
||||
if (referent == null || !referent.equals(param)) {
|
||||
return;
|
||||
}
|
||||
final PsiElement assigned = ((PsiReference)lhs).resolve();
|
||||
if (assigned == null || !(assigned instanceof PsiField)) {
|
||||
return;
|
||||
}
|
||||
fieldAssigned = (PsiField)assigned;
|
||||
}
|
||||
|
||||
public PsiField getFieldAssigned() {
|
||||
return fieldAssigned;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ParameterBean {
|
||||
private PsiField myField;
|
||||
private String myGetter;
|
||||
private String mySetter;
|
||||
|
||||
public PsiField getField() {
|
||||
return myField;
|
||||
}
|
||||
|
||||
public void setField(PsiField field) {
|
||||
myField = field;
|
||||
}
|
||||
|
||||
public String getGetter() {
|
||||
return myGetter;
|
||||
}
|
||||
|
||||
public void setGetter(String getter) {
|
||||
myGetter = getter;
|
||||
}
|
||||
|
||||
public String getSetter() {
|
||||
return mySetter;
|
||||
}
|
||||
|
||||
public void setSetter(String setter) {
|
||||
mySetter = setter;
|
||||
}
|
||||
}
|
||||
}
|
||||
+217
-93
@@ -15,118 +15,242 @@
|
||||
*/
|
||||
package com.intellij.refactoring.introduceparameterobject;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.refactoring.MoveDestination;
|
||||
import com.intellij.refactoring.changeSignature.*;
|
||||
import com.intellij.refactoring.introduceParameterObject.IntroduceParameterObjectClassDescriptor;
|
||||
import com.intellij.refactoring.introduceParameterObject.IntroduceParameterObjectDelegate;
|
||||
import com.intellij.refactoring.introduceParameterObject.IntroduceParameterObjectProcessor;
|
||||
import com.intellij.refactoring.introduceparameterobject.usageInfo.*;
|
||||
import com.intellij.refactoring.util.CanonicalTypes;
|
||||
import com.intellij.refactoring.util.FixableUsageInfo;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.VisibilityUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class JavaIntroduceParameterObjectDelegate {
|
||||
public class JavaIntroduceParameterObjectDelegate
|
||||
extends IntroduceParameterObjectDelegate<PsiMethod, ParameterInfoImpl, JavaIntroduceParameterObjectClassDescriptor> {
|
||||
|
||||
@Override
|
||||
public ParameterInfoImpl createMergedParameterInfo(Project project,
|
||||
JavaIntroduceParameterObjectClassDescriptor descriptor,
|
||||
int[] paramsToMerge,
|
||||
PsiMethod method) {
|
||||
final PsiCodeBlock body = method.getBody();
|
||||
final String baseParameterName = StringUtil.decapitalize(descriptor.getClassName());
|
||||
|
||||
final String paramName = body != null
|
||||
? JavaCodeStyleManager.getInstance(project)
|
||||
.suggestUniqueVariableName(baseParameterName, body.getLBrace(), true)
|
||||
: JavaCodeStyleManager.getInstance(project)
|
||||
.propertyNameToVariableName(baseParameterName, VariableKind.PARAMETER);
|
||||
|
||||
final boolean lastVarargsToMerge =
|
||||
method.isVarArgs() && ArrayUtil.find(paramsToMerge, method.getParameterList().getParametersCount() - 1) > -1;
|
||||
final String classTypeText = descriptor.createFakeClassTypeText();
|
||||
final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
|
||||
return new ParameterInfoImpl(-1, paramName, facade.getElementFactory().createTypeFromText(classTypeText, method), null) {
|
||||
@Override
|
||||
public PsiExpression getValue(final PsiCallExpression expr) throws IncorrectOperationException {
|
||||
final String qualifiedName = StringUtil.getQualifiedName(descriptor.getPackageName(), descriptor.getClassName());
|
||||
final PsiClass existingClass = facade.findClass(qualifiedName, expr.getResolveScope());
|
||||
if (existingClass == null) return null;
|
||||
final String mergedParam = getMergedParam(expr, existingClass, paramsToMerge, method, lastVarargsToMerge);
|
||||
return (PsiExpression)JavaCodeStyleManager.getInstance(project)
|
||||
.shortenClassReferences(facade.getElementFactory().createExpressionFromText(mergedParam, expr));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static String getMergedParam(PsiCallExpression call,
|
||||
PsiClass existingClass,
|
||||
int[] paramsToMerge,
|
||||
PsiMethod method,
|
||||
boolean lastVarargsToMerge) {
|
||||
final PsiExpression[] args = call.getArgumentList().getExpressions();
|
||||
StringBuilder newExpression = new StringBuilder();
|
||||
final JavaResolveResult resolvant = call.resolveMethodGenerics();
|
||||
final PsiSubstitutor substitutor = resolvant.getSubstitutor();
|
||||
newExpression.append("new ")
|
||||
.append(JavaPsiFacade.getElementFactory(call.getProject()).createType(existingClass, substitutor).getCanonicalText());
|
||||
newExpression.append('(');
|
||||
boolean isFirst = true;
|
||||
for (int index : paramsToMerge) {
|
||||
if (!isFirst) {
|
||||
newExpression.append(", ");
|
||||
}
|
||||
isFirst = false;
|
||||
newExpression.append(getArgument(args, index, method));
|
||||
}
|
||||
if (lastVarargsToMerge) {
|
||||
final int lastArg = paramsToMerge[paramsToMerge.length - 1];
|
||||
for (int i = lastArg + 1; i < args.length; i++) {
|
||||
newExpression.append(',');
|
||||
newExpression.append(getArgument(args, i, method));
|
||||
}
|
||||
}
|
||||
newExpression.append(')');
|
||||
return newExpression.toString();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static PsiMethod existingClassIsCompatible(PsiClass aClass, List<ParameterChunk> params) {
|
||||
if (params.size() == 1) {
|
||||
final ParameterChunk parameterChunk = params.get(0);
|
||||
final PsiType paramType = parameterChunk.getParameter().type;
|
||||
if (TypeConversionUtil.isPrimitiveWrapper(aClass.getQualifiedName())) {
|
||||
parameterChunk.setField(aClass.findFieldByName("value", false));
|
||||
parameterChunk.setGetter(paramType.getCanonicalText() + "Value");
|
||||
for (PsiMethod constructor : aClass.getConstructors()) {
|
||||
if (constructorIsCompatible(constructor, params)) return constructor;
|
||||
private static String getArgument(PsiExpression[] args, int i, PsiMethod method) {
|
||||
if (i < args.length) {
|
||||
return args[i].getText();
|
||||
}
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
if (i < parameters.length) return parameters[i].getName();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChangeInfo createChangeSignatureInfo(PsiMethod method, List<ParameterInfoImpl> infos, boolean delegate) {
|
||||
PsiType returnType = method.getReturnType();
|
||||
return new JavaChangeInfoImpl(VisibilityUtil.getVisibilityModifier(method.getModifierList()),
|
||||
method,
|
||||
method.getName(),
|
||||
returnType != null ? CanonicalTypes.createTypeWrapper(returnType) : null,
|
||||
infos.toArray(new ParameterInfoImpl[infos.size()]),
|
||||
null,
|
||||
delegate,
|
||||
Collections.emptySet(),
|
||||
Collections.emptySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <M1 extends PsiNamedElement, P1 extends ParameterInfo> Accessor collectInternalUsages(Collection<FixableUsageInfo> usages,
|
||||
PsiMethod overridingMethod,
|
||||
M1 element,
|
||||
IntroduceParameterObjectClassDescriptor<M1, P1> classDescriptor,
|
||||
int parameterIdx,
|
||||
String mergedParamName) {
|
||||
final LocalSearchScope localSearchScope = new LocalSearchScope(overridingMethod);
|
||||
final PsiParameter[] params = overridingMethod.getParameterList().getParameters();
|
||||
final PsiParameter parameter = params[parameterIdx];
|
||||
final P1 parameterInfo = classDescriptor.getParameterInfo(parameterIdx);
|
||||
final String setter = classDescriptor.getSetterName(parameterInfo, overridingMethod);
|
||||
final String getter = classDescriptor.getGetterName(parameterInfo, overridingMethod);
|
||||
final Accessor[] accessor = new Accessor[]{null};
|
||||
ReferencesSearch.search(parameter, localSearchScope).forEach(new Processor<PsiReference>() {
|
||||
@Override
|
||||
public boolean process(PsiReference reference) {
|
||||
final PsiElement refElement = reference.getElement();
|
||||
if (refElement instanceof PsiReferenceExpression) {
|
||||
final PsiReferenceExpression paramUsage = (PsiReferenceExpression)refElement;
|
||||
if (RefactoringUtil.isPlusPlusOrMinusMinus(paramUsage.getParent())) {
|
||||
accessor[0] = Accessor.Setter;
|
||||
usages.add(new ReplaceParameterIncrementDecrement(paramUsage, mergedParamName, setter, getter));
|
||||
}
|
||||
else if (RefactoringUtil.isAssignmentLHS(paramUsage)) {
|
||||
accessor[0] = Accessor.Setter;
|
||||
usages.add(new ReplaceParameterAssignmentWithCall(paramUsage, mergedParamName, setter, getter));
|
||||
}
|
||||
else {
|
||||
if (accessor[0] == null) {
|
||||
accessor[0] = Accessor.Getter;
|
||||
}
|
||||
usages.add(new ReplaceParameterReferenceWithCall(paramUsage, mergedParamName, getter));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return accessor[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collectAccessibilityUsages(Collection<FixableUsageInfo> usages,
|
||||
PsiMethod method,
|
||||
JavaIntroduceParameterObjectClassDescriptor descriptor,
|
||||
Accessor[] accessors) {
|
||||
final ParameterInfoImpl[] parameterInfos = descriptor.getParamsToMerge();
|
||||
final PsiClass existingClass = descriptor.getExistingClass();
|
||||
final boolean useExisting = descriptor.isGenerateAccessors() || !(descriptor.isUseExistingClass() && existingClass != null);
|
||||
|
||||
final PsiParameter[] psiParameters = method.getParameterList().getParameters();
|
||||
for (int i = 0; i < parameterInfos.length; i++) {
|
||||
int oldParamIdx = parameterInfos[i].getOldIndex();
|
||||
final IntroduceParameterObjectDelegate.Accessor accessor = accessors[i];
|
||||
if (accessor != null) {
|
||||
final ParameterInfoImpl parameterInfo = parameterInfos[i];
|
||||
final PsiParameter parameter = psiParameters[oldParamIdx];
|
||||
final PsiField field = descriptor.getField(parameterInfo);
|
||||
final String getter = descriptor.getGetter(parameterInfo);
|
||||
if (getter == null) {
|
||||
usages.add(new AppendAccessorsUsageInfo(parameter, existingClass, useExisting, parameterInfo, true, field));
|
||||
}
|
||||
|
||||
if (accessor == IntroduceParameterObjectDelegate.Accessor.Setter && descriptor.getSetter(parameterInfo) == null) {
|
||||
usages.add(new AppendAccessorsUsageInfo(parameter, existingClass, useExisting, parameterInfo, false, field));
|
||||
}
|
||||
}
|
||||
}
|
||||
final PsiMethod[] constructors = aClass.getConstructors();
|
||||
PsiMethod compatibleConstructor = null;
|
||||
for (PsiMethod constructor : constructors) {
|
||||
if (constructorIsCompatible(constructor, params)) {
|
||||
compatibleConstructor = constructor;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
final String newVisibility = descriptor.getNewVisibility();
|
||||
if (newVisibility != null) {
|
||||
usages.add(new BeanClassVisibilityUsageInfo(existingClass, usages.toArray(UsageInfo.EMPTY_ARRAY), newVisibility, descriptor));
|
||||
}
|
||||
if (compatibleConstructor == null) {
|
||||
return null;
|
||||
|
||||
usages.add(new ConstructorJavadocUsageInfo(method, descriptor));
|
||||
|
||||
if (!descriptor.isUseExistingClass()) {
|
||||
usages.add(new FixableUsageInfo(method) {
|
||||
@Override
|
||||
public void fixUsage() throws IncorrectOperationException {
|
||||
final PsiClass psiClass = descriptor.getExistingClass();
|
||||
for (PsiReference reference : ReferencesSearch.search(method)) {
|
||||
final PsiElement place = reference.getElement();
|
||||
VisibilityUtil.escalateVisibility(psiClass, place);
|
||||
for (PsiMethod constructor : psiClass.getConstructors()) {
|
||||
VisibilityUtil.escalateVisibility(constructor, place);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
final PsiParameterList parameterList = compatibleConstructor.getParameterList();
|
||||
final PsiParameter[] constructorParams = parameterList.getParameters();
|
||||
for (int i = 0; i < constructorParams.length; i++) {
|
||||
final PsiParameter param = constructorParams[i];
|
||||
final ParameterChunk parameterChunk = params.get(i);
|
||||
|
||||
final PsiField field = findFieldAssigned(param, compatibleConstructor);
|
||||
if (field == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
parameterChunk.setField(field);
|
||||
|
||||
final PsiMethod getterForField = PropertyUtil.findGetterForField(field);
|
||||
if (getterForField != null) {
|
||||
parameterChunk.setGetter(getterForField.getName());
|
||||
}
|
||||
|
||||
final PsiMethod setterForField = PropertyUtil.findSetterForField(field);
|
||||
if (setterForField != null) {
|
||||
parameterChunk.setSetter(setterForField.getName());
|
||||
}
|
||||
}
|
||||
return compatibleConstructor;
|
||||
}
|
||||
|
||||
private static boolean constructorIsCompatible(PsiMethod constructor, List<ParameterChunk> params) {
|
||||
final PsiParameterList parameterList = constructor.getParameterList();
|
||||
final PsiParameter[] constructorParams = parameterList.getParameters();
|
||||
if (constructorParams.length != params.size()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < constructorParams.length; i++) {
|
||||
if (!TypeConversionUtil.isAssignable(constructorParams[i].getType(), params.get(i).getParameter().type)) {
|
||||
return false;
|
||||
@Override
|
||||
public void collectConflicts(MultiMap<PsiElement, String> conflicts,
|
||||
UsageInfo[] infos,
|
||||
PsiMethod method,
|
||||
JavaIntroduceParameterObjectClassDescriptor classDescriptor) {
|
||||
final MoveDestination moveDestination = classDescriptor.getMoveDestination();
|
||||
if (moveDestination != null) {
|
||||
if (!moveDestination.isTargetAccessible(method.getProject(), method.getContainingFile().getVirtualFile())) {
|
||||
conflicts.putValue(method, "Created class won't be accessible");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static PsiField findFieldAssigned(PsiParameter param, PsiMethod constructor) {
|
||||
final ParamAssignmentFinder visitor = new ParamAssignmentFinder(param);
|
||||
constructor.accept(visitor);
|
||||
return visitor.getFieldAssigned();
|
||||
}
|
||||
if (moveDestination != null) {
|
||||
for (UsageInfo info : infos) {
|
||||
if (info instanceof IntroduceParameterObjectProcessor.ChangeSignatureUsageWrapper) {
|
||||
final UsageInfo usageInfo = ((IntroduceParameterObjectProcessor.ChangeSignatureUsageWrapper)info).getInfo();
|
||||
if (usageInfo instanceof OverriderMethodUsageInfo) {
|
||||
final PsiElement overridingMethod = ((OverriderMethodUsageInfo)usageInfo).getOverridingMethod();
|
||||
|
||||
private static class ParamAssignmentFinder extends JavaRecursiveElementWalkingVisitor {
|
||||
|
||||
private final PsiParameter param;
|
||||
|
||||
private PsiField fieldAssigned = null;
|
||||
|
||||
ParamAssignmentFinder(PsiParameter param) {
|
||||
this.param = param;
|
||||
}
|
||||
|
||||
public void visitAssignmentExpression(PsiAssignmentExpression assignment) {
|
||||
super.visitAssignmentExpression(assignment);
|
||||
final PsiExpression lhs = assignment.getLExpression();
|
||||
final PsiExpression rhs = assignment.getRExpression();
|
||||
if (!(lhs instanceof PsiReferenceExpression)) {
|
||||
return;
|
||||
if (!moveDestination.isTargetAccessible(overridingMethod.getProject(), overridingMethod.getContainingFile().getVirtualFile())) {
|
||||
conflicts.putValue(overridingMethod, "Created class won't be accessible");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!(rhs instanceof PsiReferenceExpression)) {
|
||||
return;
|
||||
}
|
||||
final PsiElement referent = ((PsiReference)rhs).resolve();
|
||||
if (referent == null || !referent.equals(param)) {
|
||||
return;
|
||||
}
|
||||
final PsiElement assigned = ((PsiReference)lhs).resolve();
|
||||
if (assigned == null || !(assigned instanceof PsiField)) {
|
||||
return;
|
||||
}
|
||||
fieldAssigned = (PsiField)assigned;
|
||||
}
|
||||
|
||||
public PsiField getFieldAssigned() {
|
||||
return fieldAssigned;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-185
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* 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 com.intellij.refactoring.introduceparameterobject;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.refactoring.changeSignature.ChangeInfo;
|
||||
import com.intellij.refactoring.changeSignature.JavaChangeInfoImpl;
|
||||
import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
|
||||
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.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class MergeMethodArguments {
|
||||
private final PsiMethod method;
|
||||
private final PsiClass myContainingClass;
|
||||
private final boolean myKeepMethodAsDelegate;
|
||||
private final List<PsiTypeParameter> typeParams;
|
||||
private final String className;
|
||||
private final String packageName;
|
||||
private final String parameterName;
|
||||
private final int[] paramsToMerge;
|
||||
private final boolean lastParamIsVararg;
|
||||
|
||||
public MergeMethodArguments(PsiMethod method,
|
||||
String className,
|
||||
String packageName,
|
||||
String parameterName,
|
||||
int[] paramsToMerge,
|
||||
List<PsiTypeParameter> typeParams,
|
||||
final boolean keepMethodAsDelegate,
|
||||
final PsiClass containingClass) {
|
||||
this.paramsToMerge = paramsToMerge;
|
||||
this.packageName = packageName;
|
||||
this.className = className;
|
||||
this.parameterName = parameterName;
|
||||
this.method = method;
|
||||
myContainingClass = containingClass;
|
||||
lastParamIsVararg = method.isVarArgs() && isParameterToMerge(method.getParameterList().getParametersCount() - 1);
|
||||
myKeepMethodAsDelegate = keepMethodAsDelegate;
|
||||
this.typeParams = new ArrayList<PsiTypeParameter>(typeParams);
|
||||
}
|
||||
|
||||
public ChangeInfo createChangeInfo() {
|
||||
final Project project = method.getProject();
|
||||
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
||||
String packageName;
|
||||
if (myContainingClass != null) {
|
||||
packageName = myContainingClass.getQualifiedName();
|
||||
if (packageName == null) {
|
||||
packageName = myContainingClass.getName();
|
||||
}
|
||||
}
|
||||
else {
|
||||
packageName = this.packageName;
|
||||
}
|
||||
|
||||
final String qualifiedName = StringUtil.getQualifiedName(packageName, className);
|
||||
String text = qualifiedName;
|
||||
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 ParameterInfoImpl mergedParamInfo = new ParameterInfoImpl(-1, parameterName, classType, null) {
|
||||
@Override
|
||||
public PsiExpression getValue(final PsiCallExpression expr) throws IncorrectOperationException {
|
||||
return (PsiExpression)JavaCodeStyleManager.getInstance(project)
|
||||
.shortenClassReferences(psiFacade.getElementFactory().createExpressionFromText(getMergedParam(expr, qualifiedName), expr));
|
||||
}
|
||||
};
|
||||
|
||||
int firstIncludedIdx = -1;
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
if (!isParameterToMerge(i)) {
|
||||
parametersInfo.add(new ParameterInfoImpl(i, parameters[i].getName(), parameters[i].getType()));
|
||||
} else if (firstIncludedIdx == -1) {
|
||||
firstIncludedIdx = i;
|
||||
}
|
||||
}
|
||||
|
||||
parametersInfo.add(firstIncludedIdx == -1 ? 0 : firstIncludedIdx, mergedParamInfo);
|
||||
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) {
|
||||
for (int i : paramsToMerge) {
|
||||
if (i == index) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private String getMergedParam(PsiCallExpression call, String qualifiedName) {
|
||||
final PsiExpression[] args = call.getArgumentList().getExpressions();
|
||||
StringBuilder newExpression = new StringBuilder();
|
||||
newExpression.append("new ").append(qualifiedName);
|
||||
if (!typeParams.isEmpty()) {
|
||||
final JavaResolveResult resolvant = call.resolveMethodGenerics();
|
||||
final PsiSubstitutor substitutor = resolvant.getSubstitutor();
|
||||
newExpression.append('<');
|
||||
final Map<PsiTypeParameter, PsiType> substitutionMap = substitutor.getSubstitutionMap();
|
||||
newExpression.append(StringUtil.join(typeParams, new Function<PsiTypeParameter, String>() {
|
||||
public String fun(final PsiTypeParameter typeParameter) {
|
||||
final PsiType boundType = substitutionMap.get(typeParameter);
|
||||
if (boundType != null) {
|
||||
return boundType.getCanonicalText();
|
||||
}
|
||||
else {
|
||||
return typeParameter.getName();
|
||||
}
|
||||
}
|
||||
}, ", "));
|
||||
newExpression.append('>');
|
||||
}
|
||||
newExpression.append('(');
|
||||
boolean isFirst = true;
|
||||
for (int index : paramsToMerge) {
|
||||
if (!isFirst) {
|
||||
newExpression.append(", ");
|
||||
}
|
||||
isFirst = false;
|
||||
newExpression.append(getArgument(args, index));
|
||||
}
|
||||
if (lastParamIsVararg) {
|
||||
final int lastArg = paramsToMerge[paramsToMerge.length - 1];
|
||||
for (int i = lastArg + 1; i < args.length; i++) {
|
||||
newExpression.append(',');
|
||||
newExpression.append(getArgument(args, i));
|
||||
}
|
||||
}
|
||||
newExpression.append(')');
|
||||
return newExpression.toString();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getArgument(PsiExpression[] args, int i) {
|
||||
if (i < args.length) {
|
||||
return args[i].getText();
|
||||
}
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
if (i < parameters.length) return parameters[i].getName();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
-98
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* 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 com.intellij.refactoring.introduceparameterobject;
|
||||
|
||||
import com.intellij.codeInsight.generation.GenerateMembersUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiField;
|
||||
import com.intellij.psi.PsiParameter;
|
||||
import com.intellij.refactoring.util.VariableData;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ParameterChunk {
|
||||
private final VariableData parameter;
|
||||
private PsiField field;
|
||||
private String getter;
|
||||
private String setter;
|
||||
|
||||
public ParameterChunk(VariableData parameter) {
|
||||
this.parameter = parameter;
|
||||
}
|
||||
|
||||
public void setField(PsiField field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
public void setGetter(String getter) {
|
||||
this.getter = getter;
|
||||
}
|
||||
|
||||
public void setSetter(String setter) {
|
||||
this.setter = setter;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiField getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ParameterChunk getChunkByParameter(PsiParameter param, List<ParameterChunk> params) {
|
||||
for (ParameterChunk chunk : params) {
|
||||
if (chunk.getParameter().variable.equals(param)) {
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public VariableData getParameter() {
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public String getGetter() {
|
||||
return getter;
|
||||
}
|
||||
|
||||
public String getSetter() {
|
||||
return setter;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getSetterName(Project project) {
|
||||
@NonNls String setter = getSetter();
|
||||
if (setter == null) {
|
||||
setter = getField() != null ? GenerateMembersUtil.suggestSetterName(getField())
|
||||
: GenerateMembersUtil.suggestSetterName(parameter.name, parameter.type, project);
|
||||
}
|
||||
|
||||
return setter;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getGetterName(Project project) {
|
||||
@NonNls String getter = getGetter();
|
||||
if (getter == null) {
|
||||
getter = getField() != null ? GenerateMembersUtil.suggestGetterName(getField())
|
||||
: GenerateMembersUtil.suggestGetterName(parameter.name, parameter.type, project);
|
||||
}
|
||||
return getter;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -17,7 +17,6 @@ package com.intellij.refactoring.introduceparameterobject;
|
||||
|
||||
import com.intellij.codeInsight.generation.GenerateMembersUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
@@ -26,6 +25,7 @@ import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
@@ -53,7 +53,7 @@ class ParameterObjectBuilder {
|
||||
fields.add(field);
|
||||
}
|
||||
|
||||
public void setTypeArguments(List<PsiTypeParameter> typeParams) {
|
||||
public void setTypeArguments(Collection<PsiTypeParameter> typeParams) {
|
||||
this.typeParams.clear();
|
||||
this.typeParams.addAll(typeParams);
|
||||
}
|
||||
|
||||
+16
-30
@@ -21,50 +21,40 @@
|
||||
package com.intellij.refactoring.introduceparameterobject.usageInfo;
|
||||
|
||||
import com.intellij.codeInsight.generation.GenerateMembersUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiField;
|
||||
import com.intellij.psi.PsiParameter;
|
||||
import com.intellij.refactoring.introduceparameterobject.ParameterChunk;
|
||||
import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
|
||||
import com.intellij.refactoring.util.FixableUsageInfo;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class AppendAccessorsUsageInfo extends FixableUsageInfo{
|
||||
private final PsiClass myExistingClass;
|
||||
private final boolean myGenerateAccessors;
|
||||
private final PsiParameter myParameter;
|
||||
private final ParameterInfoImpl myParameter;
|
||||
private final boolean myGetter;
|
||||
private final List<ParameterChunk> parameters;
|
||||
private static final Logger LOGGER = Logger.getInstance("#" + AppendAccessorsUsageInfo.class.getName());
|
||||
private final PsiField myField;
|
||||
|
||||
public AppendAccessorsUsageInfo(PsiClass existingClass,
|
||||
public AppendAccessorsUsageInfo(PsiParameter psiParameter,
|
||||
PsiClass existingClass,
|
||||
boolean generateAccessors,
|
||||
PsiParameter parameter,
|
||||
ParameterInfoImpl parameter,
|
||||
boolean isGetter,
|
||||
List<ParameterChunk> parameters) {
|
||||
super(parameter);
|
||||
PsiField field) {
|
||||
super(psiParameter);
|
||||
myExistingClass = existingClass;
|
||||
myGenerateAccessors = generateAccessors;
|
||||
myParameter = parameter;
|
||||
myGetter = isGetter;
|
||||
this.parameters = parameters;
|
||||
myField = field;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fixUsage() throws IncorrectOperationException {
|
||||
if (myGenerateAccessors) {
|
||||
if (myExistingClass != null) {
|
||||
final ParameterChunk parameterChunk = ParameterChunk.getChunkByParameter(myParameter, parameters);
|
||||
LOGGER.assertTrue(parameterChunk != null);
|
||||
final PsiField field = parameterChunk.getField();
|
||||
if (field != null) {
|
||||
myExistingClass.add(myGetter
|
||||
? GenerateMembersUtil.generateGetterPrototype(field)
|
||||
: GenerateMembersUtil.generateSetterPrototype(field));
|
||||
}
|
||||
}
|
||||
if (myGenerateAccessors && myField != null) {
|
||||
myExistingClass.add(myGetter
|
||||
? GenerateMembersUtil.generateGetterPrototype(myField)
|
||||
: GenerateMembersUtil.generateSetterPrototype(myField));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +62,7 @@ public class AppendAccessorsUsageInfo extends FixableUsageInfo{
|
||||
return myGetter;
|
||||
}
|
||||
|
||||
public PsiParameter getParameter() {
|
||||
public ParameterInfoImpl getParameter() {
|
||||
return myParameter;
|
||||
}
|
||||
|
||||
@@ -80,12 +70,8 @@ public class AppendAccessorsUsageInfo extends FixableUsageInfo{
|
||||
public String getConflictMessage() {
|
||||
if (!myGenerateAccessors) {
|
||||
String fieldName = myParameter.getName();
|
||||
final ParameterChunk chunk = ParameterChunk.getChunkByParameter(myParameter, parameters);
|
||||
if (chunk != null) {
|
||||
final PsiField field = chunk.getField();
|
||||
if (field != null) {
|
||||
fieldName = field.getName();
|
||||
}
|
||||
if (myField != null) {
|
||||
fieldName = myField.getName();
|
||||
}
|
||||
return (myGetter ? "Getter" : "Setter") + " for field \'" + fieldName + "\' is required";
|
||||
}
|
||||
|
||||
+7
-5
@@ -22,6 +22,7 @@ package com.intellij.refactoring.introduceparameterobject.usageInfo;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.refactoring.introduceparameterobject.JavaIntroduceParameterObjectClassDescriptor;
|
||||
import com.intellij.refactoring.util.FixableUsageInfo;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usageView.UsageViewUtil;
|
||||
@@ -32,24 +33,25 @@ public class BeanClassVisibilityUsageInfo extends FixableUsageInfo {
|
||||
private final PsiClass existingClass;
|
||||
private final UsageInfo[] usages;
|
||||
private final String myNewVisibility;
|
||||
private final PsiMethod myExistingClassCompatibleConstructor;
|
||||
private final JavaIntroduceParameterObjectClassDescriptor myClassDescriptor;
|
||||
|
||||
public BeanClassVisibilityUsageInfo(PsiClass existingClass,
|
||||
UsageInfo[] usages,
|
||||
String newVisibility,
|
||||
PsiMethod existingClassCompatibleConstructor) {
|
||||
JavaIntroduceParameterObjectClassDescriptor classDescriptor) {
|
||||
super(existingClass);
|
||||
this.existingClass = existingClass;
|
||||
this.usages = usages;
|
||||
myNewVisibility = newVisibility;
|
||||
myExistingClassCompatibleConstructor = existingClassCompatibleConstructor;
|
||||
myClassDescriptor = classDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fixUsage() throws IncorrectOperationException {
|
||||
VisibilityUtil.fixVisibility(UsageViewUtil.toElements(usages), existingClass, myNewVisibility);
|
||||
if (myExistingClassCompatibleConstructor != null) {
|
||||
VisibilityUtil.fixVisibility(UsageViewUtil.toElements(usages), myExistingClassCompatibleConstructor, myNewVisibility);
|
||||
final PsiMethod compatibleConstructor = myClassDescriptor.getExistingClassCompatibleConstructor();
|
||||
if (compatibleConstructor != null) {
|
||||
VisibilityUtil.fixVisibility(UsageViewUtil.toElements(usages), compatibleConstructor, myNewVisibility);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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 com.intellij.refactoring.introduceparameterobject.usageInfo;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.javadoc.PsiDocParamRef;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.javadoc.PsiDocTag;
|
||||
import com.intellij.refactoring.introduceparameterobject.JavaIntroduceParameterObjectClassDescriptor;
|
||||
import com.intellij.refactoring.util.FixableUsageInfo;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ConstructorJavadocUsageInfo extends FixableUsageInfo {
|
||||
private final PsiMethod myMethod;
|
||||
private final JavaIntroduceParameterObjectClassDescriptor myDescriptor;
|
||||
|
||||
public ConstructorJavadocUsageInfo(PsiMethod method, JavaIntroduceParameterObjectClassDescriptor descriptor) {
|
||||
super(method);
|
||||
myMethod = method;
|
||||
myDescriptor = descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fixUsage() throws IncorrectOperationException {
|
||||
final PsiDocComment docComment = myMethod.getDocComment();
|
||||
if (docComment != null) {
|
||||
final List<PsiDocTag> mergedTags = new ArrayList<PsiDocTag>();
|
||||
final PsiDocTag[] paramTags = docComment.findTagsByName("param");
|
||||
for (PsiDocTag paramTag : paramTags) {
|
||||
final PsiElement[] dataElements = paramTag.getDataElements();
|
||||
if (dataElements.length > 0) {
|
||||
if (dataElements[0] instanceof PsiDocParamRef) {
|
||||
final PsiReference reference = dataElements[0].getReference();
|
||||
if (reference != null) {
|
||||
final PsiElement resolve = reference.resolve();
|
||||
if (resolve instanceof PsiParameter) {
|
||||
final int parameterIndex = myMethod.getParameterList().getParameterIndex((PsiParameter)resolve);
|
||||
if (myDescriptor.getParameterInfo(parameterIndex) == null) continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
mergedTags.add((PsiDocTag)paramTag.copy());
|
||||
}
|
||||
}
|
||||
|
||||
PsiMethod compatibleParamObjectConstructor = null;
|
||||
final PsiMethod existingConstructor = myDescriptor.getExistingClassCompatibleConstructor();
|
||||
if (existingConstructor != null && existingConstructor.getDocComment() == null) {
|
||||
compatibleParamObjectConstructor = existingConstructor;
|
||||
}
|
||||
else if (!myDescriptor.isUseExistingClass()) {
|
||||
compatibleParamObjectConstructor = myDescriptor.getExistingClass().getConstructors()[0];
|
||||
}
|
||||
|
||||
if (compatibleParamObjectConstructor != null) {
|
||||
PsiDocComment psiDocComment = JavaPsiFacade.getElementFactory(myMethod.getProject()).createDocCommentFromText("/**\n*/");
|
||||
psiDocComment =
|
||||
(PsiDocComment)compatibleParamObjectConstructor.addBefore(psiDocComment, compatibleParamObjectConstructor.getFirstChild());
|
||||
|
||||
for (PsiDocTag tag : mergedTags) {
|
||||
psiDocComment.add(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+40
-27
@@ -25,12 +25,16 @@ import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.refactoring.introduceparameterobject.IntroduceParameterObjectProcessor;
|
||||
import com.intellij.refactoring.util.VariableData;
|
||||
import com.intellij.refactoring.changeSignature.JavaMethodDescriptor;
|
||||
import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
|
||||
import com.intellij.refactoring.introduceParameterObject.IntroduceParameterObjectProcessor;
|
||||
import com.intellij.refactoring.introduceparameterobject.JavaIntroduceParameterObjectClassDescriptor;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.VisibilityUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class IntroduceParameterObjectTest extends MultiFileTestCase{
|
||||
@NotNull
|
||||
@Override
|
||||
@@ -52,30 +56,36 @@ public class IntroduceParameterObjectTest extends MultiFileTestCase{
|
||||
|
||||
private void doTest(final boolean delegate,
|
||||
final boolean createInner,
|
||||
final Function<PsiMethod, VariableData[]> function) throws Exception {
|
||||
final Function<PsiMethod, ParameterInfoImpl[]> function) throws Exception {
|
||||
doTest((rootDir, rootAfter) -> {
|
||||
PsiClass aClass = myJavaFacade.findClass("Test", GlobalSearchScope.projectScope(getProject()));
|
||||
|
||||
assertNotNull("Class Test not found", aClass);
|
||||
|
||||
final PsiMethod method = aClass.findMethodsByName("foo", false)[0];
|
||||
final VariableData[] datas = function.fun(method);
|
||||
final ParameterInfoImpl[] datas = function.fun(method);
|
||||
|
||||
IntroduceParameterObjectProcessor processor = new IntroduceParameterObjectProcessor("Param", "", null, method, datas, delegate, false,
|
||||
createInner, null, false);
|
||||
final JavaIntroduceParameterObjectClassDescriptor classDescriptor =
|
||||
new JavaIntroduceParameterObjectClassDescriptor("Param", "", null, false, createInner, null, datas, method, false);
|
||||
final List<ParameterInfoImpl> parameters = new JavaMethodDescriptor(method).getParameters();
|
||||
IntroduceParameterObjectProcessor processor =
|
||||
new IntroduceParameterObjectProcessor<PsiMethod, ParameterInfoImpl, JavaIntroduceParameterObjectClassDescriptor>(getProject(),
|
||||
classDescriptor,
|
||||
method,
|
||||
datas,
|
||||
parameters,
|
||||
delegate);
|
||||
processor.run();
|
||||
});
|
||||
}
|
||||
|
||||
private static VariableData[] generateParams(final PsiMethod method) {
|
||||
private static ParameterInfoImpl[] generateParams(final PsiMethod method) {
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
|
||||
final VariableData[] datas = new VariableData[parameters.length];
|
||||
final ParameterInfoImpl[] datas = new ParameterInfoImpl[parameters.length];
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
PsiParameter parameter = parameters[i];
|
||||
datas[i] = new VariableData(parameter);
|
||||
datas[i].name = parameter.getName();
|
||||
datas[i].passAsParameter = true;
|
||||
datas[i] = new ParameterInfoImpl(i, parameter.getName(), parameter.getType());
|
||||
}
|
||||
return datas;
|
||||
}
|
||||
@@ -128,12 +138,10 @@ public class IntroduceParameterObjectTest extends MultiFileTestCase{
|
||||
doTest(false, false, method -> {
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
|
||||
final VariableData[] datas = new VariableData[parameters.length - 1];
|
||||
final ParameterInfoImpl[] datas = new ParameterInfoImpl[parameters.length - 1];
|
||||
for (int i = 0; i < parameters.length - 1; i++) {
|
||||
PsiParameter parameter = parameters[i];
|
||||
datas[i] = new VariableData(parameter);
|
||||
datas[i].name = parameter.getName();
|
||||
datas[i].passAsParameter = true;
|
||||
datas[i] = new ParameterInfoImpl(i, parameter.getName(), parameter.getType());
|
||||
}
|
||||
return datas;
|
||||
});
|
||||
@@ -143,12 +151,10 @@ public class IntroduceParameterObjectTest extends MultiFileTestCase{
|
||||
doTest(false, true, method -> {
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
|
||||
final VariableData[] datas = new VariableData[parameters.length - 1];
|
||||
final ParameterInfoImpl[] datas = new ParameterInfoImpl[parameters.length - 1];
|
||||
for (int i = 0; i < parameters.length - 1; i++) {
|
||||
PsiParameter parameter = parameters[i];
|
||||
datas[i] = new VariableData(parameter);
|
||||
datas[i].name = parameter.getName();
|
||||
datas[i].passAsParameter = true;
|
||||
datas[i] = new ParameterInfoImpl(i, parameter.getName(), parameter.getType());
|
||||
}
|
||||
return datas;
|
||||
});
|
||||
@@ -158,11 +164,9 @@ public class IntroduceParameterObjectTest extends MultiFileTestCase{
|
||||
doTest(false, true, psiMethod -> {
|
||||
final PsiParameter parameter = psiMethod.getParameterList().getParameters()[0];
|
||||
final PsiClass collectionClass = getJavaFacade().findClass(CommonClassNames.JAVA_UTIL_COLLECTION);
|
||||
final VariableData variableData =
|
||||
new VariableData(parameter, JavaPsiFacade.getElementFactory(getProject()).createType(collectionClass));
|
||||
variableData.name = parameter.getName();
|
||||
variableData.passAsParameter = true;
|
||||
return new VariableData[]{variableData};
|
||||
final ParameterInfoImpl variableData =
|
||||
new ParameterInfoImpl(0, parameter.getName(), JavaPsiFacade.getElementFactory(getProject()).createType(collectionClass));
|
||||
return new ParameterInfoImpl[]{variableData};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -188,9 +192,18 @@ public class IntroduceParameterObjectTest extends MultiFileTestCase{
|
||||
assertNotNull("Class Test not found", aClass);
|
||||
|
||||
final PsiMethod method = aClass.findMethodsByName("foo", false)[0];
|
||||
IntroduceParameterObjectProcessor processor = new IntroduceParameterObjectProcessor(existingClassName, existingClassPackage, null, method,
|
||||
generateParams(method), false, true,
|
||||
false, newVisibility, generateAccessors);
|
||||
final ParameterInfoImpl[] mergedParams = generateParams(method);
|
||||
final JavaIntroduceParameterObjectClassDescriptor classDescriptor =
|
||||
new JavaIntroduceParameterObjectClassDescriptor(existingClassName, existingClassPackage, null, true, false, newVisibility,
|
||||
mergedParams, method, generateAccessors);
|
||||
final List<ParameterInfoImpl> parameters = new JavaMethodDescriptor(method).getParameters();
|
||||
IntroduceParameterObjectProcessor processor =
|
||||
new IntroduceParameterObjectProcessor<PsiMethod, ParameterInfoImpl, JavaIntroduceParameterObjectClassDescriptor>(getProject(),
|
||||
classDescriptor,
|
||||
method,
|
||||
mergedParams,
|
||||
parameters,
|
||||
false);
|
||||
processor.run();
|
||||
LocalFileSystem.getInstance().refresh(false);
|
||||
FileDocumentManager.getInstance().saveAllDocuments();
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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 com.intellij.refactoring.changeSignature;
|
||||
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
|
||||
/**
|
||||
* Marker interface to distinguish overrider usages during change signature refactoring
|
||||
*/
|
||||
public interface OverriderMethodUsageInfo<T extends PsiNamedElement> {
|
||||
T getBaseMethod();
|
||||
|
||||
T getOverridingMethod();
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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 com.intellij.refactoring.introduceParameterObject;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.refactoring.changeSignature.ParameterInfo;
|
||||
|
||||
public abstract class IntroduceParameterObjectClassDescriptor<M extends PsiNamedElement, P extends ParameterInfo> {
|
||||
private final String myClassName;
|
||||
private final String myPackageName;
|
||||
private final boolean myUseExistingClass;
|
||||
private final boolean myCreateInnerClass;
|
||||
private final String myNewVisibility;
|
||||
private final boolean myGenerateAccessors;
|
||||
private final P[] myParamsToMerge;
|
||||
private PsiElement myExistingClass;
|
||||
|
||||
public IntroduceParameterObjectClassDescriptor(String className,
|
||||
String packageName,
|
||||
boolean useExistingClass,
|
||||
boolean createInnerClass,
|
||||
String newVisibility,
|
||||
boolean generateAccessors,
|
||||
P[] parameters) {
|
||||
myClassName = className;
|
||||
myPackageName = packageName;
|
||||
myUseExistingClass = useExistingClass;
|
||||
myCreateInnerClass = createInnerClass;
|
||||
myNewVisibility = newVisibility;
|
||||
myGenerateAccessors = generateAccessors;
|
||||
myParamsToMerge = parameters;
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return myClassName;
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
return myPackageName;
|
||||
}
|
||||
|
||||
public boolean isUseExistingClass() {
|
||||
return myUseExistingClass;
|
||||
}
|
||||
|
||||
public boolean isCreateInnerClass() {
|
||||
return myCreateInnerClass;
|
||||
}
|
||||
|
||||
public String getNewVisibility() {
|
||||
return myNewVisibility;
|
||||
}
|
||||
|
||||
public P[] getParamsToMerge() {
|
||||
return myParamsToMerge;
|
||||
}
|
||||
|
||||
public PsiElement getExistingClass() {
|
||||
return myExistingClass;
|
||||
}
|
||||
|
||||
public void setExistingClass(PsiElement existingClass) {
|
||||
myExistingClass = existingClass;
|
||||
}
|
||||
|
||||
public boolean isGenerateAccessors() {
|
||||
return myGenerateAccessors;
|
||||
}
|
||||
|
||||
public P getParameterInfo(int parameterIdx) {
|
||||
for (P info : myParamsToMerge) {
|
||||
if (info.getOldIndex() == parameterIdx) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract String getSetterName(P paramInfo, PsiElement context);
|
||||
public abstract String getGetterName(P paramInfo, PsiElement context);
|
||||
|
||||
public abstract void initExistingClass(M method);
|
||||
|
||||
public abstract PsiElement createClass(M method, IntroduceParameterObjectDelegate.Accessor[] accessors);
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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 com.intellij.refactoring.introduceParameterObject;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.LanguageExtension;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.refactoring.changeSignature.ChangeInfo;
|
||||
import com.intellij.refactoring.changeSignature.ParameterInfo;
|
||||
import com.intellij.refactoring.util.FixableUsageInfo;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class IntroduceParameterObjectDelegate<M extends PsiNamedElement, P extends ParameterInfo, C extends IntroduceParameterObjectClassDescriptor<M, P>> {
|
||||
public enum Accessor {
|
||||
Getter, Setter;
|
||||
|
||||
}
|
||||
private static final LanguageExtension<IntroduceParameterObjectDelegate> EP_NAME =
|
||||
new LanguageExtension<IntroduceParameterObjectDelegate>("com.intellij.refactoring.introduceParameterObject");
|
||||
|
||||
public static <M extends PsiNamedElement, P extends ParameterInfo, C extends IntroduceParameterObjectClassDescriptor<M, P>> IntroduceParameterObjectDelegate<M, P, C> findDelegate(
|
||||
@NotNull PsiElement element) {
|
||||
return findDelegate(element.getLanguage());
|
||||
}
|
||||
|
||||
public static <M extends PsiNamedElement, P extends ParameterInfo, C extends IntroduceParameterObjectClassDescriptor<M, P>> IntroduceParameterObjectDelegate<M, P, C> findDelegate(
|
||||
Language language) {
|
||||
return EP_NAME.forLanguage(language);
|
||||
}
|
||||
|
||||
public abstract P createMergedParameterInfo(Project project,
|
||||
C descriptor,
|
||||
int[] paramsToMerge,
|
||||
M method);
|
||||
|
||||
public abstract ChangeInfo createChangeSignatureInfo(M method,
|
||||
List<P> infos, boolean delegate);
|
||||
|
||||
public abstract <M1 extends PsiNamedElement, P1 extends ParameterInfo>
|
||||
Accessor collectInternalUsages(Collection<FixableUsageInfo> usages,
|
||||
M overridingMethod,
|
||||
M1 element,
|
||||
IntroduceParameterObjectClassDescriptor<M1, P1> classDescriptor, int parameterIdx,
|
||||
String mergedParamName);
|
||||
|
||||
public abstract void collectAccessibilityUsages(Collection<FixableUsageInfo> usages,
|
||||
M method, C descriptor,
|
||||
Accessor[] accessors);
|
||||
|
||||
public abstract void collectConflicts(MultiMap<PsiElement, String> conflicts,
|
||||
UsageInfo[] infos, M method, C classDescriptor);
|
||||
}
|
||||
+199
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* 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 com.intellij.refactoring.introduceParameterObject;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.changeSignature.ChangeInfo;
|
||||
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessorBase;
|
||||
import com.intellij.refactoring.changeSignature.OverriderMethodUsageInfo;
|
||||
import com.intellij.refactoring.changeSignature.ParameterInfo;
|
||||
import com.intellij.refactoring.util.FixableUsageInfo;
|
||||
import com.intellij.refactoring.util.FixableUsagesRefactoringProcessor;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usageView.UsageViewDescriptor;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class IntroduceParameterObjectProcessor<M extends PsiNamedElement, P extends ParameterInfo, C extends IntroduceParameterObjectClassDescriptor<M, P>>
|
||||
extends FixableUsagesRefactoringProcessor {
|
||||
private static final Logger LOG = Logger.getInstance("#" + IntroduceParameterObjectProcessor.class.getName());
|
||||
private final C myClassDescriptor;
|
||||
private final M myMethod;
|
||||
private final P[] myParameterInfos;
|
||||
private final ChangeInfo myChangeInfo;
|
||||
private final P myMergedParameterInfo;
|
||||
private final IntroduceParameterObjectDelegate<M, P, C> myDelegate;
|
||||
private final IntroduceParameterObjectDelegate.Accessor[] myAccessors;
|
||||
|
||||
public IntroduceParameterObjectProcessor(Project project,
|
||||
C classDescriptor,
|
||||
M method,
|
||||
P[] parameterInfos,
|
||||
List<P> parameters,
|
||||
boolean keepMethodAsDelegate) {
|
||||
super(project);
|
||||
myClassDescriptor = classDescriptor;
|
||||
myMethod = method;
|
||||
myParameterInfos = parameterInfos;
|
||||
|
||||
int[] paramsToMerge = new int[parameterInfos.length];
|
||||
for (int i = 0; i < paramsToMerge.length; i++) {
|
||||
paramsToMerge[i] = parameterInfos[i].getOldIndex();
|
||||
}
|
||||
|
||||
List<P> newParams = new ArrayList<>();
|
||||
int anchor = -1;
|
||||
for (P param : parameters) {
|
||||
final int i = ArrayUtil.find(paramsToMerge, param.getOldIndex());
|
||||
if (i > -1) {
|
||||
if (anchor == -1) {
|
||||
anchor = i;
|
||||
}
|
||||
}
|
||||
else {
|
||||
newParams.add(param);
|
||||
}
|
||||
}
|
||||
|
||||
myDelegate = IntroduceParameterObjectDelegate.findDelegate(method);
|
||||
LOG.assertTrue(myDelegate != null);
|
||||
myMergedParameterInfo = myDelegate.createMergedParameterInfo(project, classDescriptor, paramsToMerge, method);
|
||||
newParams.add(anchor, myMergedParameterInfo);
|
||||
|
||||
myChangeInfo = myDelegate.createChangeSignatureInfo(myMethod, newParams, keepMethodAsDelegate);
|
||||
myAccessors = new IntroduceParameterObjectDelegate.Accessor[parameterInfos.length];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void findUsages(@NotNull List<FixableUsageInfo> usages) {
|
||||
if (myClassDescriptor.isUseExistingClass()) {
|
||||
myClassDescriptor.initExistingClass(myMethod);
|
||||
}
|
||||
List<PsiNamedElement> methodHierarchy = new ArrayList<>();
|
||||
methodHierarchy.add(myMethod);
|
||||
for (UsageInfo info : ChangeSignatureProcessorBase.findUsages(myChangeInfo)) {
|
||||
if (info instanceof OverriderMethodUsageInfo) {
|
||||
methodHierarchy.add(((OverriderMethodUsageInfo)info).getOverridingMethod());
|
||||
}
|
||||
usages.add(new ChangeSignatureUsageWrapper(info));
|
||||
}
|
||||
|
||||
for (PsiElement element : methodHierarchy) {
|
||||
final IntroduceParameterObjectDelegate delegate = IntroduceParameterObjectDelegate.findDelegate(element);
|
||||
if (delegate != null) {
|
||||
for (int i = 0; i < myParameterInfos.length; i++) {
|
||||
P parameterInfo = myParameterInfos[i];
|
||||
final IntroduceParameterObjectDelegate.Accessor accessor =
|
||||
delegate.collectInternalUsages(usages, (PsiNamedElement)element, myMethod, myClassDescriptor, parameterInfo.getOldIndex(),
|
||||
myMergedParameterInfo.getName());
|
||||
if (myAccessors[i] == null || accessor == IntroduceParameterObjectDelegate.Accessor.Setter) {
|
||||
myAccessors[i] = accessor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
myDelegate.collectAccessibilityUsages(usages, myMethod, myClassDescriptor, myAccessors);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean preprocessUsages(@NotNull Ref<UsageInfo[]> refUsages) {
|
||||
final UsageInfo[] usageInfos = refUsages.get();
|
||||
MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();
|
||||
myDelegate.collectConflicts(conflicts, usageInfos, myMethod, myClassDescriptor);
|
||||
|
||||
List<UsageInfo> changeSignatureUsages = new ArrayList<>();
|
||||
for (UsageInfo usageInfo : usageInfos) {
|
||||
if (usageInfo instanceof ChangeSignatureUsageWrapper) {
|
||||
final UsageInfo info = ((ChangeSignatureUsageWrapper)usageInfo).getInfo();
|
||||
if (info instanceof OverriderMethodUsageInfo) {
|
||||
final PsiElement overridingMethod = ((OverriderMethodUsageInfo)info).getOverridingMethod();
|
||||
if (IntroduceParameterObjectDelegate.findDelegate(overridingMethod) == null) {
|
||||
conflicts.putValue(overridingMethod, "Not supported overrider detected");
|
||||
}
|
||||
}
|
||||
changeSignatureUsages.add(info);
|
||||
}
|
||||
else if (usageInfo instanceof FixableUsageInfo) {
|
||||
final String conflictMessage = ((FixableUsageInfo)usageInfo).getConflictMessage();
|
||||
if (conflictMessage != null) {
|
||||
conflicts.putValue(usageInfo.getElement(), conflictMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ChangeSignatureProcessorBase
|
||||
.collectConflictsFromExtensions(new Ref<>(changeSignatureUsages.toArray(new UsageInfo[changeSignatureUsages.size()])), conflicts,
|
||||
myChangeInfo);
|
||||
|
||||
return showConflicts(conflicts, usageInfos);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected UsageViewDescriptor createUsageViewDescriptor(@NotNull UsageInfo[] usages) {
|
||||
return new IntroduceParameterObjectUsageViewDescriptor(myMethod);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performRefactoring(@NotNull UsageInfo[] usageInfos) {
|
||||
final PsiElement aClass = myClassDescriptor.createClass(myMethod, myAccessors);
|
||||
if (aClass != null) {
|
||||
myClassDescriptor.setExistingClass(aClass);
|
||||
super.performRefactoring(usageInfos);
|
||||
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()]));
|
||||
}
|
||||
}
|
||||
|
||||
protected String getCommandName() {
|
||||
return RefactoringBundle
|
||||
.message("refactoring.introduce.parameter.object.command.name", myClassDescriptor.getClassName(), myMethod.getName());
|
||||
}
|
||||
|
||||
public 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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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 com.intellij.refactoring.introduceParameterObject;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.ui.UsageViewDescriptorAdapter;
|
||||
import com.intellij.usageView.UsageViewBundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class IntroduceParameterObjectUsageViewDescriptor extends UsageViewDescriptorAdapter {
|
||||
|
||||
private final PsiElement method;
|
||||
|
||||
public IntroduceParameterObjectUsageViewDescriptor(PsiElement method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiElement[] getElements() {
|
||||
return new PsiElement[]{method};
|
||||
}
|
||||
|
||||
public String getProcessedElementsHeader() {
|
||||
return RefactoringBundle.message("refactoring.introduce.parameter.object.method.whose.parameters.are.to.wrapped");
|
||||
}
|
||||
|
||||
public String getCodeReferencesText(int usagesCount, int filesCount) {
|
||||
return RefactoringBundle.message("refactoring.introduce.parameter.object.references.to.be.modified") +
|
||||
UsageViewBundle.getReferencesString(usagesCount, filesCount);
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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.
|
||||
@@ -18,12 +18,12 @@ package com.intellij.refactoring.util;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.refactoring.BaseRefactoringProcessor;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.intellij.xml.util.XmlUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -67,7 +67,7 @@ public abstract class FixableUsagesRefactoringProcessor extends BaseRefactoringP
|
||||
for (UsageInfo info : refUsages.get()) {
|
||||
final String conflict = ((FixableUsageInfo)info).getConflictMessage();
|
||||
if (conflict != null) {
|
||||
conflicts.putValue(info.getElement(), XmlUtil.escape(conflict));
|
||||
conflicts.putValue(info.getElement(), StringUtil.escapeXml(conflict));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -796,4 +796,7 @@ renames.project=Renames project
|
||||
introduce.functional.parameter.title=Extract Functional Parameter
|
||||
introduce.parameter.convert.lambda=&Convert to functional expression
|
||||
|
||||
expand.method.reference.warning=Method is used in method reference. Proceeding would result in conversion to lambda expression
|
||||
expand.method.reference.warning=Method is used in method reference. Proceeding would result in conversion to lambda expression
|
||||
refactoring.introduce.parameter.object.references.to.be.modified=References to be modified
|
||||
refactoring.introduce.parameter.object.method.whose.parameters.are.to.wrapped=Method whose parameters are to wrapped
|
||||
refactoring.introduce.parameter.object.command.name=Introduced parameter class {0} for {1}()
|
||||
|
||||
@@ -375,6 +375,11 @@
|
||||
<extensionPoint name="refactoring.copyHandler" interface="com.intellij.refactoring.copy.CopyHandlerDelegate"/>
|
||||
<extensionPoint name="refactoring.moveHandler" interface="com.intellij.refactoring.move.MoveHandlerDelegate"/>
|
||||
<extensionPoint name="refactoring.invertBoolean" interface="com.intellij.refactoring.invertBoolean.InvertBooleanDelegate"/>
|
||||
<extensionPoint name="refactoring.introduceParameterObject" beanClass="com.intellij.lang.LanguageExtensionPoint">
|
||||
<with attribute="implementationClass"
|
||||
implements="com.intellij.refactoring.introduceParameterObject.IntroduceParameterObjectDelegate"/>
|
||||
</extensionPoint>
|
||||
|
||||
<extensionPoint name="refactoring.pushDown" beanClass="com.intellij.lang.LanguageExtensionPoint">
|
||||
<with attribute="implementationClass" implements="com.intellij.refactoring.memberPushDown.PushDownDelegate"/>
|
||||
</extensionPoint>
|
||||
|
||||
@@ -1731,6 +1731,8 @@
|
||||
<refactoring.moveInnerClassUsagesHandler language="JAVA" implementationClass="com.intellij.refactoring.move.moveInner.MoveInnerClassJavaUsagesHandler" id="java"/>
|
||||
<actionPromoter implementation="com.intellij.execution.testframework.TestTreeViewActionsPromoter"/>
|
||||
<refactoring.invertBoolean implementation="com.intellij.refactoring.invertBoolean.JavaInvertBooleanDelegate"/>
|
||||
<refactoring.introduceParameterObject language="JAVA"
|
||||
implementationClass="com.intellij.refactoring.introduceparameterobject.JavaIntroduceParameterObjectDelegate"/>
|
||||
<refactoring.pushDown language="JAVA" implementationClass="com.intellij.refactoring.memberPushDown.JavaPushDownDelegate" id="java"/>
|
||||
<library.javaSourceRootDetector implementation="com.intellij.openapi.roots.ui.configuration.LibraryJavaSourceRootDetector"/>
|
||||
</extensions>
|
||||
|
||||
Reference in New Issue
Block a user