Optimize reference search for convention functions

This commit is contained in:
Natalia Ukhorskaya
2016-02-09 21:39:25 +03:00
parent 1f6894cdd4
commit 5ae394fec0
4 changed files with 32 additions and 25 deletions
@@ -62,18 +62,20 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
val unwrappedElement = element.namedUnwrappedElement ?: return val unwrappedElement = element.namedUnwrappedElement ?: return
val specialSymbols = runReadAction { unwrappedElement.getSpecialNamesToSearch() }
val words = runReadAction { val words = runReadAction {
val classNameForCompanionObject = unwrappedElement.getClassNameForCompanionObject() val classNameForCompanionObject = unwrappedElement.getClassNameForCompanionObject()
unwrappedElement.getSpecialNamesToSearch() + specialSymbols.first +
(if (classNameForCompanionObject != null) listOf(classNameForCompanionObject) else emptyList()) (if (classNameForCompanionObject != null) listOf(classNameForCompanionObject) else emptyList())
} }
val effectiveSearchScope = runReadAction { queryParameters.effectiveSearchScope } val effectiveSearchScope = runReadAction { queryParameters.effectiveSearchScope }
val refFilter: (PsiReference) -> Boolean = if (unwrappedElement is KtParameter) val refFilter: (PsiReference) -> Boolean = when {
({ ref: PsiReference -> !ref.isNamedArgumentReference()/* they are processed later*/ }) unwrappedElement is KtParameter -> ({ ref: PsiReference -> !ref.isNamedArgumentReference()/* they are processed later*/ })
else specialSymbols.second != null -> { ref -> ref.javaClass == specialSymbols.second }
({true}) else -> ({true})
}
val kotlinOptions = (queryParameters as? KotlinReferencesSearchParameters)?.kotlinOptions val kotlinOptions = (queryParameters as? KotlinReferencesSearchParameters)?.kotlinOptions
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.idea.search.usagesSearch package org.jetbrains.kotlin.idea.search.usagesSearch
import com.google.common.collect.ImmutableSet import com.google.common.collect.ImmutableSet
import org.jetbrains.kotlin.idea.references.*
import org.jetbrains.kotlin.lexer.KtToken import org.jetbrains.kotlin.lexer.KtToken
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -45,30 +46,30 @@ val IN_OPERATIONS_TO_SEARCH = setOf(KtTokens.IN_KEYWORD)
val COMPARISON_OPERATIONS_TO_SEARCH = setOf(KtTokens.LT, KtTokens.GT) val COMPARISON_OPERATIONS_TO_SEARCH = setOf(KtTokens.LT, KtTokens.GT)
fun Name.getOperationSymbolsToSearch(): Set<KtToken> { fun Name.getOperationSymbolsToSearch(): Pair<Set<KtToken>, Class<*>?> {
when (this) { when (this) {
OperatorNameConventions.COMPARE_TO -> return COMPARISON_OPERATIONS_TO_SEARCH OperatorNameConventions.COMPARE_TO -> return COMPARISON_OPERATIONS_TO_SEARCH to KtSimpleNameReference::class.java
OperatorNameConventions.EQUALS -> return EQUALS_OPERATIONS OperatorNameConventions.EQUALS -> return EQUALS_OPERATIONS to KtSimpleNameReference::class.java
OperatorNameConventions.CONTAINS -> return IN_OPERATIONS_TO_SEARCH OperatorNameConventions.CONTAINS -> return IN_OPERATIONS_TO_SEARCH to KtSimpleNameReference::class.java
OperatorNameConventions.ITERATOR -> return IN_OPERATIONS_TO_SEARCH OperatorNameConventions.ITERATOR -> return IN_OPERATIONS_TO_SEARCH to KtForLoopInReference::class.java
in INDEXING_OPERATION_NAMES -> return setOf(KtTokens.LBRACKET) in INDEXING_OPERATION_NAMES -> return setOf(KtTokens.LBRACKET) to KtArrayAccessReference::class.java
in DELEGATE_ACCESSOR_NAMES -> return setOf(KtTokens.BY_KEYWORD) in DELEGATE_ACCESSOR_NAMES -> return setOf(KtTokens.BY_KEYWORD) to KtPropertyDelegationMethodsReference::class.java
DelegatedPropertyResolver.PROPERTY_DELEGATED_FUNCTION_NAME -> return setOf(KtTokens.BY_KEYWORD) DelegatedPropertyResolver.PROPERTY_DELEGATED_FUNCTION_NAME -> return setOf(KtTokens.BY_KEYWORD) to KtPropertyDelegationMethodsReference::class.java
} }
if (isComponentLike(this)) return setOf(KtTokens.LPAR) if (isComponentLike(this)) return setOf(KtTokens.LPAR) to KtDestructuringDeclarationReference::class.java
val unaryOp = UNARY_OPERATION_NAMES_WITH_DEPRECATED_INVERTED[this] val unaryOp = UNARY_OPERATION_NAMES_WITH_DEPRECATED_INVERTED[this]
if (unaryOp != null) return setOf(unaryOp) if (unaryOp != null) return setOf(unaryOp) to KtSimpleNameReference::class.java
val binaryOp = BINARY_OPERATION_NAMES.inverse()[this] val binaryOp = BINARY_OPERATION_NAMES.inverse()[this]
if (binaryOp != null) { if (binaryOp != null) {
val assignmentOp = ASSIGNMENT_OPERATION_COUNTERPARTS.inverse()[binaryOp] val assignmentOp = ASSIGNMENT_OPERATION_COUNTERPARTS.inverse()[binaryOp]
return if (assignmentOp != null) setOf(binaryOp, assignmentOp) else setOf(binaryOp) return (if (assignmentOp != null) setOf(binaryOp, assignmentOp) else setOf(binaryOp)) to KtSimpleNameReference::class.java
} }
val assignmentOp = ASSIGNMENT_OPERATIONS.inverse()[this] val assignmentOp = ASSIGNMENT_OPERATIONS.inverse()[this]
if (assignmentOp != null) return setOf(assignmentOp) if (assignmentOp != null) return setOf(assignmentOp) to KtSimpleNameReference::class.java
return emptySet() return emptySet<KtToken>() to null
} }
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.asJava.LightClassUtil.PropertyAccessorsPsiMethods
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.references.KtDestructuringDeclarationReference
import org.jetbrains.kotlin.lexer.KtSingleValueToken import org.jetbrains.kotlin.lexer.KtSingleValueToken
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -63,17 +64,20 @@ fun PsiNamedElement.getClassNameForCompanionObject(): String? {
} }
} }
fun PsiNamedElement.getSpecialNamesToSearch(): List<String> { fun PsiNamedElement.getSpecialNamesToSearch(): Pair<List<String>, Class<*>?> {
val name = name val name = name
return when { return when {
name == null || !Name.isValidIdentifier(name) -> Collections.emptyList<String>() name == null || !Name.isValidIdentifier(name) -> Collections.emptyList<String>() to null
this is KtParameter -> { this is KtParameter -> {
val componentFunctionName = this.dataClassComponentFunction()?.name val componentFunctionName = this.dataClassComponentFunction()?.name
if (componentFunctionName == null) return Collections.emptyList<String>() if (componentFunctionName == null) return Collections.emptyList<String>() to null
return listOf(componentFunctionName.asString(), KtTokens.LPAR.value) return listOf(componentFunctionName.asString(), KtTokens.LPAR.value) to KtDestructuringDeclarationReference::class.java
}
else -> {
val operationSymbolsToSearch = Name.identifier(name).getOperationSymbolsToSearch()
operationSymbolsToSearch.first.map { (it as KtSingleValueToken).value } to operationSymbolsToSearch.second
} }
else -> Name.identifier(name).getOperationSymbolsToSearch().map { (it as KtSingleValueToken).value }
} }
} }
@@ -207,7 +207,7 @@ class UnusedSymbolInspection : AbstractKotlinInspection() {
private fun isConventionalName(namedDeclaration: KtNamedDeclaration): Boolean { private fun isConventionalName(namedDeclaration: KtNamedDeclaration): Boolean {
val name = namedDeclaration.nameAsName val name = namedDeclaration.nameAsName
return name!!.getOperationSymbolsToSearch().isNotEmpty() || name == OperatorNameConventions.INVOKE return name!!.getOperationSymbolsToSearch().first.isNotEmpty() || name == OperatorNameConventions.INVOKE
} }
private fun hasNonTrivialUsages(declaration: KtNamedDeclaration): Boolean { private fun hasNonTrivialUsages(declaration: KtNamedDeclaration): Boolean {