mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
StaticPseudoFunctionalStyleMethodInspection: Inspection to replace old pseudo functional code with stream api. added options to create custom templates. Tests fixed. Description improved. Moved to java-impl module
This commit is contained in:
+1
-1
@@ -85,7 +85,7 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected static PsiCallExpression canBeMethodReferenceProblem(@Nullable final PsiElement body,
|
||||
public static PsiCallExpression canBeMethodReferenceProblem(@Nullable final PsiElement body,
|
||||
final PsiParameter[] parameters,
|
||||
PsiType functionalInterfaceType) {
|
||||
final PsiCallExpression callExpression = extractMethodCallFromBlock(body);
|
||||
|
||||
-87
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* 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));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.codeInspection.java18StreamApi.AddMethodsDialog">
|
||||
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="500" height="400"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="5c4b9" class="com.intellij.ui.components.JBLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Fully qualified class name:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<vspacer id="c8137">
|
||||
<constraints>
|
||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<component id="c43e4" class="com.intellij.ui.components.JBLabel">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Method name:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="f01fe" class="com.intellij.ui.components.JBLabel">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Stream API replacement:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="1f7b6" class="com.intellij.openapi.ui.ComboBox" binding="myPatternsCombo">
|
||||
<constraints>
|
||||
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<component id="7bc3f" class="com.intellij.refactoring.ui.ClassNameReferenceEditor" binding="myClassNameEditor" custom-create="true" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<component id="f7881" class="com.intellij.openapi.ui.ComboBox" binding="myMethodNameCombo">
|
||||
<constraints>
|
||||
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.event.DocumentAdapter;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.ComboBox;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.refactoring.ui.ClassNameReferenceEditor;
|
||||
import com.intellij.ui.ColoredListCellRenderer;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class AddMethodsDialog extends DialogWrapper {
|
||||
private final static Logger LOG = Logger.getInstance(AddMethodsDialog.class);
|
||||
@NotNull private final Project myProject;
|
||||
|
||||
private JPanel myPanel;
|
||||
private ComboBox myPatternsCombo;
|
||||
private ClassNameReferenceEditor myClassNameEditor;
|
||||
private ComboBox myMethodNameCombo;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected AddMethodsDialog(@NotNull final Project project, @NotNull final Component parent, boolean canBeParent) {
|
||||
super(parent, canBeParent);
|
||||
myProject = project;
|
||||
final DefaultComboBoxModel model = new DefaultComboBoxModel();
|
||||
myPatternsCombo.setModel(model);
|
||||
for (String methodName : StreamApiConstants.STREAM_STREAM_API_METHODS.getValue()) {
|
||||
model.addElement(methodName);
|
||||
}
|
||||
for (String fakeMethodName : StreamApiConstants.FAKE_STREAM_API_METHODS_TO_PATTERN.getValue().keySet()) {
|
||||
model.addElement(fakeMethodName);
|
||||
}
|
||||
myPatternsCombo.setRenderer(new ColoredListCellRenderer<String>() {
|
||||
@Override
|
||||
protected void customizeCellRenderer(JList list, String methodName, int index, boolean selected, boolean hasFocus) {
|
||||
append("stream.");
|
||||
if (StreamApiConstants.STREAM_STREAM_API_METHODS.getValue().contains(methodName)) {
|
||||
append(methodName + "()", SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
|
||||
}
|
||||
else {
|
||||
String pattern = StreamApiConstants.FAKE_STREAM_API_METHODS_TO_PATTERN.getValue().get(methodName);
|
||||
LOG.assertTrue(pattern != null);
|
||||
append(String.format(pattern, ""), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
|
||||
}
|
||||
}
|
||||
});
|
||||
myMethodNameCombo.setModel(new DefaultComboBoxModel());
|
||||
myClassNameEditor.addDocumentListener(new DocumentAdapter() {
|
||||
@Override
|
||||
public void documentChanged(DocumentEvent e) {
|
||||
final String classFqn = e.getDocument().getText();
|
||||
final PsiClass aClass = JavaPsiFacade.getInstance(project).findClass(classFqn, GlobalSearchScope.allScope(project));
|
||||
final DefaultComboBoxModel comboBoxModel = (DefaultComboBoxModel)myMethodNameCombo.getModel();
|
||||
comboBoxModel.removeAllElements();
|
||||
if (aClass == null) {
|
||||
myMethodNameCombo.setEnabled(false);
|
||||
}
|
||||
else {
|
||||
for (String name : ContainerUtil.newTreeSet(ContainerUtil.mapNotNull(aClass.getMethods(), new Function<PsiMethod, String>() {
|
||||
@Override
|
||||
public String fun(PsiMethod method) {
|
||||
if (method.isConstructor() ||
|
||||
!method.hasModifierProperty(PsiModifier.STATIC) ||
|
||||
method.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
return null;
|
||||
}
|
||||
return method.getName();
|
||||
}
|
||||
}))) {
|
||||
comboBoxModel.addElement(name);
|
||||
}
|
||||
myMethodNameCombo.setEnabled(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
init();
|
||||
}
|
||||
|
||||
private void createUIComponents() {
|
||||
myClassNameEditor = new ClassNameReferenceEditor(myProject, null);
|
||||
}
|
||||
|
||||
public StaticPseudoFunctionalStyleMethodOptions.PipelineElement getSelectedElement() {
|
||||
return new StaticPseudoFunctionalStyleMethodOptions.PipelineElement(myClassNameEditor.getText(),
|
||||
(String)myMethodNameCombo.getSelectedItem(),
|
||||
(String)myPatternsCombo.getSelectedItem());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected JComponent createCenterPanel() {
|
||||
return myPanel;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myClassNameEditor;
|
||||
}
|
||||
}
|
||||
+21
-7
@@ -32,6 +32,7 @@ import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@@ -40,18 +41,22 @@ import java.util.List;
|
||||
*/
|
||||
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);
|
||||
myOptions.readExternal(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeSettings(@NotNull Element node) throws WriteExternalException {
|
||||
super.writeSettings(node);
|
||||
myOptions.writeExternal(node);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JComponent createOptionsPanel() {
|
||||
return myOptions.createPanel();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -226,7 +231,7 @@ public class StaticPseudoFunctionalStyleMethodInspection extends BaseJavaBatchLo
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static PsiExpression convertToJavaLambda(final PsiExpression expression, String streamApiMethodName) {
|
||||
private static PsiExpression convertToJavaLambda(PsiExpression expression, String streamApiMethodName) {
|
||||
if (expression instanceof PsiLambdaExpression) {
|
||||
return expression;
|
||||
}
|
||||
@@ -244,7 +249,7 @@ public class StaticPseudoFunctionalStyleMethodInspection extends BaseJavaBatchLo
|
||||
return null;
|
||||
}
|
||||
final String methodName = lambdaClass.getMethods()[0].getName();
|
||||
if (tryConvertLambdaToStreamApi(method, resolveStreamApiLambdaClass(expression.getProject(), streamApiMethodName))) {
|
||||
if (tryConvertPseudoLambdaToStreamApi(method, resolveStreamApiLambdaClass(expression.getProject(), streamApiMethodName))) {
|
||||
return expression;
|
||||
}
|
||||
else {
|
||||
@@ -272,7 +277,16 @@ public class StaticPseudoFunctionalStyleMethodInspection extends BaseJavaBatchLo
|
||||
return resolved;
|
||||
}
|
||||
|
||||
private static boolean tryConvertLambdaToStreamApi(final PsiMethod method, final PsiClass expectedReturnClass) {
|
||||
private static boolean tryConvertPseudoLambdaToStreamApi(final @NotNull PsiMethod method, final @NotNull PsiClass expectedReturnClass) {
|
||||
final PsiType currentReturnType = method.getReturnType();
|
||||
if (!(currentReturnType instanceof PsiClassType)) {
|
||||
LOG.error("pseudo-lambda return type must be class " + currentReturnType);
|
||||
return true;
|
||||
}
|
||||
final PsiClass resolvedCurrentReturnType = ((PsiClassType)currentReturnType).resolve();
|
||||
if (expectedReturnClass.getManager().areElementsEquivalent(expectedReturnClass, resolvedCurrentReturnType)) {
|
||||
return true;
|
||||
}
|
||||
final PsiCodeBlock body = method.getBody();
|
||||
Collection<PsiReturnStatement> returnStatements = PsiTreeUtil.findChildrenOfType(body, PsiReturnStatement.class);
|
||||
returnStatements = ContainerUtil.filter(returnStatements, new Condition<PsiReturnStatement>() {
|
||||
+230
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* 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.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.LangDataKeys;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.components.JBList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ListDataListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class StaticPseudoFunctionalStyleMethodOptions {
|
||||
private static final String PIPELINE_ELEMENT_NAME = "pipelineElement";
|
||||
private static final String FQN_ATTR = "classFqn";
|
||||
private static final String METHOD_ATTR = "method";
|
||||
private static final String STREAM_API_METHOD_ATTR = "streamApiMethod";
|
||||
private static final String DELETE_ATTR = "toDelete";
|
||||
private final List<PipelineElement> myElements;
|
||||
|
||||
public StaticPseudoFunctionalStyleMethodOptions() {
|
||||
myElements = new ArrayList<PipelineElement>();
|
||||
restoreDefault(myElements);
|
||||
}
|
||||
|
||||
private static void restoreDefault(final List<PipelineElement> elements) {
|
||||
elements.clear();
|
||||
final String guavaIterables = "com.google.common.collect.Iterables";
|
||||
elements.add(new PipelineElement(guavaIterables, "transform", StreamApiConstants.MAP));
|
||||
elements.add(new PipelineElement(guavaIterables, "filter", StreamApiConstants.FILTER));
|
||||
elements.add(new PipelineElement(guavaIterables, "find", StreamApiConstants.FAKE_FIND_MATCHED));
|
||||
elements.add(new PipelineElement(guavaIterables, "all", StreamApiConstants.ALL_MATCH));
|
||||
elements.add(new PipelineElement(guavaIterables, "any", StreamApiConstants.ANY_MATCH));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<PipelineElement> findElementsByMethodName(final @NotNull String methodName) {
|
||||
return ContainerUtil.filter(myElements, new Condition<PipelineElement>() {
|
||||
@Override
|
||||
public boolean value(PipelineElement element) {
|
||||
return methodName.equals(element.getMethodName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void readExternal(final @NotNull Element xmlElement) {
|
||||
restoreDefault(myElements);
|
||||
for (Element element : xmlElement.getChildren(PIPELINE_ELEMENT_NAME)) {
|
||||
final String fqn = element.getAttributeValue(FQN_ATTR);
|
||||
final String method = element.getAttributeValue(METHOD_ATTR);
|
||||
final String streamApiMethod = element.getAttributeValue(STREAM_API_METHOD_ATTR);
|
||||
final boolean toDelete = element.getAttribute(DELETE_ATTR) != null;
|
||||
final PipelineElement pipelineElement = new PipelineElement(fqn, method, streamApiMethod);
|
||||
if (toDelete) {
|
||||
myElements.remove(pipelineElement);
|
||||
}
|
||||
else {
|
||||
myElements.add(pipelineElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void writeExternal(final @NotNull Element xmlElement) {
|
||||
final List<PipelineElement> toRemoveElements = new ArrayList<PipelineElement>();
|
||||
restoreDefault(toRemoveElements);
|
||||
toRemoveElements.removeAll(myElements);
|
||||
|
||||
for (PipelineElement element : toRemoveElements) {
|
||||
xmlElement.addContent(createXmlElement(element)
|
||||
.setAttribute(DELETE_ATTR, ""));
|
||||
}
|
||||
final List<PipelineElement> defaultElements = new ArrayList<PipelineElement>();
|
||||
restoreDefault(defaultElements);
|
||||
for (PipelineElement element : myElements) {
|
||||
if (!defaultElements.contains(element)) {
|
||||
xmlElement.addContent(createXmlElement(element));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Element createXmlElement(PipelineElement element) {
|
||||
return new Element(PIPELINE_ELEMENT_NAME)
|
||||
.setAttribute(FQN_ATTR, element.getHandlerClass())
|
||||
.setAttribute(METHOD_ATTR, element.getMethodName())
|
||||
.setAttribute(STREAM_API_METHOD_ATTR, element.getStreamApiMethodName());
|
||||
}
|
||||
|
||||
public JComponent createPanel() {
|
||||
final JBList list = new JBList();
|
||||
list.setModel(new SettingsListModel());
|
||||
|
||||
list.setCellRenderer(new ColoredListCellRenderer<PipelineElement>() {
|
||||
@Override
|
||||
protected void customizeCellRenderer(JList list, PipelineElement element, int index, boolean selected, boolean hasFocus) {
|
||||
final String classFQName = element.getHandlerClass();
|
||||
final String[] split = classFQName.split("\\.");
|
||||
final int classShortNameIndex = classFQName.length() - split[split.length - 1].length();
|
||||
append(classFQName.substring(0, classShortNameIndex));
|
||||
append(classFQName.substring(classShortNameIndex),
|
||||
SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES.derive(SimpleTextAttributes.STYLE_BOLD,
|
||||
JBColor.BLUE, null, null));
|
||||
append("." + element.getMethodName(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
|
||||
}
|
||||
});
|
||||
return ToolbarDecorator.createDecorator(list).disableUpDownActions().setAddAction(new AnActionButtonRunnable() {
|
||||
@Override
|
||||
public void run(AnActionButton button) {
|
||||
final Project currentProject = CommonDataKeys.PROJECT.getData(button.getDataContext());
|
||||
if (currentProject == null) {
|
||||
return;
|
||||
}
|
||||
final AddMethodsDialog dlg = new AddMethodsDialog(currentProject, list, false);
|
||||
if (dlg.showAndGet()) {
|
||||
final PipelineElement newElement = dlg.getSelectedElement();
|
||||
if (myElements.contains(newElement)) {
|
||||
return;
|
||||
}
|
||||
myElements.add(newElement);
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
list.updateUI();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}).setRemoveAction(new AnActionButtonRunnable() {
|
||||
@Override
|
||||
public void run(AnActionButton button) {
|
||||
myElements.remove(list.getSelectedIndex());
|
||||
}
|
||||
}).createPanel();
|
||||
}
|
||||
|
||||
public static class PipelineElement {
|
||||
private final String myHandlerClass;
|
||||
private final String myMethodName;
|
||||
private final String myStreamApiMethod;
|
||||
|
||||
public PipelineElement(@NotNull String handlerClass, @NotNull String methodName, @NotNull String streamApiMethod) {
|
||||
myHandlerClass = handlerClass;
|
||||
myMethodName = methodName;
|
||||
myStreamApiMethod = streamApiMethod;
|
||||
}
|
||||
|
||||
public String getHandlerClass() {
|
||||
return myHandlerClass;
|
||||
}
|
||||
|
||||
public String getMethodName() {
|
||||
return myMethodName;
|
||||
}
|
||||
|
||||
public String getStreamApiMethodName() {
|
||||
return myStreamApiMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
PipelineElement element = (PipelineElement)o;
|
||||
|
||||
if (!myHandlerClass.equals(element.myHandlerClass)) return false;
|
||||
if (!myMethodName.equals(element.myMethodName)) return false;
|
||||
if (!myStreamApiMethod.equals(element.myStreamApiMethod)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = myHandlerClass.hashCode();
|
||||
result = 31 * result + myMethodName.hashCode();
|
||||
result = 31 * result + myStreamApiMethod.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private class SettingsListModel implements ListModel {
|
||||
@Override
|
||||
public int getSize() {
|
||||
return myElements.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PipelineElement getElementAt(int index) {
|
||||
return myElements.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListDataListener(ListDataListener l) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListDataListener(ListDataListener l) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-1
@@ -33,6 +33,10 @@ public interface StreamApiConstants {
|
||||
String ALL_MATCH = "allMatch";
|
||||
String MAP = "map";
|
||||
String FILTER = "filter";
|
||||
String FOR_EACH = "forEach";
|
||||
String FIND_FIRST = "findFirst";
|
||||
String LIMIT = "limit";
|
||||
String FLAT_MAP = "flatMap";
|
||||
|
||||
String FAKE_FIND_MATCHED = "#findMatched";
|
||||
String FAKE_FIND_MATCHED_PATTERN = "filter(%s).findFirst().get()";
|
||||
@@ -43,7 +47,7 @@ public interface StreamApiConstants {
|
||||
@NotNull
|
||||
@Override
|
||||
protected Set<String> compute() {
|
||||
return ContainerUtil.newHashSet(MAP, FILTER);
|
||||
return ContainerUtil.newLinkedHashSet(MAP, FILTER, FOR_EACH, ANY_MATCH, ALL_MATCH, FIND_FIRST, LIMIT, FLAT_MAP);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -56,4 +60,7 @@ public interface StreamApiConstants {
|
||||
return map;
|
||||
}
|
||||
};
|
||||
|
||||
String SKIP = "skip";
|
||||
String TO_ARRAY = "toArray";
|
||||
}
|
||||
+15
-13
@@ -20,10 +20,15 @@ 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.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
|
||||
import com.intellij.util.Processor;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -41,43 +46,40 @@ public class StaticPseudoFunctionalStyleMethodTest extends JavaCodeInsightFixtur
|
||||
moduleBuilder.setLanguageLevel(LanguageLevel.JDK_1_8);
|
||||
moduleBuilder.addLibraryJars("guava-17.0.jar", PathManager.getHomePath().replace(File.separatorChar, '/') + "/community/lib/",
|
||||
"guava-17.0.jar");
|
||||
moduleBuilder.addLibraryJars("guava-17.0.jar-2", PathManager.getHomePath().replace(File.separatorChar, '/') + "/lib/",
|
||||
"guava-17.0.jar");
|
||||
moduleBuilder.addJdk(IdeaTestUtil.getMockJdk18Path().getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void _testSimpleTransform() {
|
||||
public void testSimpleTransform() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void _testSimpleFilter() {
|
||||
public void testSimpleFilter() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void _testSimpleFind() {
|
||||
public void testSimpleFind() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void _testSimpleAll() {
|
||||
public void testSimpleAll() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void _testSimpleAny() {
|
||||
public void testSimpleAny() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void _testLambdaIsntAnonymous() {
|
||||
public void testLambdaIsntAnonymous() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void _testLambdaIsntAnonymous2() {
|
||||
public void testLambdaIsntAnonymous2() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void _testLambdaIsntAnonymous3() {
|
||||
public void testLambdaIsntAnonymous3() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
Inspection detects usages of pseudo-lambda code if Java Stream API is available (language level >= Java 1.8)
|
||||
Inspection detects usages of pseudo-functional code if Java Stream API is available.
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user