blob: 06c0523619ff8baf898f219b2559ad5ad00d4a5d [file] [log] [blame] [edit]
package org.jetbrains.uast.test.kotlin
import com.intellij.mock.MockProject
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.util.io.URLUtil
import org.jetbrains.kotlin.checkers.CompilerTestLanguageVersionSettings
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoot
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.parsing.KotlinParserDefinition
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
import org.jetbrains.kotlin.script.loadScriptingPlugin
import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.TestJdkKind
import org.jetbrains.kotlin.test.testFramework.resetApplicationToNull
import org.jetbrains.uast.UastLanguagePlugin
import org.jetbrains.uast.evaluation.UEvaluatorExtension
import org.jetbrains.uast.kotlin.KotlinUastLanguagePlugin
import org.jetbrains.uast.kotlin.KotlinUastResolveProviderService
import org.jetbrains.uast.kotlin.evaluation.KotlinEvaluatorExtension
import org.jetbrains.uast.kotlin.internal.CliKotlinUastResolveProviderService
import org.jetbrains.uast.kotlin.internal.UastAnalysisHandlerExtension
import org.jetbrains.uast.test.env.kotlin.AbstractCoreEnvironment
import org.jetbrains.uast.test.env.kotlin.AbstractUastTest
import java.io.File
abstract class AbstractKotlinUastTest : AbstractUastTest() {
private lateinit var compilerConfiguration: CompilerConfiguration
private var kotlinCoreEnvironment: KotlinCoreEnvironment? = null
override fun getVirtualFile(testName: String): VirtualFile {
val testFile = TEST_KOTLIN_MODEL_DIR.listFiles { pathname -> pathname.nameWithoutExtension == testName }.first()
super.initializeEnvironment(testFile)
initializeKotlinEnvironment()
enableNewTypeInferenceIfNeeded()
val trace = NoScopeRecordCliBindingTrace()
val environment = kotlinCoreEnvironment!!
TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
project, environment.getSourceFiles(), trace, compilerConfiguration, environment::createPackagePartProvider
)
val vfs = VirtualFileManager.getInstance().getFileSystem(URLUtil.FILE_PROTOCOL)
val ideaProject = project
ideaProject.baseDir = vfs.findFileByPath(TEST_KOTLIN_MODEL_DIR.canonicalPath)
return vfs.findFileByPath(testFile.canonicalPath)!!
}
private fun enableNewTypeInferenceIfNeeded() {
val currentLanguageVersionSettings = compilerConfiguration.languageVersionSettings
if (currentLanguageVersionSettings.supportsFeature(LanguageFeature.NewInference)) return
val extraLanguageFeatures = mutableMapOf<LanguageFeature, LanguageFeature.State>()
val extraAnalysisFlags = mutableMapOf<AnalysisFlag<*>, Any?>()
if (currentLanguageVersionSettings is CompilerTestLanguageVersionSettings) {
extraLanguageFeatures += currentLanguageVersionSettings.extraLanguageFeatures
extraAnalysisFlags += currentLanguageVersionSettings.analysisFlags
}
compilerConfiguration.languageVersionSettings = CompilerTestLanguageVersionSettings(
extraLanguageFeatures + (LanguageFeature.NewInference to LanguageFeature.State.ENABLED),
currentLanguageVersionSettings.apiVersion,
currentLanguageVersionSettings.languageVersion,
extraAnalysisFlags
)
}
private fun initializeKotlinEnvironment() {
val area = Extensions.getRootArea()
area.getExtensionPoint(UastLanguagePlugin.extensionPointName)
.registerExtension(KotlinUastLanguagePlugin())
area.getExtensionPoint(UEvaluatorExtension.EXTENSION_POINT_NAME)
.registerExtension(KotlinEvaluatorExtension())
project.registerService(
KotlinUastResolveProviderService::class.java,
CliKotlinUastResolveProviderService::class.java
)
}
override fun createEnvironment(source: File): AbstractCoreEnvironment {
val appWasNull = ApplicationManager.getApplication() == null
compilerConfiguration = createKotlinCompilerConfiguration(source)
compilerConfiguration.put(JVMConfigurationKeys.USE_PSI_CLASS_FILES_READING, true)
val parentDisposable = Disposer.newDisposable()
val kotlinCoreEnvironment =
KotlinCoreEnvironment.createForTests(parentDisposable, compilerConfiguration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
this.kotlinCoreEnvironment = kotlinCoreEnvironment
AnalysisHandlerExtension.registerExtension(
kotlinCoreEnvironment.project, UastAnalysisHandlerExtension()
)
return KotlinCoreEnvironmentWrapper(kotlinCoreEnvironment, parentDisposable, appWasNull)
}
override fun tearDown() {
kotlinCoreEnvironment = null
super.tearDown()
}
private fun createKotlinCompilerConfiguration(sourceFile: File): CompilerConfiguration {
return KotlinTestUtils.newConfiguration(ConfigurationKind.ALL, TestJdkKind.FULL_JDK).apply {
addKotlinSourceRoot(sourceFile.canonicalPath)
val messageCollector = PrintingMessageCollector(System.err, MessageRenderer.PLAIN_RELATIVE_PATHS, true)
put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
put(CommonConfigurationKeys.MODULE_NAME, "test-module")
if (sourceFile.extension == KotlinParserDefinition.STD_SCRIPT_SUFFIX) {
loadScriptingPlugin(this)
}
}
}
private class KotlinCoreEnvironmentWrapper(
val environment: KotlinCoreEnvironment,
val parentDisposable: Disposable,
val appWasNull: Boolean
) : AbstractCoreEnvironment() {
override fun addJavaSourceRoot(root: File) {
TODO("not implemented")
}
override fun addJar(root: File) {
TODO("not implemented")
}
override val project: MockProject
get() = environment.project as MockProject
override fun dispose() {
Disposer.dispose(parentDisposable)
if (appWasNull) {
resetApplicationToNull()
}
}
}
}
val TEST_KOTLIN_MODEL_DIR = File("plugins/uast-kotlin/testData")