From f6fbd0b62374c048f6f1e6416d1b01b3bfa02821 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Fri, 2 Sep 2016 16:22:16 +0300 Subject: [PATCH] Fast search of contains operator --- .../kotlin/psi/KtBinaryExpression.java | 4 +- .../kotlin/psi/KtWhenConditionInRange.java | 4 +- .../ContainsOperatorReferenceSearcher.kt | 64 +++++++++++++++++++ .../usagesSearch/OperatorReferenceSearch.kt | 4 ++ .../idea/search/usagesSearch/conventions.kt | 2 - .../kotlin/conventions/contains.log | 7 ++ 6 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/ContainsOperatorReferenceSearcher.kt create mode 100644 idea/testData/findUsages/kotlin/conventions/contains.log diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtBinaryExpression.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtBinaryExpression.java index aa3b2f73822..6e5571fb9dd 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtBinaryExpression.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtBinaryExpression.java @@ -63,8 +63,8 @@ public class KtBinaryExpression extends KtExpressionImpl implements KtOperationE @Override @NotNull - public KtSimpleNameExpression getOperationReference() { - return (KtSimpleNameExpression) findChildByType(KtNodeTypes.OPERATION_REFERENCE); + public KtOperationReferenceExpression getOperationReference() { + return (KtOperationReferenceExpression) findChildByType(KtNodeTypes.OPERATION_REFERENCE); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtWhenConditionInRange.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtWhenConditionInRange.java index ec329709068..5294bd2648a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtWhenConditionInRange.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtWhenConditionInRange.java @@ -53,7 +53,7 @@ public class KtWhenConditionInRange extends KtWhenCondition { } @NotNull - public KtSimpleNameExpression getOperationReference() { - return (KtSimpleNameExpression) findChildByType(KtNodeTypes.OPERATION_REFERENCE); + public KtOperationReferenceExpression getOperationReference() { + return (KtOperationReferenceExpression) findChildByType(KtNodeTypes.OPERATION_REFERENCE); } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/ContainsOperatorReferenceSearcher.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/ContainsOperatorReferenceSearcher.kt new file mode 100644 index 00000000000..09ae28bc2e2 --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/ContainsOperatorReferenceSearcher.kt @@ -0,0 +1,64 @@ +/* + * 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.KtSimpleNameReference +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance + +class ContainsOperatorReferenceSearcher( + targetFunction: KtFunction, + searchScope: SearchScope, + consumer: Processor, + optimizer: SearchRequestCollector +) : OperatorReferenceSearcher(targetFunction, searchScope, consumer, optimizer, wordsToSearch = listOf("in")) { + + private val OPERATION_TOKENS = setOf(KtTokens.IN_KEYWORD, KtTokens.NOT_IN) + + override fun processSuspiciousExpression(expression: KtExpression) { + val parent = expression.parent + when (parent) { + is KtBinaryExpression -> { + if (parent.operationToken in OPERATION_TOKENS && expression == parent.right) { + processReferenceElement(parent.operationReference) + } + } + + is KtWhenConditionInRange -> { + processReferenceElement(parent.operationReference) + } + } + } + + override fun isReferenceToCheck(ref: PsiReference): Boolean { + if (ref !is KtSimpleNameReference) return false + val element = ref.element as? KtOperationReferenceExpression ?: return false + return element.getReferencedNameElementType() in OPERATION_TOKENS + } + + override fun extractReference(element: PsiElement): PsiReference? { + val referenceExpression = element as? KtOperationReferenceExpression ?: return null + if (referenceExpression.getReferencedNameElementType() !in OPERATION_TOKENS) return null + return referenceExpression.references.firstIsInstance() + } +} \ No newline at end of file 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 cdf60f02bda..748c415a6e5 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 @@ -141,6 +141,10 @@ abstract class OperatorReferenceSearcher( return IndexingOperatorReferenceSearcher(declaration, searchScope, consumer, optimizer, isSet = true) } + if (name == OperatorNameConventions.CONTAINS) { + return ContainsOperatorReferenceSearcher(declaration, searchScope, consumer, optimizer) + } + return null } 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 6ba8d714800..962d334af7f 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 @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.idea.search.usagesSearch import com.google.common.collect.ImmutableSet -import org.jetbrains.kotlin.idea.references.KtArrayAccessReference import org.jetbrains.kotlin.idea.references.KtForLoopInReference import org.jetbrains.kotlin.idea.references.KtPropertyDelegationMethodsReference import org.jetbrains.kotlin.idea.references.KtSimpleNameReference @@ -50,7 +49,6 @@ fun Name.getOperationSymbolsToSearch(): Pair, Class<*>>? { when (this) { OperatorNameConventions.COMPARE_TO -> return COMPARISON_OPERATIONS_TO_SEARCH to KtSimpleNameReference::class.java 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 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/contains.log b/idea/testData/findUsages/kotlin/conventions/contains.log new file mode 100644 index 00000000000..ef71e737adc --- /dev/null +++ b/idea/testData/findUsages/kotlin/conventions/contains.log @@ -0,0 +1,7 @@ +Resolved !in +Resolved !in +Resolved in +Resolved in +Searched references to A +Used plain search of A.contains(k: Int) in LocalSearchScope: + CLASS:A