Implement search of derived Kotlin classes/traits and Java classes/interfaces
This commit is contained in:
@@ -272,6 +272,7 @@ find.what.overriding.methods.checkbox=Over&riding functions
|
||||
find.options.include.overloaded.methods.checkbox=Include o&verloaded functions and extensions
|
||||
find.what.functions.usages.checkbox=Usages of &functions
|
||||
find.what.properties.usages.checkbox=Usages of &properties
|
||||
find.what.constructor.usages.checkbox=Usages of &constructor
|
||||
find.what.derived.traits.checkbox=&Derived traits
|
||||
find.what.derived.classes.checkbox=&Derived classes
|
||||
|
||||
|
||||
+23
-19
@@ -19,6 +19,8 @@ import javax.swing.*;
|
||||
|
||||
public class KotlinFindClassUsagesDialog extends FindClassUsagesDialog {
|
||||
private StateRestoringCheckBox constructorUsages;
|
||||
private StateRestoringCheckBox derivedClasses;
|
||||
private StateRestoringCheckBox derivedTraits;
|
||||
|
||||
public KotlinFindClassUsagesDialog(
|
||||
PsiClass klass,
|
||||
@@ -47,22 +49,22 @@ public class KotlinFindClassUsagesDialog extends FindClassUsagesDialog {
|
||||
FindBundle.message("find.what.fields.usages.checkbox"),
|
||||
JetBundle.message("find.what.properties.usages.checkbox")
|
||||
);
|
||||
Utils.renameCheckbox(
|
||||
findWhatPanel,
|
||||
FindBundle.message("find.what.implementing.classes.checkbox"),
|
||||
JetBundle.message("find.what.implementing.classes.checkbox")
|
||||
);
|
||||
Utils.renameCheckbox(
|
||||
findWhatPanel,
|
||||
FindBundle.message("find.what.derived.interfaces.checkbox"),
|
||||
JetBundle.message("find.what.derived.traits.checkbox")
|
||||
);
|
||||
Utils.renameCheckbox(
|
||||
findWhatPanel,
|
||||
FindBundle.message("find.what.derived.classes.checkbox"),
|
||||
JetBundle.message("find.what.derived.classes.checkbox")
|
||||
);
|
||||
Utils.removeCheckbox(findWhatPanel, FindBundle.message("find.what.implementing.classes.checkbox"));
|
||||
Utils.removeCheckbox(findWhatPanel, FindBundle.message("find.what.derived.interfaces.checkbox"));
|
||||
Utils.removeCheckbox(findWhatPanel, FindBundle.message("find.what.derived.classes.checkbox"));
|
||||
|
||||
derivedClasses = addCheckboxToPanel(
|
||||
JetBundle.message("find.what.derived.classes.checkbox"),
|
||||
getFindUsagesOptions().isDerivedClasses,
|
||||
findWhatPanel,
|
||||
true
|
||||
);
|
||||
derivedTraits = addCheckboxToPanel(
|
||||
JetBundle.message("find.what.derived.traits.checkbox"),
|
||||
getFindUsagesOptions().isDerivedInterfaces,
|
||||
findWhatPanel,
|
||||
true
|
||||
);
|
||||
constructorUsages = addCheckboxToPanel(
|
||||
JetBundle.message("find.what.constructor.usages.checkbox"),
|
||||
getFindUsagesOptions().searchConstructorUsages,
|
||||
@@ -89,16 +91,18 @@ public class KotlinFindClassUsagesDialog extends FindClassUsagesDialog {
|
||||
@Override
|
||||
protected void update() {
|
||||
super.update();
|
||||
if (!isOKActionEnabled() && constructorUsages.isSelected()) {
|
||||
if (!isOKActionEnabled() && (constructorUsages.isSelected() || derivedTraits.isSelected() || derivedClasses.isSelected())) {
|
||||
setOKActionEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void calcFindUsagesOptions(JavaClassFindUsagesOptions options) {
|
||||
assert options instanceof KotlinClassFindUsagesOptions;
|
||||
|
||||
super.calcFindUsagesOptions(options);
|
||||
((KotlinClassFindUsagesOptions) options).searchConstructorUsages = constructorUsages.isSelected();
|
||||
|
||||
KotlinClassFindUsagesOptions kotlinOptions = (KotlinClassFindUsagesOptions) options;
|
||||
kotlinOptions.searchConstructorUsages = constructorUsages.isSelected();
|
||||
kotlinOptions.isDerivedClasses = derivedClasses.isSelected();
|
||||
kotlinOptions.isDerivedInterfaces = derivedTraits.isSelected();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,4 +22,18 @@ class Utils {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static boolean removeCheckbox(@NotNull JPanel panel, @NotNull String srcText) {
|
||||
for (Component component : panel.getComponents()) {
|
||||
if (component instanceof JCheckBox) {
|
||||
JCheckBox checkBox = (JCheckBox) component;
|
||||
if (checkBox.getText().equals(srcText)) {
|
||||
panel.remove(checkBox);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+61
-22
@@ -23,8 +23,12 @@ 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.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.PsiElementProcessor;
|
||||
import com.intellij.psi.search.PsiElementProcessorAdapter;
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
@@ -92,7 +96,63 @@ public class KotlinFindClassUsagesHandler extends KotlinFindUsagesHandler<JetCla
|
||||
}
|
||||
}
|
||||
|
||||
return processDeclarationsUsages(jetClass, processor, kotlinOptions);
|
||||
if (!processInheritors(lightClass, processor, kotlinOptions)) return false;
|
||||
if (!processDeclarationsUsages(jetClass, processor, kotlinOptions)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean processDeclarationsUsages(
|
||||
@NotNull JetClass klass,
|
||||
@NotNull final Processor<UsageInfo> processor,
|
||||
@NotNull final JavaClassFindUsagesOptions options
|
||||
) {
|
||||
for (JetDeclaration declaration : klass.getDeclarations()) {
|
||||
if (declaration instanceof JetNamedFunction && options.isMethodsUsages
|
||||
|| declaration instanceof JetProperty && options.isFieldsUsages) {
|
||||
if (!ReferencesSearch.search(new ReferencesSearch.SearchParameters(declaration, options.searchScope, false)).forEach(
|
||||
new ReadActionProcessor<PsiReference>() {
|
||||
@Override
|
||||
public boolean processInReadAction(PsiReference ref) {
|
||||
return processUsage(processor, ref, options);
|
||||
}
|
||||
}
|
||||
)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static ClassInheritorsSearch.InheritanceChecker INHERITANCE_CHECKER = new ClassInheritorsSearch.InheritanceChecker() {
|
||||
@Override
|
||||
public boolean checkInheritance(@NotNull PsiClass subClass, @NotNull PsiClass parentClass) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
private static boolean processInheritors(
|
||||
@NotNull PsiClass klass,
|
||||
@NotNull final Processor<UsageInfo> processor,
|
||||
@NotNull final KotlinClassFindUsagesOptions options
|
||||
) {
|
||||
//noinspection unchecked
|
||||
ClassInheritorsSearch.SearchParameters searchParameters = new ClassInheritorsSearch.SearchParameters(
|
||||
klass, options.searchScope, options.isCheckDeepInheritance, true, true, Condition.TRUE, INHERITANCE_CHECKER
|
||||
);
|
||||
return ClassInheritorsSearch.search(searchParameters).forEach(
|
||||
new PsiElementProcessorAdapter<PsiClass>(
|
||||
new PsiElementProcessor<PsiClass>() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiClass element) {
|
||||
if ((element.isInterface() && options.isDerivedInterfaces)
|
||||
|| (!element.isInterface() && options.isDerivedClasses)) {
|
||||
return processUsage(processor, element, options);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private static DeclarationDescriptor getCallDescriptor(PsiElement element, BindingContext bindingContext) {
|
||||
@@ -114,27 +174,6 @@ public class KotlinFindClassUsagesHandler extends KotlinFindUsagesHandler<JetCla
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean processDeclarationsUsages(
|
||||
@NotNull JetClass klass,
|
||||
@NotNull final Processor<UsageInfo> processor,
|
||||
@NotNull final JavaClassFindUsagesOptions options
|
||||
) {
|
||||
for (JetDeclaration declaration : klass.getDeclarations()) {
|
||||
if (declaration instanceof JetNamedFunction && options.isMethodsUsages
|
||||
|| declaration instanceof JetProperty && options.isFieldsUsages) {
|
||||
if (!ReferencesSearch.search(new ReferencesSearch.SearchParameters(declaration, options.searchScope, false)).forEach(
|
||||
new ReadActionProcessor<PsiReference>() {
|
||||
@Override
|
||||
public boolean processInReadAction(PsiReference ref) {
|
||||
return processUsage(processor, ref, options);
|
||||
}
|
||||
}
|
||||
)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isConstructorUsage(PsiElement element, JetClass jetClass) {
|
||||
PsiConstructorCall constructorCall = PsiTreeUtil.getParentOfType(element, PsiConstructorCall.class);
|
||||
if (constructorCall != null && constructorCall == element.getParent()) {
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetClass
|
||||
// OPTIONS: derivedClasses
|
||||
trait X {
|
||||
|
||||
}
|
||||
|
||||
open class <caret>A: X {
|
||||
|
||||
}
|
||||
|
||||
open class C: Y {
|
||||
|
||||
}
|
||||
|
||||
trait Z: A {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class B extends A {
|
||||
|
||||
}
|
||||
|
||||
interface Y extends X {
|
||||
|
||||
}
|
||||
|
||||
interface U extends Z {
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
Unclassified usage (1: 7) class B extends A {
|
||||
@@ -0,0 +1,17 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetClass
|
||||
// OPTIONS: derivedClasses
|
||||
trait <caret>X {
|
||||
|
||||
}
|
||||
|
||||
open class A: X {
|
||||
|
||||
}
|
||||
|
||||
open class C: Y {
|
||||
|
||||
}
|
||||
|
||||
trait Z: A {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class B extends A {
|
||||
|
||||
}
|
||||
|
||||
interface Y extends X {
|
||||
|
||||
}
|
||||
|
||||
interface U extends Z {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
Unclassified usage (11: 12) open class C: Y {
|
||||
Unclassified usage (1: 7) class B extends A {
|
||||
Unclassified usage (7: 12) open class A: X {
|
||||
@@ -0,0 +1,17 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetClass
|
||||
// OPTIONS: derivedInterfaces
|
||||
trait X {
|
||||
|
||||
}
|
||||
|
||||
open class <caret>A: X {
|
||||
|
||||
}
|
||||
|
||||
open class C: Y {
|
||||
|
||||
}
|
||||
|
||||
trait Z: A {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class B extends A {
|
||||
|
||||
}
|
||||
|
||||
interface Y extends X {
|
||||
|
||||
}
|
||||
|
||||
interface U extends Z {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
Unclassified usage (15: 7) trait Z: A {
|
||||
Unclassified usage (9: 11) interface U extends Z {
|
||||
@@ -0,0 +1,17 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetClass
|
||||
// OPTIONS: derivedInterfaces
|
||||
trait <caret>X {
|
||||
|
||||
}
|
||||
|
||||
open class A: X {
|
||||
|
||||
}
|
||||
|
||||
open class C: Y {
|
||||
|
||||
}
|
||||
|
||||
trait Z: A {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class B extends A {
|
||||
|
||||
}
|
||||
|
||||
interface Y extends X {
|
||||
|
||||
}
|
||||
|
||||
interface U extends Z {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
Unclassified usage (15: 7) trait Z: A {
|
||||
Unclassified usage (5: 11) interface Y extends X {
|
||||
Unclassified usage (9: 11) interface U extends Z {
|
||||
@@ -0,0 +1,13 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetClass
|
||||
// OPTIONS: derivedClasses
|
||||
trait X {
|
||||
|
||||
}
|
||||
|
||||
open class <caret>A: X {
|
||||
|
||||
}
|
||||
|
||||
trait Y: X {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetClass
|
||||
// OPTIONS: derivedClasses
|
||||
open class B: A() {
|
||||
|
||||
}
|
||||
|
||||
open class C: Y {
|
||||
|
||||
}
|
||||
|
||||
trait Z: A {
|
||||
|
||||
}
|
||||
|
||||
trait U: Z {
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
Unclassified usage (3: 12) open class B: A() {
|
||||
@@ -0,0 +1,13 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetClass
|
||||
// OPTIONS: derivedClasses
|
||||
trait <caret>X {
|
||||
|
||||
}
|
||||
|
||||
open class A: X {
|
||||
|
||||
}
|
||||
|
||||
trait Y: X {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetClass
|
||||
// OPTIONS: derivedClasses
|
||||
open class B: A() {
|
||||
|
||||
}
|
||||
|
||||
open class C: Y {
|
||||
|
||||
}
|
||||
|
||||
trait Z: A {
|
||||
|
||||
}
|
||||
|
||||
trait U: Z {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
Unclassified usage (3: 12) open class B: A() {
|
||||
Unclassified usage (7: 12) open class A: X {
|
||||
Unclassified usage (7: 12) open class C: Y {
|
||||
@@ -0,0 +1,13 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetClass
|
||||
// OPTIONS: derivedInterfaces
|
||||
trait <caret>X {
|
||||
|
||||
}
|
||||
|
||||
open class A: X {
|
||||
|
||||
}
|
||||
|
||||
trait Y: X {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetClass
|
||||
// OPTIONS: derivedInterfaces
|
||||
open class B: A() {
|
||||
|
||||
}
|
||||
|
||||
open class C: Y {
|
||||
|
||||
}
|
||||
|
||||
trait Z: A {
|
||||
|
||||
}
|
||||
|
||||
trait U: Z {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
Unclassified usage (11: 7) trait Y: X {
|
||||
Unclassified usage (11: 7) trait Z: A {
|
||||
Unclassified usage (15: 7) trait U: Z {
|
||||
@@ -0,0 +1,13 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetClass
|
||||
// OPTIONS: derivedInterfaces
|
||||
trait X {
|
||||
|
||||
}
|
||||
|
||||
open class <caret>A: X {
|
||||
|
||||
}
|
||||
|
||||
trait Y: X {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetClass
|
||||
// OPTIONS: derivedInterfaces
|
||||
open class B: A() {
|
||||
|
||||
}
|
||||
|
||||
open class C: Y {
|
||||
|
||||
}
|
||||
|
||||
trait Z: A {
|
||||
|
||||
}
|
||||
|
||||
trait U: Z {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
Unclassified usage (11: 7) trait Z: A {
|
||||
Unclassified usage (15: 7) trait U: Z {
|
||||
@@ -74,6 +74,12 @@ public abstract class AbstractJetFindUsagesTest extends LightCodeInsightFixtureT
|
||||
else if (s.equals("constructorUsages")) {
|
||||
options.searchConstructorUsages = true;
|
||||
}
|
||||
else if (s.equals("derivedInterfaces")) {
|
||||
options.isDerivedInterfaces = true;
|
||||
}
|
||||
else if (s.equals("derivedClasses")) {
|
||||
options.isDerivedClasses = true;
|
||||
}
|
||||
else if (s.equals("functionUsages")) {
|
||||
options.isMethodsUsages = true;
|
||||
}
|
||||
|
||||
@@ -78,6 +78,26 @@ public class JetFindUsagesTest extends AbstractJetFindUsagesTest {
|
||||
doTest("idea/testData/findUsages/findClassUsages/javaClassPropertyUsages2.0.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("javaDerivedClassUsages1.0.kt")
|
||||
public void testJavaDerivedClassUsages1() throws Exception {
|
||||
doTest("idea/testData/findUsages/findClassUsages/javaDerivedClassUsages1.0.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("javaDerivedClassUsages2.0.kt")
|
||||
public void testJavaDerivedClassUsages2() throws Exception {
|
||||
doTest("idea/testData/findUsages/findClassUsages/javaDerivedClassUsages2.0.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("javaDerivedInterfaceUsages1.0.kt")
|
||||
public void testJavaDerivedInterfaceUsages1() throws Exception {
|
||||
doTest("idea/testData/findUsages/findClassUsages/javaDerivedInterfaceUsages1.0.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("javaDerivedInterfaceUsages2.0.kt")
|
||||
public void testJavaDerivedInterfaceUsages2() throws Exception {
|
||||
doTest("idea/testData/findUsages/findClassUsages/javaDerivedInterfaceUsages2.0.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kotlinClassAllUsages.0.kt")
|
||||
public void testKotlinClassAllUsages() throws Exception {
|
||||
doTest("idea/testData/findUsages/findClassUsages/kotlinClassAllUsages.0.kt");
|
||||
@@ -123,6 +143,26 @@ public class JetFindUsagesTest extends AbstractJetFindUsagesTest {
|
||||
doTest("idea/testData/findUsages/findClassUsages/kotlinClassPropertyUsages2.0.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kotlinDerivedClassUsages1.0.kt")
|
||||
public void testKotlinDerivedClassUsages1() throws Exception {
|
||||
doTest("idea/testData/findUsages/findClassUsages/kotlinDerivedClassUsages1.0.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kotlinDerivedClassUsages2.0.kt")
|
||||
public void testKotlinDerivedClassUsages2() throws Exception {
|
||||
doTest("idea/testData/findUsages/findClassUsages/kotlinDerivedClassUsages2.0.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kotlinDerivedInterfaceUsages1.0.kt")
|
||||
public void testKotlinDerivedInterfaceUsages1() throws Exception {
|
||||
doTest("idea/testData/findUsages/findClassUsages/kotlinDerivedInterfaceUsages1.0.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kotlinDerivedInterfaceUsages2.0.kt")
|
||||
public void testKotlinDerivedInterfaceUsages2() throws Exception {
|
||||
doTest("idea/testData/findUsages/findClassUsages/kotlinDerivedInterfaceUsages2.0.kt");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/findUsages/findMethodUsages")
|
||||
|
||||
Reference in New Issue
Block a user