Minor: reformat and cleanup org.jetbrains.kotlin.idea.search package

This commit is contained in:
Nikolay Krasko
2019-02-14 12:02:50 +03:00
parent 16c79b562e
commit 7f1e7cc461
19 changed files with 411 additions and 328 deletions
@@ -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
}
@@ -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<KtToken> = ImmutableSet
.builder<KtToken>()
.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<KtToken>()
.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<IElementType>(MAX_PREV_TOKENS)
}
private val MAX_PREV_TOKENS = 2
private val prevTokens = ArrayDeque<IElementType>(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)
@@ -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<CachedValue<PsiBasedClassResolver>>("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)
@@ -29,17 +29,17 @@ import org.jetbrains.kotlin.psi.KtClassOrObject
fun HierarchySearchRequest<*>.searchInheritors(): Query<PsiClass> {
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
)
}
@@ -39,18 +39,18 @@ interface SearchRequestWithElement<T : PsiElement> : DeclarationSearchRequest<T>
override val project: Project get() = originalElement.project
}
abstract class DeclarationsSearch<T: PsiElement, R: DeclarationSearchRequest<T>>: QueryFactory<T, R>() {
abstract class DeclarationsSearch<T : PsiElement, R : DeclarationSearchRequest<T>> : QueryFactory<T, R>() {
init {
registerExecutor(
object : QueryExecutorBase<T, R>(true) {
override fun processQuery(queryParameters: R, consumer: ExecutorProcessor<T>) {
doSearch(queryParameters, consumer)
}
object : QueryExecutorBase<T, R>(true) {
override fun processQuery(queryParameters: R, consumer: ExecutorProcessor<T>) {
doSearch(queryParameters, consumer)
}
}
)
}
override final fun registerExecutor(executor: QueryExecutor<T, R>) {
final override fun registerExecutor(executor: QueryExecutor<T, R>) {
super.registerExecutor(executor)
}
@@ -60,13 +60,13 @@ abstract class DeclarationsSearch<T: PsiElement, R: DeclarationSearchRequest<T>>
fun search(request: R): Query<T> = if (isApplicable(request)) createUniqueResultsQuery(request) else EmptyQuery.getEmptyQuery<T>()
}
class HierarchySearchRequest<T: PsiElement> (
override val originalElement: T,
override val searchScope: SearchScope,
val searchDeeply: Boolean = true
class HierarchySearchRequest<T : PsiElement>(
override val originalElement: T,
override val searchScope: SearchScope,
val searchDeeply: Boolean = true
) : SearchRequestWithElement<T> {
fun <U: PsiElement> copy(newOriginalElement: U): HierarchySearchRequest<U> =
HierarchySearchRequest(newOriginalElement, searchScope, searchDeeply)
fun <U : PsiElement> copy(newOriginalElement: U): HierarchySearchRequest<U> =
HierarchySearchRequest(newOriginalElement, searchScope, searchDeeply)
}
interface HierarchyTraverser<T> {
@@ -97,7 +97,7 @@ interface HierarchyTraverser<T> {
}
}
fun <T: PsiElement> ExecutorProcessor<T>.consumeHierarchy(request: SearchRequestWithElement<T>, traverser: HierarchyTraverser<T>) {
fun <T : PsiElement> ExecutorProcessor<T>.consumeHierarchy(request: SearchRequestWithElement<T>, traverser: HierarchyTraverser<T>) {
traverser.forEach(request.originalElement) { element ->
if (element in request.searchScope) {
process(element)
@@ -105,9 +105,9 @@ fun <T: PsiElement> ExecutorProcessor<T>.consumeHierarchy(request: SearchRequest
}
}
abstract class HierarchySearch<T: PsiElement>(
protected val traverser: HierarchyTraverser<T>
): DeclarationsSearch<T, HierarchySearchRequest<T>>() {
abstract class HierarchySearch<T : PsiElement>(
private val traverser: HierarchyTraverser<T>
) : DeclarationsSearch<T, HierarchySearchRequest<T>>() {
protected open fun doSearchAll(request: HierarchySearchRequest<T>, consumer: ExecutorProcessor<T>) {
consumer.consumeHierarchy(request, traverser)
}
@@ -117,8 +117,7 @@ abstract class HierarchySearch<T: PsiElement>(
override fun doSearch(request: HierarchySearchRequest<T>, consumer: ExecutorProcessor<T>) {
if (request.searchDeeply) {
doSearchAll(request, consumer)
}
else {
} else {
doSearchDirect(request, consumer)
}
}
@@ -52,34 +52,33 @@ fun HierarchySearchRequest<*>.searchOverriders(): Query<PsiMethod> {
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<PsiMethod>(PsiMethodOverridingHierarchyTraverser) {
fun searchDirectOverriders(psiMethod: PsiMethod): Iterable<PsiMethod> {
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<PsiClass, PsiMethod>()
val classTraverser = object : HierarchyTraverser<PsiClass> {
override fun nextElements(current: PsiClass): Iterable<PsiClass> =
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<PsiMethod>(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<PsiMethod>(PsiMethodOve
}
override fun isApplicable(request: HierarchySearchRequest<PsiMethod>): Boolean =
runReadAction { request.originalElement.isOverridableElement() }
runReadAction { request.originalElement.isOverridableElement() }
override fun doSearchDirect(request: HierarchySearchRequest<PsiMethod>, consumer: ExecutorProcessor<PsiMethod>) {
searchDirectOverriders(request.originalElement).forEach { method -> consumer.process(method) }
}
}
object PsiMethodOverridingHierarchyTraverser: HierarchyTraverser<PsiMethod> {
object PsiMethodOverridingHierarchyTraverser : HierarchyTraverser<PsiMethod> {
override fun nextElements(current: PsiMethod): Iterable<PsiMethod> = KotlinPsiMethodOverridersSearch.searchDirectOverriders(current)
override fun shouldDescend(element: PsiMethod): Boolean = PsiUtil.canBeOverridden(element)
}
@@ -119,23 +118,26 @@ fun PsiElement.toPossiblyFakeLightMethods(): List<PsiMethod> {
}
private fun forEachKotlinOverride(
ktClass: KtClass,
members: List<KtNamedDeclaration>,
scope: SearchScope,
processor: (superMember: PsiElement, overridingMember: PsiElement) -> Boolean
ktClass: KtClass,
members: List<KtNamedDeclaration>,
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<KtNamedDeclaration>() +
ktClass.primaryConstructorParameters.filter { it.hasValOrVar() }
ktClass.primaryConstructorParameters.filter { it.hasValOrVar() }
forEachKotlinOverride(ktClass, members, scope, processor)
}
@@ -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
}
}
@@ -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)
}
@@ -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<PsiClass>) : RequestResultProcessor(psiMember) {
private class StaticMemberRequestResultProcessor(val psiMember: PsiMember, classes: List<PsiClass>) :
RequestResultProcessor(psiMember) {
val possibleClassesNames: Set<String> = runReadAction { classes.map { it.qualifiedName }.filterNotNullTo(HashSet()) }
override fun processTextOccurrence(element: PsiElement, offsetInElement: Int, consumer: ExecutorProcessor<PsiReference>): 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
}
}
@@ -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<KtSingleValueToken>,
searchScope: SearchScope,
consumer: ExecutorProcessor<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
) : OperatorReferenceSearcher<KtBinaryExpression>(targetFunction, searchScope, consumer, optimizer, options, wordsToSearch = operationTokens.map { it.value }) {
targetFunction: PsiElement,
private val operationTokens: List<KtSingleValueToken>,
searchScope: SearchScope,
consumer: ExecutorProcessor<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
) : OperatorReferenceSearcher<KtBinaryExpression>(
targetFunction,
searchScope,
consumer,
optimizer,
options,
wordsToSearch = operationTokens.map { it.value }) {
override fun processPossibleReceiverExpression(expression: KtExpression) {
val binaryExpression = expression.parent as? KtBinaryExpression ?: return
@@ -28,14 +28,22 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
class ContainsOperatorReferenceSearcher(
targetFunction: PsiElement,
searchScope: SearchScope,
consumer: ExecutorProcessor<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
) : OperatorReferenceSearcher<KtOperationReferenceExpression>(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<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
) : OperatorReferenceSearcher<KtOperationReferenceExpression>(
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
@@ -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<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
) : OperatorReferenceSearcher<KtDestructuringDeclaration>(targetDeclaration, searchScope, consumer, optimizer, options, wordsToSearch = listOf("(")) {
targetDeclaration: PsiElement,
private val componentIndex: Int,
searchScope: SearchScope,
consumer: ExecutorProcessor<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
) : OperatorReferenceSearcher<KtDestructuringDeclaration>(
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
}
}
@@ -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<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions,
private val isSet: Boolean
) : OperatorReferenceSearcher<KtArrayAccessExpression>(targetFunction, searchScope, consumer, optimizer, options, wordsToSearch = listOf("[")) {
targetFunction: PsiElement,
searchScope: SearchScope,
consumer: ExecutorProcessor<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions,
private val isSet: Boolean
) : OperatorReferenceSearcher<KtArrayAccessExpression>(
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
@@ -34,11 +34,11 @@ import org.jetbrains.uast.UastContext
import org.jetbrains.uast.convertOpt
class InvokeOperatorReferenceSearcher(
targetFunction: PsiElement,
searchScope: SearchScope,
consumer: ExecutorProcessor<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
targetFunction: PsiElement,
searchScope: SearchScope,
consumer: ExecutorProcessor<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
) : OperatorReferenceSearcher<KtCallExpression>(targetFunction, searchScope, consumer, optimizer, options, wordsToSearch = emptyList()) {
private val callArgumentsSize: Int?
@@ -49,15 +49,24 @@ class InvokeOperatorReferenceSearcher(
val uMethod = uastContext.convertOpt<UMethod>(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
@@ -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<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
targetFunction: PsiElement,
searchScope: SearchScope,
consumer: ExecutorProcessor<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
) : OperatorReferenceSearcher<KtForExpression>(targetFunction, searchScope, consumer, optimizer, options, wordsToSearch = listOf("in")) {
override fun processPossibleReceiverExpression(expression: KtExpression) {
@@ -54,12 +54,12 @@ import org.jetbrains.kotlin.util.isValidOperator
import java.util.*
abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
protected val targetDeclaration: PsiElement,
private val searchScope: SearchScope,
private val consumer: ExecutorProcessor<PsiReference>,
private val optimizer: SearchRequestCollector,
private val options: KotlinReferencesSearchOptions,
private val wordsToSearch: List<String>
protected val targetDeclaration: PsiElement,
private val searchScope: SearchScope,
private val consumer: ExecutorProcessor<PsiReference>,
private val optimizer: SearchRequestCollector,
private val options: KotlinReferencesSearchOptions,
private val wordsToSearch: List<String>
) {
private val project = targetDeclaration.project
@@ -83,19 +83,18 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
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<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
declaration: PsiElement,
searchScope: SearchScope,
consumer: ExecutorProcessor<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
): OperatorReferenceSearcher<*>? {
return runReadAction {
if (declaration.isValid)
@@ -106,13 +105,13 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
}
private fun createInReadAction(
declaration: PsiElement,
searchScope: SearchScope,
consumer: ExecutorProcessor<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
declaration: PsiElement,
searchScope: SearchScope,
consumer: ExecutorProcessor<PsiReference>,
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<TReferenceElement : KtElement>(
val declarationToUse = if (declaration is KtLightMethod) {
declaration.kotlinOrigin ?: return null
}
else {
} else {
declaration
}
@@ -132,12 +130,12 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
}
private fun createInReadAction(
declaration: PsiElement,
name: Name,
consumer: ExecutorProcessor<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions,
searchScope: SearchScope
declaration: PsiElement,
name: Name,
consumer: ExecutorProcessor<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions,
searchScope: SearchScope
): OperatorReferenceSearcher<*>? {
if (DataClassDescriptorResolver.isComponentLike(name)) {
if (!options.searchForComponentConventions) return null
@@ -154,7 +152,7 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
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<TReferenceElement : KtElement>(
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<TReferenceElement : KtElement>(
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<TReferenceElement : KtElement>(
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<TReferenceElement : KtElement>(
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<TReferenceElement : KtElement>(
(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<TReferenceElement : KtElement>(
}
}
}
}
finally {
} finally {
progress?.popState()
}
}
@@ -335,24 +354,24 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
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
@@ -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<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
targetFunction: PsiElement,
searchScope: SearchScope,
consumer: ExecutorProcessor<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
) : OperatorReferenceSearcher<KtPropertyDelegate>(targetFunction, searchScope, consumer, optimizer, options, wordsToSearch = listOf("by")) {
override fun processPossibleReceiverExpression(expression: KtExpression) {
@@ -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<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
) : OperatorReferenceSearcher<KtUnaryExpression>(targetFunction, searchScope, consumer, optimizer, options, wordsToSearch = listOf(operationToken.value)) {
targetFunction: PsiElement,
private val operationToken: KtSingleValueToken,
searchScope: SearchScope,
consumer: ExecutorProcessor<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
) : OperatorReferenceSearcher<KtUnaryExpression>(
targetFunction,
searchScope,
consumer,
optimizer,
options,
wordsToSearch = listOf(operationToken.value)
) {
override fun processPossibleReceiverExpression(expression: KtExpression) {
val unaryExpression = expression.parent as? KtUnaryExpression ?: return
@@ -81,9 +81,9 @@ fun PsiReference.checkUsageVsOriginalDescriptor(
}
fun PsiReference.isImportUsage(): Boolean =
element!!.getNonStrictParentOfType<KtImportDirective>() != null
element.getNonStrictParentOfType<KtImportDirective>() != null
fun PsiReference.isConstructorUsage(ktClassOrObject: KtClassOrObject): Boolean = with(element!!) {
fun PsiReference.isConstructorUsage(ktClassOrObject: KtClassOrObject): Boolean = with(element) {
fun checkJavaUsage(): Boolean {
val call = getNonStrictParentOfType<PsiConstructorCall>()
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
}
}