From 0f32574be0a8d2da32a353b7d2a0bf5b914c7413 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Fri, 2 Sep 2016 15:43:23 +0300 Subject: [PATCH] Fast get/set operators search --- .../BinaryOperatorReferenceSearcher.kt | 6 +-- .../IndexingOperatorReferenceSearcher.kt | 50 +++++++++++++++++++ .../InvokeOperatorReferenceSearcher.kt | 4 +- .../usagesSearch/OperatorReferenceSearch.kt | 4 ++ .../UnaryOperatorReferenceSearcher.kt | 6 +-- .../idea/search/usagesSearch/conventions.kt | 1 - .../findUsages/kotlin/conventions/get.log | 5 ++ .../findUsages/kotlin/conventions/set.log | 8 +++ 8 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/IndexingOperatorReferenceSearcher.kt create mode 100644 idea/testData/findUsages/kotlin/conventions/get.log create mode 100644 idea/testData/findUsages/kotlin/conventions/set.log diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/BinaryOperatorReferenceSearcher.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/BinaryOperatorReferenceSearcher.kt index a6f3dedcd0d..cbb6af8e71f 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/BinaryOperatorReferenceSearcher.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/BinaryOperatorReferenceSearcher.kt @@ -24,17 +24,17 @@ import com.intellij.util.Processor import org.jetbrains.kotlin.idea.references.KtSimpleNameReference import org.jetbrains.kotlin.lexer.KtSingleValueToken import org.jetbrains.kotlin.psi.KtBinaryExpression -import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance class BinaryOperatorReferenceSearcher( - targetDeclaration: KtDeclaration, + targetFunction: KtFunction, private val operationTokens: List, searchScope: SearchScope, consumer: Processor, optimizer: SearchRequestCollector -) : OperatorReferenceSearcher(targetDeclaration, searchScope, consumer, optimizer, wordsToSearch = operationTokens.map { it.value }) { +) : OperatorReferenceSearcher(targetFunction, searchScope, consumer, optimizer, wordsToSearch = operationTokens.map { it.value }) { override fun processSuspiciousExpression(expression: KtExpression) { val binaryExpression = expression.parent as? KtBinaryExpression ?: return diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/IndexingOperatorReferenceSearcher.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/IndexingOperatorReferenceSearcher.kt new file mode 100644 index 00000000000..7cdace0ac16 --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/IndexingOperatorReferenceSearcher.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.search.usagesSearch + +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiReference +import com.intellij.psi.search.SearchRequestCollector +import com.intellij.psi.search.SearchScope +import com.intellij.util.Processor +import org.jetbrains.kotlin.idea.references.KtArrayAccessReference +import org.jetbrains.kotlin.psi.KtArrayAccessExpression +import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.psi.KtFunction +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance + +//TODO: more effective search of 'set' +class IndexingOperatorReferenceSearcher( + targetFunction: KtFunction, + searchScope: SearchScope, + consumer: Processor, + optimizer: SearchRequestCollector +) : OperatorReferenceSearcher(targetFunction, searchScope, consumer, optimizer, wordsToSearch = listOf("[")) { + + override fun processSuspiciousExpression(expression: KtExpression) { + val accessExpression = expression.parent as? KtArrayAccessExpression ?: return + if (expression != accessExpression.arrayExpression) return + processReferenceElement(accessExpression) + } + + override fun isReferenceToCheck(ref: PsiReference) = ref is KtArrayAccessReference + + override fun extractReference(element: PsiElement): PsiReference? { + val accessExpression = element as? KtArrayAccessExpression ?: return null + return accessExpression.references.firstIsInstance() + } +} \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/InvokeOperatorReferenceSearcher.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/InvokeOperatorReferenceSearcher.kt index 062e2c4f32c..c2a763c0796 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/InvokeOperatorReferenceSearcher.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/InvokeOperatorReferenceSearcher.kt @@ -30,11 +30,11 @@ import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance class InvokeOperatorReferenceSearcher( - targetDeclaration: KtFunction, + targetFunction: KtFunction, searchScope: SearchScope, consumer: Processor, optimizer: SearchRequestCollector -) : OperatorReferenceSearcher(targetDeclaration, searchScope, consumer, optimizer, wordsToSearch = emptyList()) { +) : OperatorReferenceSearcher(targetFunction, searchScope, consumer, optimizer, wordsToSearch = emptyList()) { companion object { fun runForPsiMethod( diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/OperatorReferenceSearch.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/OperatorReferenceSearch.kt index 36d35c4579d..59b86f39f2e 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/OperatorReferenceSearch.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/OperatorReferenceSearch.kt @@ -133,6 +133,10 @@ abstract class OperatorReferenceSearcher( return UnaryOperatorReferenceSearcher(declaration, unaryOp, searchScope, consumer, optimizer) } + if (name in INDEXING_OPERATION_NAMES) { + return IndexingOperatorReferenceSearcher(declaration, searchScope, consumer, optimizer) + } + return null } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/UnaryOperatorReferenceSearcher.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/UnaryOperatorReferenceSearcher.kt index 5ebc821d144..3b2defa00b7 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/UnaryOperatorReferenceSearcher.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/UnaryOperatorReferenceSearcher.kt @@ -23,18 +23,18 @@ import com.intellij.psi.search.SearchScope import com.intellij.util.Processor import org.jetbrains.kotlin.idea.references.KtSimpleNameReference import org.jetbrains.kotlin.lexer.KtSingleValueToken -import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.psi.KtUnaryExpression import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance class UnaryOperatorReferenceSearcher( - targetDeclaration: KtDeclaration, + targetFunction: KtFunction, private val operationToken: KtSingleValueToken, searchScope: SearchScope, consumer: Processor, optimizer: SearchRequestCollector -) : OperatorReferenceSearcher(targetDeclaration, searchScope, consumer, optimizer, wordsToSearch = listOf(operationToken.value)) { +) : OperatorReferenceSearcher(targetFunction, searchScope, consumer, optimizer, wordsToSearch = listOf(operationToken.value)) { override fun processSuspiciousExpression(expression: KtExpression) { val unaryExpression = expression.parent as? KtUnaryExpression ?: return diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/conventions.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/conventions.kt index 7dfdebbc70a..de6bc335204 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/conventions.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/conventions.kt @@ -54,7 +54,6 @@ fun Name.getOperationSymbolsToSearch(): Pair, Class<*>>? { OperatorNameConventions.EQUALS -> return EQUALS_OPERATIONS to KtSimpleNameReference::class.java OperatorNameConventions.CONTAINS -> return IN_OPERATIONS_TO_SEARCH to KtSimpleNameReference::class.java OperatorNameConventions.ITERATOR -> return IN_OPERATIONS_TO_SEARCH to KtForLoopInReference::class.java - in INDEXING_OPERATION_NAMES -> return setOf(KtTokens.LBRACKET) to KtArrayAccessReference::class.java in DELEGATE_ACCESSOR_NAMES -> return setOf(KtTokens.BY_KEYWORD) to KtPropertyDelegationMethodsReference::class.java DelegatedPropertyResolver.PROPERTY_DELEGATED_FUNCTION_NAME -> return setOf(KtTokens.BY_KEYWORD) to KtPropertyDelegationMethodsReference::class.java } diff --git a/idea/testData/findUsages/kotlin/conventions/get.log b/idea/testData/findUsages/kotlin/conventions/get.log new file mode 100644 index 00000000000..573753c0a2d --- /dev/null +++ b/idea/testData/findUsages/kotlin/conventions/get.log @@ -0,0 +1,5 @@ +Resolved B(1)[2] +Searched references to B +Searched references to B.get(i: Int) in Kotlin files +Used plain search of B.get(i: Int) in LocalSearchScope: + CLASS:B diff --git a/idea/testData/findUsages/kotlin/conventions/set.log b/idea/testData/findUsages/kotlin/conventions/set.log new file mode 100644 index 00000000000..7c5c86d399d --- /dev/null +++ b/idea/testData/findUsages/kotlin/conventions/set.log @@ -0,0 +1,8 @@ +Checked type of a +Resolved a[2] +Resolved a[2] +Searched references to B +Searched references to a in Kotlin files +Searched references to parameter a of B.set(i: Int, a: B) in Kotlin files +Used plain search of B.set(i: Int, a: B) in LocalSearchScope: + CLASS:B