package org.jetbrains.plugins.clojure.findUsages;
import com.intellij.openapi.application.QueryExecutorBase;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiVariable;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.RequestResultProcessor;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.UsageSearchContext;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.clojure.file.ClojureFileType;
import org.jetbrains.plugins.clojure.psi.api.symbols.ClSymbol;
/**
* @author ilyas
*/
public class ClojureReferenceSearcher extends QueryExecutorBase<PsiReference, ReferencesSearch.SearchParameters> {
public ClojureReferenceSearcher() {
super(true);
}
@Override
public void processQuery(@NotNull ReferencesSearch.SearchParameters params, @NotNull Processor<PsiReference> consumer) {
final PsiElement elem = params.getElementToSearch();
SearchScope scope = params.getEffectiveSearchScope();
if (elem instanceof PsiNamedElement
/* An optimization for Java refactorings */
&& !(elem instanceof PsiVariable)) {
final PsiNamedElement symbolToSearch = (PsiNamedElement) elem;
final String name = symbolToSearch.getName();
if (name != null) {
RequestResultProcessor processor = new RequestResultProcessor() {
@Override
public boolean processTextOccurrence(@NotNull PsiElement element, int offsetInElement, @NotNull Processor<PsiReference> consumer) {
if (element instanceof ClSymbol) {
ClSymbol refSymbol = (ClSymbol) element;
for (PsiReference ref : refSymbol.getReferences()) {
if (ref.getRangeInElement().contains(offsetInElement) &&
// atom may refer to definition or to the symbol in it
(ref.resolve() == symbolToSearch ||
ref.resolve() == symbolToSearch.getParent())) {
if (!consumer.process(ref)) return false;
}
}
}
return true;
}
};
if (scope instanceof GlobalSearchScope) {
scope = GlobalSearchScope.getScopeRestrictedByFileTypes((GlobalSearchScope) scope, ClojureFileType.CLOJURE_FILE_TYPE);
}
for (String word : StringUtil.getWordsIn(name)) {
params.getOptimizer().searchWord(word, scope, UsageSearchContext.ANY, true, processor);
}
}
}
}
}