mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
enable overriding marks for functional expressions
This commit is contained in:
+13
-2
@@ -37,6 +37,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.searches.AllOverridingMethodsSearch;
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
||||
import com.intellij.psi.search.searches.FunctionalExpressionSearch;
|
||||
import com.intellij.psi.search.searches.SuperMethodsSearch;
|
||||
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
@@ -179,8 +180,7 @@ public class JavaLineMarkerProvider implements LineMarkerProvider, DumbAware {
|
||||
}
|
||||
if (CommonClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) return; // It's useless to have overridden markers for object.
|
||||
|
||||
PsiClass inheritor = ClassInheritorsSearch.search(aClass, false).findFirst();
|
||||
if (inheritor != null) {
|
||||
if (ClassInheritorsSearch.search(aClass, false).findFirst() != null || FunctionalExpressionSearch.search(aClass).findFirst() != null) {
|
||||
final Icon icon = aClass.isInterface() ? AllIcons.Gutter.ImplementedMethod : AllIcons.Gutter.OverridenMethod;
|
||||
PsiElement range = aClass.getNameIdentifier();
|
||||
if (range == null) range = aClass;
|
||||
@@ -219,6 +219,17 @@ public class JavaLineMarkerProvider implements LineMarkerProvider, DumbAware {
|
||||
});
|
||||
}
|
||||
|
||||
if (!methods.isEmpty()) {
|
||||
for (PsiClass aClass : classes) {
|
||||
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(aClass);
|
||||
if (interfaceMethod != null) {
|
||||
if (FunctionalExpressionSearch.search(aClass).findFirst() != null) {
|
||||
overridden.add(interfaceMethod);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (PsiMethod method : overridden) {
|
||||
ProgressManager.checkCanceled();
|
||||
boolean overrides = !method.hasModifierProperty(PsiModifier.ABSTRACT);
|
||||
|
||||
@@ -23,9 +23,7 @@ import com.intellij.codeInsight.CodeInsightBundle;
|
||||
import com.intellij.codeInsight.daemon.DaemonBundle;
|
||||
import com.intellij.codeInsight.daemon.GutterIconNavigationHandler;
|
||||
import com.intellij.codeInsight.navigation.ListBackgroundUpdaterTask;
|
||||
import com.intellij.ide.util.MethodCellRenderer;
|
||||
import com.intellij.ide.util.PsiClassListCellRenderer;
|
||||
import com.intellij.ide.util.PsiElementListCellRenderer;
|
||||
import com.intellij.ide.util.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
@@ -36,6 +34,7 @@ import com.intellij.psi.search.PsiElementProcessor;
|
||||
import com.intellij.psi.search.PsiElementProcessorAdapter;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
||||
import com.intellij.psi.search.searches.FunctionalExpressionSearch;
|
||||
import com.intellij.psi.search.searches.OverridingMethodsSearch;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.*;
|
||||
@@ -136,7 +135,7 @@ public class MarkerType {
|
||||
}
|
||||
});
|
||||
|
||||
public static String getOverriddenMethodTooltip(PsiMethod method) {
|
||||
public static String getOverriddenMethodTooltip(final PsiMethod method) {
|
||||
PsiElementProcessor.CollectElementsWithLimit<PsiMethod> processor = new PsiElementProcessor.CollectElementsWithLimit<PsiMethod>(5);
|
||||
OverridingMethodsSearch.search(method, true).forEach(new PsiElementProcessorAdapter<PsiMethod>(processor));
|
||||
|
||||
@@ -146,8 +145,14 @@ public class MarkerType {
|
||||
return isAbstract ? DaemonBundle.message("method.is.implemented.too.many") : DaemonBundle.message("method.is.overridden.too.many");
|
||||
}
|
||||
|
||||
PsiMethod[] overridings = processor.toArray(new PsiMethod[processor.getCollection().size()]);
|
||||
if (overridings.length == 0) return null;
|
||||
PsiMethod[] overridings = processor.toArray(PsiMethod.EMPTY_ARRAY);
|
||||
if (overridings.length == 0) {
|
||||
final PsiClass aClass = method.getContainingClass();
|
||||
if (aClass != null && FunctionalExpressionSearch.search(aClass).findFirst() != null) {
|
||||
return "Has functional implementations";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Comparator<PsiMethod> comparator = new MethodCellRenderer(false).getComparator();
|
||||
Arrays.sort(overridings, comparator);
|
||||
@@ -166,19 +171,33 @@ public class MarkerType {
|
||||
|
||||
final PsiElementProcessor.CollectElementsWithLimit<PsiMethod> collectProcessor =
|
||||
new PsiElementProcessor.CollectElementsWithLimit<PsiMethod>(2, new THashSet<PsiMethod>());
|
||||
final PsiElementProcessor.CollectElementsWithLimit<PsiFunctionalExpression> collectExprProcessor =
|
||||
new PsiElementProcessor.CollectElementsWithLimit<PsiFunctionalExpression>(2, new THashSet<PsiFunctionalExpression>());
|
||||
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
OverridingMethodsSearch.search(method, true).forEach(new PsiElementProcessorAdapter<PsiMethod>(collectProcessor));
|
||||
if (collectProcessor.getCollection().isEmpty()) {
|
||||
final PsiClass aClass = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
|
||||
@Override
|
||||
public PsiClass compute() {
|
||||
return method.getContainingClass();
|
||||
}
|
||||
});
|
||||
if (aClass != null) {
|
||||
FunctionalExpressionSearch.search(aClass).forEach(new PsiElementProcessorAdapter<PsiFunctionalExpression>(collectExprProcessor));
|
||||
}
|
||||
}
|
||||
}
|
||||
}, SEARCHING_FOR_OVERRIDING_METHODS, true, method.getProject(), (JComponent)e.getComponent())) {
|
||||
return;
|
||||
}
|
||||
|
||||
PsiMethod[] overridings = collectProcessor.toArray(PsiMethod.EMPTY_ARRAY);
|
||||
final PsiMethod[] methodOverriders = collectProcessor.toArray(PsiMethod.EMPTY_ARRAY);
|
||||
NavigatablePsiElement[] overridings = ArrayUtil.mergeArrays(methodOverriders, collectExprProcessor.toArray(PsiFunctionalExpression.EMPTY_ARRAY));
|
||||
if (overridings.length == 0) return;
|
||||
boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature(overridings);
|
||||
MethodCellRenderer renderer = new MethodCellRenderer(showMethodNames);
|
||||
boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature(methodOverriders);
|
||||
MethodOrFunctionalExpressionCellRenderer renderer = new MethodOrFunctionalExpressionCellRenderer(showMethodNames);
|
||||
Arrays.sort(overridings, renderer.getComparator());
|
||||
final OverridingMethodsUpdater methodsUpdater = new OverridingMethodsUpdater(method, renderer);
|
||||
PsiElementListNavigator.openTargets(e, overridings, methodsUpdater.getCaption(overridings.length), "Overriding methods of " + method.getName(), renderer, methodsUpdater);
|
||||
@@ -214,8 +233,16 @@ public class MarkerType {
|
||||
: DaemonBundle.message("class.is.subclassed.too.many");
|
||||
}
|
||||
|
||||
PsiClass[] subclasses = processor.toArray(new PsiClass[processor.getCollection().size()]);
|
||||
if (subclasses.length == 0) return null;
|
||||
PsiClass[] subclasses = processor.toArray(PsiClass.EMPTY_ARRAY);
|
||||
if (subclasses.length == 0) {
|
||||
final PsiElementProcessor.CollectElementsWithLimit<PsiFunctionalExpression> functionalImplementations =
|
||||
new PsiElementProcessor.CollectElementsWithLimit<>(2, new THashSet<PsiFunctionalExpression>());
|
||||
FunctionalExpressionSearch.search(aClass).forEach(new PsiElementProcessorAdapter<PsiFunctionalExpression>(functionalImplementations));
|
||||
if (!functionalImplementations.getCollection().isEmpty()) {
|
||||
return "Has functional implementations";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Comparator<PsiClass> comparator = new PsiClassListCellRenderer().getComparator();
|
||||
Arrays.sort(subclasses, comparator);
|
||||
@@ -234,18 +261,23 @@ public class MarkerType {
|
||||
}
|
||||
|
||||
final PsiElementProcessor.CollectElementsWithLimit<PsiClass> collectProcessor = new PsiElementProcessor.CollectElementsWithLimit<PsiClass>(2, new THashSet<PsiClass>());
|
||||
final PsiElementProcessor.CollectElementsWithLimit<PsiFunctionalExpression> collectExprProcessor = new PsiElementProcessor.CollectElementsWithLimit<PsiFunctionalExpression>(2, new THashSet<PsiFunctionalExpression>());
|
||||
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ClassInheritorsSearch.search(aClass, true).forEach(new PsiElementProcessorAdapter<PsiClass>(collectProcessor));
|
||||
if (collectProcessor.getCollection().isEmpty()) {
|
||||
FunctionalExpressionSearch.search(aClass).forEach(new PsiElementProcessorAdapter<PsiFunctionalExpression>(collectExprProcessor));
|
||||
}
|
||||
}
|
||||
}, SEARCHING_FOR_OVERRIDDEN_METHODS, true, aClass.getProject(), (JComponent)e.getComponent())) {
|
||||
return;
|
||||
}
|
||||
|
||||
PsiClass[] inheritors = collectProcessor.toArray(PsiClass.EMPTY_ARRAY);
|
||||
NavigatablePsiElement[] inheritors = ArrayUtil.mergeArrays(collectProcessor.toArray(PsiClass.EMPTY_ARRAY),
|
||||
collectExprProcessor.toArray(PsiFunctionalExpression.EMPTY_ARRAY));
|
||||
if (inheritors.length == 0) return;
|
||||
final PsiClassListCellRenderer renderer = new PsiClassListCellRenderer();
|
||||
final PsiClassOrFunctionalExpressionListCellRenderer renderer = new PsiClassOrFunctionalExpressionListCellRenderer();
|
||||
final SubclassUpdater subclassUpdater = new SubclassUpdater(aClass, renderer);
|
||||
Arrays.sort(inheritors, renderer.getComparator());
|
||||
PsiElementListNavigator.openTargets(e, inheritors, subclassUpdater.getCaption(inheritors.length), CodeInsightBundle.message("goto.implementation.findUsages.title", aClass.getName()), renderer, subclassUpdater);
|
||||
@@ -276,9 +308,9 @@ public class MarkerType {
|
||||
|
||||
private static class SubclassUpdater extends ListBackgroundUpdaterTask {
|
||||
private final PsiClass myClass;
|
||||
private final PsiClassListCellRenderer myRenderer;
|
||||
private final PsiClassOrFunctionalExpressionListCellRenderer myRenderer;
|
||||
|
||||
public SubclassUpdater(PsiClass aClass, PsiClassListCellRenderer renderer) {
|
||||
public SubclassUpdater(PsiClass aClass, PsiClassOrFunctionalExpressionListCellRenderer renderer) {
|
||||
super(aClass.getProject(), SEARCHING_FOR_OVERRIDDEN_METHODS);
|
||||
myClass = aClass;
|
||||
myRenderer = renderer;
|
||||
@@ -309,6 +341,17 @@ public class MarkerType {
|
||||
return super.process(o);
|
||||
}
|
||||
});
|
||||
|
||||
FunctionalExpressionSearch.search(myClass).forEach(new CommonProcessors.CollectProcessor<PsiFunctionalExpression>() {
|
||||
@Override
|
||||
public boolean process(final PsiFunctionalExpression expr) {
|
||||
if (!updateComponent(expr, myRenderer.getComparator())) {
|
||||
indicator.cancel();
|
||||
}
|
||||
indicator.checkCanceled();
|
||||
return super.process(expr);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -344,6 +387,22 @@ public class MarkerType {
|
||||
return super.process(psiMethod);
|
||||
}
|
||||
});
|
||||
final PsiClass psiClass = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
|
||||
@Override
|
||||
public PsiClass compute() {
|
||||
return myMethod.getContainingClass();
|
||||
}
|
||||
});
|
||||
FunctionalExpressionSearch.search(psiClass).forEach(new CommonProcessors.CollectProcessor<PsiFunctionalExpression>() {
|
||||
@Override
|
||||
public boolean process(final PsiFunctionalExpression expr) {
|
||||
if (!updateComponent(expr, myRenderer.getComparator())) {
|
||||
indicator.cancel();
|
||||
}
|
||||
indicator.checkCanceled();
|
||||
return super.process(expr);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.ide.util;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiExpressionTrimRenderer;
|
||||
import com.intellij.psi.util.PsiFormatUtil;
|
||||
import com.intellij.psi.util.PsiFormatUtilBase;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class MethodOrFunctionalExpressionCellRenderer extends PsiElementListCellRenderer<NavigatablePsiElement> {
|
||||
private final PsiClassListCellRenderer myClassListCellRenderer = new PsiClassListCellRenderer();
|
||||
private final MethodCellRenderer myMethodCellRenderer;
|
||||
|
||||
public MethodOrFunctionalExpressionCellRenderer(boolean showMethodNames) {
|
||||
this(showMethodNames, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS);
|
||||
}
|
||||
public MethodOrFunctionalExpressionCellRenderer(boolean showMethodNames, @PsiFormatUtil.FormatMethodOptions int options) {
|
||||
myMethodCellRenderer = new MethodCellRenderer(showMethodNames, options);
|
||||
}
|
||||
|
||||
public String getElementText(NavigatablePsiElement element) {
|
||||
return element instanceof PsiMethod ? myMethodCellRenderer.getElementText((PsiMethod)element)
|
||||
: PsiExpressionTrimRenderer.render((PsiExpression)element);
|
||||
}
|
||||
|
||||
protected Icon getIcon(PsiElement element) {
|
||||
return element instanceof PsiMethod ? myMethodCellRenderer.getIcon(element) : null;
|
||||
}
|
||||
|
||||
public String getContainerText(final NavigatablePsiElement element, final String name) {
|
||||
return element instanceof PsiMethod ? myMethodCellRenderer.getContainerText((PsiMethod)element, name)
|
||||
: PsiClassListCellRenderer.getContainerTextStatic(element);
|
||||
}
|
||||
|
||||
public int getIconFlags() {
|
||||
return myClassListCellRenderer.getIconFlags();
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.ide.util;
|
||||
|
||||
import com.intellij.psi.NavigatablePsiElement;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiExpression;
|
||||
import com.intellij.psi.presentation.java.ClassPresentationUtil;
|
||||
import com.intellij.psi.util.PsiExpressionTrimRenderer;
|
||||
|
||||
public class PsiClassOrFunctionalExpressionListCellRenderer extends PsiElementListCellRenderer<NavigatablePsiElement> {
|
||||
@Override
|
||||
public String getElementText(NavigatablePsiElement element) {
|
||||
return element instanceof PsiClass ? ClassPresentationUtil.getNameForClass((PsiClass)element, false)
|
||||
: PsiExpressionTrimRenderer.render((PsiExpression)element);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getContainerText(NavigatablePsiElement element, final String name) {
|
||||
return PsiClassListCellRenderer.getContainerTextStatic(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getIconFlags() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import com.intellij.openapi.util.Iconable;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface PsiFunctionalExpression extends PsiExpression, Iconable, NavigatablePsiElement {
|
||||
PsiFunctionalExpression[] EMPTY_ARRAY = new PsiFunctionalExpression[0];
|
||||
/**
|
||||
* @return SAM type the lambda expression corresponds to
|
||||
* null when no SAM type could be found
|
||||
|
||||
Reference in New Issue
Block a user