Hi all. I'm currently writing a compiler plugin wh...
# compiler
c
Hi all. I'm currently writing a compiler plugin which needs to extract the assignment of certain properties from the source files. The problem is i always need to be able to extract those assignments for all files. But when the current run is incremental, i only get the new/changed files. My current way of doing this is to provide a
DeclarationChecker
which extracts the
assignmentPsi
from the `PropertyDescriptor`'s. Is there another hook or a better way with which i can do this for all source files not just those that have changed since the last run? I just need this to work on the JVM.
a
The problem is i always need to be able to extract those assignments for all files.
Do You want to extract all assignments in all files of the module? The project? All libraries in your classpath? It seems to me that your goal is not so good. What is your root goal?
c
Hey @aleksey.tomin Thanks for your time We're developing a kotlin language binding for the Godot Game Engine. The idea is that a user can write his game logic scripts in kotlin. Now for the engine to know about our classes, properties and functions, we need to register them. In scripts one can "export" properties. These exported properties can be changed in the engines GUI editor. For the engine to know what the default values are, we need to provide them when we register the property. At the time the engine wan'ts to know what the default value is, we do not have an instance of the class that contains the property. Now we introduced annotations. If a user annotates a property with it, we register that property through some code generation. In the compiler plugin i extract the assignment of the annotated property to be able to provide that when we register that property and implemented some checks to make sure the assignment is valid (the engine can handle the type and the assignment is a compile time constant). So no i don't need to extract the assignments of all properties from everywhere, Just for the ones annotated with our annotation. I'd love to just use an annotation processor for this, but sadly as far as i can see, there is no way to access the assignment of a property from withing an annotation processor which does not involve manual parsing which would really be a bad idea IMO.
a
I think you better use kotlin script instead of compiler plugins.
c
what do you mean by that? How should i be able to register properties of a class with a kotlin script?
🤔 1
Investigated further and found a solution for my problem. I get the srcDirs from our gradle plugin and pass them as an argument to our compiler plugin. There i use the same logic the
KotlinCoreEnvironment
uses to get the source files in the function `createSourceFilesFromSourceRoots`:
Copy code
val localFileSystem = VirtualFileManager.getInstance()
        .getFileSystem(StandardFileSystems.FILE_PROTOCOL)
    val psiManager = PsiManager.getInstance(project)

    val processedFiles = hashSetOf<VirtualFile>()
    val result = mutableListOf<KtFile>()

    val virtualFileCreator = PreprocessedFileCreator(project)

    for ((sourceRootPath, isCommon) in sourceRoots) {
        val vFile = localFileSystem.findFileByPath(sourceRootPath)
        if (vFile == null) {
            val message = "Source file or directory not found: $sourceRootPath"

            val buildFilePath = configuration.get(JVMConfigurationKeys.MODULE_XML_FILE)
            if (buildFilePath != null && Logger.isInitialized()) {
                Logger.getInstance(KotlinCoreEnvironment::class.java)
                    .warn("$message\n\nbuild file path: $buildFilePath\ncontent:\n${buildFilePath.readText()}")
            }

            configuration.report(CompilerMessageSeverity.ERROR, message, reportLocation)
            continue
        }

        if (!vFile.isDirectory && vFile.fileType != KotlinFileType.INSTANCE) {
            configuration.report(CompilerMessageSeverity.ERROR, "Source entry is not a Kotlin file: $sourceRootPath", reportLocation)
            continue
        }

        for (file in File(sourceRootPath).walkTopDown()) {
            if (!file.isFile) continue

            val virtualFile = localFileSystem.findFileByPath(file.absolutePath)?.let(virtualFileCreator::create)
            if (virtualFile != null && processedFiles.add(virtualFile)) {
                val psiFile = psiManager.findFile(virtualFile)
                if (psiFile is KtFile) {
                    result.add(psiFile)
                    if (isCommon) {
                        psiFile.isCommonSource = true
                    }
                }
            }
        }
    }

    return result
With this I'm able to access all assignment psi's from all properties that are annotated with our annotation. But maybe someone has a better idea that does not involve the need to pass the sourcesDirs as an argument to the compiler plugin