Home | History | Annotate | Download | only in findUsages
      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 
     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
     74         public String getText() {
     75             return fileText.replace(REF_TAG, "").replace(USAGE_TAG, "");
     76         }
     77 
     78         public int getRefIndex() {
     79             return fileText.replace(USAGE_TAG, "").indexOf(REF_TAG);
     80         }
     81 
     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
     98     public void setUp() throws Exception {
     99         testFiles = Lists.newArrayList();
    100         super.setUp();
    101     }
    102 
    103     protected void addFile(String fileName, String fileText) throws Exception {
    104         testFiles.add(new TestFile(fileName, fileText));
    105     }
    106 
    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 
    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 
    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