summaryrefslogtreecommitdiff
path: root/plugins/kotlin/uast/uast-kotlin-base/src/org/jetbrains/uast/kotlin/declarations/KotlinUFile.kt
blob: 9f3b9a3ede570a6e7e075047fce526f56ff3bcea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// Copyright 2000-2021 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.uast.kotlin

import com.intellij.psi.*
import org.jetbrains.kotlin.asJava.findFacadeClass
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.uast.*
import org.jetbrains.uast.kotlin.internal.KotlinUElementWithComments
import java.util.ArrayList

class KotlinUFile(
    override val psi: KtFile,
    override val languagePlugin: UastLanguagePlugin
) : UFile, KotlinUElementWithComments {
    override val javaPsi: PsiClassOwner? by lz {
        val lightClasses = this@KotlinUFile.classes.map { it.javaPsi }.toTypedArray()
        val lightFile = lightClasses.asSequence()
            .mapNotNull { it.containingFile as? PsiClassOwner }
            .firstOrNull()

        if (lightFile == null) null
        else
            object : PsiClassOwner by lightFile {
                override fun getClasses() = lightClasses
                override fun setPackageName(packageName: String?) = error("Incorrect operation for non-physical Java PSI")
            }
    }

    override val sourcePsi: KtFile = psi

    override val uAnnotations: List<UAnnotation> by lz {
        sourcePsi.annotationEntries.mapNotNull { languagePlugin.convertOpt(it, this) }
    }

    override val packageName: String by lz {
        sourcePsi.packageFqName.asString()
    }

    override val allCommentsInFile by lz {
        val comments = ArrayList<UComment>(0)
        sourcePsi.accept(object : PsiRecursiveElementWalkingVisitor() {
            override fun visitComment(comment: PsiComment) {
                comments += UComment(comment, this@KotlinUFile)
            }
        })
        comments
    }

    override val imports: List<UImportStatement> by lz {
        sourcePsi.importDirectives.mapNotNull { languagePlugin.convertOpt(it, this@KotlinUFile) }
    }

    override val classes: List<UClass> by lz {
        val facadeOrScriptClass = if (sourcePsi.isScript()) sourcePsi.script?.toLightClass() else sourcePsi.findFacadeClass()
        val facadeOrScriptUClass = facadeOrScriptClass?.toUClass()?.let { listOf(it) } ?: emptyList()
        val classes = sourcePsi.declarations.mapNotNull { (it as? KtClassOrObject)?.toLightClass()?.toUClass() }
        facadeOrScriptUClass + classes
    }

    private fun PsiClass.toUClass() = languagePlugin.convertOpt<UClass>(this, this@KotlinUFile)
}