Add fast find usages for data class components

This commit add feature for disabling searching for data class ComponentN method and destruction declarations that could encrease usages search.
See KT-23278
This commit is contained in:
Igor Yakovlev
2019-11-05 21:02:25 +03:00
parent 6d9c00addd
commit 1ccda6a8d4
47 changed files with 687 additions and 32 deletions
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.asJava.classes.AbstractUltraLightFacadeClassTest
import org.jetbrains.kotlin.checkers.*
import org.jetbrains.kotlin.copyright.AbstractUpdateKotlinCopyrightTest
import org.jetbrains.kotlin.findUsages.AbstractFindUsagesTest
import org.jetbrains.kotlin.findUsages.AbstractFindUsagesWithDisableComponentSearchTest
import org.jetbrains.kotlin.findUsages.AbstractKotlinFindUsagesWithLibraryTest
import org.jetbrains.kotlin.formatter.AbstractFormatterTest
import org.jetbrains.kotlin.formatter.AbstractTypingIndentationTestBase
@@ -521,6 +522,10 @@ fun main(args: Array<String>) {
model("findUsages/propertyFiles", pattern = """^(.+)\.0\.properties$""")
}
testClass<AbstractFindUsagesWithDisableComponentSearchTest> {
model("findUsages/kotlin/conventions/components", pattern = """^(.+)\.0\.(kt|kts)$""")
}
testClass<AbstractKotlinFindUsagesWithLibraryTest> {
model("findUsages/libraryUsages", pattern = """^(.+)\.0\.kt$""")
}
@@ -39,6 +39,7 @@ import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
import org.jetbrains.kotlin.idea.search.*
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions.Companion.Empty
import org.jetbrains.kotlin.idea.search.usagesSearch.dataClassComponentFunction
import org.jetbrains.kotlin.idea.search.usagesSearch.filterDataClassComponentsIfDisabled
import org.jetbrains.kotlin.idea.search.usagesSearch.getClassNameForCompanionObject
import org.jetbrains.kotlin.idea.search.usagesSearch.operators.OperatorReferenceSearcher
import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope
@@ -77,6 +78,7 @@ class KotlinReferencesSearchParameters(
) : ReferencesSearch.SearchParameters(elementToSearch, scope, ignoreAccessScope, optimizer)
class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearch.SearchParameters>() {
override fun processQuery(queryParameters: ReferencesSearch.SearchParameters, consumer: Processor<in PsiReference>) {
val processor = QueryProcessor(queryParameters, consumer)
runReadAction { processor.processInReadAction() }
@@ -108,7 +110,7 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
val effectiveSearchScope = run {
val elements = if (elementToSearch is KtDeclaration && !isOnlyKotlinSearch(queryParameters.scopeDeterminedByUser)) {
elementToSearch.toLightElements().nullize()
elementToSearch.toLightElements().filterDataClassComponentsIfDisabled(kotlinOptions).nullize()
} else {
null
} ?: listOf(elementToSearch)
@@ -236,7 +238,7 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
if (element.getStrictParentOfType<KtPrimaryConstructor>() != null) {
// Simple parameters without val and var shouldn't be processed here because of local search scope
val methods = LightClassUtil.getLightClassPropertyMethods(element)
methods.allDeclarations.forEach { searchNamedElement(it) }
methods.allDeclarations.filterDataClassComponentsIfDisabled(kotlinOptions).forEach { searchNamedElement(it) }
}
}
@@ -264,7 +266,7 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
}
private fun searchPropertyAccessorMethods(origin: KtParameter) {
origin.toLightElements().forEach { searchNamedElement(it) }
origin.toLightElements().filterDataClassComponentsIfDisabled(kotlinOptions).forEach { searchNamedElement(it) }
}
private fun processKtClassOrObject(element: KtClassOrObject) {
@@ -17,14 +17,12 @@
package org.jetbrains.kotlin.idea.search.usagesSearch
import com.intellij.openapi.application.ApplicationManager
import com.intellij.psi.PsiConstructorCall
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiReference
import com.intellij.psi.*
import com.intellij.psi.search.SearchScope
import com.intellij.psi.search.searches.MethodReferencesSearch
import com.intellij.psi.search.searches.ReferencesSearch
import com.intellij.psi.util.MethodSignatureUtil
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.KtLightElement
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
@@ -38,14 +36,13 @@ import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaMethodDescriptor
import org.jetbrains.kotlin.idea.references.unwrappedTargets
import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchRequest
import org.jetbrains.kotlin.idea.search.declarationsSearch.searchInheritors
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.contains
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.OverridingUtil
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.descriptorUtil.isTypeRefinementEnabled
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
@@ -289,3 +286,23 @@ fun PsiElement.searchReferencesOrMethodReferences(): Collection<PsiReference> {
ReferencesSearch.search(this).findAll()
}
}
fun <T : PsiNamedElement> List<T>.filterDataClassComponentsIfDisabled(kotlinOptions: KotlinReferencesSearchOptions): List<T> {
if (kotlinOptions.searchForComponentConventions) return this
fun PsiNamedElement.isComponentElement(): Boolean {
if (this !is PsiMethod) return false
val dataClassParent = ((parent as? KtLightClass)?.kotlinOrigin as? KtClass)?.isData() == true
if (!dataClassParent) return false
if (!Name.isValidIdentifier(name)) return false
val nameIdentifier = Name.identifier(name)
if (!DataClassDescriptorResolver.isComponentLike(nameIdentifier)) return false
return true
}
return filter { !it.isComponentElement() }
}
@@ -20,6 +20,7 @@ import com.intellij.find.FindBundle;
import com.intellij.find.FindSettings;
import com.intellij.find.findUsages.FindUsagesHandler;
import com.intellij.find.findUsages.JavaFindUsagesDialog;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.ui.IdeBorderFactory;
@@ -29,7 +30,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.idea.KotlinBundle;
import org.jetbrains.kotlin.idea.findUsages.KotlinPropertyFindUsagesOptions;
import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.psi.KtNamedDeclaration;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
import javax.swing.*;
@@ -132,10 +133,49 @@ public class KotlinFindPropertyUsagesDialog extends JavaFindUsagesDialog<KotlinP
false
);
}
if (isDataClassConstructorProperty(property)) {
JCheckBox dataClassComponentCheckBox =
new JCheckBox("Fast data class component search");
dataClassComponentCheckBox.setToolTipText("Disable search for data class components and destruction declarations. (Project wide setting)");
Project project = property.getProject();
dataClassComponentCheckBox.setSelected(getDisableComponentAndDestructionSearch(project));
optionsPanel.add(dataClassComponentCheckBox);
dataClassComponentCheckBox.addActionListener(
___ -> setDisableComponentAndDestructionSearch(project, dataClassComponentCheckBox.isSelected())
);
}
}
@Override
protected void update() {
setOKActionEnabled(isSelected(readAccesses) || isSelected(writeAccesses));
}
private static final boolean disableComponentAndDestructionSearchDefault = false;
private static final String optionName = "kotlin.disable.search.component.and.destruction";
public static boolean getDisableComponentAndDestructionSearch(Project project) {
return PropertiesComponent.getInstance(project).getBoolean(optionName, disableComponentAndDestructionSearchDefault);
}
public static void setDisableComponentAndDestructionSearch(Project project, boolean value) {
PropertiesComponent.getInstance(project).setValue(optionName, value, disableComponentAndDestructionSearchDefault);
}
private static boolean isDataClassConstructorProperty(KtNamedDeclaration declaration) {
if (declaration instanceof KtParameter) {
PsiElement parent = declaration.getParent();
if (parent instanceof KtParameterList) {
parent = parent.getParent();
if (parent instanceof KtPrimaryConstructor) {
parent = parent.getParent();
if (parent instanceof KtClass) {
return ((KtClass)parent).isData();
}
}
}
}
return false;
}
}
@@ -82,7 +82,7 @@ class KotlinFindClassUsagesHandler(
private val kotlinOptions = options as KotlinClassFindUsagesOptions
private val referenceProcessor = createReferenceProcessor(processor)
override fun buildTaskList(): Boolean {
override fun buildTaskList(forHighlight: Boolean): Boolean {
val classOrObject = element as KtClassOrObject
if (kotlinOptions.isUsages || kotlinOptions.searchConstructorUsages) {
@@ -21,7 +21,17 @@ import com.intellij.find.FindManager
import com.intellij.find.findUsages.AbstractFindUsagesDialog
import com.intellij.find.findUsages.FindUsagesOptions
import com.intellij.find.impl.FindManagerImpl
import com.intellij.icons.AllIcons.Actions
import com.intellij.openapi.Disposable
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.MessageType
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.wm.ToolWindowId
import com.intellij.openapi.wm.ToolWindowManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiReference
import com.intellij.psi.search.SearchScope
@@ -29,10 +39,12 @@ import com.intellij.psi.search.searches.MethodReferencesSearch
import com.intellij.psi.search.searches.ReferencesSearch
import com.intellij.usageView.UsageInfo
import com.intellij.util.*
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.asJava.toLightMethods
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.debugger.readAction
import org.jetbrains.kotlin.idea.findUsages.KotlinCallableFindUsagesOptions
import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesHandlerFactory
import org.jetbrains.kotlin.idea.findUsages.KotlinFunctionFindUsagesOptions
@@ -47,11 +59,16 @@ import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOpt
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchParameters
import org.jetbrains.kotlin.idea.search.isOnlyKotlinSearch
import org.jetbrains.kotlin.idea.search.usagesSearch.dataClassComponentFunction
import org.jetbrains.kotlin.idea.search.usagesSearch.filterDataClassComponentsIfDisabled
import org.jetbrains.kotlin.idea.search.usagesSearch.isImportUsage
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.findOriginalTopMostOverriddenDescriptors
import org.jetbrains.kotlin.resolve.source.getPsi
import javax.swing.event.HyperlinkEvent
import javax.swing.event.HyperlinkListener
import com.intellij.openapi.util.Key
import com.intellij.usageView.UsageViewContentManager
abstract class KotlinFindMemberUsagesHandler<T : KtNamedDeclaration> protected constructor(
declaration: T,
@@ -81,7 +98,7 @@ abstract class KotlinFindMemberUsagesHandler<T : KtNamedDeclaration> protected c
return super.getFindUsagesDialog(isSingleFile, toShowInNewTab, mustOpenInNewTab)
}
override fun createKotlinReferencesSearchOptions(options: FindUsagesOptions): KotlinReferencesSearchOptions {
override fun createKotlinReferencesSearchOptions(options: FindUsagesOptions, forHighlight: Boolean): KotlinReferencesSearchOptions {
val kotlinOptions = options as KotlinFunctionFindUsagesOptions
return KotlinReferencesSearchOptions(
acceptCallableOverrides = true,
@@ -99,10 +116,33 @@ abstract class KotlinFindMemberUsagesHandler<T : KtNamedDeclaration> protected c
}
private class Property(
declaration: KtNamedDeclaration,
propertyDeclaration: KtNamedDeclaration,
elementsToSearch: Collection<PsiElement>,
factory: KotlinFindUsagesHandlerFactory
) : KotlinFindMemberUsagesHandler<KtNamedDeclaration>(declaration, elementsToSearch, factory) {
) : KotlinFindMemberUsagesHandler<KtNamedDeclaration>(propertyDeclaration, elementsToSearch, factory) {
override fun processElementUsages(element: PsiElement, processor: Processor<UsageInfo>, options: FindUsagesOptions): Boolean {
if (ApplicationManager.getApplication().isUnitTestMode ||
!isPropertyOfDataClass ||
psiElement.getDisableComponentAndDestructionSearch(resetSingleFind = false)
) return super.processElementUsages(element, processor, options)
val indicator = ProgressManager.getInstance().progressIndicator
val notificationCanceller = scheduleNotificationForDataClassComponent(project, element, indicator)
try {
return super.processElementUsages(element, processor, options)
} finally {
Disposer.dispose(notificationCanceller)
}
}
private val isPropertyOfDataClass = readAction {
propertyDeclaration.parent is KtParameterList &&
propertyDeclaration.parent.parent is KtPrimaryConstructor &&
propertyDeclaration.parent.parent.parent.let { it is KtClass && it.isData() }
}
override fun getFindUsagesOptions(dataContext: DataContext?): FindUsagesOptions = factory.findPropertyOptions
@@ -145,13 +185,36 @@ abstract class KotlinFindMemberUsagesHandler<T : KtNamedDeclaration> protected c
return result
}
override fun createKotlinReferencesSearchOptions(options: FindUsagesOptions): KotlinReferencesSearchOptions {
private fun PsiElement.getDisableComponentAndDestructionSearch(resetSingleFind: Boolean): Boolean {
if (!isPropertyOfDataClass) return false
if (forceDisableComponentAndDestructionSearch) return true
if (KotlinFindPropertyUsagesDialog.getDisableComponentAndDestructionSearch(project)) return true
return if (getUserData(FIND_USAGES_ONES_FOR_DATA_CLASS_KEY) == true) {
if (resetSingleFind) {
putUserData(FIND_USAGES_ONES_FOR_DATA_CLASS_KEY, null)
}
true
} else false
}
override fun createKotlinReferencesSearchOptions(options: FindUsagesOptions, forHighlight: Boolean): KotlinReferencesSearchOptions {
val kotlinOptions = options as KotlinPropertyFindUsagesOptions
val disabledComponentsAndOperatorsSearch =
!forHighlight && psiElement.getDisableComponentAndDestructionSearch(resetSingleFind = true)
return KotlinReferencesSearchOptions(
acceptCallableOverrides = true,
acceptOverloads = false,
acceptExtensionsOfDeclarationClass = false,
searchForExpectedUsages = kotlinOptions.searchExpected
searchForExpectedUsages = kotlinOptions.searchExpected,
searchForOperatorConventions = !disabledComponentsAndOperatorsSearch,
searchForComponentConventions = !disabledComponentsAndOperatorsSearch
)
}
}
@@ -166,12 +229,12 @@ abstract class KotlinFindMemberUsagesHandler<T : KtNamedDeclaration> protected c
private val kotlinOptions = options as KotlinCallableFindUsagesOptions
override fun buildTaskList(): Boolean {
override fun buildTaskList(forHighlight: Boolean): Boolean {
val referenceProcessor = createReferenceProcessor(processor)
val uniqueProcessor = CommonProcessors.UniqueProcessor(processor)
if (options.isUsages) {
val kotlinSearchOptions = createKotlinReferencesSearchOptions(options)
val kotlinSearchOptions = createKotlinReferencesSearchOptions(options, forHighlight)
val searchParameters = KotlinReferencesSearchParameters(element, options.searchScope, kotlinOptions = kotlinSearchOptions)
addTask { applyQueryFilters(element, options, ReferencesSearch.search(searchParameters)).forEach(referenceProcessor) }
@@ -184,7 +247,7 @@ abstract class KotlinFindMemberUsagesHandler<T : KtNamedDeclaration> protected c
else -> options.searchScope
}
for (psiMethod in element.toLightMethods()) {
for (psiMethod in element.toLightMethods().filterDataClassComponentsIfDisabled(kotlinSearchOptions)) {
addTask {
applyQueryFilters(
element,
@@ -210,7 +273,10 @@ abstract class KotlinFindMemberUsagesHandler<T : KtNamedDeclaration> protected c
}
}
protected abstract fun createKotlinReferencesSearchOptions(options: FindUsagesOptions): KotlinReferencesSearchOptions
protected abstract fun createKotlinReferencesSearchOptions(
options: FindUsagesOptions,
forHighlight: Boolean
): KotlinReferencesSearchOptions
protected abstract fun applyQueryFilters(
element: PsiElement,
@@ -242,6 +308,51 @@ abstract class KotlinFindMemberUsagesHandler<T : KtNamedDeclaration> protected c
companion object {
@Volatile
@get:TestOnly
var forceDisableComponentAndDestructionSearch = false
private const val DISABLE_ONCE = "DISABLE_ONCE"
private const val DISABLE = "DISABLE"
private const val DISABLE_COMPONENT_AND_DESTRUCTION_SEARCH_TEXT =
"<p>Find usages for data class components and destruction declarations<br/>could be <a href=\"$DISABLE_ONCE\">disabled once</a> or <a href=\"$DISABLE\">disabled for a project</a>.</p>"
private const val DISABLE_COMPONENT_AND_DESTRUCTION_SEARCH_TIMEOUT = 5000
private val FIND_USAGES_ONES_FOR_DATA_CLASS_KEY = Key<Boolean>("FIND_USAGES_ONES")
private fun scheduleNotificationForDataClassComponent(
project: Project,
element: PsiElement,
indicator: ProgressIndicator
): Disposable {
val notification = {
val listener = HyperlinkListener { event ->
if (event.eventType == HyperlinkEvent.EventType.ACTIVATED) {
indicator.cancel()
if (event.description == DISABLE) {
KotlinFindPropertyUsagesDialog.setDisableComponentAndDestructionSearch(project, /* value = */ true)
} else {
element.putUserData(FIND_USAGES_ONES_FOR_DATA_CLASS_KEY, true)
}
FindManager.getInstance(project).findUsages(element)
}
}
ToolWindowManager.getInstance(project).notifyByBalloon(
ToolWindowId.FIND,
MessageType.INFO,
DISABLE_COMPONENT_AND_DESTRUCTION_SEARCH_TEXT,
Actions.Find,
listener
)
}
return Alarm().also {
it.addRequest(notification, DISABLE_COMPONENT_AND_DESTRUCTION_SEARCH_TIMEOUT)
}
}
fun getInstance(
declaration: KtNamedDeclaration,
elementsToSearch: Collection<PsiElement> = emptyList(),
@@ -71,12 +71,17 @@ abstract class KotlinFindUsagesHandler<T : PsiElement>(
}
override fun processElementUsages(element: PsiElement, processor: Processor<UsageInfo>, options: FindUsagesOptions): Boolean {
return searchReferences(element, processor, options) && searchTextOccurrences(element, processor, options)
return searchReferences(element, processor, options, forHighlight = false) && searchTextOccurrences(element, processor, options)
}
private fun searchReferences(element: PsiElement, processor: Processor<UsageInfo>, options: FindUsagesOptions): Boolean {
private fun searchReferences(
element: PsiElement,
processor: Processor<UsageInfo>,
options: FindUsagesOptions,
forHighlight: Boolean
): Boolean {
val searcher = createSearcher(element, processor, options)
if (!runReadAction { project }.runReadActionInSmartMode { searcher.buildTaskList() }) return false
if (!runReadAction { project }.runReadActionInSmartMode { searcher.buildTaskList(forHighlight) }) return false
return searcher.executeTasks()
}
@@ -92,7 +97,7 @@ abstract class KotlinFindUsagesHandler<T : PsiElement>(
results.add(reference)
}
true
}, options)
}, options, forHighlight = true)
return results
}
@@ -116,7 +121,7 @@ abstract class KotlinFindUsagesHandler<T : PsiElement>(
/**
* Invoked under read-action, should use [addTask] for all time-consuming operations
*/
abstract fun buildTaskList(): Boolean
abstract fun buildTaskList(forHighlight: Boolean): Boolean
}
companion object {
@@ -41,7 +41,7 @@ class KotlinTypeParameterFindUsagesHandler(
override fun createSearcher(element: PsiElement, processor: Processor<UsageInfo>, options: FindUsagesOptions): Searcher {
return object : Searcher(element, processor, options) {
override fun buildTaskList(): Boolean {
override fun buildTaskList(forHighlight: Boolean): Boolean {
addTask {
ReferencesSearch.search(element, options.searchScope).all { processUsage(processor, it) }
}
@@ -0,0 +1,7 @@
Resolved java class to descriptor: JavaSAM
Searched references to JavaClass.takeSAM(JavaSAM sam) in non-Java files
Searched references to JavaSAM in non-Kotlin files
Searched references to pack.A
Used plain search of parameter a of A(val a: Int, val b: String) in LocalSearchScope:
CLASS:A
{ val (x, y) = it }
@@ -0,0 +1,3 @@
Searched references to A
Used plain search of parameter x of A(val x: Int, val y: Int) in LocalSearchScope:
CLASS:A
@@ -0,0 +1,10 @@
Checked type of f()
Checked type of x
Checked type of y
Resolved (x, y)
Searched references to X
Searched references to f() in non-Java files
Used plain search of component1() in LocalSearchScope:
CLASS:X
FUN:component1
FUN:component2
@@ -0,0 +1 @@
Value read 12 val (x, y) = f()
@@ -0,0 +1,13 @@
Checked type of f()
Checked type of g()
Checked type of x1
Checked type of y1
Resolved (x1, y1)
Searched references to X
Searched references to f() in non-Java files
Used plain search of component1() in LocalSearchScope:
CLASS:X
FUN:component1
FUN:component1
FUN:component2
FUN:component2
@@ -0,0 +1 @@
Value read 16 val (x1, y1) = f()
@@ -0,0 +1,62 @@
Checked type of a
Checked type of g()
Checked type of h()
Checked type of listOfA()
Checked type of listOfA()
Checked type of x
Checked type of x1
Checked type of x1
Checked type of x2
Checked type of x2
Checked type of x3
Checked type of x3
Checked type of x3
Checked type of x4
Checked type of x5
Checked type of y
Checked type of y1
Checked type of y1
Checked type of y2
Checked type of y2
Checked type of y3
Checked type of y3
Checked type of y3
Checked type of y4
Checked type of y5
Checked type of z
Checked type of z1
Checked type of z2
Checked type of z3
Checked type of z4
Checked type of z5
Resolved (x, y, z)
Resolved (x1, y1)
Resolved (x1, y1, z1)
Resolved (x2, y2)
Resolved (x2, y2, z2)
Resolved (x3, y3)
Resolved (x3, y3)
Resolved (x3, y3, z3)
Resolved (x4, y4, z4)
Resolved (x5, y5, z5)
Searched references to JavaClass.getA() in non-Java files
Searched references to JavaClass2
Searched references to JavaClass3
Searched references to JavaClass4.NestedPrivate
Searched references to JavaClass4.NestedPublic
Searched references to a in non-Java files
Searched references to f() in non-Java files
Searched references to g() in non-Java files
Searched references to h() in non-Java files
Searched references to listOfA() in non-Java files
Searched references to pack.A
Searched references to pack.X
Searched references to parameter p1 of test2(p1: JavaClass2, p2: JavaClass3) in non-Java files
Searched references to parameter p2 of test2(p1: JavaClass2, p2: JavaClass3) in non-Java files
Searched references to static getNested in non-Java files by request JavaClass4.*
Searched references to static getNested in non-Java files by request JavaClass4.getNested
Used plain search of parameter n of A(val n: Int, val s: String, val o: Any) in LocalSearchScope:
CLASS:A
CLASS:X
FUN:ext1
FUN:ext1
@@ -0,0 +1 @@
Value read 5 a.n
@@ -0,0 +1,9 @@
Checked type of a
Checked type of x
Checked type of y
Checked type of z
Resolved (x, y, z)
Searched references to A
Searched references to a in non-Java files
Used plain search of parameter n of A(val n: Int, val s: String, val o: Any) in LocalSearchScope:
CLASS:A
@@ -0,0 +1 @@
Used plain search of kotlin.Pair.component1() in whole search scope
@@ -0,0 +1,3 @@
Function call 6 p.component1()
Value read 11 val (x, y) = 1 to "a"
Value read 7 val (x, y) = p
@@ -0,0 +1,29 @@
Checked type of a
Checked type of a1
Checked type of n
Checked type of n1
Checked type of x
Checked type of x1
Checked type of y
Checked type of y1
Checked type of z
Checked type of z1
Resolved (a, n)
Resolved (a1, n1)
Resolved (x, y, z)
Resolved (x1, y1, z1)
Searched references to A
Searched references to B
Searched references to C
Searched references to C.component1() in non-Java files
Searched references to a in non-Java files
Searched references to a1 in non-Java files
Searched references to parameter a of B(val a: A, val n: Int) in non-Java files
Searched references to parameter b of f(b: B, c: C) in non-Java files
Searched references to parameter c of f(b: B, c: C) in non-Java files
Used plain search of C.component1() in LocalSearchScope:
CLASS:C
Used plain search of parameter a of B(val a: A, val n: Int) in LocalSearchScope:
CLASS:B
Used plain search of parameter x of A(val x: Int, val y: Int, val z: String) in LocalSearchScope:
CLASS:A
@@ -0,0 +1 @@
Value read 14 val (x, y, z) = a
@@ -0,0 +1,25 @@
Checked type of f()
Checked type of x
Checked type of x1
Checked type of x2
Checked type of y
Checked type of y1
Checked type of y2
Resolved (x, y)
Resolved (x1, y1)
Resolved (x2, y2)
Searched references to X
Searched references to Y
Searched references to Z1
Searched references to Z2
Searched references to f() in non-Java files
Searched references to parameter z1 of g(z1: Z1, z2: Z2) in non-Java files
Searched references to parameter z2 of g(z1: Z1, z2: Z2) in non-Java files
Used plain search of component2() in LocalSearchScope:
CLASS:X
CLASS:Y
CLASS:Z1
CLASS:Z2
FUN:component1
FUN:component2
FUN:ext
@@ -0,0 +1,4 @@
Value read 21 val (x, y) = f()
Value read 25 val (a, b) = this
Value read 29 val (x1, y1) = z1[0]
Value read 30 val (x2, y2) = z2.get()
@@ -0,0 +1,12 @@
Checked type of parameter a of FOR
Checked type of x
Checked type of x
Checked type of y
Checked type of y
Checked type of z
Resolved (x, y)
Resolved (x, y, z)
Searched references to A
Searched references to parameter a of FOR in non-Java files
Used plain search of parameter n of A(val n: Int, val s: String, val o: Any) in LocalSearchScope:
CLASS:A
@@ -0,0 +1,12 @@
Checked type of list
Checked type of x
Checked type of x1
Checked type of y
Checked type of y1
Resolved (x, y)
Resolved (x1, y1)
Searched references to A
Searched references to list in non-Java files
Used plain search of parameter x of A(val x: Int, val y: Int) in LocalSearchScope:
CLASS:A
FUN:x
@@ -0,0 +1,2 @@
Value read 15 val (x, y) = list[0]
Value read 8 val (x, y) = o
@@ -0,0 +1,23 @@
Searched references to A
Searched references to parameter p of foo(p: A) in non-Java files
Searched references to parameter p of takeExtFun(p: A.() -> Unit) in non-Java files
Searched references to parameter p of takeFun1(p: (A) -> Unit) in non-Java files
Searched references to parameter p of takeFun2(p: ((A?, Int) -> Unit)?) in non-Java files
Searched references to parameter p of takeFun3(p: (List<A>) -> Unit) in non-Java files
Searched references to parameter p of takeFuns(p: MutableList<(A) -> Unit>) in non-Java files
Searched references to takeExtFun(p: A.() -> Unit) in non-Java files
Searched references to takeFun1(p: (A) -> Unit) in non-Java files
Searched references to takeFun2(p: ((A?, Int) -> Unit)?) in non-Java files
Searched references to takeFun3(p: (List<A>) -> Unit) in non-Java files
Searched references to takeFuns(p: MutableList<(A) -> Unit>) in non-Java files
Searched references to v in non-Java files
Used plain search of parameter a of A(val a: Int, val b: Int) in LocalSearchScope:
CLASS:A
FUN:null
{ a, n -> val (x, y) = a!! }
{ val (x, y ) = it }
{ val (x, y) = it }
{ val (x, y) = it }
{ val (x, y) = it }
{ val (x, y) = it[0] }
{ val (x, y) = this }
@@ -0,0 +1 @@
Value read 28 takeFun2 { a, n -> val (x, y) = a!! }
@@ -0,0 +1,13 @@
Checked type of x1
Checked type of y1
Checked type of y1(a: A)
Resolved (x1, y1)
Searched references to A
Searched references to parameter a of condition(a: A) in non-Java files
Searched references to parameter a of x(a: A, b: Boolean, list: List<Int>) in non-Java files
Searched references to parameter a of y1(a: A) in non-Java files
Searched references to parameter a of y2(a: A) in non-Java files
Searched references to parameter a of y3(a: A) in non-Java files
Used plain search of parameter n of A(val n: Int, val s: String) in LocalSearchScope:
CLASS:A
{ val (x2, y2) = this }
@@ -0,0 +1,22 @@
Checked type of f()
Checked type of g()
Checked type of h()
Checked type of x
Checked type of x1
Checked type of x2
Checked type of y
Checked type of y1
Checked type of y2
Resolved (x, y)
Resolved (x1, y1)
Resolved (x2, y2)
Searched references to X
Searched references to Y
Searched references to Z
Searched references to f() in non-Java files
Searched references to g() in non-Java files
Searched references to h() in non-Java files
Used plain search of X.component1() in LocalSearchScope:
CLASS:X
CLASS:Y
CLASS:Z
@@ -0,0 +1,5 @@
Value read 17 val (x, y) = this
Value read 26 val (x, y) = f()
Value read 27 val (x1, y1) = g()
Value read 28 val (x2, y2) = h()
Value read 9 val (x, y) = this
@@ -0,0 +1,19 @@
Checked type of x
Checked type of x
Checked type of x
Checked type of y
Checked type of y
Checked type of y
Resolved (x, y)
Resolved b1 + b2
Searched references to A
Searched references to B
Searched references to parameter b1 of f(b1: B, b2: B) in non-Java files
Searched references to parameter b2 of f(b1: B, b2: B) in non-Java files
Searched references to parameter other of plus(other: B) in non-Java files
Searched references to plus(other: B) in non-Java files
Used plain search of parameter x of A(val x: Int, val y: Int) in LocalSearchScope:
CLASS:A
Used plain search of plus(other: B) in LocalSearchScope:
CLASS:B
FUN:plus
@@ -0,0 +1,2 @@
Value read 15 val (x, y) = b1 + b2
Value read 6 val (x, y) = this
@@ -0,0 +1,15 @@
Checked type of a1
Checked type of a2
Checked type of a2
Checked type of n1
Checked type of n2
Checked type of n2
ExpressionOfTypeProcessor is already started for A. Exit for operator parameter a of A(val a: A?, val n: Int).
Resolved (a1, n1)
Resolved (a2, n2)
Resolved (a2, n2)
Searched references to A
Searched references to parameter a of A(val a: A?, val n: Int) in non-Java files
Searched references to parameter a of f(a: A) in non-Java files
Used plain search of parameter a of A(val a: A?, val n: Int) in LocalSearchScope:
CLASS:A
@@ -0,0 +1,3 @@
Value read 7 val (a1, n1) = a
Value read 8 val (a2, n2) =
Value read 9 a?.a ?: return
@@ -0,0 +1,18 @@
Checked type of a1
Checked type of b
Checked type of n
Checked type of s
ExpressionOfTypeProcessor is already started for A. Exit for operator parameter b of A(val b: B, val n: Int).
Resolved (a1, s)
Resolved (b, n)
Searched references to A
Searched references to B
Searched references to a1 in non-Java files
Searched references to b in non-Java files
Searched references to parameter a of B(val a: A?, val s: String) in non-Java files
Searched references to parameter a of f(a: A) in non-Java files
Searched references to parameter b of A(val b: B, val n: Int) in non-Java files
Used plain search of parameter a of B(val a: A?, val s: String) in LocalSearchScope:
CLASS:B
Used plain search of parameter b of A(val b: B, val n: Int) in LocalSearchScope:
CLASS:A
@@ -0,0 +1 @@
Value read 8 val (b, n) = a
@@ -0,0 +1,5 @@
Searched references to A
Used plain search of parameter a of A(val a: Int, val b: Int) in LocalSearchScope:
CLASS:A
KtWhenEntry "else"
KtWhenEntry "is A"
@@ -40,6 +40,8 @@ import com.intellij.usages.rules.UsageGroupingRule
import com.intellij.util.CommonProcessors
import org.jetbrains.kotlin.idea.core.util.clearDialogsResults
import org.jetbrains.kotlin.idea.core.util.setDialogsResult
import org.jetbrains.kotlin.idea.findUsages.dialogs.KotlinFindPropertyUsagesDialog
import org.jetbrains.kotlin.idea.findUsages.handlers.KotlinFindMemberUsagesHandler
import org.jetbrains.kotlin.idea.refactoring.CHECK_SUPER_METHODS_YES_NO_DIALOG
import org.jetbrains.kotlin.idea.search.usagesSearch.ExpressionsOfTypeProcessor
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
@@ -53,6 +55,21 @@ import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File
import java.util.*
abstract class AbstractFindUsagesWithDisableComponentSearchTest : AbstractFindUsagesTest() {
override fun <T : PsiElement> doTest(path: String) {
val oldValue = KotlinFindMemberUsagesHandler.forceDisableComponentAndDestructionSearch
try {
KotlinFindMemberUsagesHandler.forceDisableComponentAndDestructionSearch = true
super.doTest<T>(path)
} finally {
KotlinFindMemberUsagesHandler.forceDisableComponentAndDestructionSearch = oldValue
}
}
override val prefixForResults = "DisabledComponents."
}
abstract class AbstractFindUsagesTest : KotlinLightCodeInsightFixtureTestCase() {
override fun getProjectDescriptor(): LightProjectDescriptor = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
@@ -61,7 +78,9 @@ abstract class AbstractFindUsagesTest : KotlinLightCodeInsightFixtureTestCase()
protected open fun extraConfig(path: String) {
}
protected fun <T : PsiElement> doTest(path: String) {
protected open val prefixForResults = ""
protected open fun <T : PsiElement> doTest(path: String) {
val mainFile = File(path)
val mainFileName = mainFile.name
val mainFileText = FileUtil.loadFile(mainFile, true)
@@ -124,16 +143,17 @@ abstract class AbstractFindUsagesTest : KotlinLightCodeInsightFixtureTestCase()
val options = parser?.parse(mainFileText, project)
// Ensure that search by sources (if present) and decompiled declarations gives the same results
val prefixForCheck = prefix + prefixForResults
if (isLibraryElement) {
val originalElement = caretElement.originalElement
findUsagesAndCheckResults(mainFileText, prefix, rootPath, originalElement, options, project)
findUsagesAndCheckResults(mainFileText, prefixForCheck, rootPath, originalElement, options, project)
val navigationElement = caretElement.navigationElement
if (navigationElement !== originalElement) {
findUsagesAndCheckResults(mainFileText, prefix, rootPath, navigationElement, options, project)
findUsagesAndCheckResults(mainFileText, prefixForCheck, rootPath, navigationElement, options, project)
}
} else {
findUsagesAndCheckResults(mainFileText, prefix, rootPath, caretElement, options, project)
findUsagesAndCheckResults(mainFileText, prefixForCheck, rootPath, caretElement, options, project)
}
} finally {
fixtureClasses.forEach { TestFixtureExtension.unloadFixture(it) }
@@ -0,0 +1,125 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.findUsages;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("idea/testData/findUsages/kotlin/conventions/components")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class FindUsagesWithDisableComponentSearchTestGenerated extends AbstractFindUsagesWithDisableComponentSearchTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInComponents() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/findUsages/kotlin/conventions/components"), Pattern.compile("^(.+)\\.0\\.(kt|kts)$"), true);
}
@TestMetadata("callableReferences.0.kt")
public void testCallableReferences() throws Exception {
runTest("idea/testData/findUsages/kotlin/conventions/components/callableReferences.0.kt");
}
@TestMetadata("companionObjectAccess.0.kt")
public void testCompanionObjectAccess() throws Exception {
runTest("idea/testData/findUsages/kotlin/conventions/components/companionObjectAccess.0.kt");
}
@TestMetadata("componentFunForGenericType1.0.kt")
public void testComponentFunForGenericType1() throws Exception {
runTest("idea/testData/findUsages/kotlin/conventions/components/componentFunForGenericType1.0.kt");
}
@TestMetadata("componentFunForGenericType2.0.kt")
public void testComponentFunForGenericType2() throws Exception {
runTest("idea/testData/findUsages/kotlin/conventions/components/componentFunForGenericType2.0.kt");
}
@TestMetadata("dataClass.0.kt")
public void testDataClass() throws Exception {
runTest("idea/testData/findUsages/kotlin/conventions/components/dataClass.0.kt");
}
@TestMetadata("dataClassComponentByRef.0.kt")
public void testDataClassComponentByRef() throws Exception {
runTest("idea/testData/findUsages/kotlin/conventions/components/dataClassComponentByRef.0.kt");
}
@TestMetadata("dataClassFromStdlib.0.kt")
public void testDataClassFromStdlib() throws Exception {
runTest("idea/testData/findUsages/kotlin/conventions/components/dataClassFromStdlib.0.kt");
}
@TestMetadata("dataClassInsideDataClass.0.kt")
public void testDataClassInsideDataClass() throws Exception {
runTest("idea/testData/findUsages/kotlin/conventions/components/dataClassInsideDataClass.0.kt");
}
@TestMetadata("extensionComponentFun.0.kt")
public void testExtensionComponentFun() throws Exception {
runTest("idea/testData/findUsages/kotlin/conventions/components/extensionComponentFun.0.kt");
}
@TestMetadata("for.0.kt")
public void testFor() throws Exception {
runTest("idea/testData/findUsages/kotlin/conventions/components/for.0.kt");
}
@TestMetadata("isAndAs.0.kt")
public void testIsAndAs() throws Exception {
runTest("idea/testData/findUsages/kotlin/conventions/components/isAndAs.0.kt");
}
@TestMetadata("lambdas.0.kt")
public void testLambdas() throws Exception {
runTest("idea/testData/findUsages/kotlin/conventions/components/lambdas.0.kt");
}
@TestMetadata("mayTypeAffectAncestors.0.kt")
public void testMayTypeAffectAncestors() throws Exception {
runTest("idea/testData/findUsages/kotlin/conventions/components/mayTypeAffectAncestors.0.kt");
}
@TestMetadata("memberComponentFun.0.kt")
public void testMemberComponentFun() throws Exception {
runTest("idea/testData/findUsages/kotlin/conventions/components/memberComponentFun.0.kt");
}
@TestMetadata("operators.0.kt")
public void testOperators() throws Exception {
runTest("idea/testData/findUsages/kotlin/conventions/components/operators.0.kt");
}
@TestMetadata("recursiveDataClass1.0.kt")
public void testRecursiveDataClass1() throws Exception {
runTest("idea/testData/findUsages/kotlin/conventions/components/recursiveDataClass1.0.kt");
}
@TestMetadata("recursiveDataClass2.0.kt")
public void testRecursiveDataClass2() throws Exception {
runTest("idea/testData/findUsages/kotlin/conventions/components/recursiveDataClass2.0.kt");
}
@TestMetadata("SAM.0.kt")
public void testSAM() throws Exception {
runTest("idea/testData/findUsages/kotlin/conventions/components/SAM.0.kt");
}
@TestMetadata("when.0.kt")
public void testWhen() throws Exception {
runTest("idea/testData/findUsages/kotlin/conventions/components/when.0.kt");
}
}