[java] create method reference from usage: prefer non-static methods (IDEA-278074)

GitOrigin-RevId: 84e0fd64f0697df44cbaf6a7b8174fcd42ece504
This commit is contained in:
Anna Kozlova
2021-09-20 14:23:34 +02:00
committed by intellij-monorepo-bot
parent bbc9f06505
commit d19e2011be
3 changed files with 50 additions and 29 deletions

View File

@@ -1,18 +1,4 @@
/*
* Copyright 2000-2014 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.
*/
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.ExpectedTypeInfo;
@@ -134,19 +120,6 @@ public class CreateMethodFromMethodReferenceFix extends CreateFromUsageBaseFix {
expression = getMethodReference();
LOG.assertTrue(expression.isValid());
boolean shouldBeAbstract = false;
if (!expression.isConstructor()) {
if (shouldCreateStaticMember(expression, targetClass)) {
PsiUtil.setModifierProperty(method, PsiModifier.STATIC, true);
}
else if (targetClass.isInterface()) {
shouldBeAbstract = true;
PsiCodeBlock body = method.getBody();
assert body != null;
body.delete();
}
}
final PsiElement context = PsiTreeUtil.getParentOfType(expression, PsiClass.class, PsiMethod.class);
final PsiType functionalInterfaceType = getFunctionalExpressionType(expression);
@@ -159,8 +132,32 @@ public class CreateMethodFromMethodReferenceFix extends CreateFromUsageBaseFix {
final PsiSubstitutor substitutor = LambdaUtil.getSubstitutor(interfaceMethod, classResolveResult);
final ExpectedTypeInfo[] expectedTypes = {new ExpectedTypeInfoImpl(interfaceReturnType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, interfaceReturnType, TailType.NONE, null, ExpectedTypeInfoImpl.NULL)};
PsiParameter[] parameters = interfaceMethod.getParameterList().getParameters();
List<Pair<PsiExpression, PsiType>> arguments = ContainerUtil.map2List(parameters, parameter -> Pair.create(null, substitutor.substitute(parameter.getType())));
boolean shouldBeAbstract = false;
if (!expression.isConstructor()) {
PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult(expression);
boolean secondSearchPossible = PsiMethodReferenceUtil.isSecondSearchPossible(arguments.stream().map(p -> p.second).toArray(PsiType[]::new),
qualifierResolveResult, expression);
if (!secondSearchPossible && shouldCreateStaticMember(expression, targetClass)) {
PsiUtil.setModifierProperty(method, PsiModifier.STATIC, true);
}
else {
if (secondSearchPossible) {
arguments.remove(0);
}
if (targetClass.isInterface()) {
shouldBeAbstract = true;
PsiCodeBlock body = method.getBody();
assert body != null;
body.delete();
}
}
}
CreateMethodFromUsageFix.doCreate(targetClass, method, shouldBeAbstract,
ContainerUtil.map2List(interfaceMethod.getParameterList().getParameters(), parameter -> Pair.create(null, substitutor.substitute(parameter.getType()))),
arguments,
PsiSubstitutor.EMPTY,
expectedTypes, context);
}

View File

@@ -0,0 +1,14 @@
// "Create method 'fooBar'" "true"
interface I {
String str(Container c);
}
class FooBar {
{
I i = Container::fooBar;
}
}
class Container{
public String fooBar() {
return null;
}
}

View File

@@ -0,0 +1,10 @@
// "Create method 'fooBar'" "true"
interface I {
String str(Container c);
}
class FooBar {
{
I i = Container::foo<caret>Bar;
}
}
class Container{}