mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
convert static method to instance: expand method reference to lambda, fix qualifier when needed
This commit is contained in:
+45
-8
@@ -106,8 +106,12 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor {
|
||||
for (final PsiReference ref : methodReferences) {
|
||||
final PsiElement element = ref.getElement();
|
||||
if (element instanceof PsiReferenceExpression) {
|
||||
if (element.getParent() instanceof PsiMethodCallExpression) {
|
||||
result.add(new MethodCallUsageInfo((PsiMethodCallExpression)element.getParent()));
|
||||
PsiElement parent = element.getParent();
|
||||
if (parent instanceof PsiMethodCallExpression) {
|
||||
result.add(new MethodCallUsageInfo((PsiMethodCallExpression)parent));
|
||||
}
|
||||
else if (element instanceof PsiMethodReferenceExpression) {
|
||||
result.add(new MethodReferenceUsageInfo((PsiMethodReferenceExpression)element, myMethod.getParameterList().getParameterIndex(myTargetParameter) == 0));
|
||||
}
|
||||
}
|
||||
else if (element instanceof PsiDocTagValue) {
|
||||
@@ -188,6 +192,9 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (usageInfo instanceof MethodReferenceUsageInfo && !((MethodReferenceUsageInfo)usageInfo).isApplicableBySecondSearch()) {
|
||||
conflicts.putValue(((MethodReferenceUsageInfo)usageInfo).getExpression(), RefactoringBundle.message("expand.method.reference.warning"));
|
||||
}
|
||||
}
|
||||
|
||||
return showConflicts(conflicts, usagesIn);
|
||||
@@ -216,7 +223,7 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor {
|
||||
// Process usages
|
||||
for (final UsageInfo usage : usages) {
|
||||
if (usage instanceof MethodCallUsageInfo) {
|
||||
processMethodCall((MethodCallUsageInfo)usage);
|
||||
processMethodCall(((MethodCallUsageInfo)usage).getMethodCall());
|
||||
}
|
||||
else if (usage instanceof ParameterUsageInfo) {
|
||||
processParameterUsage((ParameterUsageInfo)usage);
|
||||
@@ -224,6 +231,9 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor {
|
||||
else if (usage instanceof ImplementingClassUsageInfo) {
|
||||
inheritors.add(((ImplementingClassUsageInfo)usage).getPsiClass());
|
||||
}
|
||||
else if (usage instanceof MethodReferenceUsageInfo) {
|
||||
processMethodReference((MethodReferenceUsageInfo)usage);
|
||||
}
|
||||
}
|
||||
|
||||
prepareTypeParameterReplacement();
|
||||
@@ -256,15 +266,43 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor {
|
||||
myMethod.delete();
|
||||
}
|
||||
|
||||
private void processMethodReference(MethodReferenceUsageInfo usage) {
|
||||
PsiMethodReferenceExpression expression = usage.getExpression();
|
||||
if (usage.isApplicableBySecondSearch()) {
|
||||
PsiExpression qualifierExpression = expression.getQualifierExpression();
|
||||
LOG.assertTrue(qualifierExpression != null);
|
||||
qualifierExpression.replace(JavaPsiFacade.getElementFactory(myProject).createReferenceExpression(myTargetClass));
|
||||
}
|
||||
else {
|
||||
PsiLambdaExpression lambdaExpression = LambdaRefactoringUtil.convertMethodReferenceToLambda(expression, false, true);
|
||||
List<PsiExpression> returnExpressions = LambdaUtil.getReturnExpressions(lambdaExpression);
|
||||
if (!returnExpressions.isEmpty()) {
|
||||
PsiMethodCallExpression methodCall = (PsiMethodCallExpression)returnExpressions.get(0);
|
||||
processMethodCall(methodCall);
|
||||
usage.setReplacement(methodCall);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fixVisibility(final PsiMethod method, final UsageInfo[] usages) throws IncorrectOperationException {
|
||||
final PsiModifierList modifierList = method.getModifierList();
|
||||
if (VisibilityUtil.ESCALATE_VISIBILITY.equals(myNewVisibility)) {
|
||||
for (UsageInfo usage : usages) {
|
||||
PsiElement place = null;
|
||||
if (usage instanceof MethodCallUsageInfo) {
|
||||
final PsiElement place = usage.getElement();
|
||||
if (place != null) {
|
||||
VisibilityUtil.escalateVisibility(method, place);
|
||||
place = usage.getElement();
|
||||
}
|
||||
else if (usage instanceof MethodReferenceUsageInfo) {
|
||||
PsiMethodReferenceExpression expression = ((MethodReferenceUsageInfo)usage).getExpression();
|
||||
if (expression != null && expression.isValid()) {
|
||||
place = expression;
|
||||
}
|
||||
else {
|
||||
place = ((MethodReferenceUsageInfo)usage).getReplacement();
|
||||
}
|
||||
}
|
||||
if (place != null) {
|
||||
VisibilityUtil.escalateVisibility(method, place);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -364,8 +402,7 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void processMethodCall(MethodCallUsageInfo usageInfo) throws IncorrectOperationException {
|
||||
PsiMethodCallExpression methodCall = usageInfo.getMethodCall();
|
||||
private void processMethodCall(final PsiMethodCallExpression methodCall) throws IncorrectOperationException {
|
||||
PsiParameterList parameterList = myMethod.getParameterList();
|
||||
PsiElementFactory factory = JavaPsiFacade.getInstance(myMethod.getProject()).getElementFactory();
|
||||
int parameterIndex = parameterList.getParameterIndex(myTargetParameter);
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.convertToInstanceMethod;
|
||||
|
||||
import com.intellij.psi.PsiMethodCallExpression;
|
||||
import com.intellij.psi.PsiMethodReferenceExpression;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
|
||||
public class MethodReferenceUsageInfo extends UsageInfo {
|
||||
private final PsiMethodReferenceExpression myExpression;
|
||||
private final boolean myApplicableBySecondSearch;
|
||||
private PsiMethodCallExpression myReplacement;
|
||||
|
||||
public MethodReferenceUsageInfo(PsiMethodReferenceExpression methodReferenceExpression, boolean bySecondSearch) {
|
||||
super(methodReferenceExpression);
|
||||
myExpression = methodReferenceExpression;
|
||||
myApplicableBySecondSearch = bySecondSearch;
|
||||
}
|
||||
|
||||
public PsiMethodReferenceExpression getExpression() {
|
||||
return myExpression;
|
||||
}
|
||||
|
||||
public boolean isApplicableBySecondSearch() {
|
||||
return myApplicableBySecondSearch;
|
||||
}
|
||||
|
||||
public void setReplacement(PsiMethodCallExpression replacement) {
|
||||
myReplacement = replacement;
|
||||
}
|
||||
|
||||
public PsiMethodCallExpression getReplacement() {
|
||||
return myReplacement;
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class Bar0 {}
|
||||
class Bar {
|
||||
void f() {
|
||||
I r = Bar::foo;
|
||||
}
|
||||
|
||||
private static void fo<caret>o(Bar0 bar) { }
|
||||
}
|
||||
interface I {
|
||||
void m(Bar0 b);
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
class Bar0 {
|
||||
void foo() { }
|
||||
}
|
||||
class Bar {
|
||||
void f() {
|
||||
I r = Bar0::foo;
|
||||
}
|
||||
|
||||
}
|
||||
interface I {
|
||||
void m(Bar0 b);
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class Bar0 {}
|
||||
class Bar {
|
||||
void f() {
|
||||
I r = Bar::foo;
|
||||
}
|
||||
|
||||
private static void fo<caret>o(Integer i, Bar0 bar) { }
|
||||
}
|
||||
interface I {
|
||||
void m(Integer i, Bar0 b);
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
class Bar0 {
|
||||
void foo(Integer i) { }
|
||||
}
|
||||
class Bar {
|
||||
void f() {
|
||||
I r = (i, bar) -> bar.foo(i);
|
||||
}
|
||||
|
||||
}
|
||||
interface I {
|
||||
void m(Integer i, Bar0 b);
|
||||
}
|
||||
+9
@@ -16,6 +16,7 @@
|
||||
package com.intellij.refactoring.convertToInstanceMethod;
|
||||
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.refactoring.BaseRefactoringProcessor;
|
||||
|
||||
public class ConvertToInstance8MethodTest extends ConvertToInstanceMethodTest {
|
||||
@Override
|
||||
@@ -27,6 +28,14 @@ public class ConvertToInstance8MethodTest extends ConvertToInstanceMethodTest {
|
||||
doTest(0);
|
||||
}
|
||||
|
||||
public void testMethodReferenceAcceptableBySecondSearch() throws Exception {
|
||||
doTest(0);
|
||||
}
|
||||
|
||||
public void testMethodReferenceToLambda() throws Exception {
|
||||
BaseRefactoringProcessor.ConflictsInTestsException.withIgnoredConflicts(() -> doTest(1));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LanguageLevel getLanguageLevel() {
|
||||
return LanguageLevel.JDK_1_8;
|
||||
|
||||
@@ -584,6 +584,17 @@ public abstract class BaseRefactoringProcessor implements Runnable {
|
||||
return myTestIgnore;
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
public static <T extends Throwable> void withIgnoredConflicts(ThrowableRunnable<T> r) throws T {
|
||||
try {
|
||||
myTestIgnore = true;
|
||||
r.run();
|
||||
}
|
||||
finally {
|
||||
myTestIgnore = false;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<String> getMessages() {
|
||||
List<String> result = new ArrayList<>(messages);
|
||||
|
||||
Reference in New Issue
Block a user