• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015, Google Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 package org.jf.smalidea.findUsages;
33 
34 import com.intellij.openapi.application.ApplicationManager;
35 import com.intellij.openapi.application.QueryExecutorBase;
36 import com.intellij.openapi.progress.EmptyProgressIndicator;
37 import com.intellij.openapi.util.Computable;
38 import com.intellij.psi.PsiClass;
39 import com.intellij.psi.PsiElement;
40 import com.intellij.psi.PsiFile;
41 import com.intellij.psi.PsiReference;
42 import com.intellij.psi.impl.search.LowLevelSearchUtil;
43 import com.intellij.psi.search.*;
44 import com.intellij.psi.search.searches.ReferencesSearch;
45 import com.intellij.psi.search.searches.ReferencesSearch.SearchParameters;
46 import com.intellij.util.Processor;
47 import com.intellij.util.text.StringSearcher;
48 import org.jetbrains.annotations.NotNull;
49 import org.jf.smalidea.util.NameUtils;
50 
51 public class SmaliClassReferenceSearcher extends QueryExecutorBase<PsiReference, ReferencesSearch.SearchParameters> {
processQuery(final SearchParameters queryParameters, final Processor<PsiReference> consumer)52     @Override public void processQuery(final SearchParameters queryParameters, final Processor<PsiReference> consumer) {
53         final PsiElement element = queryParameters.getElementToSearch();
54         if (!(element instanceof PsiClass)) {
55             return;
56         }
57 
58         String smaliType = ApplicationManager.getApplication().runReadAction(
59                 new Computable<String>() {
60                     @Override public String compute() {
61                         String qualifiedName = ((PsiClass)element).getQualifiedName();
62                         if (qualifiedName != null) {
63                             return NameUtils.javaToSmaliType((PsiClass)element);
64                         }
65                         return null;
66                     }
67                 });
68         if (smaliType == null) {
69             return;
70         }
71 
72         final StringSearcher stringSearcher = new StringSearcher(smaliType, true, true, false, false);
73 
74         final SingleTargetRequestResultProcessor processor = new SingleTargetRequestResultProcessor(element);
75 
76         SearchScope querySearchScope = ApplicationManager.getApplication().runReadAction(
77                 new Computable<SearchScope>() {
78                     @Override public SearchScope compute() {
79                         return queryParameters.getEffectiveSearchScope();
80                     }
81                 });
82 
83         if (querySearchScope instanceof LocalSearchScope) {
84             for (final PsiElement scopeElement : ((LocalSearchScope)querySearchScope).getScope()) {
85                 ApplicationManager.getApplication().runReadAction(new Runnable() {
86                     @Override
87                     public void run() {
88                         LowLevelSearchUtil.processElementsContainingWordInElement(
89                                 new TextOccurenceProcessor() {
90                                     @Override public boolean execute(
91                                             @NotNull PsiElement element, int offsetInElement) {
92                                         return processor.processTextOccurrence(element, offsetInElement, consumer);
93                                     }
94                                 },
95                                 scopeElement, stringSearcher, true, new EmptyProgressIndicator());
96                     }
97                 });
98             }
99         } else if (querySearchScope instanceof GlobalSearchScope) {
100             PsiSearchHelper helper = PsiSearchHelper.SERVICE.getInstance(element.getProject());
101             // TODO: limit search scope to only smali files. See, e.g. AnnotatedPackagesSearcher.PackageInfoFilesOnly
102             helper.processAllFilesWithWord(smaliType, (GlobalSearchScope)querySearchScope,
103                     new Processor<PsiFile>() {
104                         @Override
105                         public boolean process(PsiFile file) {
106                             LowLevelSearchUtil.processElementsContainingWordInElement(
107                                     new TextOccurenceProcessor() {
108                                         @Override public boolean execute(
109                                                 @NotNull PsiElement element, int offsetInElement) {
110                                             return processor.processTextOccurrence(element, offsetInElement, consumer);
111                                         }
112                                     },
113                                     file, stringSearcher, true, new EmptyProgressIndicator());
114                             return true;
115                         }
116                     }, true);
117         } else {
118             assert false;
119             return;
120         }
121     }
122 }
123