mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-13 09:19:13 +07:00
inspection to highlight and convert pseudo-functional code (like guava Iterables) to java 8 api. initial version
This commit is contained in:
+118
-92
@@ -24,6 +24,7 @@ import com.intellij.codeInsight.intention.HighPriorityAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
@@ -41,6 +42,7 @@ import com.intellij.psi.util.PsiTypesUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.ArrayUtilRt;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import com.intellij.util.containers.hash.LinkedHashMap;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
@@ -207,6 +209,120 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
return false;
|
||||
}
|
||||
|
||||
public static PsiLambdaExpression replacePsiElementWithLambda(@NotNull PsiElement element, final boolean ignoreEqualsMethod) {
|
||||
if (element instanceof PsiNewExpression) {
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return null;
|
||||
final PsiAnonymousClass anonymousClass = ((PsiNewExpression)element).getAnonymousClass();
|
||||
|
||||
LOG.assertTrue(anonymousClass != null);
|
||||
|
||||
ChangeContextUtil.encodeContextInfo(anonymousClass, true);
|
||||
final PsiElement lambdaContext = anonymousClass.getParent().getParent();
|
||||
boolean validContext = LambdaUtil.isValidLambdaContext(lambdaContext);
|
||||
final String canonicalText = anonymousClass.getBaseClassType().getCanonicalText();
|
||||
|
||||
final PsiMethod method;
|
||||
if (ignoreEqualsMethod) {
|
||||
final List<PsiMethod> methods = ContainerUtil.filter(anonymousClass.getMethods(), new Condition<PsiMethod>() {
|
||||
@Override
|
||||
public boolean value(PsiMethod method) {
|
||||
return !"equals".equals(method.getName());
|
||||
}
|
||||
});
|
||||
method = methods.get(0);
|
||||
} else {
|
||||
method = anonymousClass.getMethods()[0];
|
||||
}
|
||||
LOG.assertTrue(method != null);
|
||||
|
||||
final PsiCodeBlock body = method.getBody();
|
||||
LOG.assertTrue(body != null);
|
||||
|
||||
final ForbiddenRefsChecker checker = new ForbiddenRefsChecker(method, anonymousClass);
|
||||
body.accept(checker);
|
||||
|
||||
PsiResolveHelper helper = PsiResolveHelper.SERVICE.getInstance(body.getProject());
|
||||
final Set<PsiLocalVariable> conflictingLocals = checker.getLocals();
|
||||
for (Iterator<PsiLocalVariable> iterator = conflictingLocals.iterator(); iterator.hasNext(); ) {
|
||||
PsiLocalVariable local = iterator.next();
|
||||
final String localName = local.getName();
|
||||
if (localName == null || helper.resolveReferencedVariable(localName, anonymousClass) == null) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
final Project project = element.getProject();
|
||||
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
|
||||
|
||||
ReplaceWithLambdaFix
|
||||
.giveUniqueNames(project, lambdaContext, elementFactory, body, conflictingLocals.toArray(new PsiVariable[conflictingLocals.size()]));
|
||||
|
||||
final String lambdaWithTypesDeclared = ReplaceWithLambdaFix.composeLambdaText(method, true);
|
||||
final String withoutTypesDeclared = ReplaceWithLambdaFix.composeLambdaText(method, false);
|
||||
|
||||
PsiLambdaExpression lambdaExpression =
|
||||
(PsiLambdaExpression)elementFactory.createExpressionFromText(withoutTypesDeclared, anonymousClass);
|
||||
|
||||
PsiElement lambdaBody = lambdaExpression.getBody();
|
||||
LOG.assertTrue(lambdaBody != null);
|
||||
lambdaBody.replace(body);
|
||||
|
||||
ReplaceWithLambdaFix
|
||||
.giveUniqueNames(project, lambdaContext, elementFactory, lambdaExpression, lambdaExpression.getParameterList().getParameters());
|
||||
|
||||
final PsiNewExpression newExpression = (PsiNewExpression)anonymousClass.getParent();
|
||||
lambdaExpression = (PsiLambdaExpression)newExpression.replace(lambdaExpression);
|
||||
final PsiExpression singleExpr = RedundantLambdaCodeBlockInspection.isCodeBlockRedundant(lambdaExpression,
|
||||
lambdaExpression.getBody());
|
||||
if (singleExpr != null) {
|
||||
lambdaExpression.getBody().replace(singleExpr);
|
||||
}
|
||||
ChangeContextUtil.decodeContextInfo(lambdaExpression, null, null);
|
||||
if (!validContext) {
|
||||
final PsiParenthesizedExpression typeCast =
|
||||
(PsiParenthesizedExpression)elementFactory.createExpressionFromText("((" + canonicalText + ")" + withoutTypesDeclared + ")", lambdaExpression);
|
||||
final PsiExpression typeCastExpr = typeCast.getExpression();
|
||||
LOG.assertTrue(typeCastExpr != null);
|
||||
final PsiExpression typeCastOperand = ((PsiTypeCastExpression)typeCastExpr).getOperand();
|
||||
LOG.assertTrue(typeCastOperand != null);
|
||||
final PsiElement fromText = ((PsiLambdaExpression)typeCastOperand).getBody();
|
||||
LOG.assertTrue(fromText != null);
|
||||
lambdaBody = lambdaExpression.getBody();
|
||||
LOG.assertTrue(lambdaBody != null);
|
||||
fromText.replace(lambdaBody);
|
||||
lambdaExpression.replace(typeCast);
|
||||
return lambdaExpression;
|
||||
}
|
||||
|
||||
PsiType interfaceType = lambdaExpression.getFunctionalInterfaceType();
|
||||
if (ReplaceWithLambdaFix.isInferred(lambdaExpression, interfaceType)) {
|
||||
final PsiLambdaExpression withTypes =
|
||||
(PsiLambdaExpression)elementFactory.createExpressionFromText(lambdaWithTypesDeclared, lambdaExpression);
|
||||
final PsiElement withTypesBody = withTypes.getBody();
|
||||
LOG.assertTrue(withTypesBody != null);
|
||||
lambdaBody = lambdaExpression.getBody();
|
||||
LOG.assertTrue(lambdaBody != null);
|
||||
withTypesBody.replace(lambdaBody);
|
||||
lambdaExpression = (PsiLambdaExpression)lambdaExpression.replace(withTypes);
|
||||
|
||||
interfaceType = lambdaExpression.getFunctionalInterfaceType();
|
||||
if (ReplaceWithLambdaFix.isInferred(lambdaExpression, interfaceType)) {
|
||||
final PsiTypeCastExpression typeCast = (PsiTypeCastExpression)elementFactory.createExpressionFromText("(" + canonicalText + ")" + withoutTypesDeclared, lambdaExpression);
|
||||
final PsiExpression typeCastOperand = typeCast.getOperand();
|
||||
LOG.assertTrue(typeCastOperand instanceof PsiLambdaExpression);
|
||||
final PsiElement fromText = ((PsiLambdaExpression)typeCastOperand).getBody();
|
||||
LOG.assertTrue(fromText != null);
|
||||
lambdaBody = lambdaExpression.getBody();
|
||||
LOG.assertTrue(lambdaBody != null);
|
||||
fromText.replace(lambdaBody);
|
||||
lambdaExpression.replace(typeCast);
|
||||
}
|
||||
}
|
||||
return lambdaExpression;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class ReplaceWithLambdaFix implements LocalQuickFix, HighPriorityAction {
|
||||
@NotNull
|
||||
@Override
|
||||
@@ -223,98 +339,8 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
final PsiElement element = descriptor.getPsiElement();
|
||||
if (element instanceof PsiNewExpression) {
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return;
|
||||
final PsiAnonymousClass anonymousClass = ((PsiNewExpression)element).getAnonymousClass();
|
||||
|
||||
LOG.assertTrue(anonymousClass != null);
|
||||
|
||||
ChangeContextUtil.encodeContextInfo(anonymousClass, true);
|
||||
final PsiElement lambdaContext = anonymousClass.getParent().getParent();
|
||||
boolean validContext = LambdaUtil.isValidLambdaContext(lambdaContext);
|
||||
final String canonicalText = anonymousClass.getBaseClassType().getCanonicalText();
|
||||
final PsiMethod method = anonymousClass.getMethods()[0];
|
||||
LOG.assertTrue(method != null);
|
||||
|
||||
final PsiCodeBlock body = method.getBody();
|
||||
LOG.assertTrue(body != null);
|
||||
|
||||
final ForbiddenRefsChecker checker = new ForbiddenRefsChecker(method, anonymousClass);
|
||||
body.accept(checker);
|
||||
|
||||
PsiResolveHelper helper = PsiResolveHelper.SERVICE.getInstance(body.getProject());
|
||||
final Set<PsiLocalVariable> conflictingLocals = checker.getLocals();
|
||||
for (Iterator<PsiLocalVariable> iterator = conflictingLocals.iterator(); iterator.hasNext(); ) {
|
||||
PsiLocalVariable local = iterator.next();
|
||||
final String localName = local.getName();
|
||||
if (localName == null || helper.resolveReferencedVariable(localName, anonymousClass) == null) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
|
||||
|
||||
giveUniqueNames(project, lambdaContext, elementFactory, body, conflictingLocals.toArray(new PsiVariable[conflictingLocals.size()]));
|
||||
|
||||
final String lambdaWithTypesDeclared = composeLambdaText(method, true);
|
||||
final String withoutTypesDeclared = composeLambdaText(method, false);
|
||||
|
||||
PsiLambdaExpression lambdaExpression =
|
||||
(PsiLambdaExpression)elementFactory.createExpressionFromText(withoutTypesDeclared, anonymousClass);
|
||||
|
||||
PsiElement lambdaBody = lambdaExpression.getBody();
|
||||
LOG.assertTrue(lambdaBody != null);
|
||||
lambdaBody.replace(body);
|
||||
|
||||
giveUniqueNames(project, lambdaContext, elementFactory, lambdaExpression, lambdaExpression.getParameterList().getParameters());
|
||||
|
||||
final PsiNewExpression newExpression = (PsiNewExpression)anonymousClass.getParent();
|
||||
lambdaExpression = (PsiLambdaExpression)newExpression.replace(lambdaExpression);
|
||||
final PsiExpression singleExpr = RedundantLambdaCodeBlockInspection.isCodeBlockRedundant(lambdaExpression, lambdaExpression.getBody());
|
||||
if (singleExpr != null) {
|
||||
lambdaExpression.getBody().replace(singleExpr);
|
||||
}
|
||||
ChangeContextUtil.decodeContextInfo(lambdaExpression, null, null);
|
||||
if (!validContext) {
|
||||
final PsiParenthesizedExpression typeCast =
|
||||
(PsiParenthesizedExpression)elementFactory.createExpressionFromText("((" + canonicalText + ")" + withoutTypesDeclared + ")", lambdaExpression);
|
||||
final PsiExpression typeCastExpr = typeCast.getExpression();
|
||||
LOG.assertTrue(typeCastExpr != null);
|
||||
final PsiExpression typeCastOperand = ((PsiTypeCastExpression)typeCastExpr).getOperand();
|
||||
LOG.assertTrue(typeCastOperand != null);
|
||||
final PsiElement fromText = ((PsiLambdaExpression)typeCastOperand).getBody();
|
||||
LOG.assertTrue(fromText != null);
|
||||
lambdaBody = lambdaExpression.getBody();
|
||||
LOG.assertTrue(lambdaBody != null);
|
||||
fromText.replace(lambdaBody);
|
||||
lambdaExpression.replace(typeCast);
|
||||
return;
|
||||
}
|
||||
|
||||
PsiType interfaceType = lambdaExpression.getFunctionalInterfaceType();
|
||||
if (isInferred(lambdaExpression, interfaceType)) {
|
||||
final PsiLambdaExpression withTypes =
|
||||
(PsiLambdaExpression)elementFactory.createExpressionFromText(lambdaWithTypesDeclared, lambdaExpression);
|
||||
final PsiElement withTypesBody = withTypes.getBody();
|
||||
LOG.assertTrue(withTypesBody != null);
|
||||
lambdaBody = lambdaExpression.getBody();
|
||||
LOG.assertTrue(lambdaBody != null);
|
||||
withTypesBody.replace(lambdaBody);
|
||||
lambdaExpression = (PsiLambdaExpression)lambdaExpression.replace(withTypes);
|
||||
|
||||
interfaceType = lambdaExpression.getFunctionalInterfaceType();
|
||||
if (isInferred(lambdaExpression, interfaceType)) {
|
||||
final PsiTypeCastExpression typeCast = (PsiTypeCastExpression)elementFactory.createExpressionFromText("(" + canonicalText + ")" + withoutTypesDeclared, lambdaExpression);
|
||||
final PsiExpression typeCastOperand = typeCast.getOperand();
|
||||
LOG.assertTrue(typeCastOperand instanceof PsiLambdaExpression);
|
||||
final PsiElement fromText = ((PsiLambdaExpression)typeCastOperand).getBody();
|
||||
LOG.assertTrue(fromText != null);
|
||||
lambdaBody = lambdaExpression.getBody();
|
||||
LOG.assertTrue(lambdaBody != null);
|
||||
fromText.replace(lambdaBody);
|
||||
lambdaExpression.replace(typeCast);
|
||||
}
|
||||
}
|
||||
if (element != null) {
|
||||
replacePsiElementWithLambda(element, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+359
@@ -0,0 +1,359 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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.codeInspection.java18StreamApi;
|
||||
|
||||
import com.intellij.codeInspection.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class StaticPseudoFunctionalStyleMethodInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
private final static Logger LOG = Logger.getInstance(StaticPseudoFunctionalStyleMethodInspection.class);
|
||||
|
||||
private StaticPseudoFunctionalStyleMethodOptions myOptions = new StaticPseudoFunctionalStyleMethodOptions();
|
||||
|
||||
|
||||
@Override
|
||||
public void readSettings(@NotNull Element node) throws InvalidDataException {
|
||||
super.readSettings(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeSettings(@NotNull Element node) throws WriteExternalException {
|
||||
super.writeSettings(node);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
|
||||
if (!PsiUtil.isLanguageLevel8OrHigher(holder.getFile())) {
|
||||
return PsiElementVisitor.EMPTY_VISITOR;
|
||||
}
|
||||
return new PsiElementVisitor() {
|
||||
@Override
|
||||
public void visitElement(PsiElement element) {
|
||||
if (element instanceof PsiMethodCallExpression) {
|
||||
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)element;
|
||||
String qName = methodCallExpression.getMethodExpression().getQualifiedName();
|
||||
if (qName == null) {
|
||||
return;
|
||||
}
|
||||
final int dotIndex = qName.lastIndexOf('.');
|
||||
if (dotIndex >= 0) {
|
||||
qName = qName.substring(dotIndex + 1);
|
||||
}
|
||||
final Collection<StaticPseudoFunctionalStyleMethodOptions.PipelineElement> handlerInfos = myOptions.findElementsByMethodName(qName);
|
||||
if (handlerInfos.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
final PsiMethod method = methodCallExpression.resolveMethod();
|
||||
if (method == null) {
|
||||
return;
|
||||
}
|
||||
final PsiClass aClass = method.getContainingClass();
|
||||
if (aClass == null) {
|
||||
return;
|
||||
}
|
||||
final String classQualifiedName = aClass.getQualifiedName();
|
||||
if (classQualifiedName == null) {
|
||||
return;
|
||||
}
|
||||
StaticPseudoFunctionalStyleMethodOptions.PipelineElement suitableHandler = null;
|
||||
for (StaticPseudoFunctionalStyleMethodOptions.PipelineElement h : handlerInfos) {
|
||||
if (h.getHandlerClass().equals(classQualifiedName)) {
|
||||
suitableHandler = h;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (suitableHandler == null) {
|
||||
return;
|
||||
}
|
||||
final int lambdaIndex = validateMethodParameters(methodCallExpression, method);
|
||||
if (lambdaIndex != -1) {
|
||||
holder.registerProblem(methodCallExpression.getMethodExpression(), "",
|
||||
new ReplacePseudoLambdaWithLambda(lambdaIndex, methodCallExpression, method, suitableHandler));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static class ReplacePseudoLambdaWithLambda implements LocalQuickFix {
|
||||
private final int myLambdaIndex;
|
||||
private final SmartPsiElementPointer<PsiMethod> myMethodPointer;
|
||||
private final StaticPseudoFunctionalStyleMethodOptions.PipelineElement mySuitableHandler;
|
||||
|
||||
private ReplacePseudoLambdaWithLambda(int lambdaIndex,
|
||||
@NotNull PsiMethodCallExpression expression,
|
||||
@NotNull PsiMethod method,
|
||||
@NotNull StaticPseudoFunctionalStyleMethodOptions.PipelineElement suitableHandler) {
|
||||
myLambdaIndex = lambdaIndex;
|
||||
myMethodPointer = SmartPointerManager.getInstance(expression.getProject()).createSmartPsiElementPointer(method);
|
||||
mySuitableHandler = suitableHandler;
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return getFamilyName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return "Replace with Java Stream API pipeline";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
PsiMethodCallExpression expression = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiMethodCallExpression.class);
|
||||
LOG.assertTrue(expression != null);
|
||||
final PsiExpression[] expressions = expression.getArgumentList().getExpressions();
|
||||
PsiExpression lambdaExpression = expressions[myLambdaIndex];
|
||||
lambdaExpression = convertToJavaLambda(lambdaExpression, mySuitableHandler.getStreamApiMethodName());
|
||||
LOG.assertTrue(lambdaExpression != null);
|
||||
|
||||
final PsiExpression collectionExpression = expressions[(1 + myLambdaIndex) % 2];
|
||||
final String pipelineHead = createPipelineHeadText(collectionExpression);
|
||||
|
||||
final String patternForFake =
|
||||
StreamApiConstants.FAKE_STREAM_API_METHODS_TO_PATTERN.getValue().get(mySuitableHandler.getStreamApiMethodName());
|
||||
|
||||
final String lambdaExpressionText;
|
||||
final String elementText;
|
||||
if (patternForFake == null) {
|
||||
elementText = mySuitableHandler.getStreamApiMethodName();
|
||||
lambdaExpressionText = lambdaExpression.getText();
|
||||
}
|
||||
else {
|
||||
elementText = String.format(patternForFake, lambdaExpression.getText());
|
||||
lambdaExpressionText = null;
|
||||
}
|
||||
|
||||
final String pipelineTail =
|
||||
StreamApiConstants.STREAM_STREAM_API_METHODS.getValue().contains(mySuitableHandler.getStreamApiMethodName())
|
||||
? findSuitableTailMethodForCollection(myMethodPointer.getElement())
|
||||
: null;
|
||||
|
||||
final PsiElement replaced =
|
||||
expression.replace(createPipelineExpression(pipelineHead, elementText, lambdaExpressionText, pipelineTail, project));
|
||||
JavaCodeStyleManager.getInstance(project).shortenClassReferences(replaced.getParent());
|
||||
}
|
||||
|
||||
private static String createPipelineHeadText(PsiExpression collectionExpression) {
|
||||
final PsiType type = collectionExpression.getType();
|
||||
if (type instanceof PsiClassType) {
|
||||
final PsiClass resolved = ((PsiClassType)type).resolve();
|
||||
LOG.assertTrue(resolved != null && resolved.getQualifiedName() != null);
|
||||
return collectionExpression.getText() + ".stream()";
|
||||
}
|
||||
else if (type instanceof PsiArrayType) {
|
||||
return CommonClassNames.JAVA_UTIL_ARRAYS + ".stream(" + collectionExpression.getText() + ")";
|
||||
}
|
||||
throw new AssertionError("type: " + type + " is unexpected");
|
||||
}
|
||||
|
||||
private static PsiExpression createPipelineExpression(String pipelineHead,
|
||||
String elementText,
|
||||
String lambdaExpression,
|
||||
String pipelineTail,
|
||||
Project project) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(pipelineHead).append(".").append(elementText);
|
||||
if (lambdaExpression != null) {
|
||||
sb.append("(").append(lambdaExpression).append(")");
|
||||
}
|
||||
if (pipelineTail != null) {
|
||||
sb.append(".").append(pipelineTail);
|
||||
}
|
||||
return JavaPsiFacade.getElementFactory(project).createExpressionFromText(sb.toString(), null);
|
||||
}
|
||||
}
|
||||
|
||||
private static int validateMethodParameters(final PsiMethodCallExpression methodCallExpression, final PsiMethod method) {
|
||||
final PsiType[] argumentTypes = methodCallExpression.getArgumentList().getExpressionTypes();
|
||||
final PsiParameter[] expectedParameters = method.getParameterList().getParameters();
|
||||
if (argumentTypes.length != expectedParameters.length || expectedParameters.length != 2) {
|
||||
return -1;
|
||||
}
|
||||
final int collectionOrArrayIndex = findCollectionOrArrayPlacement(expectedParameters);
|
||||
if (collectionOrArrayIndex == -1) {
|
||||
return -1;
|
||||
}
|
||||
return (1 + collectionOrArrayIndex) % 2;
|
||||
}
|
||||
|
||||
private static int findCollectionOrArrayPlacement(final PsiParameter[] parameters) {
|
||||
for (int i = 0, length = parameters.length; i < length; i++) {
|
||||
PsiParameter parameter = parameters[i];
|
||||
final PsiType type = parameter.getType();
|
||||
if (type instanceof PsiClassType || type instanceof PsiArrayType) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static PsiExpression convertToJavaLambda(final PsiExpression expression, String streamApiMethodName) {
|
||||
if (expression instanceof PsiLambdaExpression) {
|
||||
return expression;
|
||||
}
|
||||
if (expression instanceof PsiMethodCallExpression) {
|
||||
final PsiMethod method = ((PsiMethodCallExpression)expression).resolveMethod();
|
||||
if (method == null) {
|
||||
return null;
|
||||
}
|
||||
final PsiType type = method.getReturnType();
|
||||
if (!(type instanceof PsiClassType)) {
|
||||
return null;
|
||||
}
|
||||
final PsiClass lambdaClass = ((PsiClassType)type).resolve();
|
||||
if (lambdaClass == null) {
|
||||
return null;
|
||||
}
|
||||
final String methodName = lambdaClass.getMethods()[0].getName();
|
||||
if (tryConvertLambdaToStreamApi(method, resolveStreamApiLambdaClass(expression.getProject(), streamApiMethodName))) {
|
||||
return expression;
|
||||
}
|
||||
else {
|
||||
return JavaPsiFacade.getElementFactory(expression.getProject())
|
||||
.createExpressionFromText(expression.getText() + "::" + methodName, null);
|
||||
}
|
||||
}
|
||||
return AnonymousCanBeLambdaInspection.replacePsiElementWithLambda(expression, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiClass resolveStreamApiLambdaClass(Project project, String streamApiMethodName) {
|
||||
final PsiClass javaUtilStream = JavaPsiFacade.getInstance(project)
|
||||
.findClass(StreamApiConstants.JAVA_UTIL_STREAM_STREAM, GlobalSearchScope.notScope(GlobalSearchScope.projectScope(project)));
|
||||
LOG.assertTrue(javaUtilStream != null);
|
||||
final PsiMethod[] methods = javaUtilStream.findMethodsByName(streamApiMethodName, false);
|
||||
LOG.assertTrue(methods.length == 1);
|
||||
final PsiMethod method = methods[0];
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
LOG.assertTrue(parameters.length == 1);
|
||||
final PsiType type = parameters[0].getType();
|
||||
LOG.assertTrue(type instanceof PsiClassType);
|
||||
final PsiClass resolved = ((PsiClassType)type).resolve();
|
||||
LOG.assertTrue(resolved != null);
|
||||
return resolved;
|
||||
}
|
||||
|
||||
private static boolean tryConvertLambdaToStreamApi(final PsiMethod method, final PsiClass expectedReturnClass) {
|
||||
final PsiCodeBlock body = method.getBody();
|
||||
Collection<PsiReturnStatement> returnStatements = PsiTreeUtil.findChildrenOfType(body, PsiReturnStatement.class);
|
||||
returnStatements = ContainerUtil.filter(returnStatements, new Condition<PsiReturnStatement>() {
|
||||
@Override
|
||||
public boolean value(PsiReturnStatement statement) {
|
||||
return PsiTreeUtil.getParentOfType(statement, PsiMethod.class) == method;
|
||||
}
|
||||
});
|
||||
if (returnStatements.size() != 1) {
|
||||
return false;
|
||||
}
|
||||
final PsiReturnStatement returnStatement = ContainerUtil.getFirstItem(returnStatements);
|
||||
assert returnStatement != null;
|
||||
final PsiExpression returnValue = returnStatement.getReturnValue();
|
||||
if (returnValue instanceof PsiNewExpression) {
|
||||
convertNewExpression(method, (PsiNewExpression)returnValue, expectedReturnClass);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void convertNewExpression(PsiMethod containingMethod, PsiNewExpression newExpression, PsiClass expectedReturnClass) {
|
||||
final String expectedReturnQName = expectedReturnClass.getQualifiedName();
|
||||
LOG.assertTrue(expectedReturnQName != null);
|
||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(newExpression.getProject());
|
||||
PsiAnonymousClass anonymousClass = PsiTreeUtil.findChildOfType(newExpression, PsiAnonymousClass.class);
|
||||
LOG.assertTrue(anonymousClass != null);
|
||||
PsiJavaCodeReferenceElement referenceElement = PsiTreeUtil.findChildOfType(anonymousClass, PsiJavaCodeReferenceElement.class);
|
||||
LOG.assertTrue(referenceElement != null);
|
||||
final PsiReferenceParameterList parameterList = PsiTreeUtil.findChildOfType(referenceElement, PsiReferenceParameterList.class);
|
||||
final PsiJavaCodeReferenceElement newCodeReferenceElement = factory.createReferenceFromText(expectedReturnClass.getQualifiedName()
|
||||
+
|
||||
(parameterList == null
|
||||
? ""
|
||||
: parameterList.getText()), null);
|
||||
referenceElement.replace(newCodeReferenceElement);
|
||||
final List<PsiMethod> methods = ContainerUtil.filter(anonymousClass.getMethods(), new Condition<PsiMethod>() {
|
||||
@Override
|
||||
public boolean value(PsiMethod method) {
|
||||
return !"equals".equals(method.getName());
|
||||
}
|
||||
});
|
||||
LOG.assertTrue(methods.size() == 1, methods);
|
||||
final PsiMethod method = methods.get(0);
|
||||
method.setName(expectedReturnClass.getMethods()[0].getName());
|
||||
final PsiTypeElement element = containingMethod.getReturnTypeElement();
|
||||
if (element != null) {
|
||||
final PsiReferenceParameterList genericParameter = PsiTreeUtil.findChildOfType(element, PsiReferenceParameterList.class);
|
||||
element.replace(factory.createTypeElementFromText(expectedReturnQName + (genericParameter == null ? "" : genericParameter.getText()), null));
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String findSuitableTailMethodForCollection(PsiMethod lambdaHandler) {
|
||||
final PsiType type = lambdaHandler.getReturnType();
|
||||
if (type instanceof PsiArrayType) {
|
||||
return "toArray(String[]::new)";
|
||||
}
|
||||
else if (type instanceof PsiClassType) {
|
||||
final PsiClass resolvedClass = ((PsiClassType)type).resolve();
|
||||
if (resolvedClass == null) {
|
||||
return null;
|
||||
}
|
||||
final String qName = resolvedClass.getQualifiedName();
|
||||
if (qName == null) {
|
||||
return null;
|
||||
}
|
||||
if (qName.equals(CommonClassNames.JAVA_UTIL_LIST)
|
||||
|| qName.equals(CommonClassNames.JAVA_UTIL_COLLECTION)
|
||||
|| qName.equals(CommonClassNames.JAVA_LANG_ITERABLE)) {
|
||||
return "collect(" + StreamApiConstants.JAVA_UTIL_STREAM_COLLECTORS + ".toList())";
|
||||
}
|
||||
else if (qName.equals(CommonClassNames.JAVA_UTIL_SET)) {
|
||||
return "collect(" + StreamApiConstants.JAVA_UTIL_STREAM_COLLECTORS + ".toSet())";
|
||||
}
|
||||
else if (qName.equals(CommonClassNames.JAVA_UTIL_ITERATOR)) {
|
||||
return "iterator()";
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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.codeInspection.java18StreamApi;
|
||||
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class StaticPseudoFunctionalStyleMethodOptions {
|
||||
private final MultiMap<String, PipelineElement> myIndex;
|
||||
|
||||
public StaticPseudoFunctionalStyleMethodOptions() {
|
||||
myIndex = new MultiMap<String, PipelineElement>();
|
||||
restoreDefault();
|
||||
}
|
||||
|
||||
public static class PipelineElement {
|
||||
private final String myHandlerClass;
|
||||
private final String myMethodName;
|
||||
private final String myStreamApiMethod;
|
||||
|
||||
public PipelineElement(String handlerClass, String methodName, @Nullable String streamApiMethod) {
|
||||
myHandlerClass = handlerClass;
|
||||
myMethodName = methodName;
|
||||
myStreamApiMethod = streamApiMethod;
|
||||
}
|
||||
|
||||
public String getHandlerClass() {
|
||||
return myHandlerClass;
|
||||
}
|
||||
|
||||
public String getMethodName() {
|
||||
return myMethodName;
|
||||
}
|
||||
|
||||
public String getStreamApiMethodName() {
|
||||
return myStreamApiMethod;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<PipelineElement> findElementsByMethodName(final String methodName) {
|
||||
return myIndex.get(methodName);
|
||||
}
|
||||
|
||||
public void addElement(PipelineElement element) {
|
||||
myIndex.putValue(element.getMethodName(), element);
|
||||
}
|
||||
|
||||
public void readExternal(final @NotNull Element element) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void writeExternal(final @NotNull Element element) {
|
||||
|
||||
}
|
||||
|
||||
private void restoreDefault() {
|
||||
myIndex.clear();
|
||||
final String guavaIterables = "com.google.common.collect.Iterables";
|
||||
addElement(new PipelineElement(guavaIterables, "transform", StreamApiConstants.MAP));
|
||||
addElement(new PipelineElement(guavaIterables, "filter", StreamApiConstants.FILTER));
|
||||
addElement(new PipelineElement(guavaIterables, "find", StreamApiConstants.FAKE_FIND_MATCHED));
|
||||
addElement(new PipelineElement(guavaIterables, "all", StreamApiConstants.ALL_MATCH));
|
||||
addElement(new PipelineElement(guavaIterables, "any", StreamApiConstants.ANY_MATCH));
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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.codeInspection.java18StreamApi;
|
||||
|
||||
import com.intellij.reference.SoftLazyValue;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.hash.HashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public interface StreamApiConstants {
|
||||
String JAVA_UTIL_STREAM_STREAM = "java.util.stream.Stream";
|
||||
|
||||
String ANY_MATCH = "anyMatch";
|
||||
String ALL_MATCH = "allMatch";
|
||||
String MAP = "map";
|
||||
String FILTER = "filter";
|
||||
|
||||
String FAKE_FIND_MATCHED = "#findMatched";
|
||||
String FAKE_FIND_MATCHED_PATTERN = "filter(%s).findFirst().get()";
|
||||
|
||||
String JAVA_UTIL_STREAM_COLLECTORS = "java.util.stream.Collectors";
|
||||
|
||||
SoftLazyValue<Set<String>> STREAM_STREAM_API_METHODS = new SoftLazyValue<Set<String>>() {
|
||||
@NotNull
|
||||
@Override
|
||||
protected Set<String> compute() {
|
||||
return ContainerUtil.newHashSet(MAP, FILTER);
|
||||
}
|
||||
};
|
||||
|
||||
SoftLazyValue<Map<String, String>> FAKE_STREAM_API_METHODS_TO_PATTERN = new SoftLazyValue<Map<String, String>>() {
|
||||
@NotNull
|
||||
@Override
|
||||
protected Map<String, String> compute() {
|
||||
final HashMap<String, String> map = new HashMap<String, String>();
|
||||
map.put(FAKE_FIND_MATCHED, FAKE_FIND_MATCHED_PATTERN);
|
||||
return map;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import java.lang.String;
|
||||
import java.util.Collections;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
Iterables.al<caret>l(Collections.emptyList(), getPredicate(100));
|
||||
}
|
||||
|
||||
public Predicate<String> getPredicate(final int param) {
|
||||
return new Predicate<String>() {
|
||||
@Override
|
||||
public boolean apply(String input) {
|
||||
System.out.println("lambda param " + param);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import java.lang.String;
|
||||
import java.util.Collections;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
Collections.emptyList().stream().allMatch(getPredicate(100));
|
||||
}
|
||||
|
||||
public java.util.function.Predicate<String> getPredicate(final int param) {
|
||||
return new java.util.function.Predicate<String>() {
|
||||
@Override
|
||||
public boolean test(String input) {
|
||||
System.out.println("lambda param " + param);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import java.lang.String;
|
||||
import java.util.Collections;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
Iterables.al<caret>l(Collections.emptyList(), getPredicate(100));
|
||||
}
|
||||
|
||||
public Predicate<String> getPredicate(final int param) {
|
||||
final MyComplexPredicate predicate = new MyComplexPredicate(param);
|
||||
predicate.setParam2(200);
|
||||
return predicate;
|
||||
}
|
||||
|
||||
class MyComplexPredicate extends Predicate<String> {
|
||||
int param;
|
||||
int param2;
|
||||
|
||||
public MyComplexPredicate(int param) {
|
||||
this.param = param;
|
||||
}
|
||||
|
||||
public void setParam2(int param2) {
|
||||
this.param2 = param2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(String input) {
|
||||
System.out.println("lambda param " + param);
|
||||
doMagic();
|
||||
return false;
|
||||
}
|
||||
|
||||
private void doMagic() {
|
||||
//do something
|
||||
}
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import java.lang.String;
|
||||
import java.util.Collections;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
Collections.emptyList().stream().allMatch(getPredicate(100)::apply);
|
||||
}
|
||||
|
||||
public Predicate<String> getPredicate(final int param) {
|
||||
final MyComplexPredicate predicate = new MyComplexPredicate(param);
|
||||
predicate.setParam2(200);
|
||||
return predicate;
|
||||
}
|
||||
|
||||
class MyComplexPredicate extends Predicate<String> {
|
||||
int param;
|
||||
int param2;
|
||||
|
||||
public MyComplexPredicate(int param) {
|
||||
this.param = param;
|
||||
}
|
||||
|
||||
public void setParam2(int param2) {
|
||||
this.param2 = param2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(String input) {
|
||||
System.out.println("lambda param " + param);
|
||||
doMagic();
|
||||
return false;
|
||||
}
|
||||
|
||||
private void doMagic() {
|
||||
//do something
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
|
||||
import java.lang.String;
|
||||
import java.util.Collections;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
Iterables.al<caret>l(Collections.<String>emptyList(), getPredicate(100));
|
||||
}
|
||||
|
||||
public Predicate<String> getPredicate(final int param) {
|
||||
return Predicates.not(new Predicate<String>() {
|
||||
@Override
|
||||
public boolean apply(String input) {
|
||||
System.out.println("lambda param " + param);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
|
||||
import java.lang.String;
|
||||
import java.util.Collections;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
Collections.<String>emptyList().stream().allMatch(getPredicate(100)::apply);
|
||||
}
|
||||
|
||||
public Predicate<String> getPredicate(final int param) {
|
||||
return Predicates.not(new Predicate<String>() {
|
||||
@Override
|
||||
public boolean apply(String input) {
|
||||
System.out.println("lambda param " + param);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import java.lang.String;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
List<String> l = new ArrayList<>();
|
||||
Iterable<Boolean> transform = Iterables.tr<caret>ansform(l, new Function<String, Boolean>() {
|
||||
@Override
|
||||
public Boolean apply(String input) {
|
||||
return input.isEmpty();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import java.lang.String;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
List<String> l = new ArrayList<>();
|
||||
Iterable<Boolean> transform = l.stream().map(String::isEmpty).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import java.lang.String;
|
||||
import java.util.Collections;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
Iterables.al<caret>l(Collections.emptyList(), in -> false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import java.lang.String;
|
||||
import java.util.Collections;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
Collections.emptyList().stream().allMatch(in -> false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import java.lang.String;
|
||||
import java.util.Collections;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
Iterables.an<caret>y(Collections.emptyList(), in -> false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import java.lang.String;
|
||||
import java.util.Collections;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
Collections.emptyList().stream().anyMatch(in -> false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import java.lang.String;
|
||||
import java.util.Collections;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
Iterables.fil<caret>ter(Collections.emptyList(), new Predicate<Object>() {
|
||||
@Override
|
||||
public boolean apply(Object input) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import java.lang.String;
|
||||
import java.util.Collections;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
Collections.emptyList().stream().filter(input -> true).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import java.lang.String;
|
||||
import java.util.Collections;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
Iterables.f<caret>ind(Collections.emptyList(), new Predicate<Object>() {
|
||||
@Override
|
||||
public boolean apply(Object input) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import java.lang.String;
|
||||
import java.util.Collections;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
Collections.emptyList().stream().filter(input -> true).findFirst().get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.base.Function;
|
||||
|
||||
import java.lang.String;
|
||||
import java.util.Collections;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
Iterables.transf<caret>orm(Collections.emptyList(), new Function<String, String> () {
|
||||
@Override
|
||||
public String apply(String input) {
|
||||
java.util.stream.Collectors c;
|
||||
java.util.ArrayList l;
|
||||
System.out.println(input);
|
||||
//do something
|
||||
int i = 1;
|
||||
return input;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.base.Function;
|
||||
|
||||
import java.lang.String;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class c {
|
||||
void m() {
|
||||
Collections.emptyList().stream().map(input -> {
|
||||
Collectors c;
|
||||
ArrayList l;
|
||||
System.out.println(input);
|
||||
//do something
|
||||
int i = 1;
|
||||
return input;
|
||||
}).collect(Collectors.toList())
|
||||
}
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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.codeInspection;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInspection.ex.QuickFixWrapper;
|
||||
import com.intellij.codeInspection.java18StreamApi.StaticPseudoFunctionalStyleMethodInspection;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class StaticPseudoFunctionalStyleMethodTest extends JavaCodeInsightFixtureTestCase {
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return JavaTestUtil.getJavaTestDataPath() + "/inspection/lambdaLibsStatic";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tuneFixture(JavaModuleFixtureBuilder moduleBuilder) throws Exception {
|
||||
moduleBuilder.setLanguageLevel(LanguageLevel.JDK_1_8);
|
||||
moduleBuilder.addLibraryJars("guava-17.0.jar", PathManager.getHomePath().replace(File.separatorChar, '/') + "/community/lib/",
|
||||
"guava-17.0.jar");
|
||||
moduleBuilder.addJdk(IdeaTestUtil.getMockJdk18Path().getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testSimpleTransform() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testSimpleFilter() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testSimpleFind() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testSimpleAll() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testSimpleAny() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testLambdaIsntAnonymous() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testLambdaIsntAnonymous2() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testLambdaIsntAnonymous3() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void _testReplaceWithMethodReference() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
myFixture.configureByFile(getTestName(true) + "/test.java");
|
||||
myFixture.enableInspections(new StaticPseudoFunctionalStyleMethodInspection());
|
||||
boolean isQuickFixFound = false;
|
||||
for (IntentionAction action : myFixture.getAvailableIntentions()) {
|
||||
if (action instanceof QuickFixWrapper) {
|
||||
final LocalQuickFix fix = ((QuickFixWrapper)action).getFix();
|
||||
if (fix instanceof StaticPseudoFunctionalStyleMethodInspection.ReplacePseudoLambdaWithLambda) {
|
||||
myFixture.launchAction(action);
|
||||
isQuickFixFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
assertTrue(isQuickFixFound);
|
||||
myFixture.checkResultByFile(getTestName(true) + "/test_after.java");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
Inspection detects usages of pseudo-lambda code if Java Stream API is available (language level >= Java 1.8)
|
||||
</body>
|
||||
</html>
|
||||
@@ -718,6 +718,11 @@
|
||||
groupName="Code style issues" enabledByDefault="false" level="WARNING"
|
||||
implementationClass="com.intellij.codeInspection.BlockMarkerCommentsInspection"
|
||||
displayName="Block marker comment"/>
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="StaticPseudoFunctionalStyleMethod"
|
||||
groupBundle="messages.InspectionsBundle"
|
||||
groupName="Code style issues" enabledByDefault="false" level="WARNING"
|
||||
implementationClass="com.intellij.codeInspection.java18StreamApi.StaticPseudoFunctionalStyleMethodInspection"
|
||||
displayName="Pseudo functional expression using static class"/>
|
||||
|
||||
<intentionAction>
|
||||
<className>com.intellij.codeInsight.daemon.quickFix.RedundantLambdaParameterTypeIntention</className>
|
||||
|
||||
Reference in New Issue
Block a user