• 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.google.common.collect.Lists;
35 import com.intellij.codeInsight.TargetElementUtilBase;
36 import com.intellij.find.FindManager;
37 import com.intellij.find.findUsages.FindUsagesHandler;
38 import com.intellij.find.findUsages.FindUsagesManager;
39 import com.intellij.find.findUsages.FindUsagesOptions;
40 import com.intellij.find.impl.FindManagerImpl;
41 import com.intellij.psi.PsiElement;
42 import com.intellij.psi.PsiFile;
43 import com.intellij.psi.PsiReference;
44 import com.intellij.testFramework.PsiTestCase;
45 import com.intellij.usageView.UsageInfo;
46 import com.intellij.usages.PsiElementUsageTarget;
47 import com.intellij.usages.UsageTarget;
48 import com.intellij.usages.UsageTargetUtil;
49 import com.intellij.util.CommonProcessors;
50 import org.jetbrains.annotations.NotNull;
51 import org.junit.Assert;
52 
53 import java.util.Collection;
54 import java.util.List;
55 import java.util.regex.Matcher;
56 import java.util.regex.Pattern;
57 
58 public abstract class FindUsagesTest extends PsiTestCase {
59     public static final String USAGE_TAG = "<usage>";
60     public static final String REF_TAG = "<ref>";
61 
62     private class TestFile {
63         @NotNull public final String fileName;
64         @NotNull public final String fileText;
65         @NotNull public final PsiFile psiFile;
66 
TestFile(@otNull String fileName, @NotNull String fileText)67         public TestFile(@NotNull String fileName, @NotNull String fileText) throws Exception {
68             this.fileName = fileName;
69             this.fileText = fileText;
70             this.psiFile = createFile(fileName, getText());
71         }
72 
73         @NotNull
getText()74         public String getText() {
75             return fileText.replace(REF_TAG, "").replace(USAGE_TAG, "");
76         }
77 
getRefIndex()78         public int getRefIndex() {
79             return fileText.replace(USAGE_TAG, "").indexOf(REF_TAG);
80         }
81 
getUsageIndices()82         public List<Integer> getUsageIndices() {
83             Matcher matcher = Pattern.compile(USAGE_TAG).matcher(fileText.replace(REF_TAG, ""));
84             List<Integer> matches = Lists.newArrayList();
85 
86             int adjustment = 0;
87             while (matcher.find()) {
88                 matches.add(matcher.start() - adjustment);
89                 adjustment += USAGE_TAG.length();
90             }
91             return matches;
92         }
93     }
94 
95     private List<TestFile> testFiles;
96 
97     @Override
setUp()98     public void setUp() throws Exception {
99         testFiles = Lists.newArrayList();
100         super.setUp();
101     }
102 
addFile(String fileName, String fileText)103     protected void addFile(String fileName, String fileText) throws Exception {
104         testFiles.add(new TestFile(fileName, fileText));
105     }
106 
doTest()107     protected void doTest() {
108 
109         PsiReference reference = null;
110         PsiElement targetElement = null;
111 
112         for (TestFile testFile: testFiles) {
113             int refIndex = testFile.getRefIndex();
114             if (refIndex != -1) {
115                 PsiElement element = testFile.psiFile.findElementAt(refIndex);
116 
117                 UsageTarget[] targets = UsageTargetUtil.findUsageTargets(element);
118                 if (targets != null) {
119                     for (UsageTarget target : targets) {
120                         if (target instanceof PsiElementUsageTarget) {
121                             targetElement = ((PsiElementUsageTarget)target).getElement();
122                             break;
123                         }
124                     }
125                 }
126 
127                 if (targetElement == null) {
128                     reference = testFile.psiFile.findReferenceAt(refIndex);
129                     if (reference != null) {
130                         targetElement = reference.resolve();
131                     } else {
132                         targetElement = TargetElementUtilBase.getInstance().getNamedElement(
133                                 testFile.psiFile.findElementAt(refIndex), 0);
134                     }
135                 }
136                 break;
137             }
138         }
139 
140         Assert.assertNotNull(targetElement);
141 
142         Collection<UsageInfo> usages = findUsages(targetElement);
143         for (TestFile testFile: testFiles) {
144             assertUsages(testFile, usages);
145         }
146     }
147 
assertUsages(@otNull TestFile testFile, @NotNull Collection<UsageInfo> usages)148     private void assertUsages(@NotNull TestFile testFile, @NotNull Collection<UsageInfo> usages) {
149         List<UsageInfo> fileUsages = Lists.newArrayList();
150         for (UsageInfo usage: usages) {
151             if (usage.getFile().getName().equals(testFile.fileName)) {
152                 fileUsages.add(usage);
153             }
154         }
155 
156         for (Integer usageIndex: testFile.getUsageIndices()) {
157             boolean found = false;
158             for (UsageInfo usage: fileUsages) {
159                 int startOffset = usage.getElement().getNode().getStartOffset();
160                 int length = usage.getElement().getTextLength();
161 
162                 if (usageIndex >= startOffset && usageIndex < startOffset + length) {
163                     fileUsages.remove(usage);
164                     found = true;
165                     break;
166                 }
167             }
168             Assert.assertTrue(found);
169         }
170         Assert.assertEquals(0, fileUsages.size());
171     }
172 
findUsages(@otNull PsiElement element)173     private Collection<UsageInfo> findUsages(@NotNull PsiElement element) {
174         FindUsagesManager findUsagesManager =
175                 ((FindManagerImpl)FindManager.getInstance(getProject())).getFindUsagesManager();
176 
177         FindUsagesHandler findUsagesHandler =
178                 findUsagesManager.getFindUsagesHandler(element, false);
179         Assert.assertNotNull(findUsagesHandler);
180 
181         final FindUsagesOptions options = findUsagesHandler.getFindUsagesOptions();
182         final CommonProcessors.CollectProcessor<UsageInfo> processor =
183                 new CommonProcessors.CollectProcessor<UsageInfo>();
184 
185         for (PsiElement primaryElement : findUsagesHandler.getPrimaryElements()) {
186             findUsagesHandler.processElementUsages(primaryElement, processor, options);
187         }
188 
189         for (PsiElement secondaryElement: findUsagesHandler.getSecondaryElements()) {
190             findUsagesHandler.processElementUsages(secondaryElement, processor, options);
191         }
192 
193         return processor.getResults();
194     }
195 }
196