From d9c6dfc42c098362378e31fbd2e660f85aa2361e Mon Sep 17 00:00:00 2001 From: "Anna.Kozlova" Date: Wed, 12 Apr 2017 14:03:46 +0200 Subject: [PATCH] convert static method to instance method of the same class without corresponding parameter (IDEA-64834) --- .../ConvertToInstanceMethodDialog.java | 11 +- .../ConvertToInstanceMethodHandler.java | 41 ++---- .../ConvertToInstanceMethodProcessor.java | 135 +++++++++++++----- .../MoveInstanceMethodDialog.java | 2 +- .../MoveInstanceMethodDialogBase.java | 26 ++-- .../MoveInstanceMethodViewDescriptor.java | 9 +- ...ConvertToInstanceMethodOfTheSameClass.java | 26 ++++ ...tToInstanceMethodOfTheSameClass.java.after | 26 ++++ ...nceMethodOfTheSameClassWithTypeParams.java | 26 ++++ .../ConvertToInstance8MethodTest.java | 14 ++ .../ConvertToInstanceMethodTest.java | 2 +- .../src/messages/RefactoringBundle.properties | 2 +- 12 files changed, 228 insertions(+), 92 deletions(-) create mode 100644 java/java-tests/testData/refactoring/convertToInstance8Method/ConvertToInstanceMethodOfTheSameClass.java create mode 100644 java/java-tests/testData/refactoring/convertToInstance8Method/ConvertToInstanceMethodOfTheSameClass.java.after create mode 100644 java/java-tests/testData/refactoring/convertToInstance8Method/ConvertToInstanceMethodOfTheSameClassWithTypeParams.java diff --git a/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodDialog.java b/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodDialog.java index 9d4c19394ae3..183523f02d30 100644 --- a/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodDialog.java @@ -17,9 +17,8 @@ package com.intellij.refactoring.convertToInstanceMethod; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.help.HelpManager; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiParameter; -import com.intellij.psi.PsiVariable; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.move.moveInstanceMethod.MoveInstanceMethodDialogBase; @@ -35,16 +34,16 @@ import java.awt.event.MouseEvent; */ public class ConvertToInstanceMethodDialog extends MoveInstanceMethodDialogBase { private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.convertToInstanceMethod.ConvertToInstanceMethodDialog"); - public ConvertToInstanceMethodDialog(final PsiMethod method, final PsiParameter[] variables) { + public ConvertToInstanceMethodDialog(final PsiMethod method, final PsiElement[] variables) { super(method, variables, ConvertToInstanceMethodHandler.REFACTORING_NAME); init(); } protected void doAction() { - final PsiVariable targetVariable = (PsiVariable)myList.getSelectedValue(); - LOG.assertTrue(targetVariable instanceof PsiParameter, targetVariable); + final PsiElement targetVariable = (PsiElement)myList.getSelectedValue(); + LOG.assertTrue(targetVariable != null); final ConvertToInstanceMethodProcessor processor = new ConvertToInstanceMethodProcessor(myMethod.getProject(), - myMethod, (PsiParameter)targetVariable, + myMethod, targetVariable, myVisibilityPanel.getVisibility()); if (!verifyTargetClass(processor.getTargetClass())) return; invokeRefactoring(processor); diff --git a/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodHandler.java b/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodHandler.java index 90ad06ce5ed5..4a4fd9e8bc06 100644 --- a/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodHandler.java @@ -17,8 +17,6 @@ package com.intellij.refactoring.convertToInstanceMethod; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.actionSystem.LangDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ScrollType; @@ -31,6 +29,7 @@ import com.intellij.refactoring.util.CommonRefactoringUtil; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -71,44 +70,30 @@ public class ConvertToInstanceMethodHandler implements RefactoringActionHandler return; } final PsiParameter[] parameters = method.getParameterList().getParameters(); - List suitableParameters = new ArrayList<>(); - boolean classTypesFound = false; - boolean resolvableClassesFound = false; - boolean classesInProjectFound = false; + List targetQualifiers = new ArrayList<>(); for (final PsiParameter parameter : parameters) { final PsiType type = parameter.getType(); if (type instanceof PsiClassType) { - classTypesFound = true; final PsiClass psiClass = ((PsiClassType)type).resolve(); if (psiClass != null && !(psiClass instanceof PsiTypeParameter)) { - resolvableClassesFound = true; - final boolean inProject = method.getManager().isInProject(psiClass); - if (inProject) { - classesInProjectFound = true; - suitableParameters.add(parameter); + if (method.getManager().isInProject(psiClass)) { + targetQualifiers.add(parameter); } } } } - if (suitableParameters.isEmpty()) { - String message = null; - if (!classTypesFound) { - message = RefactoringBundle.message("convertToInstanceMethod.no.parameters.with.reference.type"); - } - else if (!resolvableClassesFound) { - message = RefactoringBundle.message("convertToInstanceMethod.all.reference.type.parametres.have.unknown.types"); - } - else if (!classesInProjectFound) { - message = RefactoringBundle.message("convertToInstanceMethod.all.reference.type.parameters.are.not.in.project"); - } - LOG.assertTrue(message != null); - Editor editor = CommonDataKeys.EDITOR.getData(dataContext); - CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage(message), REFACTORING_NAME, HelpID.CONVERT_TO_INSTANCE_METHOD); - return; + PsiClass containingClass = method.getContainingClass(); + if (containingClass == null || containingClass.getQualifiedName() == null) return; + String className = containingClass.getName(); + PsiMethod[] constructors = containingClass.getConstructors(); + boolean noArgConstructor = + constructors.length == 0 || Arrays.stream(constructors).anyMatch(constructor -> constructor.getParameterList().getParametersCount() == 0); + if (noArgConstructor) { + targetQualifiers.add(JavaPsiFacade.getElementFactory(project).createExpressionFromText("new " + className + "()", method)); } new ConvertToInstanceMethodDialog( method, - suitableParameters.toArray(new PsiParameter[suitableParameters.size()])).show(); + targetQualifiers.toArray(new PsiElement[targetQualifiers.size()])).show(); } } diff --git a/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodProcessor.java index 905cd540c383..fa286c9a0dd9 100644 --- a/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodProcessor.java @@ -29,6 +29,7 @@ import com.intellij.psi.javadoc.PsiDocTagValue; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.refactoring.BaseRefactoringProcessor; @@ -54,7 +55,7 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor { private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.convertToInstanceMethod.ConvertToInstanceMethodProcessor"); private PsiMethod myMethod; - private PsiParameter myTargetParameter; + private @Nullable PsiParameter myTargetParameter; private PsiClass myTargetClass; private Map myTypeParameterReplacements; private static final Key BIND_TO_TYPE_PARAMETER = Key.create("REPLACEMENT"); @@ -64,17 +65,22 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor { public ConvertToInstanceMethodProcessor(final Project project, final PsiMethod method, - final PsiParameter targetParameter, + final PsiElement targetParameter, final String newVisibility) { super(project); myMethod = method; - myTargetParameter = targetParameter; + myTargetParameter = targetParameter instanceof PsiParameter ? (PsiParameter)targetParameter : null; LOG.assertTrue(method.hasModifierProperty(PsiModifier.STATIC)); - LOG.assertTrue(myTargetParameter.getDeclarationScope() == myMethod); - LOG.assertTrue(myTargetParameter.getType() instanceof PsiClassType); - final PsiType type = myTargetParameter.getType(); - LOG.assertTrue(type instanceof PsiClassType); - myTargetClass = ((PsiClassType)type).resolve(); + if (myTargetParameter != null) { + LOG.assertTrue(myTargetParameter.getDeclarationScope() == myMethod); + LOG.assertTrue(myTargetParameter.getType() instanceof PsiClassType); + final PsiType type = myTargetParameter.getType(); + LOG.assertTrue(type instanceof PsiClassType); + myTargetClass = ((PsiClassType)type).resolve(); + } + else { + myTargetClass = method.getContainingClass(); + } myOldVisibility = VisibilityUtil.getVisibilityModifier(method.getModifierList()); myNewVisibility = newVisibility; } @@ -89,15 +95,15 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor { } protected void refreshElements(@NotNull PsiElement[] elements) { - LOG.assertTrue(elements.length == 3); + LOG.assertTrue(elements.length > 1); myMethod = (PsiMethod)elements[0]; - myTargetParameter = (PsiParameter)elements[1]; - myTargetClass = (PsiClass)elements[2]; + myTargetParameter = elements.length == 3 ? (PsiParameter)elements[1] : null; + myTargetClass = (PsiClass)elements[elements.length - 1]; } @NotNull protected UsageInfo[] findUsages() { - LOG.assertTrue(myTargetParameter.getDeclarationScope() == myMethod); + LOG.assertTrue(myTargetParameter == null || myTargetParameter.getDeclarationScope() == myMethod); final Project project = myMethod.getProject(); final PsiReference[] methodReferences = @@ -111,7 +117,7 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor { result.add(new MethodCallUsageInfo((PsiMethodCallExpression)parent)); } else if (element instanceof PsiMethodReferenceExpression) { - result.add(new MethodReferenceUsageInfo((PsiMethodReferenceExpression)element, myMethod.getParameterList().getParameterIndex(myTargetParameter) == 0)); + result.add(new MethodReferenceUsageInfo((PsiMethodReferenceExpression)element, myTargetParameter == null || myMethod.getParameterList().getParameterIndex(myTargetParameter) == 0)); } } else if (element instanceof PsiDocTagValue) { @@ -119,10 +125,12 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor { } } - for (final PsiReference ref : ReferencesSearch.search(myTargetParameter, new LocalSearchScope(myMethod), false)) { - final PsiElement element = ref.getElement(); - if (element instanceof PsiReferenceExpression || element instanceof PsiDocParamRef) { - result.add(new ParameterUsageInfo(ref)); + if (myTargetParameter != null) { + for (final PsiReference ref : ReferencesSearch.search(myTargetParameter, new LocalSearchScope(myMethod), false)) { + final PsiElement element = ref.getElement(); + if (element instanceof PsiReferenceExpression || element instanceof PsiDocParamRef) { + result.add(new ParameterUsageInfo(ref)); + } } } @@ -177,23 +185,33 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor { } for (final UsageInfo usageInfo : usagesIn) { + PsiElement place = null; if (usageInfo instanceof MethodCallUsageInfo) { - final PsiMethodCallExpression methodCall = ((MethodCallUsageInfo)usageInfo).getMethodCall(); - final PsiExpression[] expressions = methodCall.getArgumentList().getExpressions(); - final int index = myMethod.getParameterList().getParameterIndex(myTargetParameter); - if (index < expressions.length) { - PsiExpression instanceValue = expressions[index]; - instanceValue = RefactoringUtil.unparenthesizeExpression(instanceValue); - if (instanceValue instanceof PsiLiteralExpression && ((PsiLiteralExpression)instanceValue).getValue() == null) { - String message = RefactoringBundle.message("0.contains.call.with.null.argument.for.parameter.1", - RefactoringUIUtil.getDescription(ConflictsUtil.getContainer(methodCall), true), - CommonRefactoringUtil.htmlEmphasize(myTargetParameter.getName())); - conflicts.putValue(methodCall, message); + place = ((MethodCallUsageInfo)usageInfo).getMethodCall(); + if (myTargetParameter != null) { + final PsiExpression[] expressions = ((PsiMethodCallExpression)place).getArgumentList().getExpressions(); + final int index = myMethod.getParameterList().getParameterIndex(myTargetParameter); + if (index < expressions.length) { + PsiExpression instanceValue = expressions[index]; + instanceValue = RefactoringUtil.unparenthesizeExpression(instanceValue); + if (instanceValue instanceof PsiLiteralExpression && ((PsiLiteralExpression)instanceValue).getValue() == null) { + String message = RefactoringBundle.message("0.contains.call.with.null.argument.for.parameter.1", + RefactoringUIUtil.getDescription(ConflictsUtil.getContainer(place), true), + CommonRefactoringUtil.htmlEmphasize(myTargetParameter.getName())); + conflicts.putValue(place, message); + } } } } - else if (usageInfo instanceof MethodReferenceUsageInfo && !((MethodReferenceUsageInfo)usageInfo).isApplicableBySecondSearch()) { - conflicts.putValue(((MethodReferenceUsageInfo)usageInfo).getExpression(), RefactoringBundle.message("expand.method.reference.warning")); + else if (usageInfo instanceof MethodReferenceUsageInfo) { + place = ((MethodReferenceUsageInfo)usageInfo).getExpression(); + if (!((MethodReferenceUsageInfo)usageInfo).isApplicableBySecondSearch()) { + conflicts.putValue(place, RefactoringBundle.message("expand.method.reference.warning")); + } + } + + if (myTargetParameter == null && place != null && myTargetClass.hasTypeParameters() && !thisAccessExpressionApplicable(place)) { + conflicts.putValue(place, "Impossible to infer class type arguments. When proceed, raw " + myTargetClass.getName() + " would be created"); } } @@ -237,7 +255,7 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor { } prepareTypeParameterReplacement(); - myTargetParameter.delete(); + if (myTargetParameter != null) myTargetParameter.delete(); ChangeContextUtil.encodeContextInfo(myMethod, true); if (!myTargetClass.isInterface()) { PsiMethod method = addMethodToClass(myTargetClass); @@ -271,7 +289,18 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor { if (usage.isApplicableBySecondSearch()) { PsiExpression qualifierExpression = expression.getQualifierExpression(); LOG.assertTrue(qualifierExpression != null); - qualifierExpression.replace(JavaPsiFacade.getElementFactory(myProject).createReferenceExpression(myTargetClass)); + PsiElementFactory factory = JavaPsiFacade.getElementFactory(myProject); + PsiElement qualifier; + if (myTargetParameter != null) { + qualifier = factory.createReferenceExpression(myTargetClass); + } + else { + boolean thisAccess = thisAccessExpressionApplicable(expression); + qualifier = thisAccess + ? factory.createExpressionFromText("this", qualifierExpression) + : createSyntheticAccessExpression(factory, expression); + } + qualifierExpression.replace(qualifier); } else { PsiLambdaExpression lambdaExpression = LambdaRefactoringUtil.convertMethodReferenceToLambda(expression, false, true); @@ -403,12 +432,28 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor { } private void processMethodCall(final PsiMethodCallExpression methodCall) throws IncorrectOperationException { - PsiParameterList parameterList = myMethod.getParameterList(); PsiElementFactory factory = JavaPsiFacade.getInstance(myMethod.getProject()).getElementFactory(); - int parameterIndex = parameterList.getParameterIndex(myTargetParameter); - PsiExpression[] arguments = methodCall.getArgumentList().getExpressions(); - if (arguments.length <= parameterIndex) return; final PsiReferenceExpression methodExpression = methodCall.getMethodExpression(); + PsiExpression argument; + if (myTargetParameter != null) { + PsiParameterList parameterList = myMethod.getParameterList(); + int parameterIndex = parameterList.getParameterIndex(myTargetParameter); + PsiExpression[] arguments = methodCall.getArgumentList().getExpressions(); + if (arguments.length <= parameterIndex) return; + argument = arguments[parameterIndex]; + } + else { + if (thisAccessExpressionApplicable(methodCall)) { + PsiExpression qualifierExpression = methodExpression.getQualifierExpression(); + if (qualifierExpression != null) { + qualifierExpression.delete(); + } + return; + } + + argument = createSyntheticAccessExpression(factory, methodCall); + } + final PsiExpression qualifier; if (methodExpression.getQualifierExpression() != null) { qualifier = methodExpression.getQualifierExpression(); @@ -417,16 +462,29 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor { final PsiReferenceExpression newRefExpr = (PsiReferenceExpression)factory.createExpressionFromText("x." + myMethod.getName(), null); qualifier = ((PsiReferenceExpression)methodExpression.replace(newRefExpr)).getQualifierExpression(); } - qualifier.replace(arguments[parameterIndex]); - arguments[parameterIndex].delete(); + qualifier.replace(argument); + argument.delete(); } + private PsiExpression createSyntheticAccessExpression(PsiElementFactory factory, PsiElement context) { + return factory.createExpressionFromText("new " + myTargetClass.getName() + "()", context); + } + + + private boolean thisAccessExpressionApplicable(PsiElement expression) { + return PsiTreeUtil.isAncestor(myTargetClass, expression, false) && PsiUtil.getEnclosingStaticElement(expression, myTargetClass) == null; + } + + @NotNull protected String getCommandName() { return ConvertToInstanceMethodHandler.REFACTORING_NAME; } @Nullable public Map buildTypeParameterReplacements() { + if (myTargetParameter == null) { + return Collections.emptyMap(); + } final PsiClassType type = (PsiClassType)myTargetParameter.getType(); final PsiSubstitutor substitutor = type.resolveGenerics().getSubstitutor(); return calculateReplacementMap(substitutor, myTargetClass, myMethod); @@ -454,6 +512,7 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor { return myMethod; } + @Nullable public PsiParameter getTargetParameter() { return myTargetParameter; } diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodDialog.java b/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodDialog.java index 0646d43fde71..6e4ef1cd41da 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodDialog.java @@ -106,7 +106,7 @@ public class MoveInstanceMethodDialog extends MoveInstanceMethodDialogBase { textField.setEnabled(true); } - final PsiVariable variable = myVariables[selectedIndex]; + final PsiElement variable = myVariables[selectedIndex]; if (variable instanceof PsiField) { final PsiField field = (PsiField)variable; final PsiClass hisClass = field.getContainingClass(); diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodDialogBase.java b/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodDialogBase.java index a5b7faa910b0..7bc4df8e6c25 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodDialogBase.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodDialogBase.java @@ -18,10 +18,7 @@ package com.intellij.refactoring.move.moveInstanceMethod; import com.intellij.lang.findUsages.DescriptiveNameUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiSubstitutor; -import com.intellij.psi.PsiVariable; +import com.intellij.psi.*; import com.intellij.psi.search.searches.ClassInheritorsSearch; import com.intellij.psi.util.PsiFormatUtil; import com.intellij.psi.util.PsiUtil; @@ -42,7 +39,7 @@ import java.awt.*; */ public abstract class MoveInstanceMethodDialogBase extends MoveDialogBase { protected final PsiMethod myMethod; - protected final PsiVariable[] myVariables; + protected final PsiElement[] myVariables; public JComponent getPreferredFocusedComponent() { return myList; @@ -52,7 +49,7 @@ public abstract class MoveInstanceMethodDialogBase extends MoveDialogBase { protected JavaVisibilityPanel myVisibilityPanel; protected final String myRefactoringName; - public MoveInstanceMethodDialogBase(PsiMethod method, PsiVariable[] variables, String refactoringName) { + public MoveInstanceMethodDialogBase(PsiMethod method, PsiElement[] variables, String refactoringName) { super(method.getProject(), true); myMethod = method; myVariables = variables; @@ -142,12 +139,17 @@ public abstract class MoveInstanceMethodDialogBase extends MoveDialogBase { private static class MyListCellRenderer extends DefaultListCellRenderer { public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - final PsiVariable psiVariable = (PsiVariable)value; - final String text = PsiFormatUtil.formatVariable(psiVariable, - PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_TYPE, - PsiSubstitutor.EMPTY); - setIcon(psiVariable.getIcon(0)); - setText(text); + if (value instanceof PsiVariable) { + final PsiVariable psiVariable = (PsiVariable)value; + final String text = PsiFormatUtil.formatVariable(psiVariable, + PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_TYPE, + PsiSubstitutor.EMPTY); + setIcon(psiVariable.getIcon(0)); + setText(text); + } + else if (value instanceof PsiExpression) { + setText(((PsiExpression)value).getText()); + } return this; } } diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodViewDescriptor.java b/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodViewDescriptor.java index 5665c5621289..2a42cc1803f5 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodViewDescriptor.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodViewDescriptor.java @@ -31,10 +31,9 @@ public class MoveInstanceMethodViewDescriptor extends UsageViewDescriptorAdapter private final PsiVariable myTargetVariable; private final PsiClass myTargetClass; - public MoveInstanceMethodViewDescriptor( - PsiMethod method, - PsiVariable targetVariable, - PsiClass targetClass) { + public MoveInstanceMethodViewDescriptor(PsiMethod method, + PsiVariable targetVariable, + PsiClass targetClass) { super(); myMethod = method; myTargetVariable = targetVariable; @@ -43,7 +42,7 @@ public class MoveInstanceMethodViewDescriptor extends UsageViewDescriptorAdapter @NotNull public PsiElement[] getElements() { - return new PsiElement[] {myMethod, myTargetVariable, myTargetClass}; + return myTargetVariable == null ? new PsiElement[] {myTargetClass} : new PsiElement[] {myMethod, myTargetVariable, myTargetClass}; } public String getProcessedElementsHeader() { diff --git a/java/java-tests/testData/refactoring/convertToInstance8Method/ConvertToInstanceMethodOfTheSameClass.java b/java/java-tests/testData/refactoring/convertToInstance8Method/ConvertToInstanceMethodOfTheSameClass.java new file mode 100644 index 000000000000..620832bdc25c --- /dev/null +++ b/java/java-tests/testData/refactoring/convertToInstance8Method/ConvertToInstanceMethodOfTheSameClass.java @@ -0,0 +1,26 @@ + +class Bar { + static void foo() { + } + + void m(){ + Bar.foo(); + } + + { + Runnable r = Bar::foo; + } + + static { + Runnable r = Bar::foo; + } +} + +class Bar1 { + void m() { + Bar.foo(); + } + { + Runnable r = Bar::foo; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/convertToInstance8Method/ConvertToInstanceMethodOfTheSameClass.java.after b/java/java-tests/testData/refactoring/convertToInstance8Method/ConvertToInstanceMethodOfTheSameClass.java.after new file mode 100644 index 000000000000..2167412c087b --- /dev/null +++ b/java/java-tests/testData/refactoring/convertToInstance8Method/ConvertToInstanceMethodOfTheSameClass.java.after @@ -0,0 +1,26 @@ + +class Bar { + void foo() { + } + + void m(){ + foo(); + } + + { + Runnable r = this::foo; + } + + static { + Runnable r = new Bar()::foo; + } +} + +class Bar1 { + void m() { + new Bar().foo(); + } + { + Runnable r = new Bar()::foo; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/convertToInstance8Method/ConvertToInstanceMethodOfTheSameClassWithTypeParams.java b/java/java-tests/testData/refactoring/convertToInstance8Method/ConvertToInstanceMethodOfTheSameClassWithTypeParams.java new file mode 100644 index 000000000000..93a77ddd0f6b --- /dev/null +++ b/java/java-tests/testData/refactoring/convertToInstance8Method/ConvertToInstanceMethodOfTheSameClassWithTypeParams.java @@ -0,0 +1,26 @@ + +class Bar { + static void foo() { + } + + void m(){ + Bar.foo(); + } + + { + Runnable r = Bar::foo; + } + + static { + Runnable r = Bar::foo; + } +} + +class Bar1 { + void m() { + Bar.foo(); + } + { + Runnable r = Bar::foo; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstance8MethodTest.java b/java/java-tests/testSrc/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstance8MethodTest.java index 00913c2fc5fd..f6ee7dd856c2 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstance8MethodTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstance8MethodTest.java @@ -15,6 +15,7 @@ */ package com.intellij.refactoring.convertToInstanceMethod; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.pom.java.LanguageLevel; import com.intellij.refactoring.BaseRefactoringProcessor; @@ -32,6 +33,19 @@ public class ConvertToInstance8MethodTest extends ConvertToInstanceMethodTest { doTest(0); } + public void testConvertToInstanceMethodOfTheSameClass() throws Exception { + doTest(-1); + } + + public void testConvertToInstanceMethodOfTheSameClassWithTypeParams() throws Exception { + try { + doTest(-1); + } + catch (BaseRefactoringProcessor.ConflictsInTestsException e) { + assertEquals(StringUtil.trimEnd(StringUtil.repeat("Impossible to infer class type arguments. When proceed, raw Bar would be created\n", 3), "\n"), e.getMessage()); + } + } + public void testMethodReferenceToLambda() throws Exception { BaseRefactoringProcessor.ConflictsInTestsException.withIgnoredConflicts(() -> doTest(1)); } diff --git a/java/java-tests/testSrc/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodTest.java b/java/java-tests/testSrc/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodTest.java index 0bac6197f4ca..ab21da215b16 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodTest.java @@ -62,7 +62,7 @@ public class ConvertToInstanceMethodTest extends LightRefactoringTestCase { assertTrue(" is not on method name", targetElement instanceof PsiMethod); PsiMethod method = (PsiMethod) targetElement; new ConvertToInstanceMethodProcessor(getProject(), - method, method.getParameterList().getParameters()[targetParameter], + method, targetParameter < 0 ? null : method.getParameterList().getParameters()[targetParameter], visibility).run(); checkResultByFile(filePath + ".after"); diff --git a/platform/platform-resources-en/src/messages/RefactoringBundle.properties b/platform/platform-resources-en/src/messages/RefactoringBundle.properties index 75b84b669f56..f43667a758ba 100644 --- a/platform/platform-resources-en/src/messages/RefactoringBundle.properties +++ b/platform/platform-resources-en/src/messages/RefactoringBundle.properties @@ -76,7 +76,7 @@ visibility.package.local=Pac&kage local visibility.border.title=Visibility default.visibility.border.title=Default Visibility visibility.combo.title=&Visibility: -moveInstanceMethod.select.an.instance.parameter=Select an &instance parameter: +moveInstanceMethod.select.an.instance.parameter=Select an &instance expression: destination.package=Destination &package: choose.destination.package=Choose Destination Package interface.name.prompt=&Interface name: