[LL API] Support FirScript declarations in declaration providers (KTIJ-21108)
This commit is contained in:
+7
@@ -49,6 +49,13 @@ internal class FileBasedKotlinDeclarationProvider(private val kotlinFile: KtFile
|
|||||||
val (chunks, element) = tasks.removeFirst()
|
val (chunks, element) = tasks.removeFirst()
|
||||||
assert(chunks.isNotEmpty())
|
assert(chunks.isNotEmpty())
|
||||||
|
|
||||||
|
if (element is KtScript) {
|
||||||
|
for (child in element.declarations) {
|
||||||
|
tasks.addLast(Task(chunks, child))
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if (element !is KtNamedDeclaration || element.nameAsName != chunks[0]) {
|
if (element !is KtNamedDeclaration || element.nameAsName != chunks[0]) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-5
@@ -7,10 +7,7 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.util
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.analysis.utils.errors.requireWithAttachmentBuilder
|
import org.jetbrains.kotlin.analysis.utils.errors.requireWithAttachmentBuilder
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.classId
|
import org.jetbrains.kotlin.fir.declarations.utils.classId
|
||||||
import org.jetbrains.kotlin.fir.packageFqName
|
import org.jetbrains.kotlin.fir.packageFqName
|
||||||
import org.jetbrains.kotlin.fir.render
|
import org.jetbrains.kotlin.fir.render
|
||||||
@@ -33,11 +30,17 @@ object FirElementFinder {
|
|||||||
val classIdPathSegment = classId.relativeClassName.pathSegments()
|
val classIdPathSegment = classId.relativeClassName.pathSegments()
|
||||||
var result: FirClassLikeDeclaration? = null
|
var result: FirClassLikeDeclaration? = null
|
||||||
|
|
||||||
fun find(declarations: List<FirDeclaration>, classIdPathIndex: Int) {
|
fun find(declarations: Iterable<FirDeclaration>, classIdPathIndex: Int) {
|
||||||
if (result != null) return
|
if (result != null) return
|
||||||
val currentClassSegment = classIdPathSegment[classIdPathIndex]
|
val currentClassSegment = classIdPathSegment[classIdPathIndex]
|
||||||
|
|
||||||
for (subDeclaration in declarations) {
|
for (subDeclaration in declarations) {
|
||||||
|
if (subDeclaration is FirScript) {
|
||||||
|
val scriptDeclarations = subDeclaration.statements.asSequence().filterIsInstance<FirDeclaration>()
|
||||||
|
find(scriptDeclarations.asIterable(), classIdPathIndex)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if (subDeclaration is FirClassLikeDeclaration && currentClassSegment == subDeclaration.symbol.name) {
|
if (subDeclaration is FirClassLikeDeclaration && currentClassSegment == subDeclaration.symbol.name) {
|
||||||
if (classIdPathIndex == classIdPathSegment.lastIndex) {
|
if (classIdPathIndex == classIdPathSegment.lastIndex) {
|
||||||
result = subDeclaration
|
result = subDeclaration
|
||||||
|
|||||||
+7
-3
@@ -61,9 +61,13 @@ internal fun KtElement.findSourceByTraversingWholeTree(
|
|||||||
val firFile = containerFirFile ?: firFileBuilder.buildRawFirFileWithCaching(containingKtFile)
|
val firFile = containerFirFile ?: firFileBuilder.buildRawFirFileWithCaching(containingKtFile)
|
||||||
val originalDeclaration = (this as? KtDeclaration)?.originalDeclaration
|
val originalDeclaration = (this as? KtDeclaration)?.originalDeclaration
|
||||||
val isDeclaration = this is KtDeclaration
|
val isDeclaration = this is KtDeclaration
|
||||||
return FirElementFinder.findElementIn(firFile, canGoInside = { it is FirRegularClass }) { firDeclaration ->
|
return FirElementFinder.findElementIn(
|
||||||
firDeclaration.psi == this || isDeclaration && firDeclaration.psi == originalDeclaration
|
firFile,
|
||||||
}
|
canGoInside = { it is FirRegularClass || it is FirScript },
|
||||||
|
predicate = { firDeclaration ->
|
||||||
|
firDeclaration.psi == this || isDeclaration && firDeclaration.psi == originalDeclaration
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtDeclaration.findSourceNonLocalFirDeclarationByProvider(
|
private fun KtDeclaration.findSourceNonLocalFirDeclarationByProvider(
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.psi.psiUtil
|
package org.jetbrains.kotlin.psi.psiUtil
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.SpecialNames
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
@@ -14,9 +13,9 @@ import org.jetbrains.kotlin.psi.*
|
|||||||
internal object ClassIdCalculator {
|
internal object ClassIdCalculator {
|
||||||
fun calculateClassId(declaration: KtClassLikeDeclaration): ClassId? {
|
fun calculateClassId(declaration: KtClassLikeDeclaration): ClassId? {
|
||||||
var ktFile: KtFile? = null
|
var ktFile: KtFile? = null
|
||||||
var element: PsiElement? = declaration
|
|
||||||
val containingClasses = mutableListOf<KtClassLikeDeclaration>()
|
val containingClasses = mutableListOf<KtClassLikeDeclaration>()
|
||||||
while (element != null) {
|
|
||||||
|
for (element in declaration.parentsWithSelf) {
|
||||||
when (element) {
|
when (element) {
|
||||||
is KtEnumEntry -> {
|
is KtEnumEntry -> {
|
||||||
return null
|
return null
|
||||||
@@ -24,24 +23,23 @@ internal object ClassIdCalculator {
|
|||||||
is KtClassLikeDeclaration -> {
|
is KtClassLikeDeclaration -> {
|
||||||
containingClasses += element
|
containingClasses += element
|
||||||
}
|
}
|
||||||
is KtObjectLiteralExpression -> {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
is KtFile -> {
|
is KtFile -> {
|
||||||
ktFile = element
|
ktFile = element
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
is KtDeclaration -> {
|
is KtScript -> {
|
||||||
|
// Skip script parent
|
||||||
|
}
|
||||||
|
is KtDeclaration, is KtObjectLiteralExpression -> {
|
||||||
|
// Local declarations don't have a 'ClassId'
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
element = element.parent
|
|
||||||
}
|
}
|
||||||
if (ktFile == null) return null
|
if (ktFile == null) return null
|
||||||
val relativeClassName = FqName.fromSegments(
|
val relativeClassName = FqName.fromSegments(containingClasses.reversed().map { containingClass ->
|
||||||
containingClasses.reversed().map { containingClass ->
|
containingClass.name ?: SpecialNames.NO_NAME_PROVIDED.asString()
|
||||||
containingClass.name ?: SpecialNames.NO_NAME_PROVIDED.asString()
|
}
|
||||||
}
|
|
||||||
)
|
)
|
||||||
return ClassId(ktFile.packageFqName, relativeClassName, /*local=*/false)
|
return ClassId(ktFile.packageFqName, relativeClassName, /*local=*/false)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user