mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Java inspection: convert the intention for "Replace method reference with lambda" into an INFORMATION-level inspection
This commit is contained in:
@@ -2551,6 +2551,10 @@
|
||||
key="replace.lambda.with.anonymous.name" groupBundle="messages.InspectionsBundle"
|
||||
groupKey="group.names.code.style.issues" enabledByDefault="true" level="INFORMATION"
|
||||
implementationClass="com.siyeh.ig.style.ReplaceLambdaWithAnonymousInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="ReplaceMethodRefWithLambda" bundle="com.siyeh.InspectionGadgetsBundle"
|
||||
key="replace.method.ref.with.lambda.name" groupBundle="messages.InspectionsBundle"
|
||||
groupKey="group.names.code.style.issues" enabledByDefault="true" level="INFORMATION"
|
||||
implementationClass="com.siyeh.ig.style.ReplaceMethodRefWithLambdaInspection"/>
|
||||
|
||||
<!--group.names.threading.issues-->
|
||||
<localInspection groupPath="Java" language="JAVA" suppressId="AccessToNonThreadSafeStaticField" shortName="AccessToNonThreadSafeStaticFieldFromInstance"
|
||||
|
||||
+3
-1
@@ -2184,4 +2184,6 @@ infer.lambda.parameter.type.descriptor=Expand lambda to {0} -> '{'...'}'
|
||||
replace.diamond.with.explicit.type.arguments.name=Replace diamond with explicit type arguments
|
||||
replace.diamond.with.explicit.type.arguments.descriptor=Replace '<>' with explicit type arguments
|
||||
replace.lambda.with.anonymous.name=Replace lambda with anonymous class
|
||||
replace.lambda.with.anonymous.descriptor=Replace lambda with anonymous class
|
||||
replace.lambda.with.anonymous.descriptor=Replace lambda with anonymous class
|
||||
replace.method.ref.with.lambda.name=Replace method reference with lambda
|
||||
replace.method.ref.with.lambda.descriptor=Replace method reference with lambda
|
||||
+2
-2
@@ -236,14 +236,14 @@ public class ReplaceLambdaWithAnonymousInspection extends BaseInspection {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return InspectionGadgetsBundle.message("replace.lambda.with.anonymous.name");
|
||||
return InspectionGadgetsBundle.message("replace.lambda.with.anonymous.descriptor");
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return InspectionGadgetsBundle.message("replace.lambda.with.anonymous.descriptor");
|
||||
return InspectionGadgetsBundle.message("replace.lambda.with.anonymous.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright 2011 Bas Leijdekkers
|
||||
*
|
||||
* 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.siyeh.ig.style;
|
||||
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.AsyncResult;
|
||||
import com.intellij.openapi.util.Factory;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.refactoring.util.LambdaRefactoringUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.InspectionGadgetsFix;
|
||||
import com.siyeh.ig.psiutils.SideEffectChecker;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ReplaceMethodRefWithLambdaInspection extends BaseInspection {
|
||||
private static final Logger LOG = Logger.getInstance("#" + ReplaceMethodRefWithLambdaInspection.class.getName());
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return InspectionGadgetsBundle.message("replace.method.ref.with.lambda.name");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String buildErrorString(Object... infos) {
|
||||
return InspectionGadgetsBundle.message("replace.method.ref.with.lambda.descriptor");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseInspectionVisitor buildVisitor() {
|
||||
return new MethodRefToLambdaVisitor();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected InspectionGadgetsFix buildFix(Object... infos) {
|
||||
if (infos.length == 1) {
|
||||
final Object info = infos[0];
|
||||
if (info instanceof FixFactory) {
|
||||
return ((FixFactory)info).create();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class MethodRefToLambdaVisitor extends BaseInspectionVisitor {
|
||||
@Override
|
||||
public void visitMethodReferenceExpression(PsiMethodReferenceExpression methodReferenceExpression) {
|
||||
super.visitMethodReferenceExpression(methodReferenceExpression);
|
||||
final PsiType interfaceType = methodReferenceExpression.getFunctionalInterfaceType();
|
||||
if (interfaceType != null &&
|
||||
LambdaUtil.getFunctionalInterfaceMethod(interfaceType) != null &&
|
||||
methodReferenceExpression.resolve() != null) {
|
||||
registerError(methodReferenceExpression, getFixFactory(isWithSideEffects(methodReferenceExpression), isOnTheFly()));
|
||||
}
|
||||
}
|
||||
|
||||
private static FixFactory getFixFactory(boolean withSideEffects, boolean onTheFly) {
|
||||
if (!withSideEffects) return MethodRefToLambdaFix::new;
|
||||
if (onTheFly || ApplicationManager.getApplication().isUnitTestMode()) return SideEffectsMethodRefToLambdaFix::new;
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isWithSideEffects(PsiMethodReferenceExpression methodReferenceExpression) {
|
||||
final PsiExpression qualifierExpression = methodReferenceExpression.getQualifierExpression();
|
||||
if (qualifierExpression != null) {
|
||||
final List<PsiElement> sideEffects = new ArrayList<PsiElement>();
|
||||
SideEffectChecker.checkSideEffects(qualifierExpression, sideEffects);
|
||||
return !sideEffects.isEmpty();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MethodRefToLambdaFix extends InspectionGadgetsFix {
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return InspectionGadgetsBundle.message("replace.method.ref.with.lambda.descriptor");
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return InspectionGadgetsBundle.message("replace.method.ref.with.lambda.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFix(Project project, ProblemDescriptor descriptor) {
|
||||
final PsiElement element = descriptor.getPsiElement();
|
||||
if (element instanceof PsiMethodReferenceExpression) {
|
||||
doFix(project, (PsiMethodReferenceExpression)element);
|
||||
}
|
||||
}
|
||||
|
||||
protected void doFix(Project project, @NotNull PsiMethodReferenceExpression methodReferenceExpression) {
|
||||
LambdaRefactoringUtil.convertMethodReferenceToLambda(methodReferenceExpression, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
private static class SideEffectsMethodRefToLambdaFix extends MethodRefToLambdaFix {
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFix(Project project, @NotNull PsiMethodReferenceExpression methodReferenceExpression) {
|
||||
final AsyncResult<DataContext> contextFromFocus = DataManager.getInstance().getDataContextFromFocus();
|
||||
contextFromFocus.doWhenDone((Consumer<DataContext>)context -> {
|
||||
final Editor editor = CommonDataKeys.EDITOR.getData(context);
|
||||
if (editor != null) {
|
||||
CommandProcessor.getInstance()
|
||||
.executeCommand(project, () -> doFixAndRemoveSideEffects(editor, methodReferenceExpression), getFamilyName(), null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void doFixAndRemoveSideEffects(@NotNull Editor editor, @NotNull PsiMethodReferenceExpression methodReferenceExpression) {
|
||||
if (!FileModificationService.getInstance().preparePsiElementsForWrite(methodReferenceExpression)) return;
|
||||
final PsiLambdaExpression lambdaExpression =
|
||||
WriteAction.compute(() -> LambdaRefactoringUtil.convertMethodReferenceToLambda(methodReferenceExpression, false, true));
|
||||
if (lambdaExpression != null) {
|
||||
LambdaRefactoringUtil.removeSideEffectsFromLambdaBody(editor, lambdaExpression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private interface FixFactory extends Factory<InspectionGadgetsFix> {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This inspection expands method reference to lambda expression
|
||||
</body>
|
||||
</html>
|
||||
+14
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,23 +13,26 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.siyeh.ipp.types;
|
||||
package com.siyeh.ig.fixes.style;
|
||||
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.siyeh.IntentionPowerPackBundle;
|
||||
import com.siyeh.ipp.IPPTestCase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import com.intellij.openapi.roots.ModuleRootModificationUtil;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.IGQuickFixesTestCase;
|
||||
import com.siyeh.ig.style.ReplaceMethodRefWithLambdaInspection;
|
||||
|
||||
public class ReplaceMethodReferenceWithLambdaIntentionTest extends IPPTestCase {
|
||||
|
||||
public class ReplaceMethodReferenceWithLambdaFixTest extends IGQuickFixesTestCase {
|
||||
@Override
|
||||
protected String getIntentionName() {
|
||||
return IntentionPowerPackBundle.message("replace.method.ref.with.lambda.intention.name");
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
ModuleRootModificationUtil.setModuleSdk(myModule, IdeaTestUtil.getMockJdk18());
|
||||
myFixture.enableInspections(new ReplaceMethodRefWithLambdaInspection());
|
||||
myDefaultHint = InspectionGadgetsBundle.message("replace.method.ref.with.lambda.descriptor");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getRelativePath() {
|
||||
return "types/methodRefs2lambda";
|
||||
return "style/methodRefs2lambda";
|
||||
}
|
||||
|
||||
public void testRedundantCast() throws Exception {
|
||||
@@ -127,10 +130,4 @@ public class ReplaceMethodReferenceWithLambdaIntentionTest extends IPPTestCase {
|
||||
public void testPreserveExpressionQualifier() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected LightProjectDescriptor getProjectDescriptor() {
|
||||
return JAVA_8;
|
||||
}
|
||||
}
|
||||
@@ -259,12 +259,6 @@
|
||||
<categoryKey>intention.category.declaration</categoryKey>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>com.siyeh.ipp.types.ReplaceMethodRefWithLambdaIntention</className>
|
||||
<bundleName>com.siyeh.IntentionPowerPackBundle</bundleName>
|
||||
<categoryKey>intention.category.declaration</categoryKey>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>com.siyeh.ipp.decls.ChangeVariableTypeToRhsTypeIntention</className>
|
||||
<bundleName>com.siyeh.IntentionPowerPackBundle</bundleName>
|
||||
|
||||
@@ -162,8 +162,6 @@ split.try.with.multiple.resources.intention.name=Split 'try' statement with mult
|
||||
split.try.with.multiple.resources.intention.family.name=Split Try Statement with Multiple Resources
|
||||
obscure.thrown.exceptions.intention.family.name=Replace Exceptions in Throws Clause with Single More General Exception
|
||||
add.array.creation.expression.intention.family.name=Add Array Creation Expression
|
||||
replace.method.ref.with.lambda.intention.name=Replace method reference with lambda
|
||||
replace.method.ref.with.lambda.intention.family.name=Replace method reference with lambda
|
||||
make.public.intention.name=Make 'public'
|
||||
make.public.intention.family.name=Make Public
|
||||
make.package.private.intention.name=Make package-private
|
||||
|
||||
-70
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 Bas Leijdekkers
|
||||
*
|
||||
* 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.siyeh.ipp.types;
|
||||
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.util.LambdaRefactoringUtil;
|
||||
import com.siyeh.ipp.base.Intention;
|
||||
import com.siyeh.ipp.base.PsiElementPredicate;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ReplaceMethodRefWithLambdaIntention extends Intention {
|
||||
private static final Logger LOG = Logger.getInstance("#" + ReplaceMethodRefWithLambdaIntention.class.getName());
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected PsiElementPredicate getElementPredicate() {
|
||||
return new MethodRefPredicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processIntention(@NotNull PsiElement element) {}
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processIntention(final Editor editor, @NotNull PsiElement element) {
|
||||
PsiMethodReferenceExpression ref = PsiTreeUtil.getParentOfType(element, PsiMethodReferenceExpression.class);
|
||||
PsiLambdaExpression expr = ref != null
|
||||
? WriteAction.compute(() -> LambdaRefactoringUtil.convertMethodReferenceToLambda(ref, false, true))
|
||||
: null;
|
||||
if (expr == null) return;
|
||||
LambdaRefactoringUtil.removeSideEffectsFromLambdaBody(editor, expr);
|
||||
}
|
||||
|
||||
private static class MethodRefPredicate implements PsiElementPredicate {
|
||||
@Override
|
||||
public boolean satisfiedBy(PsiElement element) {
|
||||
final PsiMethodReferenceExpression methodReferenceExpression = PsiTreeUtil.getParentOfType(element, PsiMethodReferenceExpression.class);
|
||||
if (methodReferenceExpression != null) {
|
||||
final PsiType interfaceType = methodReferenceExpression.getFunctionalInterfaceType();
|
||||
if (interfaceType != null &&
|
||||
LambdaUtil.getFunctionalInterfaceMethod(interfaceType) != null &&
|
||||
methodReferenceExpression.resolve() != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
class X {
|
||||
interface I {
|
||||
void _();
|
||||
}
|
||||
|
||||
static void m() {}
|
||||
{
|
||||
I i = () -> m();
|
||||
}
|
||||
}
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
class X {
|
||||
interface I {
|
||||
void _();
|
||||
}
|
||||
|
||||
static void m() {}
|
||||
{
|
||||
I i = <spot>X :: m</spot>;
|
||||
}
|
||||
}
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention expands method reference to lambda expression
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user