mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-04 17:20:55 +07:00
[functional expressions search] check method equality when applicable (IDEA-276298)
otherwise unrelated lambdas/method references may land in results when intermediate inheritors contain default methods GitOrigin-RevId: aa5baae37ff676ca477ca41d82b782c42d5fda6c
This commit is contained in:
committed by
intellij-monorepo-bot
parent
d43848c086
commit
f33a1f5426
@@ -25,10 +25,7 @@ import com.intellij.psi.search.searches.FunctionalExpressionSearch;
|
|||||||
import com.intellij.psi.search.searches.OverridingMethodsSearch;
|
import com.intellij.psi.search.searches.OverridingMethodsSearch;
|
||||||
import com.intellij.psi.util.PsiUtil;
|
import com.intellij.psi.util.PsiUtil;
|
||||||
import com.intellij.psi.util.PsiUtilCore;
|
import com.intellij.psi.util.PsiUtilCore;
|
||||||
import com.intellij.util.ArrayUtil;
|
import com.intellij.util.*;
|
||||||
import com.intellij.util.CommonProcessors;
|
|
||||||
import com.intellij.util.Function;
|
|
||||||
import com.intellij.util.NullableFunction;
|
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import org.jetbrains.annotations.Nls;
|
import org.jetbrains.annotations.Nls;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -253,10 +250,7 @@ public class MarkerType {
|
|||||||
GlobalSearchScope scope = GlobalSearchScope.allScope(PsiUtilCore.getProjectInReadAction(method));
|
GlobalSearchScope scope = GlobalSearchScope.allScope(PsiUtilCore.getProjectInReadAction(method));
|
||||||
OverridingMethodsSearch.search(method, scope,true).forEach(new PsiElementProcessorAdapter<>(collectProcessor));
|
OverridingMethodsSearch.search(method, scope,true).forEach(new PsiElementProcessorAdapter<>(collectProcessor));
|
||||||
if (isAbstract && collectProcessor.getCollection().size() < 2) {
|
if (isAbstract && collectProcessor.getCollection().size() < 2) {
|
||||||
final PsiClass aClass = ReadAction.compute(method::getContainingClass);
|
FunctionalExpressionSearch.search(method).forEach(new PsiElementProcessorAdapter<>(collectExprProcessor));
|
||||||
if (aClass != null) {
|
|
||||||
FunctionalExpressionSearch.search(aClass).forEach(new PsiElementProcessorAdapter<>(collectExprProcessor));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, JavaAnalysisBundle.message("searching.for.overriding.methods"), true, method.getProject(), (JComponent)e.getComponent())) {
|
}, JavaAnalysisBundle.message("searching.for.overriding.methods"), true, method.getProject(), (JComponent)e.getComponent())) {
|
||||||
return;
|
return;
|
||||||
@@ -353,8 +347,10 @@ public class MarkerType {
|
|||||||
super(project, title, createComparatorWrapper((Comparator)renderer.getComparator()));
|
super(project, title, createComparatorWrapper((Comparator)renderer.getComparator()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void collectFunctionalInheritors(@NotNull ProgressIndicator indicator, PsiClass psiClass) {
|
void collectFunctionalInheritors(@NotNull ProgressIndicator indicator, PsiMember member) {
|
||||||
FunctionalExpressionSearch.search(psiClass).forEach(expr -> {
|
Query<PsiFunctionalExpression> search = member instanceof PsiClass ? FunctionalExpressionSearch.search((PsiClass)member)
|
||||||
|
: FunctionalExpressionSearch.search((PsiMethod)member);
|
||||||
|
search.forEach(expr -> {
|
||||||
if (!updateComponent(expr)) {
|
if (!updateComponent(expr)) {
|
||||||
indicator.cancel();
|
indicator.cancel();
|
||||||
}
|
}
|
||||||
@@ -449,9 +445,7 @@ public class MarkerType {
|
|||||||
return super.process(psiMethod);
|
return super.process(psiMethod);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (ReadAction.compute(() -> myMethod.hasModifierProperty(PsiModifier.ABSTRACT))) {
|
collectFunctionalInheritors(indicator, myMethod);
|
||||||
collectFunctionalInheritors(indicator, ReadAction.compute(myMethod::getContainingClass));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,17 +92,14 @@ public class JavaFindUsagesHandler extends FindUsagesHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final PsiClass aClass = ReadAction.compute(method::getContainingClass);
|
FunctionalExpressionSearch.search(method).forEach(element -> {
|
||||||
if (aClass != null) {
|
if (element instanceof PsiLambdaExpression) {
|
||||||
FunctionalExpressionSearch.search(aClass).forEach(element -> {
|
PsiParameter[] parameters = ((PsiLambdaExpression)element).getParameterList().getParameters();
|
||||||
if (element instanceof PsiLambdaExpression) {
|
if (idx < parameters.length) {
|
||||||
PsiParameter[] parameters = ((PsiLambdaExpression)element).getParameterList().getParameters();
|
elementsToSearch.add(parameters[idx]);
|
||||||
if (idx < parameters.length) {
|
|
||||||
elementsToSearch.add(parameters[idx]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
return PsiUtilCore.toPsiElementArray(elementsToSearch);
|
return PsiUtilCore.toPsiElementArray(elementsToSearch);
|
||||||
}
|
}
|
||||||
@@ -122,7 +119,7 @@ public class JavaFindUsagesHandler extends FindUsagesHandler {
|
|||||||
|
|
||||||
ProgressManager pm = ProgressManager.getInstance();
|
ProgressManager pm = ProgressManager.getInstance();
|
||||||
boolean hasOverriden = pm.runProcessWithProgressSynchronously(() ->
|
boolean hasOverriden = pm.runProcessWithProgressSynchronously(() ->
|
||||||
OverridingMethodsSearch.search(method).findFirst() != null || FunctionalExpressionSearch.search(aClass).findFirst() != null,
|
OverridingMethodsSearch.search(method).findFirst() != null || FunctionalExpressionSearch.search(method).findFirst() != null,
|
||||||
JavaBundle.message("progress.title.detect.overridden.methods"), true, getProject()) == Boolean.TRUE;
|
JavaBundle.message("progress.title.detect.overridden.methods"), true, getProject()) == Boolean.TRUE;
|
||||||
|
|
||||||
if (hasOverriden && myFactory.getFindVariableOptions().isSearchInOverridingMethods) {
|
if (hasOverriden && myFactory.getFindVariableOptions().isSearchInOverridingMethods) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
package com.intellij.psi.search.searches;
|
package com.intellij.psi.search.searches;
|
||||||
|
|
||||||
import com.intellij.openapi.application.ReadAction;
|
import com.intellij.openapi.application.ReadAction;
|
||||||
@@ -11,21 +11,36 @@ import com.intellij.psi.util.PsiUtilCore;
|
|||||||
import com.intellij.util.EmptyQuery;
|
import com.intellij.util.EmptyQuery;
|
||||||
import com.intellij.util.Query;
|
import com.intellij.util.Query;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public final class FunctionalExpressionSearch extends ExtensibleQueryFactory<PsiFunctionalExpression, FunctionalExpressionSearch.SearchParameters> {
|
public final class FunctionalExpressionSearch extends ExtensibleQueryFactory<PsiFunctionalExpression, FunctionalExpressionSearch.SearchParameters> {
|
||||||
private static final FunctionalExpressionSearch INSTANCE = new FunctionalExpressionSearch();
|
private static final FunctionalExpressionSearch INSTANCE = new FunctionalExpressionSearch();
|
||||||
|
|
||||||
public static class SearchParameters {
|
public static class SearchParameters {
|
||||||
private final PsiClass myElementToSearch;
|
private final PsiClass myElementToSearch;
|
||||||
|
private final PsiMethod myMethod;
|
||||||
private final SearchScope myScope;
|
private final SearchScope myScope;
|
||||||
private final @NotNull Project myProject;
|
private final @NotNull Project myProject;
|
||||||
|
|
||||||
public SearchParameters(@NotNull PsiClass aClass, @NotNull SearchScope scope) {
|
public SearchParameters(@NotNull PsiClass aClass,
|
||||||
|
@NotNull SearchScope scope) {
|
||||||
|
this(aClass, null, scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SearchParameters(@NotNull PsiClass aClass,
|
||||||
|
@Nullable PsiMethod psiMethod,
|
||||||
|
@NotNull SearchScope scope) {
|
||||||
myProject = aClass.getProject();
|
myProject = aClass.getProject();
|
||||||
myElementToSearch = aClass;
|
myElementToSearch = aClass;
|
||||||
|
myMethod = psiMethod;
|
||||||
myScope = scope;
|
myScope = scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public PsiMethod getMethod() {
|
||||||
|
return myMethod;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public PsiClass getElementToSearch() {
|
public PsiClass getElementToSearch() {
|
||||||
return myElementToSearch;
|
return myElementToSearch;
|
||||||
@@ -56,10 +71,10 @@ public final class FunctionalExpressionSearch extends ExtensibleQueryFactory<Psi
|
|||||||
@NotNull
|
@NotNull
|
||||||
public static Query<PsiFunctionalExpression> search(@NotNull PsiMethod psiMethod, @NotNull SearchScope scope) {
|
public static Query<PsiFunctionalExpression> search(@NotNull PsiMethod psiMethod, @NotNull SearchScope scope) {
|
||||||
return ReadAction.compute(() -> {
|
return ReadAction.compute(() -> {
|
||||||
if (!psiMethod.hasModifierProperty(PsiModifier.STATIC) && !psiMethod.hasModifierProperty(PsiModifier.DEFAULT)) {
|
if (psiMethod.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||||
PsiClass containingClass = psiMethod.getContainingClass();
|
PsiClass containingClass = psiMethod.getContainingClass();
|
||||||
if (containingClass != null) {
|
if (containingClass != null) {
|
||||||
return INSTANCE.createUniqueResultsQuery(new SearchParameters(containingClass, scope));
|
return INSTANCE.createUniqueResultsQuery(new SearchParameters(containingClass, psiMethod, scope));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return EmptyQuery.getEmptyQuery();
|
return EmptyQuery.getEmptyQuery();
|
||||||
|
|||||||
@@ -39,10 +39,7 @@ import com.intellij.psi.search.searches.FunctionalExpressionSearch.SearchParamet
|
|||||||
import com.intellij.psi.stubs.StubIndex;
|
import com.intellij.psi.stubs.StubIndex;
|
||||||
import com.intellij.psi.stubs.StubTextInconsistencyException;
|
import com.intellij.psi.stubs.StubTextInconsistencyException;
|
||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
import com.intellij.psi.util.InheritanceUtil;
|
import com.intellij.psi.util.*;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
|
||||||
import com.intellij.psi.util.PsiUtil;
|
|
||||||
import com.intellij.psi.util.PsiUtilCore;
|
|
||||||
import com.intellij.util.Processor;
|
import com.intellij.util.Processor;
|
||||||
import com.intellij.util.Processors;
|
import com.intellij.util.Processors;
|
||||||
import com.intellij.util.ThreeState;
|
import com.intellij.util.ThreeState;
|
||||||
@@ -94,6 +91,11 @@ public final class JavaFunctionalExpressionSearcher extends QueryExecutorBase<Ps
|
|||||||
PsiMethod saMethod = Objects.requireNonNull(LambdaUtil.getFunctionalInterfaceMethod(samClass));
|
PsiMethod saMethod = Objects.requireNonNull(LambdaUtil.getFunctionalInterfaceMethod(samClass));
|
||||||
PsiType samType = saMethod.getReturnType();
|
PsiType samType = saMethod.getReturnType();
|
||||||
if (samType == null) continue;
|
if (samType == null) continue;
|
||||||
|
if (session.method != null &&
|
||||||
|
!saMethod.equals(session.method) &&
|
||||||
|
!MethodSignatureUtil.isSuperMethod(saMethod, session.method)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
SearchScope scope = psiSearchHelper.getUseScope(samClass).intersectWith(session.scope);
|
SearchScope scope = psiSearchHelper.getUseScope(samClass).intersectWith(session.scope);
|
||||||
descriptors.add(new SamDescriptor(samClass, saMethod, samType, GlobalSearchScopeUtil.toGlobalSearchScope(scope, project)));
|
descriptors.add(new SamDescriptor(samClass, saMethod, samType, GlobalSearchScopeUtil.toGlobalSearchScope(scope, project)));
|
||||||
@@ -461,10 +463,12 @@ public final class JavaFunctionalExpressionSearcher extends QueryExecutorBase<Ps
|
|||||||
private final AtomicInteger sureExprsAfterLightCheck = new AtomicInteger();
|
private final AtomicInteger sureExprsAfterLightCheck = new AtomicInteger();
|
||||||
private final AtomicInteger exprsToHeavyCheck = new AtomicInteger();
|
private final AtomicInteger exprsToHeavyCheck = new AtomicInteger();
|
||||||
private final Set<VirtualFile> filesLookedInside = ContainerUtil.newConcurrentSet();
|
private final Set<VirtualFile> filesLookedInside = ContainerUtil.newConcurrentSet();
|
||||||
|
private final @Nullable PsiMethod method;
|
||||||
|
|
||||||
public Session(@NotNull SearchParameters parameters, @NotNull Processor<? super PsiFunctionalExpression> consumer) {
|
public Session(@NotNull SearchParameters parameters, @NotNull Processor<? super PsiFunctionalExpression> consumer) {
|
||||||
this.consumer = consumer;
|
this.consumer = consumer;
|
||||||
elementToSearch = parameters.getElementToSearch();
|
elementToSearch = parameters.getElementToSearch();
|
||||||
|
method = parameters.getMethod();
|
||||||
project = parameters.getProject();
|
project = parameters.getProject();
|
||||||
psiManager = PsiManager.getInstance(project);
|
psiManager = PsiManager.getInstance(project);
|
||||||
scope = parameters.getEffectiveSearchScope();
|
scope = parameters.getEffectiveSearchScope();
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
class Clazz {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Child child = x -> System.out.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I {
|
||||||
|
void execute(int i);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Child extends I {
|
||||||
|
default void execute(int i) {}
|
||||||
|
void f(int i);
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
package com.intellij.psi.impl.search;
|
package com.intellij.psi.impl.search;
|
||||||
|
|
||||||
import com.intellij.JavaTestUtil;
|
import com.intellij.JavaTestUtil;
|
||||||
@@ -111,6 +111,11 @@ public class FindFunctionalInterfaceTest extends LightJavaCodeInsightFixtureTest
|
|||||||
assertSize(1, FunctionalExpressionSearch.search(findClass("I")).findAll());
|
assertSize(1, FunctionalExpressionSearch.search(findClass("I")).findAll());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testDefaultInHierarchy() {
|
||||||
|
configure();
|
||||||
|
assertEmpty(FunctionalExpressionSearch.search(findClass("I").getMethods()[0]).findAll());
|
||||||
|
}
|
||||||
|
|
||||||
public void testStreamOfLikeApiWithField() {
|
public void testStreamOfLikeApiWithField() {
|
||||||
myFixture.addClass("class Base { StrType Stream = null; }");
|
myFixture.addClass("class Base { StrType Stream = null; }");
|
||||||
configure();
|
configure();
|
||||||
|
|||||||
Reference in New Issue
Block a user