FIR IDE: Search for the first non-local declaration in EnclosingDeclarationContext::detect
Local declarations do not have a stable `ClassId`, which is used in `declarationUtils.collectDesignation`. Local classes will always have `outerClassId.isLocal = true`, even when it is not true (see `org.jetbrains.kotlin.fir.builder.Context.currentClassId` for why this happens)
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
// FIR_COMPARISON
|
||||
class A(private val xxx1: Int, val xxx2: Int) {
|
||||
private val xxx3: Int = 0
|
||||
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package test
|
||||
|
||||
class T
|
||||
|
||||
fun topLevelFun(param: T) {
|
||||
val firstVariable = T()
|
||||
|
||||
class LocalClass(constructorParam: T) {
|
||||
val localClassField = constructorParam
|
||||
|
||||
init {
|
||||
<caret>
|
||||
}
|
||||
}
|
||||
|
||||
val secondVariable = T()
|
||||
}
|
||||
|
||||
// EXIST: firstVariable, param, constructorParam, localClassField
|
||||
// ABSENT: secondVariable
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package test
|
||||
|
||||
class T
|
||||
|
||||
fun topLevelFun(param: T) {
|
||||
val firstVariable = T()
|
||||
|
||||
class LocalClass(constructorParam: T) {
|
||||
val localClassField = constructorParam
|
||||
|
||||
fun localClassMethod(localParam: T) {
|
||||
<caret>
|
||||
}
|
||||
}
|
||||
|
||||
val secondVariable = T()
|
||||
}
|
||||
|
||||
// EXIST: firstVariable, param, constructorParam, localClassField, localParam
|
||||
// ABSENT: secondVariable
|
||||
+10
@@ -2328,6 +2328,16 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
||||
runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/insideFunctionWithParameters.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localClassConstructor.kt")
|
||||
public void testLocalClassConstructor() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/localClassConstructor.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localClassMember.kt")
|
||||
public void testLocalClassMember() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/localClassMember.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localVariablesAndFunctions.kt")
|
||||
public void testLocalVariablesAndFunctions() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/localVariablesAndFunctions.kt");
|
||||
|
||||
+10
@@ -2328,6 +2328,16 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
||||
runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/insideFunctionWithParameters.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localClassConstructor.kt")
|
||||
public void testLocalClassConstructor() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/localClassConstructor.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localClassMember.kt")
|
||||
public void testLocalClassMember() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/localClassMember.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localVariablesAndFunctions.kt")
|
||||
public void testLocalVariablesAndFunctions() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/localVariablesAndFunctions.kt");
|
||||
|
||||
+10
@@ -2328,6 +2328,16 @@ public class HighLevelJvmBasicCompletionTestGenerated extends AbstractHighLevelJ
|
||||
runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/insideFunctionWithParameters.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localClassConstructor.kt")
|
||||
public void testLocalClassConstructor() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/localClassConstructor.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localClassMember.kt")
|
||||
public void testLocalClassMember() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/localClassMember.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localVariablesAndFunctions.kt")
|
||||
public void testLocalVariablesAndFunctions() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/localVariablesAndFunctions.kt");
|
||||
|
||||
+8
-2
@@ -12,12 +12,15 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.api.LowLevelFirApiFacadeForCo
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.util.originalDeclaration
|
||||
import org.jetbrains.kotlin.idea.util.getElementTextInContext
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
|
||||
internal sealed class EnclosingDeclarationContext {
|
||||
companion object {
|
||||
fun detect(originalFile: KtFile, positionInFakeFile: KtElement): EnclosingDeclarationContext {
|
||||
val fakeFunction = positionInFakeFile.parentsOfType<KtNamedFunction>().firstOrNull { !it.isLocal }
|
||||
val fakeFunction = positionInFakeFile.parentsOfType<KtNamedFunction>().firstOrNull {
|
||||
it.isTopLevel || it.containingClassOrObject?.isLocal == false
|
||||
}
|
||||
if (fakeFunction != null) {
|
||||
val originalFunction = originalFile.findDeclarationOfTypeAt<KtNamedFunction>(fakeFunction.textOffset)
|
||||
?: error("Cannot find original function matching to ${fakeFunction.getElementTextInContext()} in $originalFile")
|
||||
@@ -25,7 +28,10 @@ internal sealed class EnclosingDeclarationContext {
|
||||
return FunctionContext(fakeFunction, originalFunction)
|
||||
}
|
||||
|
||||
val fakeProperty = positionInFakeFile.parentsOfType<KtProperty>().firstOrNull { !it.isLocal }
|
||||
val fakeProperty = positionInFakeFile.parentsOfType<KtProperty>().firstOrNull {
|
||||
it.isTopLevel || it.containingClassOrObject?.isLocal == false
|
||||
}
|
||||
|
||||
if (fakeProperty != null) {
|
||||
val originalProperty = originalFile.findDeclarationOfTypeAt<KtProperty>(fakeProperty.textOffset)
|
||||
?: error("Cannot find original property matching to ${fakeProperty.getElementTextInContext()} in $originalFile")
|
||||
|
||||
Reference in New Issue
Block a user