/* * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jf.smalidea.findUsages; import com.google.common.collect.Lists; import com.intellij.codeInsight.TargetElementUtilBase; import com.intellij.find.FindManager; import com.intellij.find.findUsages.FindUsagesHandler; import com.intellij.find.findUsages.FindUsagesManager; import com.intellij.find.findUsages.FindUsagesOptions; import com.intellij.find.impl.FindManagerImpl; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiReference; import com.intellij.testFramework.PsiTestCase; import com.intellij.usageView.UsageInfo; import com.intellij.usages.PsiElementUsageTarget; import com.intellij.usages.UsageTarget; import com.intellij.usages.UsageTargetUtil; import com.intellij.util.CommonProcessors; import org.jetbrains.annotations.NotNull; import org.junit.Assert; import java.util.Collection; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; public abstract class FindUsagesTest extends PsiTestCase { public static final String USAGE_TAG = "<usage>"; public static final String REF_TAG = "<ref>"; private class TestFile { @NotNull public final String fileName; @NotNull public final String fileText; @NotNull public final PsiFile psiFile; public TestFile(@NotNull String fileName, @NotNull String fileText) throws Exception { this.fileName = fileName; this.fileText = fileText; this.psiFile = createFile(fileName, getText()); } @NotNull public String getText() { return fileText.replace(REF_TAG, "").replace(USAGE_TAG, ""); } public int getRefIndex() { return fileText.replace(USAGE_TAG, "").indexOf(REF_TAG); } public List<Integer> getUsageIndices() { Matcher matcher = Pattern.compile(USAGE_TAG).matcher(fileText.replace(REF_TAG, "")); List<Integer> matches = Lists.newArrayList(); int adjustment = 0; while (matcher.find()) { matches.add(matcher.start() - adjustment); adjustment += USAGE_TAG.length(); } return matches; } } private List<TestFile> testFiles; @Override public void setUp() throws Exception { testFiles = Lists.newArrayList(); super.setUp(); } protected void addFile(String fileName, String fileText) throws Exception { testFiles.add(new TestFile(fileName, fileText)); } protected void doTest() { PsiReference reference = null; PsiElement targetElement = null; for (TestFile testFile: testFiles) { int refIndex = testFile.getRefIndex(); if (refIndex != -1) { PsiElement element = testFile.psiFile.findElementAt(refIndex); UsageTarget[] targets = UsageTargetUtil.findUsageTargets(element); if (targets != null) { for (UsageTarget target : targets) { if (target instanceof PsiElementUsageTarget) { targetElement = ((PsiElementUsageTarget)target).getElement(); break; } } } if (targetElement == null) { reference = testFile.psiFile.findReferenceAt(refIndex); if (reference != null) { targetElement = reference.resolve(); } else { targetElement = TargetElementUtilBase.getInstance().getNamedElement( testFile.psiFile.findElementAt(refIndex), 0); } } break; } } Assert.assertNotNull(targetElement); Collection<UsageInfo> usages = findUsages(targetElement); for (TestFile testFile: testFiles) { assertUsages(testFile, usages); } } private void assertUsages(@NotNull TestFile testFile, @NotNull Collection<UsageInfo> usages) { List<UsageInfo> fileUsages = Lists.newArrayList(); for (UsageInfo usage: usages) { if (usage.getFile().getName().equals(testFile.fileName)) { fileUsages.add(usage); } } for (Integer usageIndex: testFile.getUsageIndices()) { boolean found = false; for (UsageInfo usage: fileUsages) { int startOffset = usage.getElement().getNode().getStartOffset(); int length = usage.getElement().getTextLength(); if (usageIndex >= startOffset && usageIndex < startOffset + length) { fileUsages.remove(usage); found = true; break; } } Assert.assertTrue(found); } Assert.assertEquals(0, fileUsages.size()); } private Collection<UsageInfo> findUsages(@NotNull PsiElement element) { FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(getProject())).getFindUsagesManager(); FindUsagesHandler findUsagesHandler = findUsagesManager.getFindUsagesHandler(element, false); Assert.assertNotNull(findUsagesHandler); final FindUsagesOptions options = findUsagesHandler.getFindUsagesOptions(); final CommonProcessors.CollectProcessor<UsageInfo> processor = new CommonProcessors.CollectProcessor<UsageInfo>(); for (PsiElement primaryElement : findUsagesHandler.getPrimaryElements()) { findUsagesHandler.processElementUsages(primaryElement, processor, options); } for (PsiElement secondaryElement: findUsagesHandler.getSecondaryElements()) { findUsagesHandler.processElementUsages(secondaryElement, processor, options); } return processor.getResults(); } }