Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -19,161 +19,163 @@
import com.intellij.java.language.psi.*;
import com.intellij.java.language.psi.util.PsiFormatUtil;
import com.intellij.java.language.psi.util.PsiFormatUtilBase;
import consulo.application.util.function.Processor;
import consulo.annotation.access.RequiredReadAction;
import consulo.find.FindUsagesOptions;
import consulo.language.psi.PsiElement;
import consulo.language.psi.PsiReference;
import consulo.logging.Logger;
import consulo.usage.UsageInfo;
import consulo.util.dataholder.Key;

import consulo.util.lang.ObjectUtil;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;

import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;

/**
* Author: msk
*/
public class ThrowSearchUtil {

private static final Logger LOG = Logger.getInstance(ThrowSearchUtil.class);
private static final Logger LOG = Logger.getInstance(ThrowSearchUtil.class);

private ThrowSearchUtil() {
}
private ThrowSearchUtil() {
}

public static class Root {
final PsiElement myElement;
final PsiType myType;
final boolean isExact;
public static class Root {
PsiElement myElement;
PsiType myType;
boolean isExact;

public Root(final PsiElement root, final PsiType type, final boolean exact) {
myElement = root;
myType = type;
isExact = exact;
}
public Root(PsiElement root, PsiType type, boolean exact) {
myElement = root;
myType = type;
isExact = exact;
}

public String toString() {
return PsiFormatUtil.formatType(myType, PsiFormatUtilBase.SHOW_FQ_CLASS_NAMES, PsiSubstitutor.EMPTY);
}
}

public static Key<Root> THROW_SEARCH_ROOT_KEY = Key.create("ThrowSearchUtil.root");

/**
* @param aCatch
* @param processor
* @param root
* @return true, if we should continue processing
*/
private static boolean processExn(@Nonnull PsiParameter aCatch, @Nonnull Processor<UsageInfo> processor, @Nonnull Root root) {
final PsiType type = aCatch.getType();
if (type.isAssignableFrom(root.myType)) {
processor.process(new UsageInfo(aCatch));
return false;
}
if (!root.isExact && root.myType.isAssignableFrom(type)) {
processor.process(new UsageInfo(aCatch));
return true;
}
return true;
}

private static boolean scanCatches(@Nonnull PsiElement elem,
@Nonnull Processor<UsageInfo> processor,
@Nonnull Root root,
@Nonnull FindUsagesOptions options,
@Nonnull Set<PsiMethod> processed) {
while (elem != null) {
final PsiElement parent = elem.getParent();
if (elem instanceof PsiMethod) {
final PsiMethod deepestSuperMethod = ((PsiMethod) elem).findDeepestSuperMethod();
final PsiMethod method = deepestSuperMethod != null ? deepestSuperMethod : (PsiMethod) elem;
if (!processed.contains(method)) {
processed.add(method);
final PsiReference[] refs = MethodReferencesSearch.search(method, options.searchScope, true).toArray(PsiReference.EMPTY_ARRAY);
for (int i = 0; i != refs.length; ++i) {
if (!scanCatches(refs[i].getElement(), processor, root, options, processed)) return false;
}
@Override
public String toString() {
return PsiFormatUtil.formatType(myType, PsiFormatUtilBase.SHOW_FQ_CLASS_NAMES, PsiSubstitutor.EMPTY);
}
return true;
}
if (elem instanceof PsiTryStatement) {
final PsiTryStatement aTry = (PsiTryStatement) elem;
final PsiParameter[] catches = aTry.getCatchBlockParameters();
for (int i = 0; i != catches.length; ++i) {
if (!processExn(catches[i], processor, root)) {
}

public static Key<Root> THROW_SEARCH_ROOT_KEY = Key.create("ThrowSearchUtil.root");

/**
* @param aCatch
* @param processor
* @param root
* @return true, if we should continue processing
*/
private static boolean processExn(@Nonnull PsiParameter aCatch, @Nonnull Predicate<UsageInfo> processor, @Nonnull Root root) {
PsiType type = aCatch.getType();
if (type.isAssignableFrom(root.myType)) {
processor.test(new UsageInfo(aCatch));
return false;
}
}
} else if (parent instanceof PsiTryStatement) {
final PsiTryStatement tryStmt = (PsiTryStatement) parent;
if (elem != tryStmt.getTryBlock()) {
elem = parent.getParent();
continue;
if (!root.isExact && root.myType.isAssignableFrom(type)) {
processor.test(new UsageInfo(aCatch));
return true;
}
}
elem = parent;
return true;
}
return true;
}

public static boolean addThrowUsages(@Nonnull Processor<UsageInfo> processor, @Nonnull Root root, @Nonnull FindUsagesOptions options) {
Set<PsiMethod> processed = new HashSet<PsiMethod>();
return scanCatches(root.myElement, processor, root, options, processed);
}

/**
* @param exn
* @return is type of exn exactly known
*/

private static boolean isExactExnType(final PsiExpression exn) {
return exn instanceof PsiNewExpression;
}

@Nullable
public static Root[] getSearchRoots(final PsiElement element) {
if (element instanceof PsiThrowStatement) {
final PsiThrowStatement aThrow = (PsiThrowStatement) element;
final PsiExpression exn = aThrow.getException();
return new Root[]{new Root(aThrow.getParent(), exn.getType(), isExactExnType(exn))};

@RequiredReadAction
private static boolean scanCatches(
@Nonnull PsiElement elem,
@Nonnull Predicate<UsageInfo> processor,
@Nonnull Root root,
@Nonnull FindUsagesOptions options,
@Nonnull Set<PsiMethod> processed
) {
while (elem != null) {
PsiElement parent = elem.getParent();
if (elem instanceof PsiMethod m) {
PsiMethod method = ObjectUtil.chooseNotNull(m.findDeepestSuperMethod(), m);
if (!processed.contains(method)) {
processed.add(method);
PsiReference[] refs =
MethodReferencesSearch.search(method, options.searchScope, true).toArray(PsiReference.EMPTY_ARRAY);
for (int i = 0; i != refs.length; ++i) {
if (!scanCatches(refs[i].getElement(), processor, root, options, processed)) {
return false;
}
}
}
return true;
}
if (elem instanceof PsiTryStatement tryStmt) {
PsiParameter[] catches = tryStmt.getCatchBlockParameters();
for (int i = 0; i != catches.length; ++i) {
if (!processExn(catches[i], processor, root)) {
return false;
}
}
}
else if (parent instanceof PsiTryStatement tryStmt) {
if (elem != tryStmt.getTryBlock()) {
elem = parent.getParent();
continue;
}
}
elem = parent;
}
return true;
}

@RequiredReadAction
public static boolean addThrowUsages(@Nonnull Predicate<UsageInfo> processor, @Nonnull Root root, @Nonnull FindUsagesOptions options) {
Set<PsiMethod> processed = new HashSet<>();
return scanCatches(root.myElement, processor, root, options, processed);
}

/**
* @param exn
* @return is type of exn exactly known
*/

private static boolean isExactExnType(PsiExpression exn) {
return exn instanceof PsiNewExpression;
}
if (element instanceof PsiKeyword) {
final PsiKeyword kwd = (PsiKeyword) element;
if (PsiKeyword.THROWS.equals(kwd.getText())) {
final PsiElement parent = kwd.getParent();
if (parent != null && parent.getParent() instanceof PsiMethod) {
final PsiMethod method = (PsiMethod) parent.getParent();
final PsiReferenceList throwsList = method.getThrowsList();
final PsiClassType[] exns = throwsList.getReferencedTypes();
final Root[] roots = new Root[exns.length];
for (int i = 0; i != roots.length; ++i) {
final PsiClassType exn = exns[i];
roots[i] = new Root(method, exn, false); // TODO: test for final
}
return roots;

@Nullable
public static Root[] getSearchRoots(PsiElement element) {
if (element instanceof PsiThrowStatement aThrow) {
PsiExpression exn = aThrow.getException();
return new Root[]{new Root(aThrow.getParent(), exn.getType(), isExactExnType(exn))};
}
if (element instanceof PsiKeyword kwd && PsiKeyword.THROWS.equals(kwd.getText())) {
PsiElement parent = kwd.getParent();
if (parent != null && parent.getParent() instanceof PsiMethod method) {
PsiReferenceList throwsList = method.getThrowsList();
PsiClassType[] exns = throwsList.getReferencedTypes();
Root[] roots = new Root[exns.length];
for (int i = 0; i != roots.length; ++i) {
PsiClassType exn = exns[i];
roots[i] = new Root(method, exn, false); // TODO: test for final
}
return roots;
}
}
}
return null;
}
return null;
}

public static boolean isSearchable(final PsiElement element) {
return getSearchRoots(element) != null;
}

public static String getSearchableTypeName(final PsiElement e) {
if (e instanceof PsiThrowStatement) {
final PsiThrowStatement aThrow = (PsiThrowStatement) e;
final PsiType type = aThrow.getException().getType();
return PsiFormatUtil.formatType(type, PsiFormatUtilBase.SHOW_FQ_CLASS_NAMES, PsiSubstitutor.EMPTY);

public static boolean isSearchable(PsiElement element) {
return getSearchRoots(element) != null;
}
if (e instanceof PsiKeyword && PsiKeyword.THROWS.equals(e.getText())) {
return e.getParent().getText();

@RequiredReadAction
public static String getSearchableTypeName(PsiElement e) {
if (e instanceof PsiThrowStatement aThrow) {
PsiType type = aThrow.getException().getType();
return PsiFormatUtil.formatType(type, PsiFormatUtilBase.SHOW_FQ_CLASS_NAMES, PsiSubstitutor.EMPTY);
}
if (e instanceof PsiKeyword && PsiKeyword.THROWS.equals(e.getText())) {
return e.getParent().getText();
}
LOG.error("invalid searchable element");
return e.getText();
}
LOG.error("invalid searchable element");
return e.getText();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,53 +19,55 @@
*/
package com.intellij.java.indexing.search.searches;

import consulo.project.Project;
import consulo.util.lang.function.Condition;
import com.intellij.java.language.psi.PsiClass;
import consulo.content.scope.SearchScope;
import consulo.application.util.query.ExtensibleQueryFactory;
import consulo.application.util.query.Query;
import consulo.content.scope.SearchScope;
import consulo.project.Project;
import consulo.util.lang.function.Condition;

import java.util.function.Predicate;

public class AllClassesSearch extends ExtensibleQueryFactory<PsiClass, AllClassesSearch.SearchParameters> {
public static final AllClassesSearch INSTANCE = new AllClassesSearch();
public static final AllClassesSearch INSTANCE = new AllClassesSearch();

public static class SearchParameters {
private final SearchScope myScope;
private final Project myProject;
private final Condition<String> myShortNameCondition;
public static class SearchParameters {
private final SearchScope myScope;
private final Project myProject;
private final Predicate<String> myShortNameCondition;

public SearchParameters(final SearchScope scope, final Project project) {
this(scope, project, Condition.TRUE);
}
public SearchParameters(SearchScope scope, Project project) {
this(scope, project, Condition.TRUE);
}

public SearchParameters(final SearchScope scope, final Project project, final Condition<String> shortNameCondition) {
myScope = scope;
myProject = project;
myShortNameCondition = shortNameCondition;
}
public SearchParameters(SearchScope scope, Project project, Predicate<String> shortNameCondition) {
myScope = scope;
myProject = project;
myShortNameCondition = shortNameCondition;
}

public SearchScope getScope() {
return myScope;
}
public SearchScope getScope() {
return myScope;
}

public Project getProject() {
return myProject;
}
public Project getProject() {
return myProject;
}

public boolean nameMatches(String name) {
return myShortNameCondition.value(name);
public boolean nameMatches(String name) {
return myShortNameCondition.test(name);
}
}
}

private AllClassesSearch() {
super(AllClassesSearchExecutor.class);
}
private AllClassesSearch() {
super(AllClassesSearchExecutor.class);
}

public static Query<PsiClass> search(SearchScope scope, Project project) {
return INSTANCE.createQuery(new SearchParameters(scope, project));
}
public static Query<PsiClass> search(SearchScope scope, Project project) {
return INSTANCE.createQuery(new SearchParameters(scope, project));
}

public static Query<PsiClass> search(SearchScope scope, Project project, Condition<String> shortNameCondition) {
return INSTANCE.createQuery(new SearchParameters(scope, project, shortNameCondition));
}
public static Query<PsiClass> search(SearchScope scope, Project project, Predicate<String> shortNameCondition) {
return INSTANCE.createQuery(new SearchParameters(scope, project, shortNameCondition));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

/**
* @author VISTALL
* @since 01-Sep-22
* @since 2022-09-01
*/
@ExtensionAPI(ComponentScope.APPLICATION)
public interface AllClassesSearchExecutor extends QueryExecutor<PsiClass, AllClassesSearch.SearchParameters> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

/**
* @author VISTALL
* @since 01-Sep-22
* @since 2022-09-01
*/
@ExtensionAPI(ComponentScope.APPLICATION)
public interface AllOverridingMethodsSearchExecutor extends QueryExecutor<Pair<PsiMethod, PsiMethod>, AllOverridingMethodsSearch.SearchParameters> {
Expand Down
Loading
Loading