All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.joern.kotlin2cpg.compiler.CompilerAPI.scala Maven / Gradle / Ivy

The newest version!
package io.joern.kotlin2cpg.compiler

import io.joern.kotlin2cpg.DefaultContentRootJarPath

import java.io.{File, FileOutputStream}
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot
import org.jetbrains.kotlin.cli.jvm.compiler.{EnvironmentConfigFiles, KotlinCoreEnvironment}
import org.jetbrains.kotlin.cli.jvm.config.{JavaSourceRoot, JvmClasspathRoot}
import org.jetbrains.kotlin.config.{CommonConfigurationKeys, CompilerConfiguration, JVMConfigurationKeys}
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
import org.jetbrains.kotlin.com.intellij.openapi.util.Disposer
import org.jetbrains.kotlin.cli.common.messages.{
  CompilerMessageSeverity,
  CompilerMessageSourceLocation,
  MessageCollector
}
import org.slf4j.LoggerFactory

object CompilerAPI {
  private val logger = LoggerFactory.getLogger(getClass)

  def makeEnvironment(
    forDirectories: Seq[String],
    javaSourceRoots: Seq[String],
    defaultContentRootJarPaths: Seq[DefaultContentRootJarPath] = List(),
    messageCollector: MessageCollector
  ): KotlinCoreEnvironment = {
    val config = new CompilerConfiguration()
    config.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
    forDirectories.foreach { p =>
      config.add(CLIConfigurationKeys.CONTENT_ROOTS, new KotlinSourceRoot(p, true, null))
    }

    val javaHome = File(System.getProperty("java.home"))
    config.put(JVMConfigurationKeys.JDK_HOME, javaHome)

    defaultContentRootJarPaths.foreach { path =>
      if (!path.isResource) {
        val f = new File(path.path)
        if (f.exists()) {
          config.add(CLIConfigurationKeys.CONTENT_ROOTS, new JvmClasspathRoot(f))
          logger.debug(s"Added dependency from path `${path.path}`.")
        } else {
          logger.warn(s"Path to dependency does not point to existing file `${path.path}`.")
        }
      } else {
        val resourceStream = getClass.getClassLoader.getResourceAsStream(path.path)
        if (resourceStream != null) {
          val tempFile = File.createTempFile("kotlin2cpgDependencies", "")
          tempFile.deleteOnExit()
          val outStream = new FileOutputStream(tempFile)
          val buffer    = new Array[Byte](4096)

          while (resourceStream.available > 0) {
            val readBytes = resourceStream.read(buffer)
            outStream.write(buffer, 0, readBytes)
          }
          outStream.flush()
          outStream.close()

          config.add(CLIConfigurationKeys.CONTENT_ROOTS, new JvmClasspathRoot(tempFile))
          logger.debug(s"Added dependency from resources `${path.path}`.")
        } else {
          logger.warn(s"Path to default dependency does not point to existing resource `${path.path}`.")
        }
      }
    }

    javaSourceRoots.foreach { source =>
      val f = new File(source)
      config.add(CLIConfigurationKeys.CONTENT_ROOTS, new JavaSourceRoot(f, ""))
    }

    config.put(CommonConfigurationKeys.MODULE_NAME, JvmProtoBufUtil.DEFAULT_MODULE_NAME)

    val configFiles = EnvironmentConfigFiles.JVM_CONFIG_FILES
    val disposable  = Disposer.newDisposable()

    val environment = KotlinCoreEnvironment.createForProduction(disposable, config, configFiles)
    environment
  }
}

class ErrorLoggingMessageCollector extends MessageCollector {
  private val logger = LoggerFactory.getLogger(getClass)

  override def report(
    compilerMessageSeverity: CompilerMessageSeverity,
    s: String,
    compilerMessageSourceLocation: CompilerMessageSourceLocation
  ): Unit = {
    if (compilerMessageSeverity.isError) {
      logger.debug(s"Received error from Kotlin compiler: `$s`.")
    }
  }
  override def hasErrors: Boolean = false
  override def clear(): Unit      = {}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy