[kotlin] KTIJ-27084 fixed

GitOrigin-RevId: bafbf02e465511c489388883970e365223dafd3b
This commit is contained in:
Andrew Kozlov
2024-08-12 19:16:06 +02:00
committed by intellij-monorepo-bot
parent 4c6f8dbe4c
commit 0c7168093e
9 changed files with 96 additions and 53 deletions

View File

@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.idea.completion.checkers.CompletionVisibilityChecker
import org.jetbrains.kotlin.idea.completion.contributors.helpers.CompletionSymbolOrigin
import org.jetbrains.kotlin.idea.completion.contributors.helpers.FirClassifierProvider.getAvailableClassifiersCurrentScope
import org.jetbrains.kotlin.idea.completion.contributors.helpers.FirClassifierProvider.getAvailableClassifiersFromIndex
import org.jetbrains.kotlin.idea.completion.contributors.helpers.getStaticScopes
import org.jetbrains.kotlin.idea.completion.contributors.helpers.staticScope
import org.jetbrains.kotlin.idea.completion.impl.k2.context.FirBasicCompletionContext
import org.jetbrains.kotlin.idea.completion.lookups.ImportStrategy
import org.jetbrains.kotlin.idea.completion.reference
@@ -54,8 +54,13 @@ internal open class FirClassifierCompletionContributor(
visibilityChecker: CompletionVisibilityChecker,
context: WeighingContext
) {
val reference = receiver.reference() ?: return
getStaticScopes(reference).forEach { scopeWithKind ->
val symbols = receiver.reference()
?.resolveToSymbols()
?: return
symbols.asSequence()
.mapNotNull { it.staticScope }
.forEach { scopeWithKind ->
scopeWithKind.scope
.classifiers(scopeNameFilter)
.filter { filterClassifiers(it) }

View File

@@ -6,12 +6,12 @@ import org.jetbrains.kotlin.analysis.api.KaSession
import org.jetbrains.kotlin.idea.completion.FirCompletionSessionParameters
import org.jetbrains.kotlin.idea.completion.checkers.CompletionVisibilityChecker
import org.jetbrains.kotlin.idea.completion.contributors.helpers.CompletionSymbolOrigin
import org.jetbrains.kotlin.idea.completion.contributors.helpers.getStaticScopes
import org.jetbrains.kotlin.idea.completion.contributors.helpers.resolveToSymbols
import org.jetbrains.kotlin.idea.completion.contributors.helpers.staticScope
import org.jetbrains.kotlin.idea.completion.impl.k2.context.FirBasicCompletionContext
import org.jetbrains.kotlin.idea.completion.lookups.CallableInsertionOptions
import org.jetbrains.kotlin.idea.completion.lookups.CallableInsertionStrategy
import org.jetbrains.kotlin.idea.completion.lookups.ImportStrategy
import org.jetbrains.kotlin.idea.completion.reference
import org.jetbrains.kotlin.idea.completion.weighers.WeighingContext
import org.jetbrains.kotlin.idea.util.positionContext.KotlinImportDirectivePositionContext
@@ -27,25 +27,32 @@ internal class FirImportDirectivePackageMembersCompletionContributor(
weighingContext: WeighingContext,
sessionParameters: FirCompletionSessionParameters,
) {
val reference = positionContext.explicitReceiver?.reference() ?: return
getStaticScopes(reference).forEach { scopeWithKind ->
val symbolOrigin = CompletionSymbolOrigin.Scope(scopeWithKind.kind)
val visibilityChecker = CompletionVisibilityChecker.create(basicContext, positionContext)
positionContext.resolveToSymbols()
.mapNotNull { it.staticScope }
.forEach { scopeWithKind ->
val symbolOrigin = CompletionSymbolOrigin.Scope(scopeWithKind.kind)
val visibilityChecker = CompletionVisibilityChecker.create(basicContext, positionContext)
scopeWithKind.scope.classifiers(scopeNameFilter)
.filter { visibilityChecker.isVisible(it) }
.forEach { addClassifierSymbolToCompletion(it, weighingContext, symbolOrigin, ImportStrategy.DoNothing) }
val classifiers = scopeWithKind.scope
.classifiers(scopeNameFilter)
.toList()
classifiers
.filter { visibilityChecker.isVisible(it) }
.forEach { addClassifierSymbolToCompletion(it, weighingContext, symbolOrigin, ImportStrategy.DoNothing) }
scopeWithKind.scope.callables(scopeNameFilter)
.filter { visibilityChecker.isVisible(it) }
.forEach {
addCallableSymbolToCompletion(
weighingContext,
it.asSignature(),
CallableInsertionOptions(ImportStrategy.DoNothing, CallableInsertionStrategy.AsIdentifier),
symbolOrigin,
)
}
}
val callables = scopeWithKind.scope
.callables(scopeNameFilter)
.toList()
callables
.filter { visibilityChecker.isVisible(it) }
.forEach {
addCallableSymbolToCompletion(
weighingContext,
it.asSignature(),
CallableInsertionOptions(ImportStrategy.DoNothing, CallableInsertionStrategy.AsIdentifier),
symbolOrigin,
)
}
}
}
}

View File

@@ -9,12 +9,11 @@ import org.jetbrains.kotlin.base.analysis.isExcludedFromAutoImport
import org.jetbrains.kotlin.idea.completion.FirCompletionSessionParameters
import org.jetbrains.kotlin.idea.completion.contributors.helpers.CompletionSymbolOrigin
import org.jetbrains.kotlin.idea.completion.contributors.helpers.KtSymbolWithOrigin
import org.jetbrains.kotlin.idea.completion.contributors.helpers.resolveToSymbols
import org.jetbrains.kotlin.idea.completion.impl.k2.context.FirBasicCompletionContext
import org.jetbrains.kotlin.idea.completion.lookups.factories.KotlinFirLookupElementFactory
import org.jetbrains.kotlin.idea.completion.reference
import org.jetbrains.kotlin.idea.completion.weighers.Weighers
import org.jetbrains.kotlin.idea.completion.weighers.WeighingContext
import org.jetbrains.kotlin.idea.util.positionContext.KotlinNameReferencePositionContext
import org.jetbrains.kotlin.idea.util.positionContext.KotlinRawPositionContext
internal class FirPackageCompletionContributor(
@@ -29,11 +28,11 @@ internal class FirPackageCompletionContributor(
weighingContext: WeighingContext,
sessionParameters: FirCompletionSessionParameters,
) {
val rootSymbol = if (positionContext !is KotlinNameReferencePositionContext || positionContext.explicitReceiver == null) {
rootPackageSymbol
} else {
positionContext.explicitReceiver?.reference()?.resolveToSymbols()?.filterIsInstance<KaPackageSymbol>()?.singleOrNull()
} ?: return
val rootSymbol = positionContext.resolveToSymbols()
.filterIsInstance<KaPackageSymbol>()
.singleOrNull()
?: return
val symbolOrigin = CompletionSymbolOrigin.Scope(KaScopeKinds.PackageMemberScope(CompletionSymbolOrigin.SCOPE_OUTSIDE_TOWER_INDEX))

View File

@@ -1,46 +1,39 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.kotlin.idea.completion.contributors.helpers
import org.jetbrains.kotlin.analysis.api.KaSession
import org.jetbrains.kotlin.analysis.api.components.KaScopeKind
import org.jetbrains.kotlin.analysis.api.components.KaScopeKinds
import org.jetbrains.kotlin.analysis.api.components.KaScopeWithKindImpl
import org.jetbrains.kotlin.analysis.api.components.KaScopeWithKind
import org.jetbrains.kotlin.analysis.api.lifetime.KaLifetimeOwner
import org.jetbrains.kotlin.analysis.api.lifetime.KaLifetimeToken
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.analysis.api.signatures.KaCallableSignature
import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.api.symbols.KaClassifierSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KaNamedClassSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KaPackageSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KaSymbol
import org.jetbrains.kotlin.analysis.api.symbols.markers.KaDeclarationContainerSymbol
import org.jetbrains.kotlin.idea.references.KtReference
/**
* Resolves [reference] to symbol and returns static scope for the obtained symbol.
* Note that if the symbol is [org.jetbrains.kotlin.analysis.api.symbols.KaTypeAliasSymbol], `null` is returned.
* See KT-34281 for more details.
*/
context(KaSession)
internal fun getStaticScopes(reference: KtReference): List<KaScopeWithKind> {
val scopeIndex = CompletionSymbolOrigin.SCOPE_OUTSIDE_TOWER_INDEX
internal val KaSymbol.staticScope
get() = when (this) {
is KaDeclarationContainerSymbol -> KaScopeWithKindImpl(
backingScope = if (this is KaNamedClassSymbol && classKind.isObject) memberScope else staticMemberScope,
backingKind = KaScopeKinds.StaticMemberScope(CompletionSymbolOrigin.SCOPE_OUTSIDE_TOWER_INDEX),
)
return reference.resolveToSymbols().mapNotNull { symbol ->
when (symbol) {
is KaDeclarationContainerSymbol -> {
val scope = if (symbol is KaNamedClassSymbol && symbol.classKind.isObject) {
symbol.memberScope
} else {
symbol.staticMemberScope
}
is KaPackageSymbol -> KaScopeWithKindImpl(
backingScope = packageScope,
backingKind = KaScopeKinds.PackageMemberScope(CompletionSymbolOrigin.SCOPE_OUTSIDE_TOWER_INDEX),
)
KaScopeWithKindImpl(scope, KaScopeKinds.StaticMemberScope(scopeIndex))
}
is KaPackageSymbol -> KaScopeWithKindImpl(symbol.packageScope, KaScopeKinds.PackageMemberScope(scopeIndex))
else -> null
}
else -> null
}
}
internal data class KaClassifierSymbolWithContainingScopeKind(
private val _symbol: KaClassifierSymbol,

View File

@@ -5,9 +5,9 @@ package org.jetbrains.kotlin.idea.completion.contributors.helpers
import com.intellij.util.applyIf
import org.jetbrains.kotlin.analysis.api.KaExperimentalApi
import org.jetbrains.kotlin.analysis.api.KaSession
import org.jetbrains.kotlin.analysis.api.components.KaScopeContext
import org.jetbrains.kotlin.analysis.api.components.KaScopeKind
import org.jetbrains.kotlin.analysis.api.components.KaScopeKinds
import org.jetbrains.kotlin.analysis.api.components.KaScopeContext
import org.jetbrains.kotlin.analysis.api.scopes.KaScope
import org.jetbrains.kotlin.analysis.api.signatures.KaCallableSignature
import org.jetbrains.kotlin.analysis.api.symbols.*
@@ -15,6 +15,9 @@ import org.jetbrains.kotlin.analysis.api.types.KaType
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.idea.completion.FirCompletionSessionParameters
import org.jetbrains.kotlin.idea.completion.checkers.CompletionVisibilityChecker
import org.jetbrains.kotlin.idea.completion.reference
import org.jetbrains.kotlin.idea.util.positionContext.KotlinNameReferencePositionContext
import org.jetbrains.kotlin.idea.util.positionContext.KotlinRawPositionContext
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.Name
@@ -34,6 +37,23 @@ internal sealed class CompletionSymbolOrigin {
}
}
context(KaSession)
internal fun KotlinRawPositionContext.resolveToSymbols(): Sequence<KaSymbol> =
when (this) {
is KotlinNameReferencePositionContext -> resolveToSymbols()
else -> sequenceOf(rootPackageSymbol)
}
context(KaSession)
internal fun KotlinNameReferencePositionContext.resolveToSymbols(): Sequence<KaSymbol> =
when (val explicitReceiver = explicitReceiver) {
null -> sequenceOf(rootPackageSymbol)
else -> explicitReceiver.reference()
?.resolveToSymbols()
?.asSequence()
?: emptySequence()
}
internal fun createStarTypeArgumentsList(typeArgumentsCount: Int): String =
if (typeArgumentsCount > 0) {
List(typeArgumentsCount) { "*" }.joinToString(prefix = "<", postfix = ">")

View File

@@ -0,0 +1,8 @@
// FIR_COMPARISON
// FIR_IDENTICAL
package foo
import R<caret>
// EXIST: RootPackageClass
// NOTHING_ELSE

View File

@@ -55,6 +55,11 @@ public class MultiFileJvmBasicCompletionTestGenerated extends AbstractMultiFileJ
runTest("../testData/basic/multifile/ClassInExcludedPackage/");
}
@TestMetadata("ClassInRootPackage")
public void testClassInRootPackage() throws Exception {
runTest("../testData/basic/multifile/ClassInRootPackage/");
}
@TestMetadata("CompleteFunctionWithNoSpecifiedType")
public void testCompleteFunctionWithNoSpecifiedType() throws Exception {
runTest("../testData/basic/multifile/CompleteFunctionWithNoSpecifiedType/");

View File

@@ -55,6 +55,11 @@ public class HighLevelMultiFileJvmBasicCompletionTestGenerated extends AbstractH
runTest("../../completion/testData/basic/multifile/ClassInExcludedPackage/");
}
@TestMetadata("ClassInRootPackage")
public void testClassInRootPackage() throws Exception {
runTest("../../completion/testData/basic/multifile/ClassInRootPackage/");
}
@TestMetadata("CompleteFunctionWithNoSpecifiedType")
public void testCompleteFunctionWithNoSpecifiedType() throws Exception {
runTest("../../completion/testData/basic/multifile/CompleteFunctionWithNoSpecifiedType/");