[FIR-IDE] Hack for checking single candidate resolver in tests
This commit is contained in:
@@ -187,6 +187,7 @@ dependencies {
|
||||
testRuntime(intellijPluginDep("smali"))
|
||||
testRuntime(intellijPluginDep("testng"))
|
||||
|
||||
testRuntime(project(":idea:idea-fir"))
|
||||
testRuntime(project(":idea:idea-frontend-fir"))
|
||||
|
||||
if (Ide.AS36.orHigher()) {
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
class A
|
||||
open class B
|
||||
|
||||
class C : B()
|
||||
interface D
|
||||
|
||||
fun <T> T.ext1() where T : B {}
|
||||
fun B.ext2() {}
|
||||
fun A.ext3() {}
|
||||
fun <T> T.ext4() where T : B, T : D {}
|
||||
|
||||
fun usage() {
|
||||
val c = C()
|
||||
c.ext<caret>
|
||||
}
|
||||
|
||||
// EXIST: ext1
|
||||
// EXIST: ext2
|
||||
// ABSENT: ext3
|
||||
// ABSENT: ext4
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fun <T : Int> T.ext1() {}
|
||||
fun <T : String> T.ext2() {}
|
||||
|
||||
fun test() {
|
||||
with(42) {
|
||||
ext<caret>
|
||||
}
|
||||
}
|
||||
|
||||
// EXIST: ext1
|
||||
// ABSENT: ext2
|
||||
@@ -0,0 +1,24 @@
|
||||
class A<T1, T2> {
|
||||
fun foo1() {}
|
||||
|
||||
class B<T3, T4> {
|
||||
fun foo2() {}
|
||||
|
||||
fun foo3() {
|
||||
foo<caret>
|
||||
}
|
||||
}
|
||||
|
||||
class C
|
||||
|
||||
companion object {
|
||||
fun <T7, T8> B<T7, T8>.foo4() {}
|
||||
fun C.foo5() {}
|
||||
}
|
||||
}
|
||||
|
||||
// ABSENT: foo1
|
||||
// EXIST: foo2
|
||||
// EXIST: foo3
|
||||
// EXIST: foo4
|
||||
// ABSENT: foo5
|
||||
+15
@@ -85,6 +85,11 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
||||
runTest("idea/idea-completion/testData/basic/common/ComponentFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("ConsiderExtensionType.kt")
|
||||
public void testConsiderExtensionType() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/ConsiderExtensionType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("CoroutineContext.kt")
|
||||
public void testCoroutineContext() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/CoroutineContext.kt");
|
||||
@@ -185,6 +190,11 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
||||
runTest("idea/idea-completion/testData/basic/common/ExtensionWithManyTypeParamsInReceiver.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("ExtensionsWithTypeParameterConstraints.kt")
|
||||
public void testExtensionsWithTypeParameterConstraints() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/ExtensionsWithTypeParameterConstraints.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("FromImports.kt")
|
||||
public void testFromImports() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/FromImports.kt");
|
||||
@@ -200,6 +210,11 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
||||
runTest("idea/idea-completion/testData/basic/common/FunctionVariableCallArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("GenericCompanionExtension.kt")
|
||||
public void testGenericCompanionExtension() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/GenericCompanionExtension.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("GenericExtensionFunReceiver1.kt")
|
||||
public void testGenericExtensionFunReceiver1() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/GenericExtensionFunReceiver1.kt");
|
||||
|
||||
+15
@@ -85,6 +85,11 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
||||
runTest("idea/idea-completion/testData/basic/common/ComponentFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("ConsiderExtensionType.kt")
|
||||
public void testConsiderExtensionType() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/ConsiderExtensionType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("CoroutineContext.kt")
|
||||
public void testCoroutineContext() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/CoroutineContext.kt");
|
||||
@@ -185,6 +190,11 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
||||
runTest("idea/idea-completion/testData/basic/common/ExtensionWithManyTypeParamsInReceiver.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("ExtensionsWithTypeParameterConstraints.kt")
|
||||
public void testExtensionsWithTypeParameterConstraints() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/ExtensionsWithTypeParameterConstraints.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("FromImports.kt")
|
||||
public void testFromImports() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/FromImports.kt");
|
||||
@@ -200,6 +210,11 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
||||
runTest("idea/idea-completion/testData/basic/common/FunctionVariableCallArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("GenericCompanionExtension.kt")
|
||||
public void testGenericCompanionExtension() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/GenericCompanionExtension.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("GenericExtensionFunReceiver1.kt")
|
||||
public void testGenericExtensionFunReceiver1() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/GenericExtensionFunReceiver1.kt");
|
||||
|
||||
@@ -118,4 +118,11 @@ abstract class KtAnalysisSession(override val token: ValidityToken) : ValidityTo
|
||||
check(this is KtSymbolBasedReference) { "To get reference symbol the one should be KtSymbolBasedReference but was ${this::class}" }
|
||||
return resolveToSymbols().singleOrNull()
|
||||
}
|
||||
|
||||
abstract fun resolveAndCheckReceivers(
|
||||
firSymbolForCandidate: KtCallableSymbol,
|
||||
originalFile: KtFile,
|
||||
nameExpression: KtSimpleNameExpression,
|
||||
possibleReceiver: KtExpression?,
|
||||
): Boolean
|
||||
}
|
||||
|
||||
+60
@@ -5,6 +5,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.frontend.api.fir
|
||||
|
||||
import com.jetbrains.rd.util.getOrCreate
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.LowLevelFirApiFacade
|
||||
@@ -17,10 +20,20 @@ import org.jetbrains.kotlin.idea.frontend.api.components.KtDiagnosticProvider
|
||||
import org.jetbrains.kotlin.idea.frontend.api.components.KtSmartCastProvider
|
||||
import org.jetbrains.kotlin.idea.frontend.api.components.KtTypeProvider
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.components.*
|
||||
import org.jetbrains.kotlin.idea.fir.*
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.resolver.SingleCandidateResolver
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.resolver.SingleCandidateResolutionMode
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.resolver.ResolutionParameters
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirFunctionSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbolProvider
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.threadLocal
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolProvider
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
||||
import org.jetbrains.kotlin.idea.util.getElementTextInContext
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
internal class KtFirAnalysisSession
|
||||
private constructor(
|
||||
@@ -58,6 +71,53 @@ private constructor(
|
||||
)
|
||||
}
|
||||
|
||||
private val completionContextCache = HashMap<Pair<FirFile, KtNamedFunction>, LowLevelFirApiFacade.FirCompletionContext>()
|
||||
|
||||
// Temporary kludge to check single candidate resolver in tests
|
||||
override fun resolveAndCheckReceivers(
|
||||
firSymbolForCandidate: KtCallableSymbol,
|
||||
originalFile: KtFile,
|
||||
nameExpression: KtSimpleNameExpression,
|
||||
possibleReceiver: KtExpression?,
|
||||
): Boolean {
|
||||
firSymbolForCandidate.safeAs<KtFirFunctionSymbol>()?.firRef?.withFir { firFunction ->
|
||||
val file = originalFile.getOrBuildFirOfType<FirFile>(firResolveState)
|
||||
val explicitReceiverExpression = possibleReceiver?.getOrBuildFirOfType<FirExpression>(firResolveState)
|
||||
val resolver = SingleCandidateResolver(firResolveState.firIdeSourcesSession, file)
|
||||
val enclosingFunction = nameExpression.getNonStrictParentOfType<KtNamedFunction>()
|
||||
?: error("Cannot find enclosing function for ${nameExpression.getElementTextInContext()}")
|
||||
|
||||
val completionContext = completionContextCache.getOrCreate(file to enclosingFunction) {
|
||||
LowLevelFirApiFacade.buildCompletionContextForFunction(
|
||||
file,
|
||||
enclosingFunction,
|
||||
enclosingFunction,
|
||||
state = firResolveState
|
||||
)
|
||||
}
|
||||
|
||||
val towerDataContext = completionContext.getTowerDataContext(nameExpression)
|
||||
|
||||
val implicitReceivers = sequence {
|
||||
yield(null)
|
||||
yieldAll(towerDataContext.implicitReceiverStack)
|
||||
}
|
||||
for (implicitReceiverValue in implicitReceivers) {
|
||||
val resolutionParameters = ResolutionParameters(
|
||||
singleCandidateResolutionMode = SingleCandidateResolutionMode.CHECK_EXTENSION_FOR_COMPLETION,
|
||||
callableSymbol = firFunction.symbol,
|
||||
implicitReceiver = implicitReceiverValue,
|
||||
explicitReceiver = explicitReceiverExpression
|
||||
)
|
||||
resolver.resolveSingleCandidate(resolutionParameters)?.let {
|
||||
// not null if resolved and completed successfully
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
companion object {
|
||||
@Deprecated("Please use org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSessionProviderKt.analyze")
|
||||
internal fun createForElement(element: KtElement): KtFirAnalysisSession {
|
||||
|
||||
+2
-4
@@ -13,10 +13,7 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.scope
|
||||
import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractSimpleImportingScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractStarImportingScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.*
|
||||
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
||||
import org.jetbrains.kotlin.idea.fir.getOrBuildFirOfType
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState
|
||||
@@ -155,6 +152,7 @@ internal class KtFirScopeProvider(
|
||||
is FirAbstractStarImportingScope -> KtFirStarImportingScope(firScope, builder, project, token)
|
||||
is FirPackageMemberScope -> KtFirPackageScope(firScope, project, builder, token)
|
||||
is FirContainingNamesAwareScope -> KtFirDelegatingScopeImpl(firScope, builder, token)
|
||||
is FirMemberTypeParameterScope -> KtFirMemberTypeParameterStubbingScope(firScope, token)
|
||||
else -> TODO(firScope::class.toString())
|
||||
}
|
||||
}
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.frontend.api.fir.scopes
|
||||
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
|
||||
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
|
||||
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScope
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassLikeSymbol
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
// Does nothing, it is used to close the hole in KtFirScopeProvider
|
||||
// TODO: check if this scope should provide something useful
|
||||
class KtFirMemberTypeParameterStubbingScope(
|
||||
val firMemberTypeParameterScope: FirMemberTypeParameterScope,
|
||||
override val token: ValidityToken,
|
||||
) : KtScope {
|
||||
override fun getCallableNames(): Set<Name> {
|
||||
return emptySet()
|
||||
}
|
||||
|
||||
override fun getClassLikeSymbolNames(): Set<Name> {
|
||||
return emptySet()
|
||||
}
|
||||
|
||||
override fun getCallableSymbols(): Sequence<KtCallableSymbol> {
|
||||
return emptySequence()
|
||||
}
|
||||
|
||||
override fun getClassClassLikeSymbols(): Sequence<KtClassLikeSymbol> {
|
||||
return emptySequence()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user