Implement "Find usages with options" for kotlin functions
This commit is contained in:
@@ -460,6 +460,12 @@ public class GenerateTests {
|
||||
testModelWithFileName(
|
||||
"idea/testData/findUsages/findMethodUsages/kotlinMethodUsages", "Server.kt", "testFindMethodKotlinUsages"
|
||||
),
|
||||
testModelWithFileName(
|
||||
"idea/testData/findUsages/findMethodUsages/javaAndKotlinOverrides", "Server.kt", "testFindMethodJavaUsages"
|
||||
),
|
||||
testModelWithFileName(
|
||||
"idea/testData/findUsages/findMethodUsages/kotlinOverloadUsages", "Server.kt", "testFindMethodKotlinUsages"
|
||||
),
|
||||
testModelWithFileName(
|
||||
"idea/testData/findUsages/findPropertyUsages/javaPropertyUsages", "Server.kt", "testFindPropertyJavaUsages"
|
||||
),
|
||||
|
||||
@@ -265,4 +265,8 @@ choose.the.ones.you.want.to.be.deleted=Choose the ones you want to be deleted.
|
||||
method.column=Member
|
||||
delete.param.in.method.hierarchy={0} is a part of method hierarchy. Do you want to delete multiple parameters?
|
||||
super.methods.delete.with.usage.search=delete (with usage search)
|
||||
super.methods.action.key.find.usages=find usages of
|
||||
super.methods.action.key.find.usages=find usages of
|
||||
|
||||
find.what.implementing.methods.checkbox=&Implementing functions
|
||||
find.what.overriding.methods.checkbox=Over&riding functions
|
||||
find.options.include.overloaded.methods.checkbox=Include o&verloaded functions and extensions
|
||||
@@ -18,10 +18,12 @@ package org.jetbrains.jet.plugin.findUsages;
|
||||
|
||||
import com.intellij.find.findUsages.FindUsagesHandler;
|
||||
import com.intellij.find.findUsages.FindUsagesHandlerFactory;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.JetClass;
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
||||
import org.jetbrains.jet.plugin.findUsages.options.KotlinMethodFindUsagesOptions;
|
||||
import org.jetbrains.jet.lang.psi.JetNamedFunction;
|
||||
import org.jetbrains.jet.plugin.findUsages.handlers.KotlinFindClassUsagesHandler;
|
||||
import org.jetbrains.jet.plugin.findUsages.handlers.KotlinFindFunctionUsagesHandler;
|
||||
@@ -30,6 +32,16 @@ import org.jetbrains.jet.plugin.refactoring.JetRefactoringUtil;
|
||||
import java.util.Collection;
|
||||
|
||||
public class KotlinFindUsagesHandlerFactory extends FindUsagesHandlerFactory {
|
||||
private final KotlinMethodFindUsagesOptions findMethodOptions;
|
||||
|
||||
public KotlinFindUsagesHandlerFactory(@NotNull Project project) {
|
||||
findMethodOptions = new KotlinMethodFindUsagesOptions(project);
|
||||
}
|
||||
|
||||
public final KotlinMethodFindUsagesOptions getFindMethodOptions() {
|
||||
return findMethodOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canFindUsages(@NotNull PsiElement element) {
|
||||
return element instanceof JetClass || element instanceof JetNamedFunction;
|
||||
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
package org.jetbrains.jet.plugin.findUsages.dialogs;
|
||||
|
||||
import com.intellij.find.FindBundle;
|
||||
import com.intellij.find.FindSettings;
|
||||
import com.intellij.find.findUsages.FindMethodUsagesDialog;
|
||||
import com.intellij.find.findUsages.FindUsagesHandler;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.ui.SimpleColoredComponent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.plugin.JetBundle;
|
||||
import org.jetbrains.jet.plugin.findUsages.options.KotlinMethodFindUsagesOptions;
|
||||
import org.jetbrains.jet.plugin.refactoring.JetRefactoringUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class KotlinFindMethodUsagesDialog extends FindMethodUsagesDialog {
|
||||
public KotlinFindMethodUsagesDialog(
|
||||
PsiMethod method,
|
||||
Project project,
|
||||
KotlinMethodFindUsagesOptions findUsagesOptions,
|
||||
boolean toShowInNewTab,
|
||||
boolean mustOpenInNewTab,
|
||||
boolean isSingleFile,
|
||||
FindUsagesHandler handler
|
||||
) {
|
||||
super(method, project, findUsagesOptions, toShowInNewTab, mustOpenInNewTab, isSingleFile, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected KotlinMethodFindUsagesOptions getFindUsagesOptions() {
|
||||
return (KotlinMethodFindUsagesOptions) super.getFindUsagesOptions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureLabelComponent(@NotNull SimpleColoredComponent coloredComponent) {
|
||||
coloredComponent.append(JetRefactoringUtil.formatJavaOrLightMethod((PsiMethod) myPsiElement));
|
||||
}
|
||||
|
||||
private static boolean renameCheckbox(@NotNull JPanel panel, @NotNull String srcText, @NotNull String destText) {
|
||||
for (Component component : panel.getComponents()) {
|
||||
if (component instanceof JCheckBox) {
|
||||
JCheckBox checkBox = (JCheckBox) component;
|
||||
if (checkBox.getText().equals(srcText)) {
|
||||
checkBox.setText(destText);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JPanel createFindWhatPanel() {
|
||||
JPanel findWhatPanel = super.createFindWhatPanel();
|
||||
if (findWhatPanel != null) {
|
||||
renameCheckbox(
|
||||
findWhatPanel,
|
||||
FindBundle.message("find.what.implementing.methods.checkbox"),
|
||||
JetBundle.message("find.what.implementing.methods.checkbox")
|
||||
);
|
||||
renameCheckbox(
|
||||
findWhatPanel,
|
||||
FindBundle.message("find.what.overriding.methods.checkbox"),
|
||||
JetBundle.message("find.what.overriding.methods.checkbox")
|
||||
);
|
||||
}
|
||||
|
||||
return findWhatPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addUsagesOptions(JPanel optionsPanel) {
|
||||
super.addUsagesOptions(optionsPanel);
|
||||
|
||||
if (!renameCheckbox(
|
||||
optionsPanel,
|
||||
FindBundle.message("find.options.include.overloaded.methods.checkbox"),
|
||||
JetBundle.message("find.options.include.overloaded.methods.checkbox")
|
||||
)) {
|
||||
addCheckboxToPanel(
|
||||
JetBundle.message("find.options.include.overloaded.methods.checkbox"),
|
||||
FindSettings.getInstance().isSearchOverloadedMethods(),
|
||||
optionsPanel,
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
+104
@@ -16,9 +16,27 @@
|
||||
|
||||
package org.jetbrains.jet.plugin.findUsages.handlers;
|
||||
|
||||
import com.intellij.find.findUsages.AbstractFindUsagesDialog;
|
||||
import com.intellij.find.findUsages.FindUsagesOptions;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadActionProcessor;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.PsiElementProcessor;
|
||||
import com.intellij.psi.search.PsiElementProcessorAdapter;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.MethodReferencesSearch;
|
||||
import com.intellij.psi.search.searches.OverridingMethodsSearch;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.asJava.LightClassUtil;
|
||||
import org.jetbrains.jet.lang.psi.JetNamedFunction;
|
||||
import org.jetbrains.jet.plugin.findUsages.KotlinFindUsagesHandlerFactory;
|
||||
import org.jetbrains.jet.plugin.findUsages.dialogs.KotlinFindMethodUsagesDialog;
|
||||
import org.jetbrains.jet.plugin.findUsages.options.KotlinMethodFindUsagesOptions;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@@ -34,4 +52,90 @@ public class KotlinFindFunctionUsagesHandler extends KotlinFindUsagesHandler<Jet
|
||||
public KotlinFindFunctionUsagesHandler(@NotNull JetNamedFunction function, @NotNull KotlinFindUsagesHandlerFactory factory) {
|
||||
super(function, factory);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public AbstractFindUsagesDialog getFindUsagesDialog(boolean isSingleFile, boolean toShowInNewTab, boolean mustOpenInNewTab) {
|
||||
PsiMethod lightMethod = LightClassUtil.getLightClassMethod(getElement());
|
||||
if (lightMethod != null) {
|
||||
return new KotlinFindMethodUsagesDialog(
|
||||
lightMethod, getProject(), getFactory().getFindMethodOptions(), toShowInNewTab, mustOpenInNewTab, isSingleFile, this
|
||||
);
|
||||
}
|
||||
|
||||
return super.getFindUsagesDialog(isSingleFile, toShowInNewTab, mustOpenInNewTab);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean searchReferences(
|
||||
@NotNull PsiElement element,
|
||||
@NotNull final Processor<UsageInfo> processor,
|
||||
@NotNull FindUsagesOptions options
|
||||
) {
|
||||
final KotlinMethodFindUsagesOptions kotlinOptions = (KotlinMethodFindUsagesOptions)options;
|
||||
SearchScope searchScope = kotlinOptions.searchScope;
|
||||
|
||||
final PsiMethod lightMethod = ApplicationManager.getApplication().runReadAction(new Computable<PsiMethod>() {
|
||||
@Override
|
||||
public PsiMethod compute() {
|
||||
return LightClassUtil.getLightClassMethod(getElement());
|
||||
}
|
||||
});
|
||||
if (lightMethod == null) return true;
|
||||
|
||||
if (kotlinOptions.isUsages) {
|
||||
boolean strictSignatureSearch = !kotlinOptions.isIncludeOverloadUsages;
|
||||
if (!MethodReferencesSearch
|
||||
.search(
|
||||
new MethodReferencesSearch.SearchParameters(
|
||||
lightMethod, searchScope, strictSignatureSearch, kotlinOptions.fastTrack
|
||||
)
|
||||
)
|
||||
.forEach(
|
||||
new ReadActionProcessor<PsiReference>() {
|
||||
@Override
|
||||
public boolean processInReadAction(PsiReference ref) {
|
||||
return processUsage(processor, ref, kotlinOptions);
|
||||
}
|
||||
}
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isAbstract = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
return lightMethod.hasModifierProperty(PsiModifier.ABSTRACT);
|
||||
}
|
||||
});
|
||||
|
||||
if (isAbstract && kotlinOptions.isImplementingMethods || kotlinOptions.isOverridingMethods) {
|
||||
OverridingMethodsSearch.search(lightMethod, options.searchScope, kotlinOptions.isCheckDeepInheritance).forEach(
|
||||
new PsiElementProcessorAdapter<PsiMethod>(
|
||||
new PsiElementProcessor<PsiMethod>() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiMethod element) {
|
||||
return processUsage(processor, element.getNavigationElement(), kotlinOptions);
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSearchForTextOccurencesAvailable(@NotNull PsiElement psiElement, boolean isSingleFile) {
|
||||
return psiElement instanceof JetNamedFunction || psiElement instanceof PsiMethod;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FindUsagesOptions getFindUsagesOptions(@Nullable DataContext dataContext) {
|
||||
return getFactory().getFindMethodOptions();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -17,10 +17,20 @@
|
||||
package org.jetbrains.jet.plugin.findUsages.handlers;
|
||||
|
||||
import com.intellij.find.findUsages.FindUsagesHandler;
|
||||
import com.intellij.find.findUsages.JavaFindUsagesHandlerFactory;
|
||||
import com.intellij.find.findUsages.FindUsagesOptions;
|
||||
import com.intellij.find.findUsages.JavaFindUsagesOptions;
|
||||
import com.intellij.openapi.application.ReadActionProcessor;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetImportDirective;
|
||||
import org.jetbrains.jet.plugin.findUsages.KotlinFindUsagesHandlerFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -54,6 +64,30 @@ public abstract class KotlinFindUsagesHandler<T extends PsiElement> extends Find
|
||||
return factory;
|
||||
}
|
||||
|
||||
protected static boolean filterUsage(@NotNull PsiElement usage, @NotNull FindUsagesOptions options) {
|
||||
if (options instanceof JavaFindUsagesOptions && ((JavaFindUsagesOptions) options).isSkipImportStatements) {
|
||||
if (PsiTreeUtil.getParentOfType(usage, JetImportDirective.class) != null) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected static boolean processUsage(Processor<UsageInfo> processor, PsiReference ref, FindUsagesOptions options) {
|
||||
if (filterUsage(ref.getElement(), options)){
|
||||
TextRange rangeInElement = ref.getRangeInElement();
|
||||
return processor.process(new UsageInfo(ref.getElement(), rangeInElement.getStartOffset(), rangeInElement.getEndOffset(), false));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected static boolean processUsage(
|
||||
@NotNull Processor<UsageInfo> processor,
|
||||
@NotNull PsiElement element,
|
||||
@NotNull FindUsagesOptions options
|
||||
) {
|
||||
return !filterUsage(element, options) || processor.process(new UsageInfo(element));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement[] getPrimaryElements() {
|
||||
@@ -61,4 +95,60 @@ public abstract class KotlinFindUsagesHandler<T extends PsiElement> extends Find
|
||||
? new PsiElement[] {getPsiElement()}
|
||||
: elementsToSearch.toArray(new PsiElement[elementsToSearch.size()]);
|
||||
}
|
||||
|
||||
protected boolean searchReferences(
|
||||
@NotNull PsiElement element,
|
||||
@NotNull final Processor<UsageInfo> processor,
|
||||
@NotNull FindUsagesOptions options
|
||||
) {
|
||||
if (options.isUsages) {
|
||||
boolean success = ReferencesSearch.search(
|
||||
new ReferencesSearch.SearchParameters(element, options.searchScope, false, options.fastTrack)
|
||||
).forEach(new ReadActionProcessor<PsiReference>() {
|
||||
@Override
|
||||
public boolean processInReadAction(PsiReference ref) {
|
||||
TextRange rangeInElement = ref.getRangeInElement();
|
||||
return processor.process(
|
||||
new UsageInfo(ref.getElement(), rangeInElement.getStartOffset(), rangeInElement.getEndOffset(), false)
|
||||
);
|
||||
}
|
||||
});
|
||||
if (!success) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean searchTextOccurrences(
|
||||
@NotNull final PsiElement element,
|
||||
@NotNull final Processor<UsageInfo> processor,
|
||||
@NotNull FindUsagesOptions options
|
||||
) {
|
||||
final SearchScope scope = options.searchScope;
|
||||
|
||||
boolean searchText = options.isSearchForTextOccurrences && scope instanceof GlobalSearchScope;
|
||||
|
||||
if (searchText) {
|
||||
if (options.fastTrack != null) {
|
||||
options.fastTrack.searchCustom(new Processor<Processor<PsiReference>>() {
|
||||
@Override
|
||||
public boolean process(Processor<PsiReference> consumer) {
|
||||
return processUsagesInText(element, processor, (GlobalSearchScope)scope);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
return processUsagesInText(element, processor, (GlobalSearchScope)scope);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processElementUsages(
|
||||
@NotNull PsiElement element,
|
||||
@NotNull Processor<UsageInfo> processor,
|
||||
@NotNull FindUsagesOptions options
|
||||
) {
|
||||
return searchReferences(element, processor, options) && searchTextOccurrences(element, processor, options);
|
||||
}
|
||||
}
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package org.jetbrains.jet.plugin.findUsages.options;
|
||||
|
||||
import com.intellij.find.findUsages.JavaMethodFindUsagesOptions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class KotlinMethodFindUsagesOptions extends JavaMethodFindUsagesOptions {
|
||||
public KotlinMethodFindUsagesOptions(@NotNull Project project) {
|
||||
super(project);
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.java.JetClsMethod;
|
||||
import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -86,7 +87,8 @@ public abstract class JetPsiReference implements PsiPolyVariantReference {
|
||||
@Override
|
||||
public boolean isReferenceTo(PsiElement element) {
|
||||
PsiElement target = resolve();
|
||||
return target == element || target != null && target.getNavigationElement() == element;
|
||||
PsiElement mirrorElement = element instanceof JetClsMethod ? ((JetClsMethod) element).getOrigin() : null;
|
||||
return target == element || (mirrorElement != null && target == mirrorElement) || (target != null && target.getNavigationElement() == element);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
class C extends A<String> {
|
||||
@Override
|
||||
public void foo(String s) {
|
||||
super.foo(s);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// OPTIONS: overrides
|
||||
open class A<T> {
|
||||
open fun <caret>foo(t: T) {
|
||||
println(t)
|
||||
}
|
||||
|
||||
open fun foo(t: T, tt: T) {
|
||||
println(t)
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> A<T>.foo(t: T, x: String) {
|
||||
foo(t)
|
||||
println(x)
|
||||
}
|
||||
|
||||
fun A<String>.foo(s: String, n: Number) {
|
||||
fun <T> A<T>.foo(t: T, x: String) {
|
||||
foo(t)
|
||||
println(x)
|
||||
}
|
||||
|
||||
foo(s)
|
||||
println(n)
|
||||
}
|
||||
|
||||
open class B: A<String>() {
|
||||
override fun foo(t: String) {
|
||||
super<A>.foo(t)
|
||||
}
|
||||
|
||||
open fun baz(a: A<String>) {
|
||||
a.foo("", 0)
|
||||
}
|
||||
|
||||
open fun baz(a: A<Number>) {
|
||||
a.foo(0, "")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
Unclassified usage (28: 18) override fun foo(t: String) {
|
||||
Unclassified usage (3: 17) public void foo(String s) {
|
||||
@@ -1,3 +1,4 @@
|
||||
// OPTIONS: usages
|
||||
package testing;
|
||||
|
||||
public class Server() {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// OPTIONS: usages
|
||||
package server;
|
||||
|
||||
fun <caret>processRequest() = "foo"
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
open class B: A<String>() {
|
||||
override fun foo(t: String) {
|
||||
super<A>.foo(t)
|
||||
}
|
||||
|
||||
open fun baz(a: A<String>) {
|
||||
a.foo("", 0)
|
||||
}
|
||||
|
||||
open fun baz(a: A<Number>) {
|
||||
a.foo(0, "")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// OPTIONS: overloadUsages
|
||||
open class A<T> {
|
||||
open fun <caret>foo(t: T) {
|
||||
println(t)
|
||||
}
|
||||
|
||||
open fun foo(t: T, tt: T) {
|
||||
println(t)
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> A<T>.foo(t: T, x: String) {
|
||||
foo(t)
|
||||
println(x)
|
||||
}
|
||||
|
||||
fun A<String>.foo(s: String, n: Number) {
|
||||
fun <T> A<T>.foo(t: T, x: String) {
|
||||
foo(t)
|
||||
println(x)
|
||||
}
|
||||
|
||||
foo(s)
|
||||
println(n)
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
Function call (13: 5) foo(t)
|
||||
Function call (19: 9) foo(t)
|
||||
Function call (23: 5) foo(s)
|
||||
Function call (3: 18) super<A>.foo(t)
|
||||
@@ -22,7 +22,12 @@ import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.intellij.find.FindManager;
|
||||
import com.intellij.find.findUsages.FindUsagesHandler;
|
||||
import com.intellij.find.findUsages.FindUsagesOptions;
|
||||
import com.intellij.find.impl.FindManagerImpl;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiComment;
|
||||
@@ -35,8 +40,11 @@ import com.intellij.usages.UsageInfo2UsageAdapter;
|
||||
import com.intellij.usages.impl.rules.UsageType;
|
||||
import com.intellij.usages.impl.rules.UsageTypeProvider;
|
||||
import com.intellij.usages.rules.UsageFilteringRule;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.CommonProcessors;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.InTextDirectivesUtils;
|
||||
import org.jetbrains.jet.lang.psi.JetClass;
|
||||
import org.jetbrains.jet.lang.psi.JetFunction;
|
||||
import org.jetbrains.jet.lang.psi.JetObjectDeclarationName;
|
||||
@@ -44,6 +52,7 @@ import org.jetbrains.jet.lang.psi.JetProperty;
|
||||
import org.jetbrains.jet.plugin.JetLightProjectDescriptor;
|
||||
import org.jetbrains.jet.plugin.PluginTestCaseBase;
|
||||
import org.jetbrains.jet.plugin.findUsages.JetImportFilteringRule;
|
||||
import org.jetbrains.jet.plugin.findUsages.options.KotlinMethodFindUsagesOptions;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -52,6 +61,37 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
public abstract class AbstractJetFindUsagesTest extends LightCodeInsightFixtureTestCase {
|
||||
private interface OptionsParser {
|
||||
@NotNull
|
||||
FindUsagesOptions parse(@NotNull String text, @NotNull Project project);
|
||||
}
|
||||
|
||||
private static final OptionsParser METHOD_OPTIONS_PARSER = new OptionsParser() {
|
||||
@Override
|
||||
@NotNull
|
||||
public FindUsagesOptions parse(@NotNull String text, @NotNull Project project) {
|
||||
KotlinMethodFindUsagesOptions options = new KotlinMethodFindUsagesOptions(project);
|
||||
options.isUsages = false;
|
||||
for (String s : InTextDirectivesUtils.findListWithPrefixes(text, "// OPTIONS: ")) {
|
||||
if (s.equals("usages")) {
|
||||
options.isUsages = true;
|
||||
}
|
||||
|
||||
if (s.equals("overrides")) {
|
||||
options.isOverridingMethods = true;
|
||||
options.isImplementingMethods = true;
|
||||
}
|
||||
|
||||
if (s.equals("overloadUsages")) {
|
||||
options.isIncludeOverloadUsages = true;
|
||||
options.isUsages = true;
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected LightProjectDescriptor getProjectDescriptor() {
|
||||
@@ -65,58 +105,60 @@ public abstract class AbstractJetFindUsagesTest extends LightCodeInsightFixtureT
|
||||
}
|
||||
|
||||
public void testFindClassJavaUsages(@NotNull String path) throws Exception {
|
||||
doTestWithoutFiltering(path, true, JetClass.class);
|
||||
doTestWithoutFiltering(path, true, JetClass.class, null);
|
||||
}
|
||||
|
||||
public void testFindClassKotlinUsages(@NotNull String path) throws Exception {
|
||||
doTestWithoutFiltering(path, false, JetClass.class);
|
||||
doTestWithoutFiltering(path, false, JetClass.class, null);
|
||||
}
|
||||
|
||||
public void testFindUsagesUnresolvedAnnotation(@NotNull String path) throws Exception {
|
||||
doTestWithoutFiltering(path, true, JetClass.class);
|
||||
doTestWithoutFiltering(path, true, JetClass.class, null);
|
||||
}
|
||||
|
||||
public void testFindMethodJavaUsages(@NotNull String path) throws Exception {
|
||||
doTestWithoutFiltering(path, true, JetFunction.class);
|
||||
doTestWithoutFiltering(path, true, JetFunction.class, METHOD_OPTIONS_PARSER);
|
||||
}
|
||||
|
||||
public void testFindMethodKotlinUsages(@NotNull String path) throws Exception {
|
||||
doTestWithoutFiltering(path, false, JetFunction.class);
|
||||
doTestWithoutFiltering(path, false, JetFunction.class, METHOD_OPTIONS_PARSER);
|
||||
}
|
||||
|
||||
public void testFindPropertyJavaUsages(@NotNull String path) throws Exception {
|
||||
doTestWithoutFiltering(path, true, JetProperty.class);
|
||||
doTestWithoutFiltering(path, true, JetProperty.class, null);
|
||||
}
|
||||
|
||||
public void testFindPropertyKotlinUsages(@NotNull String path) throws Exception {
|
||||
doTestWithoutFiltering(path, false, JetProperty.class);
|
||||
doTestWithoutFiltering(path, false, JetProperty.class, null);
|
||||
}
|
||||
|
||||
public void testFindObjectJavaUsages(@NotNull String path) throws Exception {
|
||||
doTestWithoutFiltering(path, true, JetObjectDeclarationName.class);
|
||||
doTestWithoutFiltering(path, true, JetObjectDeclarationName.class, null);
|
||||
}
|
||||
|
||||
public void testFindObjectKotlinUsages(@NotNull String path) throws Exception {
|
||||
doTestWithoutFiltering(path, false, JetObjectDeclarationName.class);
|
||||
doTestWithoutFiltering(path, false, JetObjectDeclarationName.class, null);
|
||||
}
|
||||
|
||||
public void testFindWithFilteringImports(@NotNull String path) throws Exception {
|
||||
doTest(path, false, JetClass.class, Lists.newArrayList(new JetImportFilteringRule()));
|
||||
doTest(path, false, JetClass.class, Lists.newArrayList(new JetImportFilteringRule()), null);
|
||||
}
|
||||
|
||||
private <T extends PsiElement> void doTestWithoutFiltering(
|
||||
String path,
|
||||
@NotNull String path,
|
||||
boolean searchInJava,
|
||||
Class<T> caretElementClass
|
||||
@NotNull Class<T> caretElementClass,
|
||||
@Nullable OptionsParser parser
|
||||
) throws Exception {
|
||||
doTest(path, searchInJava, caretElementClass, Collections.<UsageFilteringRule>emptyList());
|
||||
doTest(path, searchInJava, caretElementClass, Collections.<UsageFilteringRule>emptyList(), parser);
|
||||
}
|
||||
|
||||
private <T extends PsiElement> void doTest(
|
||||
String path,
|
||||
@NotNull String path,
|
||||
boolean searchInJava,
|
||||
Class<T> caretElementClass,
|
||||
Collection<? extends UsageFilteringRule> filters
|
||||
@NotNull Class<T> caretElementClass,
|
||||
@NotNull Collection<? extends UsageFilteringRule> filters,
|
||||
@Nullable OptionsParser parser
|
||||
) throws IOException {
|
||||
String rootPath = path.substring(0, path.lastIndexOf("/") + 1);
|
||||
|
||||
@@ -124,7 +166,8 @@ public abstract class AbstractJetFindUsagesTest extends LightCodeInsightFixtureT
|
||||
T caretElement = PsiTreeUtil.getParentOfType(myFixture.getElementAtCaret(), caretElementClass, false);
|
||||
assertNotNull(String.format("Element with type '%s' wasn't found at caret position", caretElementClass), caretElement);
|
||||
|
||||
Collection<UsageInfo> usageInfos = myFixture.findUsages(caretElement);
|
||||
FindUsagesOptions options = parser != null ? parser.parse(FileUtil.loadFile(new File(path)), getProject()) : null;
|
||||
Collection<UsageInfo> usageInfos = findUsages(caretElement, options);
|
||||
|
||||
Collection<UsageInfo2UsageAdapter> filteredUsages = getUsageAdapters(filters, usageInfos);
|
||||
|
||||
@@ -138,10 +181,30 @@ public abstract class AbstractJetFindUsagesTest extends LightCodeInsightFixtureT
|
||||
};
|
||||
|
||||
Collection<String> finalUsages = Ordering.natural().sortedCopy(Collections2.transform(filteredUsages, convertToString));
|
||||
String expectedText = FileUtil.loadFile(new File(rootPath + "results.txt"));
|
||||
String expectedText = FileUtil.loadFile(new File(rootPath + "results.txt"), true);
|
||||
assertOrderedEquals(finalUsages, Ordering.natural().sortedCopy(StringUtil.split(expectedText, "\n")));
|
||||
}
|
||||
|
||||
private Collection<UsageInfo> findUsages(@NotNull PsiElement targetElement, @Nullable FindUsagesOptions options) {
|
||||
Project project = getProject();
|
||||
FindUsagesHandler handler =
|
||||
((FindManagerImpl) FindManager.getInstance(project)).getFindUsagesManager().getFindUsagesHandler(targetElement, false);
|
||||
assert handler != null : "Cannot find handler for: " + targetElement;
|
||||
|
||||
if (options == null) {
|
||||
options = handler.getFindUsagesOptions(null);
|
||||
}
|
||||
|
||||
CommonProcessors.CollectProcessor<UsageInfo> processor = new CommonProcessors.CollectProcessor<UsageInfo>();
|
||||
PsiElement[] psiElements = ArrayUtil.mergeArrays(handler.getPrimaryElements(), handler.getSecondaryElements());
|
||||
|
||||
for (PsiElement psiElement : psiElements) {
|
||||
handler.processElementUsages(psiElement, processor, options);
|
||||
}
|
||||
|
||||
return processor.getResults();
|
||||
}
|
||||
|
||||
private static Collection<UsageInfo2UsageAdapter> getUsageAdapters(
|
||||
final Collection<? extends UsageFilteringRule> filters,
|
||||
Collection<UsageInfo> usageInfos
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.jetbrains.jet.findUsages.AbstractJetFindUsagesTest;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@InnerTestClasses({JetFindUsagesTest.JavaClassUsages.class, JetFindUsagesTest.KotlinClassUsages1.class, JetFindUsagesTest.KotlinClassUsages2.class, JetFindUsagesTest.KotlinClassUsages3.class, JetFindUsagesTest.JavaObjectUsages.class, JetFindUsagesTest.KotlinObjectUsages.class, JetFindUsagesTest.JavaMethodUsages.class, JetFindUsagesTest.KotlinMethodUsages.class, JetFindUsagesTest.JavaPropertyUsages.class, JetFindUsagesTest.KotlinPropertyUsages.class, JetFindUsagesTest.FindWithFilteringImports.class, JetFindUsagesTest.UnresolvedAnnotation.class})
|
||||
@InnerTestClasses({JetFindUsagesTest.JavaClassUsages.class, JetFindUsagesTest.KotlinClassUsages1.class, JetFindUsagesTest.KotlinClassUsages2.class, JetFindUsagesTest.KotlinClassUsages3.class, JetFindUsagesTest.JavaObjectUsages.class, JetFindUsagesTest.KotlinObjectUsages.class, JetFindUsagesTest.JavaMethodUsages.class, JetFindUsagesTest.KotlinMethodUsages.class, JetFindUsagesTest.JavaAndKotlinOverrides.class, JetFindUsagesTest.KotlinOverloadUsages.class, JetFindUsagesTest.JavaPropertyUsages.class, JetFindUsagesTest.KotlinPropertyUsages.class, JetFindUsagesTest.FindWithFilteringImports.class, JetFindUsagesTest.UnresolvedAnnotation.class})
|
||||
public class JetFindUsagesTest extends AbstractJetFindUsagesTest {
|
||||
@TestMetadata("idea/testData/findUsages/findClassUsages/javaClassUsages")
|
||||
public static class JavaClassUsages extends AbstractJetFindUsagesTest {
|
||||
@@ -136,6 +136,32 @@ public class JetFindUsagesTest extends AbstractJetFindUsagesTest {
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/findUsages/findMethodUsages/javaAndKotlinOverrides")
|
||||
public static class JavaAndKotlinOverrides extends AbstractJetFindUsagesTest {
|
||||
@TestMetadata("Server.kt")
|
||||
public void test() throws Exception {
|
||||
testFindMethodJavaUsages("idea/testData/findUsages/findMethodUsages/javaAndKotlinOverrides/Server.kt");
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInJavaAndKotlinOverrides() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/findUsages/findMethodUsages/javaAndKotlinOverrides"), Pattern.compile("^(.*)Server.kt$"), true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/findUsages/findMethodUsages/kotlinOverloadUsages")
|
||||
public static class KotlinOverloadUsages extends AbstractJetFindUsagesTest {
|
||||
@TestMetadata("Server.kt")
|
||||
public void test() throws Exception {
|
||||
testFindMethodKotlinUsages("idea/testData/findUsages/findMethodUsages/kotlinOverloadUsages/Server.kt");
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInKotlinOverloadUsages() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/findUsages/findMethodUsages/kotlinOverloadUsages"), Pattern.compile("^(.*)Server.kt$"), true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/findUsages/findPropertyUsages/javaPropertyUsages")
|
||||
public static class JavaPropertyUsages extends AbstractJetFindUsagesTest {
|
||||
@TestMetadata("Server.kt")
|
||||
@@ -198,6 +224,8 @@ public class JetFindUsagesTest extends AbstractJetFindUsagesTest {
|
||||
suite.addTestSuite(KotlinObjectUsages.class);
|
||||
suite.addTestSuite(JavaMethodUsages.class);
|
||||
suite.addTestSuite(KotlinMethodUsages.class);
|
||||
suite.addTestSuite(JavaAndKotlinOverrides.class);
|
||||
suite.addTestSuite(KotlinOverloadUsages.class);
|
||||
suite.addTestSuite(JavaPropertyUsages.class);
|
||||
suite.addTestSuite(KotlinPropertyUsages.class);
|
||||
suite.addTestSuite(FindWithFilteringImports.class);
|
||||
|
||||
Reference in New Issue
Block a user