From 7f1e7cc4619e8f323facee60fd0e6f473471d855 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Thu, 14 Feb 2019 12:02:50 +0300 Subject: [PATCH] Minor: reformat and cleanup org.jetbrains.kotlin.idea.search package --- .../idea/search/KotlinIndexPatternBuilder.kt | 9 +- .../kotlin/idea/search/KotlinIndexers.kt | 80 +++++---- .../idea/search/PsiBasedClassResolver.kt | 48 +++--- .../classInheritorsSearch.kt | 18 +- .../declarationSearchUtil.kt | 35 ++-- .../declarationsSearch/overridersSearch.kt | 74 ++++---- .../KotlinRequestResultProcessor.kt | 11 +- .../kotlin/idea/search/searchUtil.kt | 8 +- .../ExpressionsOfTypeProcessor.kt | 105 +++++++----- .../BinaryOperatorReferenceSearcher.kt | 20 ++- .../ContainsOperatorReferenceSearcher.kt | 24 ++- ...structuringDeclarationReferenceSearcher.kt | 27 +-- .../IndexingOperatorReferenceSearcher.kt | 24 ++- .../InvokeOperatorReferenceSearcher.kt | 33 ++-- .../IteratorOperatorReferenceSearcher.kt | 10 +- .../operators/OperatorReferenceSearcher.kt | 161 ++++++++++-------- ...ertyDelegationOperatorReferenceSearcher.kt | 10 +- .../UnaryOperatorReferenceSearcher.kt | 21 ++- .../kotlin/idea/search/usagesSearch/utils.kt | 21 ++- 19 files changed, 411 insertions(+), 328 deletions(-) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/KotlinIndexPatternBuilder.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/KotlinIndexPatternBuilder.kt index 257d89d7b0e..15a0a719fe4 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/KotlinIndexPatternBuilder.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/KotlinIndexPatternBuilder.kt @@ -18,7 +18,6 @@ package org.jetbrains.kotlin.idea.search import com.intellij.lexer.Lexer import com.intellij.psi.PsiFile -import com.intellij.psi.impl.search.IndexPatternBuilder import com.intellij.psi.tree.IElementType import com.intellij.psi.tree.TokenSet import org.jetbrains.kotlin.kdoc.lexer.KDocTokens @@ -26,8 +25,10 @@ import org.jetbrains.kotlin.lexer.KotlinLexer import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtFile -class KotlinIndexPatternBuilder: IndexPatternBuilderAdapter() { - private val TODO_COMMENT_TOKENS = TokenSet.orSet(KtTokens.COMMENTS, TokenSet.create(KDocTokens.KDOC)) +class KotlinIndexPatternBuilder : IndexPatternBuilderAdapter() { + private companion object { + private val TODO_COMMENT_TOKENS = TokenSet.orSet(KtTokens.COMMENTS, TokenSet.create(KDocTokens.KDOC)) + } override fun getCommentTokenSet(file: PsiFile): TokenSet? { return if (file is KtFile) TODO_COMMENT_TOKENS else null @@ -39,7 +40,7 @@ class KotlinIndexPatternBuilder: IndexPatternBuilderAdapter() { override fun getCommentStartDelta(tokenType: IElementType?): Int = 0 - override fun getCommentEndDelta(tokenType: IElementType?): Int = when(tokenType) { + override fun getCommentEndDelta(tokenType: IElementType?): Int = when (tokenType) { KtTokens.BLOCK_COMMENT -> "*/".length else -> 0 } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/KotlinIndexers.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/KotlinIndexers.kt index 6dc663459cd..11c17ce1edd 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/KotlinIndexers.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/KotlinIndexers.kt @@ -34,30 +34,33 @@ import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.types.expressions.OperatorConventions import java.util.* -val KOTLIN_NAMED_ARGUMENT_SEARCH_CONTEXT: Short = 0x20 +const val KOTLIN_NAMED_ARGUMENT_SEARCH_CONTEXT: Short = 0x20 private val ALL_SEARCHABLE_OPERATIONS: ImmutableSet = ImmutableSet - .builder() - .addAll(OperatorConventions.UNARY_OPERATION_NAMES.keys) - .addAll(OperatorConventions.BINARY_OPERATION_NAMES.keys) - .addAll(OperatorConventions.ASSIGNMENT_OPERATIONS.keys) - .addAll(OperatorConventions.COMPARISON_OPERATIONS) - .addAll(OperatorConventions.EQUALS_OPERATIONS) - .addAll(OperatorConventions.IN_OPERATIONS) - .add(KtTokens.LBRACKET) - .add(KtTokens.BY_KEYWORD) - .build() + .builder() + .addAll(OperatorConventions.UNARY_OPERATION_NAMES.keys) + .addAll(OperatorConventions.BINARY_OPERATION_NAMES.keys) + .addAll(OperatorConventions.ASSIGNMENT_OPERATIONS.keys) + .addAll(OperatorConventions.COMPARISON_OPERATIONS) + .addAll(OperatorConventions.EQUALS_OPERATIONS) + .addAll(OperatorConventions.IN_OPERATIONS) + .add(KtTokens.LBRACKET) + .add(KtTokens.BY_KEYWORD) + .build() -class KotlinFilterLexer(private val occurrenceConsumer: OccurrenceConsumer): BaseFilterLexer(KotlinLexer(), occurrenceConsumer) { - private val codeTokens = TokenSet.orSet( +class KotlinFilterLexer(private val occurrenceConsumer: OccurrenceConsumer) : BaseFilterLexer(KotlinLexer(), occurrenceConsumer) { + private companion object { + private val codeTokens = TokenSet.orSet( TokenSet.create(*ALL_SEARCHABLE_OPERATIONS.toTypedArray()), TokenSet.create(KtTokens.IDENTIFIER) - ) + ) - private val commentTokens = TokenSet.orSet(KtTokens.COMMENTS, TokenSet.create(KDocTokens.KDOC)) + private val commentTokens = TokenSet.orSet(KtTokens.COMMENTS, TokenSet.create(KDocTokens.KDOC)) + + private const val MAX_PREV_TOKENS = 2 + private val prevTokens = ArrayDeque(MAX_PREV_TOKENS) + } - private val MAX_PREV_TOKENS = 2 - private val prevTokens = ArrayDeque(MAX_PREV_TOKENS) private var prevTokenStart = -1 private var prevTokenEnd = -1 @@ -69,7 +72,13 @@ class KotlinFilterLexer(private val occurrenceConsumer: OccurrenceConsumer): Bas if (prevTokens.peekFirst() == KtTokens.IDENTIFIER) { val prevPrev = prevTokens.elementAtOrNull(1) if (prevPrev == KtTokens.COMMA || prevPrev == KtTokens.LPAR) { - occurrenceConsumer.addOccurrence(bufferSequence, null, prevTokenStart, prevTokenEnd, KOTLIN_NAMED_ARGUMENT_SEARCH_CONTEXT.toInt()) + occurrenceConsumer.addOccurrence( + bufferSequence, + null, + prevTokenStart, + prevTokenEnd, + KOTLIN_NAMED_ARGUMENT_SEARCH_CONTEXT.toInt() + ) } } } @@ -81,22 +90,21 @@ class KotlinFilterLexer(private val occurrenceConsumer: OccurrenceConsumer): Bas } KtTokens.IDENTIFIER -> { - if (myDelegate.tokenText.startsWith("`")) { - scanWordsInToken(UsageSearchContext.IN_CODE.toInt(), false, false) - } - else { - addOccurrenceInToken(UsageSearchContext.IN_CODE.toInt()) - if (myDelegate.tokenText == "TODO" ) { - // Heuristics to reduce mismatches between indexer and searcher. The searcher returns only occurrences of TO_DO - // as the callee of a call expression, but we can't tell calls and other usages apart based on limited lexer context, - // so we just exclude occurrences in declaration names (and even that doesn't work precisely because it doesn't handle - // declarations with type parameters) - val prevToken = prevTokens.peekFirst() - if (prevToken != KtTokens.FUN_KEYWORD && prevToken != KtTokens.VAR_KEYWORD && prevToken != KtTokens.VAL_KEYWORD && prevToken != KtTokens.CLASS_KEYWORD) { - advanceTodoItemCountsInToken() - } - } - } + if (myDelegate.tokenText.startsWith("`")) { + scanWordsInToken(UsageSearchContext.IN_CODE.toInt(), false, false) + } else { + addOccurrenceInToken(UsageSearchContext.IN_CODE.toInt()) + if (myDelegate.tokenText == "TODO") { + // Heuristics to reduce mismatches between indexer and searcher. The searcher returns only occurrences of TO_DO + // as the callee of a call expression, but we can't tell calls and other usages apart based on limited lexer context, + // so we just exclude occurrences in declaration names (and even that doesn't work precisely because it doesn't handle + // declarations with type parameters) + val prevToken = prevTokens.peekFirst() + if (prevToken != KtTokens.FUN_KEYWORD && prevToken != KtTokens.VAR_KEYWORD && prevToken != KtTokens.VAL_KEYWORD && prevToken != KtTokens.CLASS_KEYWORD) { + advanceTodoItemCountsInToken() + } + } + } } in codeTokens -> addOccurrenceInToken(UsageSearchContext.IN_CODE.toInt()) @@ -128,13 +136,13 @@ class KotlinFilterLexer(private val occurrenceConsumer: OccurrenceConsumer): Bas } } -class KotlinIdIndexer: LexerBasedIdIndexer() { +class KotlinIdIndexer : LexerBasedIdIndexer() { override fun createLexer(consumer: OccurrenceConsumer): Lexer = KotlinFilterLexer(consumer) override fun getVersion() = 3 } -class KotlinTodoIndexer: LexerBasedTodoIndexer(), IdAndToDoScannerBasedOnFilterLexer { +class KotlinTodoIndexer : LexerBasedTodoIndexer(), IdAndToDoScannerBasedOnFilterLexer { override fun getVersion() = 2 override fun createLexer(consumer: OccurrenceConsumer) = KotlinFilterLexer(consumer) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/PsiBasedClassResolver.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/PsiBasedClassResolver.kt index 05c6edccfdb..867189d6477 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/PsiBasedClassResolver.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/PsiBasedClassResolver.kt @@ -62,9 +62,12 @@ class PsiBasedClassResolver @TestOnly constructor(private val targetClassFqName: private var forceAmbiguityForNonAnnotations: Boolean = false companion object { - @TestOnly val attempts = AtomicInteger() - @TestOnly val trueHits = AtomicInteger() - @TestOnly val falseHits = AtomicInteger() + @TestOnly + val attempts = AtomicInteger() + @TestOnly + val trueHits = AtomicInteger() + @TestOnly + val falseHits = AtomicInteger() private val PSI_BASED_CLASS_RESOLVER_KEY = Key>("PsiBasedClassResolver") @@ -86,7 +89,7 @@ class PsiBasedClassResolver @TestOnly constructor(private val targetClassFqName: } } - private constructor(target: PsiClass): this(target.qualifiedName ?: "") { + private constructor(target: PsiClass) : this(target.qualifiedName ?: "") { if (target.qualifiedName == null || target.containingClass != null || targetPackage.isEmpty()) { forceAmbiguity = true return @@ -105,8 +108,7 @@ class PsiBasedClassResolver @TestOnly constructor(private val targetClassFqName: if (candidate.containingClass != null && !candidate.hasModifierProperty(PsiModifier.PRIVATE)) { if (candidate.isAnnotationType) { forceAmbiguity = true - } - else { + } else { forceAmbiguityForNonAnnotations = true } break @@ -118,8 +120,7 @@ class PsiBasedClassResolver @TestOnly constructor(private val targetClassFqName: forceAmbiguity = true break } - } - else { + } else { candidate.qualifiedName?.substringBeforeLast('.', "")?.let { candidatePackage -> if (candidatePackage == "") forceAmbiguity = true @@ -137,7 +138,8 @@ class PsiBasedClassResolver @TestOnly constructor(private val targetClassFqName: } } - @TestOnly fun addConflict(fqName: String) { + @TestOnly + fun addConflict(fqName: String) { conflictingPackages.add(fqName.substringBeforeLast('.')) } @@ -192,8 +194,7 @@ class PsiBasedClassResolver @TestOnly constructor(private val targetClassFqName: if (result.returnValue == MATCH) { trueHits.incrementAndGet() - } - else if (result.returnValue == NO_MATCH) { + } else if (result.returnValue == NO_MATCH) { falseHits.incrementAndGet() } return result.returnValue @@ -202,24 +203,23 @@ class PsiBasedClassResolver @TestOnly constructor(private val targetClassFqName: private fun analyzeSingleImport(result: Result, importedFqName: FqName?, isAllUnder: Boolean, aliasName: String?): Result { if (!isAllUnder) { if (importedFqName?.asString() == targetClassFqName && - (aliasName == null || aliasName == targetShortName)) { + (aliasName == null || aliasName == targetShortName) + ) { return result.changeTo(Result.Found) - } - else if (importedFqName?.shortName()?.asString() == targetShortName && - importedFqName.parent().asString() in conflictingPackages && - aliasName == null) { + } else if (importedFqName?.shortName()?.asString() == targetShortName && + importedFqName.parent().asString() in conflictingPackages && + aliasName == null + ) { return result.changeTo(Result.FoundOther) - } - else if (importedFqName?.shortName()?.asString() == targetShortName && - importedFqName.parent().asString() in packagesWithTypeAliases && - aliasName == null) { + } else if (importedFqName?.shortName()?.asString() == targetShortName && + importedFqName.parent().asString() in packagesWithTypeAliases && + aliasName == null + ) { return Result.Ambiguity - } - else if (aliasName == targetShortName) { + } else if (aliasName == targetShortName) { return result.changeTo(Result.FoundOther) } - } - else { + } else { when { importedFqName?.asString() == targetPackage -> return result.changeTo(Result.Found) importedFqName?.asString() in conflictingPackages -> return result.changeTo(Result.FoundOther) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/classInheritorsSearch.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/classInheritorsSearch.kt index d13f21c4fec..55c29b1ba76 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/classInheritorsSearch.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/classInheritorsSearch.kt @@ -29,17 +29,17 @@ import org.jetbrains.kotlin.psi.KtClassOrObject fun HierarchySearchRequest<*>.searchInheritors(): Query { val psiClass: PsiClass = when (originalElement) { - is KtClassOrObject -> runReadAction { originalElement.toLightClassWithBuiltinMapping() ?: KtFakeLightClass(originalElement) } - is PsiClass -> originalElement - else -> null - } ?: return EmptyQuery.getEmptyQuery() + is KtClassOrObject -> runReadAction { originalElement.toLightClassWithBuiltinMapping() ?: KtFakeLightClass(originalElement) } + is PsiClass -> originalElement + else -> null + } ?: return EmptyQuery.getEmptyQuery() return ClassInheritorsSearch.search( - psiClass, - searchScope, - searchDeeply, - /* checkInheritance = */ true, - /* includeAnonymous = */ true + psiClass, + searchScope, + searchDeeply, + /* checkInheritance = */ true, + /* includeAnonymous = */ true ) } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/declarationSearchUtil.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/declarationSearchUtil.kt index 8071e0975ee..98597846273 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/declarationSearchUtil.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/declarationSearchUtil.kt @@ -39,18 +39,18 @@ interface SearchRequestWithElement : DeclarationSearchRequest override val project: Project get() = originalElement.project } -abstract class DeclarationsSearch>: QueryFactory() { +abstract class DeclarationsSearch> : QueryFactory() { init { registerExecutor( - object : QueryExecutorBase(true) { - override fun processQuery(queryParameters: R, consumer: ExecutorProcessor) { - doSearch(queryParameters, consumer) - } + object : QueryExecutorBase(true) { + override fun processQuery(queryParameters: R, consumer: ExecutorProcessor) { + doSearch(queryParameters, consumer) } + } ) } - override final fun registerExecutor(executor: QueryExecutor) { + final override fun registerExecutor(executor: QueryExecutor) { super.registerExecutor(executor) } @@ -60,13 +60,13 @@ abstract class DeclarationsSearch> fun search(request: R): Query = if (isApplicable(request)) createUniqueResultsQuery(request) else EmptyQuery.getEmptyQuery() } -class HierarchySearchRequest ( - override val originalElement: T, - override val searchScope: SearchScope, - val searchDeeply: Boolean = true +class HierarchySearchRequest( + override val originalElement: T, + override val searchScope: SearchScope, + val searchDeeply: Boolean = true ) : SearchRequestWithElement { - fun copy(newOriginalElement: U): HierarchySearchRequest = - HierarchySearchRequest(newOriginalElement, searchScope, searchDeeply) + fun copy(newOriginalElement: U): HierarchySearchRequest = + HierarchySearchRequest(newOriginalElement, searchScope, searchDeeply) } interface HierarchyTraverser { @@ -97,7 +97,7 @@ interface HierarchyTraverser { } } -fun ExecutorProcessor.consumeHierarchy(request: SearchRequestWithElement, traverser: HierarchyTraverser) { +fun ExecutorProcessor.consumeHierarchy(request: SearchRequestWithElement, traverser: HierarchyTraverser) { traverser.forEach(request.originalElement) { element -> if (element in request.searchScope) { process(element) @@ -105,9 +105,9 @@ fun ExecutorProcessor.consumeHierarchy(request: SearchRequest } } -abstract class HierarchySearch( - protected val traverser: HierarchyTraverser -): DeclarationsSearch>() { +abstract class HierarchySearch( + private val traverser: HierarchyTraverser +) : DeclarationsSearch>() { protected open fun doSearchAll(request: HierarchySearchRequest, consumer: ExecutorProcessor) { consumer.consumeHierarchy(request, traverser) } @@ -117,8 +117,7 @@ abstract class HierarchySearch( override fun doSearch(request: HierarchySearchRequest, consumer: ExecutorProcessor) { if (request.searchDeeply) { doSearchAll(request, consumer) - } - else { + } else { doSearchDirect(request, consumer) } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/overridersSearch.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/overridersSearch.kt index 7e95fd73dff..85986740888 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/overridersSearch.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/overridersSearch.kt @@ -52,34 +52,33 @@ fun HierarchySearchRequest<*>.searchOverriders(): Query { if (psiMethods.isEmpty()) return EmptyQuery.getEmptyQuery() return psiMethods - .map { psiMethod -> KotlinPsiMethodOverridersSearch.search(copy(psiMethod)) } - .reduce { query1, query2 -> MergeQuery(query1, query2)} + .map { psiMethod -> KotlinPsiMethodOverridersSearch.search(copy(psiMethod)) } + .reduce { query1, query2 -> MergeQuery(query1, query2) } } object KotlinPsiMethodOverridersSearch : HierarchySearch(PsiMethodOverridingHierarchyTraverser) { fun searchDirectOverriders(psiMethod: PsiMethod): Iterable { fun PsiMethod.isAcceptable(inheritor: PsiClass, baseMethod: PsiMethod, baseClass: PsiClass): Boolean = - when { - hasModifierProperty(PsiModifier.STATIC) -> false - baseMethod.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) -> - JavaPsiFacade.getInstance(project).arePackagesTheSame(baseClass, inheritor) - else -> true - } + when { + hasModifierProperty(PsiModifier.STATIC) -> false + baseMethod.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) -> + JavaPsiFacade.getInstance(project).arePackagesTheSame(baseClass, inheritor) + else -> true + } - val psiClass = psiMethod.containingClass - if (psiClass == null) return Collections.emptyList() + val psiClass = psiMethod.containingClass ?: return Collections.emptyList() val classToMethod = LinkedHashMap() val classTraverser = object : HierarchyTraverser { override fun nextElements(current: PsiClass): Iterable = - DirectClassInheritorsSearch.search( - current, - current.project.allScope(), - /* includeAnonymous = */ true - ) + DirectClassInheritorsSearch.search( + current, + current.project.allScope(), + /* includeAnonymous = */ true + ) override fun shouldDescend(element: PsiClass): Boolean = - element.isInheritable() && !classToMethod.containsKey(element) + element.isInheritable() && !classToMethod.containsKey(element) } classTraverser.forEach(psiClass) { inheritor -> @@ -87,7 +86,7 @@ object KotlinPsiMethodOverridersSearch : HierarchySearch(PsiMethodOve val signature = psiMethod.getSignature(substitutor) val candidate = MethodSignatureUtil.findMethodBySuperSignature(inheritor, signature, false) if (candidate != null && candidate.isAcceptable(inheritor, psiMethod, psiClass)) { - classToMethod.put(inheritor, candidate) + classToMethod[inheritor] = candidate } } @@ -95,14 +94,14 @@ object KotlinPsiMethodOverridersSearch : HierarchySearch(PsiMethodOve } override fun isApplicable(request: HierarchySearchRequest): Boolean = - runReadAction { request.originalElement.isOverridableElement() } + runReadAction { request.originalElement.isOverridableElement() } override fun doSearchDirect(request: HierarchySearchRequest, consumer: ExecutorProcessor) { searchDirectOverriders(request.originalElement).forEach { method -> consumer.process(method) } } } -object PsiMethodOverridingHierarchyTraverser: HierarchyTraverser { +object PsiMethodOverridingHierarchyTraverser : HierarchyTraverser { override fun nextElements(current: PsiMethod): Iterable = KotlinPsiMethodOverridersSearch.searchDirectOverriders(current) override fun shouldDescend(element: PsiMethod): Boolean = PsiUtil.canBeOverridden(element) } @@ -119,23 +118,26 @@ fun PsiElement.toPossiblyFakeLightMethods(): List { } private fun forEachKotlinOverride( - ktClass: KtClass, - members: List, - scope: SearchScope, - processor: (superMember: PsiElement, overridingMember: PsiElement) -> Boolean + ktClass: KtClass, + members: List, + scope: SearchScope, + processor: (superMember: PsiElement, overridingMember: PsiElement) -> Boolean ): Boolean { val baseClassDescriptor = runReadAction { ktClass.unsafeResolveToDescriptor() as ClassDescriptor } - val baseDescriptors = runReadAction { members.mapNotNull { it.unsafeResolveToDescriptor() as? CallableMemberDescriptor }.filter { it.isOverridable } } + val baseDescriptors = + runReadAction { members.mapNotNull { it.unsafeResolveToDescriptor() as? CallableMemberDescriptor }.filter { it.isOverridable } } if (baseDescriptors.isEmpty()) return true - HierarchySearchRequest(ktClass, scope, true).searchInheritors().forEach(Processor { - val inheritor = it.unwrapped as? KtClassOrObject ?: return@Processor true + HierarchySearchRequest(ktClass, scope, true).searchInheritors().forEach(Processor { psiClass -> + val inheritor = psiClass.unwrapped as? KtClassOrObject ?: return@Processor true runReadAction { val inheritorDescriptor = inheritor.unsafeResolveToDescriptor() as ClassDescriptor - val substitutor = getTypeSubstitutor(baseClassDescriptor.defaultType, inheritorDescriptor.defaultType) ?: return@runReadAction true + val substitutor = + getTypeSubstitutor(baseClassDescriptor.defaultType, inheritorDescriptor.defaultType) ?: return@runReadAction true baseDescriptors.forEach { val superMember = it.source.getPsi()!! - val overridingDescriptor = inheritorDescriptor.findCallableMemberBySignature(it.substitute(substitutor) as CallableMemberDescriptor) + val overridingDescriptor = + inheritorDescriptor.findCallableMemberBySignature(it.substitute(substitutor) as CallableMemberDescriptor) val overridingMember = overridingDescriptor?.source?.getPsi() if (overridingMember != null) { if (!processor(superMember, overridingMember)) return@runReadAction false @@ -149,8 +151,8 @@ private fun forEachKotlinOverride( } fun KtNamedDeclaration.forEachOverridingElement( - scope: SearchScope = runReadAction { useScope }, - processor: (PsiElement, PsiElement) -> Boolean + scope: SearchScope = runReadAction { useScope }, + processor: (PsiElement, PsiElement) -> Boolean ): Boolean { val ktClass = runReadAction { containingClassOrObject as? KtClass } ?: return true @@ -162,8 +164,8 @@ fun KtNamedDeclaration.forEachOverridingElement( } fun PsiMethod.forEachOverridingMethod( - scope: SearchScope = runReadAction { useScope }, - processor: (PsiMethod) -> Boolean + scope: SearchScope = runReadAction { useScope }, + processor: (PsiMethod) -> Boolean ): Boolean { if (this !is KtFakeLightMethod) { if (!OverridingMethodsSearch.search(this, scope.excludeKotlinSources(), true).forEach(processor)) return false @@ -178,11 +180,11 @@ fun PsiMethod.forEachOverridingMethod( } fun PsiMethod.forEachImplementation( - scope: SearchScope = runReadAction { useScope }, - processor: (PsiElement) -> Boolean + scope: SearchScope = runReadAction { useScope }, + processor: (PsiElement) -> Boolean ): Boolean { return forEachOverridingMethod(scope, processor) - && FunctionalExpressionSearch.search(this, scope.excludeKotlinSources()).forEach(processor) + && FunctionalExpressionSearch.search(this, scope.excludeKotlinSources()).forEach(processor) } fun PsiClass.forEachDeclaredMemberOverride(processor: (superMember: PsiElement, overridingMember: PsiElement) -> Boolean) { @@ -194,7 +196,7 @@ fun PsiClass.forEachDeclaredMemberOverride(processor: (superMember: PsiElement, val ktClass = unwrapped as? KtClass ?: return val members = ktClass.declarations.filterIsInstance() + - ktClass.primaryConstructorParameters.filter { it.hasValOrVar() } + ktClass.primaryConstructorParameters.filter { it.hasValOrVar() } forEachKotlinOverride(ktClass, members, scope, processor) } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinRequestResultProcessor.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinRequestResultProcessor.kt index 6eb7f6de5f1..2a72afc3046 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinRequestResultProcessor.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinRequestResultProcessor.kt @@ -31,10 +31,10 @@ import org.jetbrains.kotlin.psi.KtDestructuringDeclaration import org.jetbrains.kotlin.psi.KtNamedDeclaration class KotlinRequestResultProcessor( - private val unwrappedElement: PsiElement, - private val originalElement: PsiElement = unwrappedElement, - private val filter: (PsiReference) -> Boolean = { true }, - private val options: KotlinReferencesSearchOptions = KotlinReferencesSearchOptions.Empty + private val unwrappedElement: PsiElement, + private val originalElement: PsiElement = unwrappedElement, + private val filter: (PsiReference) -> Boolean = { true }, + private val options: KotlinReferencesSearchOptions = KotlinReferencesSearchOptions.Empty ) : RequestResultProcessor(unwrappedElement, originalElement, filter, options) { private val referenceService = PsiReferenceService.getService() @@ -48,8 +48,7 @@ class KotlinRequestResultProcessor( if (filter(ref) && ref.containsOffsetInElement(offsetInElement) && ref.isReferenceToTarget(unwrappedElement)) { consumer.process(ref) - } - else { + } else { true } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/searchUtil.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/searchUtil.kt index 9b9d56fd5fc..01f1e459317 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/searchUtil.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/searchUtil.kt @@ -56,7 +56,7 @@ fun PsiFile.fileScope(): GlobalSearchScope = GlobalSearchScope.fileScope(this) fun GlobalSearchScope.restrictByFileType(fileType: FileType) = GlobalSearchScope.getScopeRestrictedByFileTypes(this, fileType) -fun SearchScope.restrictByFileType(fileType: FileType) = when (this) { +fun SearchScope.restrictByFileType(fileType: FileType): SearchScope = when (this) { is GlobalSearchScope -> restrictByFileType(fileType) is LocalSearchScope -> { val elements = scope.filter { it.containingFile.fileType == fileType } @@ -79,8 +79,7 @@ fun SearchScope.excludeFileTypes(vararg fileTypes: FileType): SearchScope { return if (this is GlobalSearchScope) { val includedFileTypes = FileTypeRegistry.getInstance().registeredFileTypes.filter { it !in fileTypes }.toTypedArray() GlobalSearchScope.getScopeRestrictedByFileTypes(this, *includedFileTypes) - } - else { + } else { this as LocalSearchScope val filteredElements = scope.filter { it.containingFile.fileType !in fileTypes } if (filteredElements.isNotEmpty()) @@ -94,7 +93,8 @@ fun SearchScope.excludeFileTypes(vararg fileTypes: FileType): SearchScope { fun ReferencesSearch.SearchParameters.effectiveSearchScope(element: PsiElement): SearchScope { if (element == elementToSearch) return effectiveSearchScope if (isIgnoreAccessScope) return scopeDeterminedByUser - val accessScope = PsiSearchHelper.SERVICE.getInstance(element.project).getUseScope(element) + // BUNCH: 181 + @Suppress("DEPRECATION") val accessScope = PsiSearchHelper.SERVICE.getInstance(element.project).getUseScope(element) return scopeDeterminedByUser.intersectWith(accessScope) } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/ExpressionsOfTypeProcessor.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/ExpressionsOfTypeProcessor.kt index 1bd390c05f6..cb2ce6b76a9 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/ExpressionsOfTypeProcessor.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/ExpressionsOfTypeProcessor.kt @@ -64,12 +64,12 @@ import java.util.* //TODO: check if smart search is too expensive class ExpressionsOfTypeProcessor( - private val typeToSearch: FuzzyType, - private val classToSearch: PsiClass?, - private val searchScope: SearchScope, - private val project: Project, - private val possibleMatchHandler: (KtExpression) -> Unit, - private val possibleMatchesInScopeHandler: (SearchScope) -> Unit + private val typeToSearch: FuzzyType, + private val classToSearch: PsiClass?, + private val searchScope: SearchScope, + private val project: Project, + private val possibleMatchHandler: (KtExpression) -> Unit, + private val possibleMatchesInScopeHandler: (SearchScope) -> Unit ) { @TestOnly enum class Mode { @@ -94,7 +94,7 @@ class ExpressionsOfTypeProcessor( return runReadAction { if (element !is KtDeclaration && element !is PsiMember) return@runReadAction element.text val fqName = element.getKotlinFqName()?.asString() - ?: (element as? KtNamedDeclaration)?.name + ?: (element as? KtNamedDeclaration)?.name when (element) { is PsiMethod -> fqName + element.parameterList.text is KtFunction -> fqName + element.valueParameterList!!.text @@ -135,7 +135,12 @@ class ExpressionsOfTypeProcessor( } // optimization - if (runReadAction { searchScope is GlobalSearchScope && !FileTypeIndex.containsFileOfType(KotlinFileType.INSTANCE, searchScope) }) return + if (runReadAction { + searchScope is GlobalSearchScope && !FileTypeIndex.containsFileOfType( + KotlinFileType.INSTANCE, + searchScope + ) + }) return // for class from library always use plain search because we cannot search usages in compiled code (we could though) if (!runReadAction { classToSearch.isValid && ProjectRootsUtil.isInProjectSource(classToSearch) }) { @@ -149,9 +154,9 @@ class ExpressionsOfTypeProcessor( runReadAction { val scopeElements = scopesToUsePlainSearch.values - .flatten() - .filter { it.isValid } - .toTypedArray() + .flatten() + .filter { it.isValid } + .toTypedArray() if (scopeElements.isNotEmpty()) { possibleMatchesInScopeHandler(LocalSearchScope(scopeElements)) } @@ -173,7 +178,7 @@ class ExpressionsOfTypeProcessor( private fun downShiftToPlainSearch(reference: PsiReference) { val message = getFallbackDiagnosticsMessage(reference) - LOG.info("ExpressionsOfTypeProcessor: " + message) + LOG.info("ExpressionsOfTypeProcessor: $message") testLog { "Downgrade to plain text search: $message" } tasks.clear() @@ -207,7 +212,8 @@ class ExpressionsOfTypeProcessor( data class ProcessClassUsagesTask(val classToSearch: PsiClass) : Task { override fun perform() { testLog { "Searched references to ${logPresentation(classToSearch)}" } - val scope = GlobalSearchScope.allScope(project).excludeFileTypes(XmlFileType.INSTANCE) // ignore usages in XML - they don't affect us + val scope = GlobalSearchScope.allScope(project) + .excludeFileTypes(XmlFileType.INSTANCE) // ignore usages in XML - they don't affect us searchReferences(classToSearch, scope) { reference -> val element = reference.element val wasProcessed = when (element.language) { @@ -262,7 +268,8 @@ class ExpressionsOfTypeProcessor( }) } - private class StaticMemberRequestResultProcessor(val psiMember: PsiMember, classes: List) : RequestResultProcessor(psiMember) { + private class StaticMemberRequestResultProcessor(val psiMember: PsiMember, classes: List) : + RequestResultProcessor(psiMember) { val possibleClassesNames: Set = runReadAction { classes.map { it.qualifiedName }.filterNotNullTo(HashSet()) } override fun processTextOccurrence(element: PsiElement, offsetInElement: Int, consumer: ExecutorProcessor): Boolean { @@ -290,9 +297,9 @@ class ExpressionsOfTypeProcessor( val fqName = element.importedFqName?.asString() if (fqName != null && fqName in possibleClassesNames) { val ref = element.importedReference - ?.getQualifiedElementSelector() - ?.references - ?.firstOrNull() + ?.getQualifiedElementSelector() + ?.references + ?.firstOrNull() if (ref != null) { consumer.process(ref) } @@ -319,13 +326,18 @@ class ExpressionsOfTypeProcessor( val declarationName = runReadAction { psiMember.name } ?: return if (declarationName.isEmpty()) return - data class ProcessStaticCallableUsagesTask(val member: PsiMember, val memberScope: SearchScope, val taskProcessor: ReferenceProcessor) : Task { + data class ProcessStaticCallableUsagesTask( + val member: PsiMember, + val memberScope: SearchScope, + val taskProcessor: ReferenceProcessor + ) : Task { override fun perform() { // This class will look through the whole hierarchy anyway, so shouldn't be a big overhead here val inheritanceClasses = ClassInheritorsSearch.search( - declarationClass, - classUseScope(declarationClass), - true, true, false).findAll() + declarationClass, + classUseScope(declarationClass), + true, true, false + ).findAll() val classes = (inheritanceClasses + declarationClass).filter { it !is KtLightClass @@ -340,20 +352,24 @@ class ExpressionsOfTypeProcessor( testLog { "Searched references to static $memberName in non-Java files by request $request" } searchRequestCollector.searchWord( - request, - classUseScope(klass).intersectWith(memberScope), UsageSearchContext.IN_CODE, true, member, resultProcessor) + request, + classUseScope(klass).intersectWith(memberScope), UsageSearchContext.IN_CODE, true, member, resultProcessor + ) val qualifiedName = runReadAction { klass.qualifiedName } if (qualifiedName != null) { - val importAllUnderRequest = qualifiedName + ".*" + val importAllUnderRequest = "$qualifiedName.*" testLog { "Searched references to static $memberName in non-Java files by request $importAllUnderRequest" } searchRequestCollector.searchWord( - importAllUnderRequest, - classUseScope(klass).intersectWith(memberScope), UsageSearchContext.IN_CODE, true, member, resultProcessor) + importAllUnderRequest, + classUseScope(klass).intersectWith(memberScope), UsageSearchContext.IN_CODE, true, member, resultProcessor + ) } } + // BUNCH: 181 + @Suppress("DEPRECATION") PsiSearchHelper.SERVICE.getInstance(project).processRequests(searchRequestCollector) { reference -> if (reference.element.parents.any { it is KtImportDirective }) { // Found declaration in import - process all file with an ordinal reference search @@ -361,8 +377,7 @@ class ExpressionsOfTypeProcessor( addCallableDeclarationToProcess(member, LocalSearchScope(containingFile), taskProcessor) true - } - else { + } else { val processed = taskProcessor.handler(this@ExpressionsOfTypeProcessor, reference) if (!processed) { // we don't know how to handle this reference and down-shift to plain search downShiftToPlainSearch(reference) @@ -379,26 +394,29 @@ class ExpressionsOfTypeProcessor( } private fun addCallableDeclarationToProcess(declaration: PsiElement, scope: SearchScope, processor: ReferenceProcessor) { - if (scope !is LocalSearchScope && declaration is PsiMember && (declaration.modifierList?.hasModifierProperty(PsiModifier.STATIC) ?: false)) { + if (scope !is LocalSearchScope && declaration is PsiMember && + (declaration.modifierList?.hasModifierProperty(PsiModifier.STATIC) == true) + ) { addStaticMemberToProcess(declaration, scope, processor) return } @Suppress("NAME_SHADOWING") data class ProcessCallableUsagesTask( - val declaration: PsiElement, - val processor: ReferenceProcessor, - val scope: SearchScope) : Task { + val declaration: PsiElement, + val processor: ReferenceProcessor, + val scope: SearchScope + ) : Task { override fun perform() { if (scope is LocalSearchScope) { testLog { "Searched imported static member $declaration in ${scope.scope.toList()}" } - } - else { + } else { testLog { "Searched references to ${logPresentation(declaration)} in non-Java files" } } val searchParameters = KotlinReferencesSearchParameters( - declaration, scope, kotlinOptions = KotlinReferencesSearchOptions(searchNamedArguments = false)) + declaration, scope, kotlinOptions = KotlinReferencesSearchOptions(searchNamedArguments = false) + ) searchReferences(searchParameters) { reference -> val processed = processor.handler(this@ExpressionsOfTypeProcessor, reference) if (!processed) { // we don't know how to handle this reference and down-shift to plain search @@ -438,8 +456,7 @@ class ExpressionsOfTypeProcessor( if (reference is KtDestructuringDeclarationReference) { // declaration usage in form of destructuring declaration entry addCallableDeclarationOfOurType(reference.element) - } - else { + } else { (reference.element as? KtReferenceExpression)?.let { processSuspiciousExpression(it) } } true @@ -613,8 +630,7 @@ class ExpressionsOfTypeProcessor( val whenExpression = whenEntry.parent as KtWhenExpression val entriesAfter = whenExpression.entries.dropWhile { it != whenEntry }.drop(1) entriesAfter.forEach { usePlainSearch(it) } - } - else { + } else { usePlainSearch(whenEntry) } return true @@ -662,7 +678,7 @@ class ExpressionsOfTypeProcessor( break@ParentsLoop } - //TODO: if Java parameter has Kotlin functional type then we should process method usages + //TODO: if Java parameter has Kotlin functional type then we should process method usages is PsiParameter -> { if (prev == parent.typeElement) { // usage in parameter type - check if the method is in SAM interface processParameterInSamClass(parent) @@ -831,8 +847,7 @@ class ExpressionsOfTypeProcessor( private fun processSuspiciousDeclaration(declaration: KtDeclaration) { if (declaration is KtDestructuringDeclaration) { declaration.entries.forEach { processSuspiciousDeclaration(it) } - } - else { + } else { if (!isImplicitlyTyped(declaration)) return testLog { "Checked type of ${logPresentation(declaration)}" } @@ -873,8 +888,7 @@ class ExpressionsOfTypeProcessor( } prevElements.add(element) } - } - else { + } else { assert(restricted == GlobalSearchScope.EMPTY_SCOPE) } @@ -931,8 +945,7 @@ class ExpressionsOfTypeProcessor( runReadAction { if (ref.element.isValid) { processor(ref) - } - else { + } else { true } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/BinaryOperatorReferenceSearcher.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/BinaryOperatorReferenceSearcher.kt index 26bc39166b9..872ae195405 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/BinaryOperatorReferenceSearcher.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/BinaryOperatorReferenceSearcher.kt @@ -30,13 +30,19 @@ import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance class BinaryOperatorReferenceSearcher( - targetFunction: PsiElement, - private val operationTokens: List, - searchScope: SearchScope, - consumer: ExecutorProcessor, - optimizer: SearchRequestCollector, - options: KotlinReferencesSearchOptions -) : OperatorReferenceSearcher(targetFunction, searchScope, consumer, optimizer, options, wordsToSearch = operationTokens.map { it.value }) { + targetFunction: PsiElement, + private val operationTokens: List, + searchScope: SearchScope, + consumer: ExecutorProcessor, + optimizer: SearchRequestCollector, + options: KotlinReferencesSearchOptions +) : OperatorReferenceSearcher( + targetFunction, + searchScope, + consumer, + optimizer, + options, + wordsToSearch = operationTokens.map { it.value }) { override fun processPossibleReceiverExpression(expression: KtExpression) { val binaryExpression = expression.parent as? KtBinaryExpression ?: return diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/ContainsOperatorReferenceSearcher.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/ContainsOperatorReferenceSearcher.kt index d24f035971f..9c10575994c 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/ContainsOperatorReferenceSearcher.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/ContainsOperatorReferenceSearcher.kt @@ -28,14 +28,22 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance class ContainsOperatorReferenceSearcher( - targetFunction: PsiElement, - searchScope: SearchScope, - consumer: ExecutorProcessor, - optimizer: SearchRequestCollector, - options: KotlinReferencesSearchOptions -) : OperatorReferenceSearcher(targetFunction, searchScope, consumer, optimizer, options, wordsToSearch = listOf("in")) { - - private val OPERATION_TOKENS = setOf(KtTokens.IN_KEYWORD, KtTokens.NOT_IN) + targetFunction: PsiElement, + searchScope: SearchScope, + consumer: ExecutorProcessor, + optimizer: SearchRequestCollector, + options: KotlinReferencesSearchOptions +) : OperatorReferenceSearcher( + targetFunction, + searchScope, + consumer, + optimizer, + options, + wordsToSearch = listOf("in") +) { + private companion object { + private val OPERATION_TOKENS = setOf(KtTokens.IN_KEYWORD, KtTokens.NOT_IN) + } override fun processPossibleReceiverExpression(expression: KtExpression) { val parent = expression.parent diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/DestructuringDeclarationReferenceSearcher.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/DestructuringDeclarationReferenceSearcher.kt index 9c899dbae1c..b80f1bcedd2 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/DestructuringDeclarationReferenceSearcher.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/DestructuringDeclarationReferenceSearcher.kt @@ -30,19 +30,25 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance class DestructuringDeclarationReferenceSearcher( - targetDeclaration: PsiElement, - private val componentIndex: Int, - searchScope: SearchScope, - consumer: ExecutorProcessor, - optimizer: SearchRequestCollector, - options: KotlinReferencesSearchOptions -) : OperatorReferenceSearcher(targetDeclaration, searchScope, consumer, optimizer, options, wordsToSearch = listOf("(")) { + targetDeclaration: PsiElement, + private val componentIndex: Int, + searchScope: SearchScope, + consumer: ExecutorProcessor, + optimizer: SearchRequestCollector, + options: KotlinReferencesSearchOptions +) : OperatorReferenceSearcher( + targetDeclaration, + searchScope, + consumer, + optimizer, + options, + wordsToSearch = listOf("(") +) { override fun resolveTargetToDescriptor(): FunctionDescriptor? { return if (targetDeclaration is KtParameter) { targetDeclaration.dataClassComponentFunction() - } - else { + } else { super.resolveTargetToDescriptor() } } @@ -64,8 +70,7 @@ class DestructuringDeclarationReferenceSearcher( is KtContainerNode -> { if (parent.node.elementType == KtNodeTypes.LOOP_RANGE) { (parent.parent as KtForExpression).destructuringDeclaration - } - else { + } else { null } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/IndexingOperatorReferenceSearcher.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/IndexingOperatorReferenceSearcher.kt index 457cee80a63..1011f917169 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/IndexingOperatorReferenceSearcher.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/IndexingOperatorReferenceSearcher.kt @@ -30,13 +30,20 @@ import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance class IndexingOperatorReferenceSearcher( - targetFunction: PsiElement, - searchScope: SearchScope, - consumer: ExecutorProcessor, - optimizer: SearchRequestCollector, - options: KotlinReferencesSearchOptions, - private val isSet: Boolean -) : OperatorReferenceSearcher(targetFunction, searchScope, consumer, optimizer, options, wordsToSearch = listOf("[")) { + targetFunction: PsiElement, + searchScope: SearchScope, + consumer: ExecutorProcessor, + optimizer: SearchRequestCollector, + options: KotlinReferencesSearchOptions, + private val isSet: Boolean +) : OperatorReferenceSearcher( + targetFunction, + searchScope, + consumer, + optimizer, + options, + wordsToSearch = listOf("[") +) { override fun processPossibleReceiverExpression(expression: KtExpression) { val accessExpression = expression.parent as? KtArrayAccessExpression ?: return @@ -45,7 +52,8 @@ class IndexingOperatorReferenceSearcher( processReferenceElement(accessExpression) } - override fun isReferenceToCheck(ref: PsiReference) = ref is KtArrayAccessReference && checkAccessExpression(ref.element as KtArrayAccessExpression) + override fun isReferenceToCheck(ref: PsiReference) = + ref is KtArrayAccessReference && checkAccessExpression(ref.element) override fun extractReference(element: KtElement): PsiReference? { val accessExpression = element as? KtArrayAccessExpression ?: return null diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/InvokeOperatorReferenceSearcher.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/InvokeOperatorReferenceSearcher.kt index ca8de34a01d..9a8624c2790 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/InvokeOperatorReferenceSearcher.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/InvokeOperatorReferenceSearcher.kt @@ -34,11 +34,11 @@ import org.jetbrains.uast.UastContext import org.jetbrains.uast.convertOpt class InvokeOperatorReferenceSearcher( - targetFunction: PsiElement, - searchScope: SearchScope, - consumer: ExecutorProcessor, - optimizer: SearchRequestCollector, - options: KotlinReferencesSearchOptions + targetFunction: PsiElement, + searchScope: SearchScope, + consumer: ExecutorProcessor, + optimizer: SearchRequestCollector, + options: KotlinReferencesSearchOptions ) : OperatorReferenceSearcher(targetFunction, searchScope, consumer, optimizer, options, wordsToSearch = emptyList()) { private val callArgumentsSize: Int? @@ -49,15 +49,24 @@ class InvokeOperatorReferenceSearcher( val uMethod = uastContext.convertOpt(targetDeclaration, null) val uastParameters = uMethod?.uastParameters - val isStableNumberOfArguments = uastParameters != null && uastParameters.none { it.uastInitializer != null || it.isVarArgs } - if (isStableNumberOfArguments) { - val numberOfArguments = uastParameters!!.size - when { - targetFunction.isExtensionDeclaration() -> numberOfArguments - 1 - else -> numberOfArguments + if (uastParameters != null) { + val isStableNumberOfArguments = uastParameters.none { uParameter -> + @Suppress("UElementAsPsi") + uParameter.uastInitializer != null || uParameter.isVarArgs } + + if (isStableNumberOfArguments) { + val numberOfArguments = uastParameters.size + when { + targetFunction.isExtensionDeclaration() -> numberOfArguments - 1 + else -> numberOfArguments + } + } else { + null + } + } else { + null } - else null } else -> null diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/IteratorOperatorReferenceSearcher.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/IteratorOperatorReferenceSearcher.kt index ec07fe15aec..6d20333fafc 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/IteratorOperatorReferenceSearcher.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/IteratorOperatorReferenceSearcher.kt @@ -30,11 +30,11 @@ import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance class IteratorOperatorReferenceSearcher( - targetFunction: PsiElement, - searchScope: SearchScope, - consumer: ExecutorProcessor, - optimizer: SearchRequestCollector, - options: KotlinReferencesSearchOptions + targetFunction: PsiElement, + searchScope: SearchScope, + consumer: ExecutorProcessor, + optimizer: SearchRequestCollector, + options: KotlinReferencesSearchOptions ) : OperatorReferenceSearcher(targetFunction, searchScope, consumer, optimizer, options, wordsToSearch = listOf("in")) { override fun processPossibleReceiverExpression(expression: KtExpression) { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/OperatorReferenceSearcher.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/OperatorReferenceSearcher.kt index 8a78fda1c84..7f3735dc0c5 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/OperatorReferenceSearcher.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/OperatorReferenceSearcher.kt @@ -54,12 +54,12 @@ import org.jetbrains.kotlin.util.isValidOperator import java.util.* abstract class OperatorReferenceSearcher( - protected val targetDeclaration: PsiElement, - private val searchScope: SearchScope, - private val consumer: ExecutorProcessor, - private val optimizer: SearchRequestCollector, - private val options: KotlinReferencesSearchOptions, - private val wordsToSearch: List + protected val targetDeclaration: PsiElement, + private val searchScope: SearchScope, + private val consumer: ExecutorProcessor, + private val optimizer: SearchRequestCollector, + private val options: KotlinReferencesSearchOptions, + private val wordsToSearch: List ) { private val project = targetDeclaration.project @@ -83,19 +83,18 @@ abstract class OperatorReferenceSearcher( testLog { "Resolved ${logPresentation(element)}" } return if (reference.isReferenceTo(targetDeclaration)) { consumer.process(reference) - } - else { + } else { true } } companion object { fun create( - declaration: PsiElement, - searchScope: SearchScope, - consumer: ExecutorProcessor, - optimizer: SearchRequestCollector, - options: KotlinReferencesSearchOptions + declaration: PsiElement, + searchScope: SearchScope, + consumer: ExecutorProcessor, + optimizer: SearchRequestCollector, + options: KotlinReferencesSearchOptions ): OperatorReferenceSearcher<*>? { return runReadAction { if (declaration.isValid) @@ -106,13 +105,13 @@ abstract class OperatorReferenceSearcher( } private fun createInReadAction( - declaration: PsiElement, - searchScope: SearchScope, - consumer: ExecutorProcessor, - optimizer: SearchRequestCollector, - options: KotlinReferencesSearchOptions + declaration: PsiElement, + searchScope: SearchScope, + consumer: ExecutorProcessor, + optimizer: SearchRequestCollector, + options: KotlinReferencesSearchOptions ): OperatorReferenceSearcher<*>? { - val functionName = when (declaration) { + val functionName = when (declaration) { is KtNamedFunction -> declaration.name is PsiMethod -> declaration.name else -> null @@ -123,8 +122,7 @@ abstract class OperatorReferenceSearcher( val declarationToUse = if (declaration is KtLightMethod) { declaration.kotlinOrigin ?: return null - } - else { + } else { declaration } @@ -132,12 +130,12 @@ abstract class OperatorReferenceSearcher( } private fun createInReadAction( - declaration: PsiElement, - name: Name, - consumer: ExecutorProcessor, - optimizer: SearchRequestCollector, - options: KotlinReferencesSearchOptions, - searchScope: SearchScope + declaration: PsiElement, + name: Name, + consumer: ExecutorProcessor, + optimizer: SearchRequestCollector, + options: KotlinReferencesSearchOptions, + searchScope: SearchScope ): OperatorReferenceSearcher<*>? { if (DataClassDescriptorResolver.isComponentLike(name)) { if (!options.searchForComponentConventions) return null @@ -154,7 +152,7 @@ abstract class OperatorReferenceSearcher( when { binaryOp != null -> { val counterpartAssignmentOp = OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.inverse()[binaryOp] - val operationTokens = listOf(binaryOp, counterpartAssignmentOp).filterNotNull() + val operationTokens = listOfNotNull(binaryOp, counterpartAssignmentOp) return BinaryOperatorReferenceSearcher(declaration, operationTokens, searchScope, consumer, optimizer, options) } @@ -177,10 +175,24 @@ abstract class OperatorReferenceSearcher( return ContainsOperatorReferenceSearcher(declaration, searchScope, consumer, optimizer, options) name == OperatorNameConventions.EQUALS -> - return BinaryOperatorReferenceSearcher(declaration, listOf(KtTokens.EQEQ, KtTokens.EXCLEQ), searchScope, consumer, optimizer, options) + return BinaryOperatorReferenceSearcher( + declaration, + listOf(KtTokens.EQEQ, KtTokens.EXCLEQ), + searchScope, + consumer, + optimizer, + options + ) name == OperatorNameConventions.COMPARE_TO -> - return BinaryOperatorReferenceSearcher(declaration, listOf(KtTokens.LT, KtTokens.GT, KtTokens.LTEQ, KtTokens.GTEQ), searchScope, consumer, optimizer, options) + return BinaryOperatorReferenceSearcher( + declaration, + listOf(KtTokens.LT, KtTokens.GT, KtTokens.LTEQ, KtTokens.GTEQ), + searchScope, + consumer, + optimizer, + options + ) name == OperatorNameConventions.ITERATOR -> return IteratorOperatorReferenceSearcher(declaration, searchScope, consumer, optimizer, options) @@ -214,11 +226,14 @@ abstract class OperatorReferenceSearcher( val inProgress = SearchesInProgress.get() if (psiClass != null) { if (!inProgress.add(psiClass)) { - testLog { "ExpressionOfTypeProcessor is already started for ${runReadAction { psiClass.qualifiedName }}. Exit for operator ${logPresentation(targetDeclaration)}." } + testLog { + "ExpressionOfTypeProcessor is already started for ${runReadAction { psiClass.qualifiedName }}. Exit for operator ${logPresentation( + targetDeclaration + )}." + } return } - } - else { + } else { if (!inProgress.add(targetDeclaration)) { testLog { "ExpressionOfTypeProcessor is already started for operator ${logPresentation(targetDeclaration)}. Exit." } return //TODO: it's not quite correct @@ -227,16 +242,15 @@ abstract class OperatorReferenceSearcher( try { ExpressionsOfTypeProcessor( - receiverType, - psiClass, - searchScope, - project, - possibleMatchHandler = { expression -> processPossibleReceiverExpression(expression) }, - possibleMatchesInScopeHandler = { searchScope -> doPlainSearch(searchScope) } + receiverType, + psiClass, + searchScope, + project, + possibleMatchHandler = { expression -> processPossibleReceiverExpression(expression) }, + possibleMatchesInScopeHandler = { searchScope -> doPlainSearch(searchScope) } ).run() - } - finally { - inProgress.remove(if (psiClass != null) psiClass else targetDeclaration) + } finally { + inProgress.remove(psiClass ?: targetDeclaration) } } @@ -255,8 +269,7 @@ abstract class OperatorReferenceSearcher( return if (descriptor.isExtension) { descriptor.fuzzyExtensionReceiverType()!! - } - else { + } else { val classDescriptor = descriptor.containingDeclaration as? ClassDescriptor ?: return null classDescriptor.defaultType.toFuzzyType(classDescriptor.typeConstructor.parameters) } @@ -281,25 +294,32 @@ abstract class OperatorReferenceSearcher( (element.containingFile as KtFile).getResolutionFacade().analyze(elements, BodyResolveMode.PARTIAL) refs - .filter { it.isReferenceTo(targetDeclaration) } - .forEach { consumer.process(it) } + .filter { it.isReferenceTo(targetDeclaration) } + .forEach { consumer.process(it) } } } } } - } - else { + } else { scope as GlobalSearchScope if (wordsToSearch.isNotEmpty()) { val unwrappedElement = targetDeclaration.namedUnwrappedElement ?: return - val resultProcessor = KotlinRequestResultProcessor(unwrappedElement, - filter = { ref -> isReferenceToCheck(ref) }, - options = options) + val resultProcessor = KotlinRequestResultProcessor( + unwrappedElement, + filter = { ref -> isReferenceToCheck(ref) }, + options = options + ) wordsToSearch.forEach { - optimizer.searchWord(it, scope.restrictToKotlinSources(), UsageSearchContext.IN_CODE, true, unwrappedElement, resultProcessor) + optimizer.searchWord( + it, + scope.restrictToKotlinSources(), + UsageSearchContext.IN_CODE, + true, + unwrappedElement, + resultProcessor + ) } - } - else { + } else { val psiManager = PsiManager.getInstance(project) // we must unwrap progress indicator because ProgressWrapper does not do anything on changing text and fraction val progress = ProgressWrapper.unwrap(ProgressIndicatorProvider.getGlobalProgressIndicator()) @@ -321,8 +341,7 @@ abstract class OperatorReferenceSearcher( } } } - } - finally { + } finally { progress?.popState() } } @@ -335,24 +354,24 @@ abstract class OperatorReferenceSearcher( is LocalSearchScope -> { scope - .map { element -> - " " + runReadAction { - when (element) { - is KtFunctionLiteral -> element.text - is KtWhenEntry -> { - if (element.isElse) - "KtWhenEntry \"else\"" - else - "KtWhenEntry \"" + element.conditions.joinToString(", ") { it.text } + "\"" - } - is KtNamedDeclaration -> element.node.elementType.toString() + ":" + element.name - else -> element.toString() + .map { element -> + " " + runReadAction { + when (element) { + is KtFunctionLiteral -> element.text + is KtWhenEntry -> { + if (element.isElse) + "KtWhenEntry \"else\"" + else + "KtWhenEntry \"" + element.conditions.joinToString(", ") { it.text } + "\"" } + is KtNamedDeclaration -> element.node.elementType.toString() + ":" + element.name + else -> element.toString() } } - .toList() - .sorted() - .joinToString("\n", "LocalSearchScope:\n") + } + .toList() + .sorted() + .joinToString("\n", "LocalSearchScope:\n") } else -> this.displayName diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/PropertyDelegationOperatorReferenceSearcher.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/PropertyDelegationOperatorReferenceSearcher.kt index e1707e5aba4..fb949b89c16 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/PropertyDelegationOperatorReferenceSearcher.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/PropertyDelegationOperatorReferenceSearcher.kt @@ -29,11 +29,11 @@ import org.jetbrains.kotlin.psi.KtPropertyDelegate import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance class PropertyDelegationOperatorReferenceSearcher( - targetFunction: PsiElement, - searchScope: SearchScope, - consumer: ExecutorProcessor, - optimizer: SearchRequestCollector, - options: KotlinReferencesSearchOptions + targetFunction: PsiElement, + searchScope: SearchScope, + consumer: ExecutorProcessor, + optimizer: SearchRequestCollector, + options: KotlinReferencesSearchOptions ) : OperatorReferenceSearcher(targetFunction, searchScope, consumer, optimizer, options, wordsToSearch = listOf("by")) { override fun processPossibleReceiverExpression(expression: KtExpression) { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/UnaryOperatorReferenceSearcher.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/UnaryOperatorReferenceSearcher.kt index ca5f2d3e029..0ce538b3e03 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/UnaryOperatorReferenceSearcher.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/UnaryOperatorReferenceSearcher.kt @@ -30,13 +30,20 @@ import org.jetbrains.kotlin.psi.KtUnaryExpression import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance class UnaryOperatorReferenceSearcher( - targetFunction: PsiElement, - private val operationToken: KtSingleValueToken, - searchScope: SearchScope, - consumer: ExecutorProcessor, - optimizer: SearchRequestCollector, - options: KotlinReferencesSearchOptions -) : OperatorReferenceSearcher(targetFunction, searchScope, consumer, optimizer, options, wordsToSearch = listOf(operationToken.value)) { + targetFunction: PsiElement, + private val operationToken: KtSingleValueToken, + searchScope: SearchScope, + consumer: ExecutorProcessor, + optimizer: SearchRequestCollector, + options: KotlinReferencesSearchOptions +) : OperatorReferenceSearcher( + targetFunction, + searchScope, + consumer, + optimizer, + options, + wordsToSearch = listOf(operationToken.value) +) { override fun processPossibleReceiverExpression(expression: KtExpression) { val unaryExpression = expression.parent as? KtUnaryExpression ?: return diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt index 2aee725a841..3321fe3a124 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt @@ -81,9 +81,9 @@ fun PsiReference.checkUsageVsOriginalDescriptor( } fun PsiReference.isImportUsage(): Boolean = - element!!.getNonStrictParentOfType() != null + element.getNonStrictParentOfType() != null -fun PsiReference.isConstructorUsage(ktClassOrObject: KtClassOrObject): Boolean = with(element!!) { +fun PsiReference.isConstructorUsage(ktClassOrObject: KtClassOrObject): Boolean = with(element) { fun checkJavaUsage(): Boolean { val call = getNonStrictParentOfType() return call == parent && call?.resolveConstructor()?.containingClass?.navigationElement == ktClassOrObject @@ -92,8 +92,7 @@ fun PsiReference.isConstructorUsage(ktClassOrObject: KtClassOrObject): Boolean = fun checkKotlinUsage(): Boolean { if (this !is KtElement) return false - val descriptor = getConstructorCallDescriptor() - if (descriptor !is ConstructorDescriptor) return false + val descriptor = getConstructorCallDescriptor() as? ConstructorDescriptor ?: return false val declaration = DescriptorToSourceUtils.descriptorToDeclaration(descriptor.containingDeclaration) return declaration == ktClassOrObject || (declaration is KtConstructor<*> && declaration.getContainingClassOrObject() == ktClassOrObject) @@ -223,9 +222,9 @@ private fun processClassDelegationCallsToSpecifiedConstructor( fun PsiReference.isExtensionOfDeclarationClassUsage(declaration: KtNamedDeclaration): Boolean { val descriptor = declaration.descriptor ?: return false return checkUsageVsOriginalDescriptor(descriptor) { usageDescriptor, targetDescriptor -> - when { - usageDescriptor == targetDescriptor -> false - usageDescriptor !is FunctionDescriptor -> false + when (usageDescriptor) { + targetDescriptor -> false + !is FunctionDescriptor -> false else -> { val receiverDescriptor = usageDescriptor.extensionReceiverParameter?.type?.constructor?.declarationDescriptor @@ -251,12 +250,12 @@ fun PsiReference.isUsageInContainingDeclaration(declaration: KtNamedDeclaration) } fun PsiReference.isCallableOverrideUsage(declaration: KtNamedDeclaration): Boolean { - val toDescriptor: (KtDeclaration) -> CallableDescriptor? = { declaration -> - if (declaration is KtParameter) { + val toDescriptor: (KtDeclaration) -> CallableDescriptor? = { sourceDeclaration -> + if (sourceDeclaration is KtParameter) { // we don't treat parameters in overriding method as "override" here (overriding parameters usages are searched optionally and via searching of overriding methods first) - if (declaration.hasValOrVar()) declaration.propertyDescriptor else null + if (sourceDeclaration.hasValOrVar()) sourceDeclaration.propertyDescriptor else null } else { - declaration.descriptor as? CallableDescriptor + sourceDeclaration.descriptor as? CallableDescriptor } }