mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
guava type migration: convert anonymous Function-s with runtime retention policy annotations to anonymous classes except @javax.annotations.Nullable (can be configured in settings)
This commit is contained in:
+12
-6
@@ -100,7 +100,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
|||||||
final PsiElement lambdaContext = parent != null ? parent.getParent() : null;
|
final PsiElement lambdaContext = parent != null ? parent.getParent() : null;
|
||||||
if (lambdaContext != null &&
|
if (lambdaContext != null &&
|
||||||
(LambdaUtil.isValidLambdaContext(lambdaContext) || !(lambdaContext instanceof PsiExpressionStatement)) &&
|
(LambdaUtil.isValidLambdaContext(lambdaContext) || !(lambdaContext instanceof PsiExpressionStatement)) &&
|
||||||
canBeConvertedToLambda(aClass, false, reportNotAnnotatedInterfaces)) {
|
canBeConvertedToLambda(aClass, false, reportNotAnnotatedInterfaces, Collections.emptySet())) {
|
||||||
final PsiElement lBrace = aClass.getLBrace();
|
final PsiElement lBrace = aClass.getLBrace();
|
||||||
LOG.assertTrue(lBrace != null);
|
LOG.assertTrue(lBrace != null);
|
||||||
final TextRange rangeInElement = new TextRange(0, aClass.getStartOffsetInParent() + lBrace.getStartOffsetInParent());
|
final TextRange rangeInElement = new TextRange(0, aClass.getStartOffsetInParent() + lBrace.getStartOffsetInParent());
|
||||||
@@ -111,12 +111,15 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean hasRuntimeAnnotations(PsiMethod method) {
|
private static boolean hasRuntimeAnnotations(PsiMethod method, @NotNull Set<String> runtimeAnnotationsToIgnore) {
|
||||||
PsiAnnotation[] annotations = method.getModifierList().getAnnotations();
|
PsiAnnotation[] annotations = method.getModifierList().getAnnotations();
|
||||||
for (PsiAnnotation annotation : annotations) {
|
for (PsiAnnotation annotation : annotations) {
|
||||||
PsiJavaCodeReferenceElement ref = annotation.getNameReferenceElement();
|
PsiJavaCodeReferenceElement ref = annotation.getNameReferenceElement();
|
||||||
PsiElement target = ref != null ? ref.resolve() : null;
|
PsiElement target = ref != null ? ref.resolve() : null;
|
||||||
if (target instanceof PsiClass) {
|
if (target instanceof PsiClass) {
|
||||||
|
if (runtimeAnnotationsToIgnore.contains(((PsiClass)target).getQualifiedName())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
final PsiAnnotation retentionAnno = AnnotationUtil.findAnnotation((PsiClass)target, Retention.class.getName());
|
final PsiAnnotation retentionAnno = AnnotationUtil.findAnnotation((PsiClass)target, Retention.class.getName());
|
||||||
if (retentionAnno != null) {
|
if (retentionAnno != null) {
|
||||||
PsiAnnotationMemberValue value = retentionAnno.findAttributeValue("value");
|
PsiAnnotationMemberValue value = retentionAnno.findAttributeValue("value");
|
||||||
@@ -178,13 +181,16 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean canBeConvertedToLambda(PsiAnonymousClass aClass, boolean acceptParameterizedFunctionTypes) {
|
public static boolean canBeConvertedToLambda(PsiAnonymousClass aClass,
|
||||||
return canBeConvertedToLambda(aClass, acceptParameterizedFunctionTypes, true);
|
boolean acceptParameterizedFunctionTypes,
|
||||||
|
@NotNull Set<String> ignoredRuntimeAnnotations) {
|
||||||
|
return canBeConvertedToLambda(aClass, acceptParameterizedFunctionTypes, true, ignoredRuntimeAnnotations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean canBeConvertedToLambda(PsiAnonymousClass aClass,
|
public static boolean canBeConvertedToLambda(PsiAnonymousClass aClass,
|
||||||
boolean acceptParameterizedFunctionTypes,
|
boolean acceptParameterizedFunctionTypes,
|
||||||
boolean reportNotAnnotatedInterfaces) {
|
boolean reportNotAnnotatedInterfaces,
|
||||||
|
@NotNull Set<String> ignoredRuntimeAnnotations) {
|
||||||
if (PsiUtil.getLanguageLevel(aClass).isAtLeast(LanguageLevel.JDK_1_8)) {
|
if (PsiUtil.getLanguageLevel(aClass).isAtLeast(LanguageLevel.JDK_1_8)) {
|
||||||
final PsiClassType baseClassType = aClass.getBaseClassType();
|
final PsiClassType baseClassType = aClass.getBaseClassType();
|
||||||
final PsiClassType.ClassResolveResult resolveResult = baseClassType.resolveGenerics();
|
final PsiClassType.ClassResolveResult resolveResult = baseClassType.resolveGenerics();
|
||||||
@@ -203,7 +209,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
|||||||
final PsiMethod method = methods[0];
|
final PsiMethod method = methods[0];
|
||||||
return method.getBody() != null &&
|
return method.getBody() != null &&
|
||||||
!hasForbiddenRefsInsideBody(method, aClass) &&
|
!hasForbiddenRefsInsideBody(method, aClass) &&
|
||||||
!hasRuntimeAnnotations(method) &&
|
!hasRuntimeAnnotations(method, ignoredRuntimeAnnotations) &&
|
||||||
!method.hasModifierProperty(PsiModifier.SYNCHRONIZED);
|
!method.hasModifierProperty(PsiModifier.SYNCHRONIZED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -29,6 +29,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: anna
|
* User: anna
|
||||||
@@ -76,7 +77,7 @@ public class AnonymousCanBeMethodReferenceInspection extends BaseJavaBatchLocalI
|
|||||||
@Override
|
@Override
|
||||||
public void visitAnonymousClass(PsiAnonymousClass aClass) {
|
public void visitAnonymousClass(PsiAnonymousClass aClass) {
|
||||||
super.visitAnonymousClass(aClass);
|
super.visitAnonymousClass(aClass);
|
||||||
if (AnonymousCanBeLambdaInspection.canBeConvertedToLambda(aClass, true, reportNotAnnotatedInterfaces)) {
|
if (AnonymousCanBeLambdaInspection.canBeConvertedToLambda(aClass, true, reportNotAnnotatedInterfaces, Collections.emptySet())) {
|
||||||
final PsiMethod method = aClass.getMethods()[0];
|
final PsiMethod method = aClass.getMethods()[0];
|
||||||
final PsiCodeBlock body = method.getBody();
|
final PsiCodeBlock body = method.getBody();
|
||||||
final PsiCallExpression callExpression =
|
final PsiCallExpression callExpression =
|
||||||
|
|||||||
+2
-1
@@ -44,6 +44,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class IntroduceParameterDialog extends RefactoringDialog {
|
public class IntroduceParameterDialog extends RefactoringDialog {
|
||||||
@@ -234,7 +235,7 @@ public class IntroduceParameterDialog extends RefactoringDialog {
|
|||||||
myCbCollapseToLambda = new NonFocusableCheckBox(RefactoringBundle.message("introduce.parameter.convert.lambda"));
|
myCbCollapseToLambda = new NonFocusableCheckBox(RefactoringBundle.message("introduce.parameter.convert.lambda"));
|
||||||
final PsiAnonymousClass anonymClass = myExpression instanceof PsiNewExpression ? ((PsiNewExpression)myExpression).getAnonymousClass()
|
final PsiAnonymousClass anonymClass = myExpression instanceof PsiNewExpression ? ((PsiNewExpression)myExpression).getAnonymousClass()
|
||||||
: null;
|
: null;
|
||||||
myCbCollapseToLambda.setVisible(anonymClass != null && AnonymousCanBeLambdaInspection.canBeConvertedToLambda(anonymClass, false));
|
myCbCollapseToLambda.setVisible(anonymClass != null && AnonymousCanBeLambdaInspection.canBeConvertedToLambda(anonymClass, false, Collections.emptySet()));
|
||||||
myCbCollapseToLambda.setSelected(PropertiesComponent.getInstance(myProject).getBoolean(INTRODUCE_PARAMETER_LAMBDA));
|
myCbCollapseToLambda.setSelected(PropertiesComponent.getInstance(myProject).getBoolean(INTRODUCE_PARAMETER_LAMBDA));
|
||||||
gbConstraints.gridy++;
|
gbConstraints.gridy++;
|
||||||
panel.add(myCbCollapseToLambda, gbConstraints);
|
panel.add(myCbCollapseToLambda, gbConstraints);
|
||||||
|
|||||||
@@ -447,6 +447,11 @@ public class TypeEvaluator {
|
|||||||
return migrationTtype;
|
return migrationTtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public <T> T getSettings(Class<T> aClass) {
|
||||||
|
return myRules.getConversionSettings(aClass);
|
||||||
|
}
|
||||||
|
|
||||||
private class SubstitutorBuilder {
|
private class SubstitutorBuilder {
|
||||||
private final Map<PsiTypeParameter, PsiType> myMapping;
|
private final Map<PsiTypeParameter, PsiType> myMapping;
|
||||||
private final PsiMethod myMethod;
|
private final PsiMethod myMethod;
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import com.intellij.openapi.util.TextRange;
|
|||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
import com.intellij.psi.*;
|
import com.intellij.psi.*;
|
||||||
import com.intellij.psi.impl.PsiImplUtil;
|
import com.intellij.psi.impl.PsiImplUtil;
|
||||||
import com.intellij.psi.impl.source.PsiClassReferenceType;
|
|
||||||
import com.intellij.psi.impl.source.PsiImmediateClassType;
|
import com.intellij.psi.impl.source.PsiImmediateClassType;
|
||||||
import com.intellij.psi.javadoc.PsiDocTagValue;
|
import com.intellij.psi.javadoc.PsiDocTagValue;
|
||||||
import com.intellij.psi.search.PsiSearchScopeUtil;
|
import com.intellij.psi.search.PsiSearchScopeUtil;
|
||||||
@@ -46,7 +45,7 @@ import com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo;
|
|||||||
import com.intellij.usageView.UsageInfo;
|
import com.intellij.usageView.UsageInfo;
|
||||||
import com.intellij.util.*;
|
import com.intellij.util.*;
|
||||||
import com.intellij.util.concurrency.Semaphore;
|
import com.intellij.util.concurrency.Semaphore;
|
||||||
import com.intellij.util.containers.*;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import com.intellij.util.graph.DFSTBuilder;
|
import com.intellij.util.graph.DFSTBuilder;
|
||||||
import com.intellij.util.graph.GraphGenerator;
|
import com.intellij.util.graph.GraphGenerator;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -55,8 +54,6 @@ import org.jetbrains.annotations.TestOnly;
|
|||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author db
|
* @author db
|
||||||
@@ -296,6 +293,11 @@ public class TypeMigrationLabeler {
|
|||||||
return new MigrationProducer(conversions);
|
return new MigrationProducer(conversions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public <T> T getSettings(Class<T> aClass) {
|
||||||
|
return myRules.getConversionSettings(aClass);
|
||||||
|
}
|
||||||
|
|
||||||
class MigrationProducer {
|
class MigrationProducer {
|
||||||
private final Map<UsageInfo, Object> myRemainConversions;
|
private final Map<UsageInfo, Object> myRemainConversions;
|
||||||
|
|
||||||
@@ -353,10 +355,6 @@ public class TypeMigrationLabeler {
|
|||||||
Object getConversion(UsageInfo info) {
|
Object getConversion(UsageInfo info) {
|
||||||
return myRemainConversions.remove(info);
|
return myRemainConversions.remove(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean allOfConversionsUsed() {
|
|
||||||
return myRemainConversions.isEmpty();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void postProcessNewExpression(@NotNull PsiNewExpression expression) {
|
void postProcessNewExpression(@NotNull PsiNewExpression expression) {
|
||||||
|
|||||||
+10
-8
@@ -35,10 +35,8 @@ import com.intellij.ui.content.Content;
|
|||||||
import com.intellij.usageView.UsageInfo;
|
import com.intellij.usageView.UsageInfo;
|
||||||
import com.intellij.usageView.UsageViewDescriptor;
|
import com.intellij.usageView.UsageViewDescriptor;
|
||||||
import com.intellij.usageView.UsageViewManager;
|
import com.intellij.usageView.UsageViewManager;
|
||||||
import com.intellij.usages.Usage;
|
|
||||||
import com.intellij.util.*;
|
import com.intellij.util.*;
|
||||||
import com.intellij.util.containers.*;
|
import com.intellij.util.containers.*;
|
||||||
import com.intellij.util.containers.HashMap;
|
|
||||||
import gnu.trove.THashSet;
|
import gnu.trove.THashSet;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@@ -242,13 +240,14 @@ public class TypeMigrationProcessor extends BaseRefactoringProcessor {
|
|||||||
((PsiVariable)element).normalizeDeclaration();
|
((PsiVariable)element).normalizeDeclaration();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
change(myLabeler, usages);
|
change(usages, myLabeler, myProject);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void change(TypeMigrationLabeler labeler, UsageInfo[] usages) {
|
public static void change(UsageInfo[] usages, TypeMigrationLabeler labeler, Project project) {
|
||||||
final List<PsiNewExpression> newExpressionsToCheckDiamonds = new SmartList<PsiNewExpression>();
|
final List<SmartPsiElementPointer<PsiNewExpression>> newExpressionsToCheckDiamonds = new SmartList<>();
|
||||||
final TypeMigrationLabeler.MigrationProducer producer = labeler.createMigratorFor(usages);
|
final TypeMigrationLabeler.MigrationProducer producer = labeler.createMigratorFor(usages);
|
||||||
|
|
||||||
|
final SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(project);
|
||||||
List<UsageInfo> nonCodeUsages = new ArrayList<UsageInfo>();
|
List<UsageInfo> nonCodeUsages = new ArrayList<UsageInfo>();
|
||||||
for (UsageInfo usage : usages) {
|
for (UsageInfo usage : usages) {
|
||||||
if (((TypeMigrationUsageInfo)usage).isExcluded()) continue;
|
if (((TypeMigrationUsageInfo)usage).isExcluded()) continue;
|
||||||
@@ -260,7 +259,7 @@ public class TypeMigrationProcessor extends BaseRefactoringProcessor {
|
|||||||
producer.change((TypeMigrationUsageInfo)usage, new Consumer<PsiNewExpression>() {
|
producer.change((TypeMigrationUsageInfo)usage, new Consumer<PsiNewExpression>() {
|
||||||
@Override
|
@Override
|
||||||
public void consume(@NotNull PsiNewExpression expression) {
|
public void consume(@NotNull PsiNewExpression expression) {
|
||||||
newExpressionsToCheckDiamonds.add(expression);
|
newExpressionsToCheckDiamonds.add(smartPointerManager.createSmartPsiElementPointer(expression));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -269,8 +268,11 @@ public class TypeMigrationProcessor extends BaseRefactoringProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (PsiNewExpression newExpression : newExpressionsToCheckDiamonds) {
|
for (SmartPsiElementPointer<PsiNewExpression> newExpressionPointer : newExpressionsToCheckDiamonds) {
|
||||||
labeler.postProcessNewExpression(newExpression);
|
final PsiNewExpression newExpression = newExpressionPointer.getElement();
|
||||||
|
if (newExpression != null) {
|
||||||
|
labeler.postProcessNewExpression(newExpression);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (UsageInfo usageInfo : nonCodeUsages) {
|
for (UsageInfo usageInfo : nonCodeUsages) {
|
||||||
|
|||||||
@@ -27,28 +27,42 @@ import com.intellij.util.containers.ContainerUtil;
|
|||||||
import org.jetbrains.annotations.NonNls;
|
import org.jetbrains.annotations.NonNls;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author db
|
* @author db
|
||||||
* Date: Oct 2, 2004
|
* Date: Oct 2, 2004
|
||||||
*/
|
*/
|
||||||
public class TypeMigrationRules {
|
public class TypeMigrationRules {
|
||||||
private final LinkedList<TypeConversionRule> myConversionRules = new LinkedList<TypeConversionRule>();
|
private final List<TypeConversionRule> myConversionRules;
|
||||||
|
private final Map<Class, Object> myConversionCustomSettings = new HashMap<>();
|
||||||
private SearchScope mySearchScope;
|
private SearchScope mySearchScope;
|
||||||
|
|
||||||
private final MigrateGetterNameSetting myMigrateGetterNameSetting = new MigrateGetterNameSetting();
|
private final MigrateGetterNameSetting myMigrateGetterNameSetting = new MigrateGetterNameSetting();
|
||||||
|
|
||||||
public TypeMigrationRules() {
|
public TypeMigrationRules() {
|
||||||
|
final TypeConversionRule[] extensions = Extensions.getExtensions(TypeConversionRule.EP_NAME);
|
||||||
|
myConversionRules = new ArrayList<>(extensions.length + 2);
|
||||||
myConversionRules.add(new RootTypeConversionRule());
|
myConversionRules.add(new RootTypeConversionRule());
|
||||||
myConversionRules.add(new DisjunctionTypeConversionRule());
|
myConversionRules.add(new DisjunctionTypeConversionRule());
|
||||||
ContainerUtil.addAll(myConversionRules, Extensions.getExtensions(TypeConversionRule.EP_NAME));
|
ContainerUtil.addAll(myConversionRules, extensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addConversionDescriptor(TypeConversionRule rule) {
|
public void addConversionDescriptor(TypeConversionRule rule) {
|
||||||
myConversionRules.add(rule);
|
myConversionRules.add(rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addConversionRuleSettings(Object settings) {
|
||||||
|
myConversionCustomSettings.put(settings.getClass(), settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T getConversionSettings(Class<T> aClass) {
|
||||||
|
return (T)myConversionCustomSettings.get(aClass);
|
||||||
|
}
|
||||||
|
|
||||||
@NonNls
|
@NonNls
|
||||||
@Nullable
|
@Nullable
|
||||||
public TypeConversionDescriptorBase findConversion(final PsiType from, final PsiType to, final PsiMember member, final PsiExpression context,
|
public TypeConversionDescriptorBase findConversion(final PsiType from, final PsiType to, final PsiMember member, final PsiExpression context,
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ public class MigrationPanel extends JPanel implements Disposable {
|
|||||||
}
|
}
|
||||||
new WriteCommandAction(myProject) {
|
new WriteCommandAction(myProject) {
|
||||||
protected void run(@NotNull Result result) throws Throwable {
|
protected void run(@NotNull Result result) throws Throwable {
|
||||||
TypeMigrationProcessor.change(myLabeler, usages);
|
TypeMigrationProcessor.change(usages, myLabeler, myProject);
|
||||||
}
|
}
|
||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
|
|||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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.typeMigration.inspections;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Dmitry Batkovich
|
||||||
|
*/
|
||||||
|
public class GuavaConversionSettings {
|
||||||
|
private final Set<String> myIgnoredAnnotations;
|
||||||
|
|
||||||
|
public GuavaConversionSettings(boolean ignoreJavaxNullable) {
|
||||||
|
Set<String> ignoredAnnotations = new HashSet<>();
|
||||||
|
if (ignoreJavaxNullable) {
|
||||||
|
ignoredAnnotations.add("java.annotations.Nullable");
|
||||||
|
}
|
||||||
|
myIgnoredAnnotations = Collections.unmodifiableSet(ignoredAnnotations);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getIgnoredAnnotations() {
|
||||||
|
return myIgnoredAnnotations;
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
-4
@@ -66,6 +66,7 @@ public class GuavaInspection extends BaseJavaLocalInspectionTool {
|
|||||||
public boolean checkVariables = true;
|
public boolean checkVariables = true;
|
||||||
public boolean checkChains = true;
|
public boolean checkChains = true;
|
||||||
public boolean checkReturnTypes = true;
|
public boolean checkReturnTypes = true;
|
||||||
|
public boolean ignoreJavaxNullable = true;
|
||||||
|
|
||||||
@SuppressWarnings("Duplicates")
|
@SuppressWarnings("Duplicates")
|
||||||
@Override
|
@Override
|
||||||
@@ -74,6 +75,7 @@ public class GuavaInspection extends BaseJavaLocalInspectionTool {
|
|||||||
panel.addCheckbox("Report variables", "checkVariables");
|
panel.addCheckbox("Report variables", "checkVariables");
|
||||||
panel.addCheckbox("Report method chains", "checkChains");
|
panel.addCheckbox("Report method chains", "checkChains");
|
||||||
panel.addCheckbox("Report return types", "checkReturnTypes");
|
panel.addCheckbox("Report return types", "checkReturnTypes");
|
||||||
|
panel.addCheckbox("Erase @javax.annotations.Nullable from converted functions", "ignoreJavaxNullable");
|
||||||
return panel;
|
return panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,7 +280,7 @@ public class GuavaInspection extends BaseJavaLocalInspectionTool {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MigrateGuavaTypeFix extends LocalQuickFixAndIntentionActionOnPsiElement implements BatchQuickFix<ProblemDescriptor> {
|
public class MigrateGuavaTypeFix extends LocalQuickFixAndIntentionActionOnPsiElement implements BatchQuickFix<ProblemDescriptor> {
|
||||||
private final PsiType myTargetType;
|
private final PsiType myTargetType;
|
||||||
|
|
||||||
private MigrateGuavaTypeFix(@NotNull PsiElement element, PsiType targetType) {
|
private MigrateGuavaTypeFix(@NotNull PsiElement element, PsiType targetType) {
|
||||||
@@ -346,7 +348,7 @@ public class GuavaInspection extends BaseJavaLocalInspectionTool {
|
|||||||
if (!elementsToFix.isEmpty()) performTypeMigration(elementsToFix, migrationTypes);
|
if (!elementsToFix.isEmpty()) performTypeMigration(elementsToFix, migrationTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MigrateGuavaTypeFix getFix(ProblemDescriptor descriptor) {
|
private MigrateGuavaTypeFix getFix(ProblemDescriptor descriptor) {
|
||||||
final QuickFix[] fixes = descriptor.getFixes();
|
final QuickFix[] fixes = descriptor.getFixes();
|
||||||
LOG.assertTrue(fixes != null);
|
LOG.assertTrue(fixes != null);
|
||||||
for (QuickFix fix : fixes) {
|
for (QuickFix fix : fixes) {
|
||||||
@@ -357,7 +359,7 @@ public class GuavaInspection extends BaseJavaLocalInspectionTool {
|
|||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean performTypeMigration(List<PsiElement> elements, List<PsiType> types) {
|
private boolean performTypeMigration(List<PsiElement> elements, List<PsiType> types) {
|
||||||
PsiFile containingFile = null;
|
PsiFile containingFile = null;
|
||||||
for (PsiElement element : elements) {
|
for (PsiElement element : elements) {
|
||||||
final PsiFile currentContainingFile = element.getContainingFile();
|
final PsiFile currentContainingFile = element.getContainingFile();
|
||||||
@@ -374,6 +376,7 @@ public class GuavaInspection extends BaseJavaLocalInspectionTool {
|
|||||||
final TypeMigrationRules rules = new TypeMigrationRules();
|
final TypeMigrationRules rules = new TypeMigrationRules();
|
||||||
rules.setBoundScope(GlobalSearchScopesCore.projectProductionScope(containingFile.getProject())
|
rules.setBoundScope(GlobalSearchScopesCore.projectProductionScope(containingFile.getProject())
|
||||||
.union(GlobalSearchScopesCore.projectTestScope(containingFile.getProject())));
|
.union(GlobalSearchScopesCore.projectTestScope(containingFile.getProject())));
|
||||||
|
rules.addConversionRuleSettings(new GuavaConversionSettings(ignoreJavaxNullable));
|
||||||
TypeMigrationProcessor.runHighlightingTypeMigration(containingFile.getProject(),
|
TypeMigrationProcessor.runHighlightingTypeMigration(containingFile.getProject(),
|
||||||
null,
|
null,
|
||||||
rules,
|
rules,
|
||||||
@@ -388,7 +391,7 @@ public class GuavaInspection extends BaseJavaLocalInspectionTool {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Function<PsiElement, PsiType> createMigrationTypeFunction(@NotNull final List<PsiElement> elements,
|
private Function<PsiElement, PsiType> createMigrationTypeFunction(@NotNull final List<PsiElement> elements,
|
||||||
@NotNull final List<PsiType> types) {
|
@NotNull final List<PsiType> types) {
|
||||||
LOG.assertTrue(elements.size() == types.size());
|
LOG.assertTrue(elements.size() == types.size());
|
||||||
final Map<PsiElement, PsiType> mappings = new HashMap<PsiElement, PsiType>();
|
final Map<PsiElement, PsiType> mappings = new HashMap<PsiElement, PsiType>();
|
||||||
|
|||||||
+17
-8
@@ -20,6 +20,7 @@ import com.intellij.psi.*;
|
|||||||
import com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase;
|
import com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase;
|
||||||
import com.intellij.refactoring.typeMigration.TypeEvaluator;
|
import com.intellij.refactoring.typeMigration.TypeEvaluator;
|
||||||
import com.intellij.refactoring.typeMigration.TypeMigrationLabeler;
|
import com.intellij.refactoring.typeMigration.TypeMigrationLabeler;
|
||||||
|
import com.intellij.refactoring.typeMigration.inspections.GuavaConversionSettings;
|
||||||
import com.intellij.refactoring.typeMigration.rules.TypeConversionRule;
|
import com.intellij.refactoring.typeMigration.rules.TypeConversionRule;
|
||||||
import com.intellij.reference.SoftLazyValue;
|
import com.intellij.reference.SoftLazyValue;
|
||||||
import com.intellij.util.IncorrectOperationException;
|
import com.intellij.util.IncorrectOperationException;
|
||||||
@@ -98,14 +99,7 @@ public abstract class BaseGuavaTypeConversionRule extends TypeConversionRule {
|
|||||||
return findConversionForMethod(from, to, method, methodName, context, labeler);
|
return findConversionForMethod(from, to, method, methodName, context, labeler);
|
||||||
} else if (context instanceof PsiNewExpression) {
|
} else if (context instanceof PsiNewExpression) {
|
||||||
final PsiAnonymousClass anonymousClass = ((PsiNewExpression)context).getAnonymousClass();
|
final PsiAnonymousClass anonymousClass = ((PsiNewExpression)context).getAnonymousClass();
|
||||||
if (anonymousClass != null && AnonymousCanBeLambdaInspection.canBeConvertedToLambda(anonymousClass, false)) {
|
return anonymousClass == null ? null : findConversionForAnonymous(anonymousClass, labeler.getSettings(GuavaConversionSettings.class));
|
||||||
return new TypeConversionDescriptorBase() {
|
|
||||||
@Override
|
|
||||||
public PsiExpression replace(PsiExpression expression, TypeEvaluator evaluator) throws IncorrectOperationException {
|
|
||||||
return AnonymousCanBeLambdaInspection.replacePsiElementWithLambda(expression, false, true);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (context instanceof PsiReferenceExpression) {
|
else if (context instanceof PsiReferenceExpression) {
|
||||||
final PsiElement resolvedElement = ((PsiReferenceExpression)context).resolve();
|
final PsiElement resolvedElement = ((PsiReferenceExpression)context).resolve();
|
||||||
@@ -116,6 +110,21 @@ public abstract class BaseGuavaTypeConversionRule extends TypeConversionRule {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
protected TypeConversionDescriptorBase findConversionForAnonymous(@NotNull PsiAnonymousClass anonymousClass,
|
||||||
|
@Nullable GuavaConversionSettings settings) {
|
||||||
|
final Set<String> ignoredAnnotations = settings != null ? settings.getIgnoredAnnotations() : Collections.emptySet();
|
||||||
|
if (AnonymousCanBeLambdaInspection.canBeConvertedToLambda(anonymousClass, false, ignoredAnnotations)) {
|
||||||
|
return new TypeConversionDescriptorBase() {
|
||||||
|
@Override
|
||||||
|
public PsiExpression replace(PsiExpression expression, @NotNull TypeEvaluator evaluator) throws IncorrectOperationException {
|
||||||
|
return AnonymousCanBeLambdaInspection.replacePsiElementWithLambda(expression, false, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean isValidMethodQualifierToConvert(PsiClass aClass) {
|
protected boolean isValidMethodQualifierToConvert(PsiClass aClass) {
|
||||||
return aClass != null && (ruleFromClass().equals(aClass.getQualifiedName()) || getAdditionalUtilityClasses().contains(aClass.getQualifiedName()));
|
return aClass != null && (ruleFromClass().equals(aClass.getQualifiedName()) || getAdditionalUtilityClasses().contains(aClass.getQualifiedName()));
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-4
@@ -16,7 +16,6 @@
|
|||||||
package com.intellij.refactoring.typeMigration.rules.guava;
|
package com.intellij.refactoring.typeMigration.rules.guava;
|
||||||
|
|
||||||
import com.intellij.codeInsight.daemon.impl.analysis.JavaGenericsUtil;
|
import com.intellij.codeInsight.daemon.impl.analysis.JavaGenericsUtil;
|
||||||
import com.intellij.codeInspection.AnonymousCanBeLambdaInspection;
|
|
||||||
import com.intellij.codeInspection.java18StreamApi.StreamApiConstants;
|
import com.intellij.codeInspection.java18StreamApi.StreamApiConstants;
|
||||||
import com.intellij.openapi.diagnostic.Logger;
|
import com.intellij.openapi.diagnostic.Logger;
|
||||||
import com.intellij.openapi.util.Pair;
|
import com.intellij.openapi.util.Pair;
|
||||||
@@ -144,9 +143,7 @@ public class FluentIterableConversionUtil {
|
|||||||
PsiAnonymousClass anonymousClass;
|
PsiAnonymousClass anonymousClass;
|
||||||
if (argument instanceof PsiNewExpression &&
|
if (argument instanceof PsiNewExpression &&
|
||||||
(anonymousClass = ((PsiNewExpression)argument).getAnonymousClass()) != null) {
|
(anonymousClass = ((PsiNewExpression)argument).getAnonymousClass()) != null) {
|
||||||
if (AnonymousCanBeLambdaInspection.canBeConvertedToLambda(anonymousClass, true)) {
|
argument = GuavaConversionUtil.convertAnonymousClass((PsiNewExpression)argument, anonymousClass, typeEvaluator);
|
||||||
argument = AnonymousCanBeLambdaInspection.replacePsiElementWithLambda(argument, true, true);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
final JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(expression.getProject());
|
final JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(expression.getProject());
|
||||||
if (argument != null && !(argument instanceof PsiFunctionalExpression)) {
|
if (argument != null && !(argument instanceof PsiFunctionalExpression)) {
|
||||||
|
|||||||
+59
-4
@@ -16,18 +16,25 @@
|
|||||||
package com.intellij.refactoring.typeMigration.rules.guava;
|
package com.intellij.refactoring.typeMigration.rules.guava;
|
||||||
|
|
||||||
import com.intellij.codeInspection.AnonymousCanBeLambdaInspection;
|
import com.intellij.codeInspection.AnonymousCanBeLambdaInspection;
|
||||||
|
import com.intellij.openapi.diagnostic.Logger;
|
||||||
import com.intellij.psi.*;
|
import com.intellij.psi.*;
|
||||||
import com.intellij.psi.util.InheritanceUtil;
|
import com.intellij.psi.util.InheritanceUtil;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import com.intellij.psi.util.PsiTypesUtil;
|
import com.intellij.psi.util.PsiTypesUtil;
|
||||||
import com.intellij.refactoring.typeMigration.TypeEvaluator;
|
import com.intellij.refactoring.typeMigration.TypeEvaluator;
|
||||||
|
import com.intellij.refactoring.typeMigration.inspections.GuavaConversionSettings;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Dmitry Batkovich
|
* @author Dmitry Batkovich
|
||||||
*/
|
*/
|
||||||
public class GuavaConversionUtil {
|
public class GuavaConversionUtil {
|
||||||
|
private final static Logger LOG = Logger.getInstance(GuavaConversionUtil.class);
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static PsiType getFunctionReturnType(PsiExpression functionExpression) {
|
public static PsiType getFunctionReturnType(PsiExpression functionExpression) {
|
||||||
if (functionExpression instanceof PsiFunctionalExpression) {
|
if (functionExpression instanceof PsiFunctionalExpression) {
|
||||||
@@ -88,13 +95,14 @@ public class GuavaConversionUtil {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PsiExpression adjustLambdaContainingExpression(PsiExpression expression, boolean insertTypeCase, PsiType targetType, TypeEvaluator evaluator) {
|
public static PsiExpression adjustLambdaContainingExpression(PsiExpression expression,
|
||||||
|
boolean insertTypeCase,
|
||||||
|
PsiType targetType,
|
||||||
|
@NotNull TypeEvaluator evaluator) {
|
||||||
if (expression instanceof PsiNewExpression) {
|
if (expression instanceof PsiNewExpression) {
|
||||||
final PsiAnonymousClass anonymousClass = ((PsiNewExpression)expression).getAnonymousClass();
|
final PsiAnonymousClass anonymousClass = ((PsiNewExpression)expression).getAnonymousClass();
|
||||||
if (anonymousClass != null) {
|
if (anonymousClass != null) {
|
||||||
if (AnonymousCanBeLambdaInspection.canBeConvertedToLambda(anonymousClass, true)) {
|
return convertAnonymousClass((PsiNewExpression)expression, anonymousClass, evaluator);
|
||||||
return AnonymousCanBeLambdaInspection.replacePsiElementWithLambda(expression, true, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
final GuavaLambda lambda = GuavaLambda.findFor(evaluator.evaluateType(expression));
|
final GuavaLambda lambda = GuavaLambda.findFor(evaluator.evaluateType(expression));
|
||||||
@@ -134,6 +142,53 @@ public class GuavaConversionUtil {
|
|||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static PsiExpression convertAnonymousClass(@NotNull PsiNewExpression expression,
|
||||||
|
@NotNull PsiAnonymousClass anonymousClass,
|
||||||
|
@NotNull TypeEvaluator typeEvaluator) {
|
||||||
|
final GuavaConversionSettings settings = typeEvaluator.getSettings(GuavaConversionSettings.class);
|
||||||
|
final Set<String> ignoredAnnotations = settings != null ? settings.getIgnoredAnnotations() : Collections.emptySet();
|
||||||
|
if (AnonymousCanBeLambdaInspection.canBeConvertedToLambda(anonymousClass, true, ignoredAnnotations)) {
|
||||||
|
return AnonymousCanBeLambdaInspection.replacePsiElementWithLambda(expression, true, true);
|
||||||
|
} else {
|
||||||
|
return tryConvertClassAndSamNameToJava(expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PsiExpression tryConvertClassAndSamNameToJava(PsiNewExpression expression) {
|
||||||
|
final GuavaLambda lambda = GuavaLambda.findFor(expression.getType());
|
||||||
|
if (lambda == null) return expression;
|
||||||
|
final PsiAnonymousClass aClass = expression.getAnonymousClass();
|
||||||
|
LOG.assertTrue(aClass != null);
|
||||||
|
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(expression.getProject());
|
||||||
|
|
||||||
|
if (!lambda.getSamName().equals(lambda.getJavaAnalogueSamName())) {
|
||||||
|
boolean isFound = false;
|
||||||
|
for (PsiMethod method : aClass.findMethodsByName(lambda.getSamName(), false)) {
|
||||||
|
if (method.getParameterList().getParametersCount() == lambda.getParametersCount()) {
|
||||||
|
for (PsiMethod psiMethod : method.findSuperMethods()) {
|
||||||
|
final PsiClass superMethodContainingClass = psiMethod.getContainingClass();
|
||||||
|
if (superMethodContainingClass != null && lambda.getClassQName().equals(superMethodContainingClass.getQualifiedName())) {
|
||||||
|
final PsiIdentifier methodNameIdentifier = method.getNameIdentifier();
|
||||||
|
LOG.assertTrue(methodNameIdentifier != null);
|
||||||
|
methodNameIdentifier.replace(factory.createIdentifier(lambda.getJavaAnalogueSamName()));
|
||||||
|
isFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isFound) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final PsiElement currentClassName = aClass.getBaseClassReference().getReferenceNameElement();
|
||||||
|
if (currentClassName != null) {
|
||||||
|
final PsiElement newNameElement = factory.createReferenceFromText(lambda.getJavaAnalogueClassQName(), null);
|
||||||
|
currentClassName.replace(newNameElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (PsiExpression)expression.replace(factory.createExpressionFromText(expression.getText(), null));
|
||||||
|
}
|
||||||
|
|
||||||
private static PsiExpression addMethodReference(@NotNull PsiExpression expression, @NotNull GuavaLambda lambda) {
|
private static PsiExpression addMethodReference(@NotNull PsiExpression expression, @NotNull GuavaLambda lambda) {
|
||||||
return (PsiExpression)expression.replace(JavaPsiFacade.getElementFactory(expression.getProject())
|
return (PsiExpression)expression.replace(JavaPsiFacade.getElementFactory(expression.getProject())
|
||||||
.createExpressionFromText(expression.getText() + "::" + lambda.getSamName(), expression));
|
.createExpressionFromText(expression.getText() + "::" + lambda.getSamName(), expression));
|
||||||
|
|||||||
+10
-4
@@ -25,20 +25,26 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
* @author Dmitry Batkovich
|
* @author Dmitry Batkovich
|
||||||
*/
|
*/
|
||||||
public enum GuavaLambda {
|
public enum GuavaLambda {
|
||||||
PREDICATE("com.google.common.base.Predicate", "java.util.function.Predicate", "apply", "test"),
|
PREDICATE("com.google.common.base.Predicate", "java.util.function.Predicate", "apply", "test", 1),
|
||||||
FUNCTION("com.google.common.base.Function", "java.util.function.Function", "apply", "apply"),
|
FUNCTION("com.google.common.base.Function", "java.util.function.Function", "apply", "apply", 1),
|
||||||
SUPPLIER("com.google.common.base.Supplier", "java.util.function.Supplier", "get", "get");
|
SUPPLIER("com.google.common.base.Supplier", "java.util.function.Supplier", "get", "get", 0);
|
||||||
|
|
||||||
private final String myClassQName;
|
private final String myClassQName;
|
||||||
private final String myJavaAnalogueClassQName;
|
private final String myJavaAnalogueClassQName;
|
||||||
private final String mySamName;
|
private final String mySamName;
|
||||||
private final String myJavaAnalogueSamName;
|
private final String myJavaAnalogueSamName;
|
||||||
|
private final int myParametersCount;
|
||||||
|
|
||||||
GuavaLambda(String classQName, String javaAnalogueClassQName, String samName, String javaAnalogueSamName) {
|
GuavaLambda(String classQName, String javaAnalogueClassQName, String samName, String javaAnalogueSamName, int count) {
|
||||||
myClassQName = classQName;
|
myClassQName = classQName;
|
||||||
myJavaAnalogueClassQName = javaAnalogueClassQName;
|
myJavaAnalogueClassQName = javaAnalogueClassQName;
|
||||||
mySamName = samName;
|
mySamName = samName;
|
||||||
myJavaAnalogueSamName = javaAnalogueSamName;
|
myJavaAnalogueSamName = javaAnalogueSamName;
|
||||||
|
myParametersCount = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getParametersCount() {
|
||||||
|
return myParametersCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getClassQName() {
|
public String getClassQName() {
|
||||||
|
|||||||
+26
-3
@@ -15,10 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
package com.intellij.refactoring.typeMigration.rules.guava;
|
package com.intellij.refactoring.typeMigration.rules.guava;
|
||||||
|
|
||||||
import com.intellij.psi.PsiExpression;
|
import com.intellij.openapi.diagnostic.Logger;
|
||||||
import com.intellij.psi.PsiReferenceExpression;
|
import com.intellij.psi.*;
|
||||||
import com.intellij.psi.PsiVariable;
|
|
||||||
import com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase;
|
import com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase;
|
||||||
|
import com.intellij.refactoring.typeMigration.TypeEvaluator;
|
||||||
|
import com.intellij.refactoring.typeMigration.inspections.GuavaConversionSettings;
|
||||||
|
import com.intellij.util.IncorrectOperationException;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -28,6 +30,7 @@ import java.util.Map;
|
|||||||
* @author Dmitry Batkovich
|
* @author Dmitry Batkovich
|
||||||
*/
|
*/
|
||||||
public class GuavaLambdaConversionRule extends BaseGuavaTypeConversionRule {
|
public class GuavaLambdaConversionRule extends BaseGuavaTypeConversionRule {
|
||||||
|
private final static Logger LOG = Logger.getInstance(GuavaLambdaConversionRule.class);
|
||||||
private final GuavaLambda myLambda;
|
private final GuavaLambda myLambda;
|
||||||
|
|
||||||
protected GuavaLambdaConversionRule(GuavaLambda lambda) {
|
protected GuavaLambdaConversionRule(GuavaLambda lambda) {
|
||||||
@@ -58,6 +61,20 @@ public class GuavaLambdaConversionRule extends BaseGuavaTypeConversionRule {
|
|||||||
return myLambda.getJavaAnalogueClassQName();
|
return myLambda.getJavaAnalogueClassQName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
protected TypeConversionDescriptorBase findConversionForAnonymous(@NotNull PsiAnonymousClass anonymousClass,
|
||||||
|
GuavaConversionSettings settings) {
|
||||||
|
final TypeConversionDescriptorBase conversion = super.findConversionForAnonymous(anonymousClass, settings);
|
||||||
|
if (conversion != null) {
|
||||||
|
return conversion;
|
||||||
|
}
|
||||||
|
final PsiClass baseClass = anonymousClass.getBaseClassType().resolve();
|
||||||
|
return baseClass != null && myLambda.getClassQName().equals(baseClass.getQualifiedName())
|
||||||
|
? new ConvertLambdaClassToJavaClassDescriptor()
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
public static class Function extends GuavaLambdaConversionRule {
|
public static class Function extends GuavaLambdaConversionRule {
|
||||||
public Function() {
|
public Function() {
|
||||||
super(GuavaLambda.FUNCTION);
|
super(GuavaLambda.FUNCTION);
|
||||||
@@ -70,5 +87,11 @@ public class GuavaLambdaConversionRule extends BaseGuavaTypeConversionRule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class ConvertLambdaClassToJavaClassDescriptor extends TypeConversionDescriptorBase {
|
||||||
|
@Override
|
||||||
|
public PsiExpression replace(PsiExpression expression, @NotNull TypeEvaluator evaluator) throws IncorrectOperationException {
|
||||||
|
return GuavaConversionUtil.tryConvertClassAndSamNameToJava((PsiNewExpression)expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+25
-2
@@ -39,6 +39,14 @@ import java.util.List;
|
|||||||
* @author Dmitry Batkovich
|
* @author Dmitry Batkovich
|
||||||
*/
|
*/
|
||||||
public class GuavaInspectionTest extends JavaCodeInsightFixtureTestCase {
|
public class GuavaInspectionTest extends JavaCodeInsightFixtureTestCase {
|
||||||
|
private GuavaInspection myInspection;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
myInspection = new GuavaInspection();
|
||||||
|
myFixture.enableInspections(myInspection);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getTestDataPath() {
|
protected String getTestDataPath() {
|
||||||
@@ -49,6 +57,7 @@ public class GuavaInspectionTest extends JavaCodeInsightFixtureTestCase {
|
|||||||
protected void tuneFixture(JavaModuleFixtureBuilder moduleBuilder) throws Exception {
|
protected void tuneFixture(JavaModuleFixtureBuilder moduleBuilder) throws Exception {
|
||||||
moduleBuilder.setLanguageLevel(LanguageLevel.JDK_1_8);
|
moduleBuilder.setLanguageLevel(LanguageLevel.JDK_1_8);
|
||||||
moduleBuilder.addLibraryJars("guava", PathManager.getHomePathFor(Assert.class) + "/lib/", "guava-17.0.jar");
|
moduleBuilder.addLibraryJars("guava", PathManager.getHomePathFor(Assert.class) + "/lib/", "guava-17.0.jar");
|
||||||
|
moduleBuilder.addLibraryJars("jsr305", PathManager.getHomePathFor(Assert.class) + "/lib/", "jsr305.jar");
|
||||||
moduleBuilder.addJdk(IdeaTestUtil.getMockJdk18Path().getPath());
|
moduleBuilder.addJdk(IdeaTestUtil.getMockJdk18Path().getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +82,7 @@ public class GuavaInspectionTest extends JavaCodeInsightFixtureTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testFluentIterableChainWithoutVariable() {
|
public void testFluentIterableChainWithoutVariable() {
|
||||||
doTestAllFile();;
|
doTestAllFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testChainedFluentIterableWithChainedInitializer() {
|
public void testChainedFluentIterableWithChainedInitializer() {
|
||||||
@@ -259,9 +268,23 @@ public class GuavaInspectionTest extends JavaCodeInsightFixtureTestCase {
|
|||||||
doTest();
|
doTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for ex: javax.annotations.Nullable is runtime annotation
|
||||||
|
public void testFunctionAnnotatedWithRuntimeAnnotation() {
|
||||||
|
doTestAllFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFunctionAnnotatedWithRuntimeAnnotation2() {
|
||||||
|
try {
|
||||||
|
myInspection.ignoreJavaxNullable = false;
|
||||||
|
doTestAllFile();
|
||||||
|
} finally {
|
||||||
|
myInspection.ignoreJavaxNullable = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void doTestNoQuickFixes(Class<? extends PsiElement>... highlightedElements) {
|
private void doTestNoQuickFixes(Class<? extends PsiElement>... highlightedElements) {
|
||||||
myFixture.configureByFile(getTestName(true) + ".java");
|
myFixture.configureByFile(getTestName(true) + ".java");
|
||||||
myFixture.enableInspections(new GuavaInspection());
|
|
||||||
myFixture.doHighlighting();
|
myFixture.doHighlighting();
|
||||||
for (IntentionAction action : myFixture.getAvailableIntentions()) {
|
for (IntentionAction action : myFixture.getAvailableIntentions()) {
|
||||||
if (action instanceof GuavaInspection.MigrateGuavaTypeFix) {
|
if (action instanceof GuavaInspection.MigrateGuavaTypeFix) {
|
||||||
|
|||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.FluentIterable;
|
||||||
|
import javax.annotations.Nullable;
|
||||||
|
import static com.google.common.collect.FluentIterable.from
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
class A {
|
||||||
|
|
||||||
|
void m(List<String> l) {
|
||||||
|
Function<String, String> function = new Function<String, String>() {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String apply(@Nullable String x) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
boolean strings = FluentIterable.from(l).transform(new Function<String, String>() {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String apply(@Nullable String x) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
}).first().isPresent();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.FluentIterable;
|
||||||
|
import javax.annotations.Nullable;
|
||||||
|
import static com.google.common.collect.FluentIterable.from
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
class A {
|
||||||
|
|
||||||
|
void m(List<String> l) {
|
||||||
|
Function<String, String> function = new Function<String, String>() {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String apply(@Nullable String x) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
boolean strings = FluentIterable.from(l).transform(new Function<String, String>() {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String apply(@Nullable String x) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
}).first().isPresent();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
class A {
|
||||||
|
|
||||||
|
void m(List<String> l) {
|
||||||
|
Function<String, String> function = x -> x;
|
||||||
|
|
||||||
|
boolean strings = l.stream().map(x -> x).findFirst().isPresent();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
class A {
|
||||||
|
|
||||||
|
void m(List<String> l) {
|
||||||
|
Function<String, String> function = x -> x;
|
||||||
|
|
||||||
|
boolean strings = l.stream().map(x -> x).findFirst().isPresent();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+2
-1
@@ -28,6 +28,7 @@ import com.intellij.refactoring.util.LambdaRefactoringUtil;
|
|||||||
import org.jetbrains.annotations.Nls;
|
import org.jetbrains.annotations.Nls;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class TrivialFunctionalExpressionUsageInspection extends BaseJavaBatchLocalInspectionTool {
|
public class TrivialFunctionalExpressionUsageInspection extends BaseJavaBatchLocalInspectionTool {
|
||||||
@@ -73,7 +74,7 @@ public class TrivialFunctionalExpressionUsageInspection extends BaseJavaBatchLoc
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitAnonymousClass(final PsiAnonymousClass aClass) {
|
public void visitAnonymousClass(final PsiAnonymousClass aClass) {
|
||||||
if (AnonymousCanBeLambdaInspection.canBeConvertedToLambda(aClass, false)) {
|
if (AnonymousCanBeLambdaInspection.canBeConvertedToLambda(aClass, false, Collections.emptySet())) {
|
||||||
final PsiElement newExpression = aClass.getParent();
|
final PsiElement newExpression = aClass.getParent();
|
||||||
doCheckMethodCallOnFunctionalExpression(new Condition<PsiElement>() {
|
doCheckMethodCallOnFunctionalExpression(new Condition<PsiElement>() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user