diff --git a/idea/tests/org/jetbrains/kotlin/idea/script/AbstractScriptConfigurationTest.kt b/idea/tests/org/jetbrains/kotlin/idea/script/AbstractScriptConfigurationTest.kt index b8fbdbf5eb0..339d0928508 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/script/AbstractScriptConfigurationTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/script/AbstractScriptConfigurationTest.kt @@ -306,9 +306,9 @@ abstract class AbstractScriptConfigurationTest : KotlinCompletionTestCase() { CustomScriptTemplateProvider(environment) } - PlatformTestUtil.registerExtension( - Extensions.getArea(project), + addExtensionPointInTest( ScriptDefinitionContributor.EP_NAME, + project, provider, testRootDisposable ) diff --git a/idea/tests/org/jetbrains/kotlin/idea/script/AbstractScriptConfigurationTest.kt.193 b/idea/tests/org/jetbrains/kotlin/idea/script/AbstractScriptConfigurationTest.kt.193 deleted file mode 100644 index 6f27881dd0f..00000000000 --- a/idea/tests/org/jetbrains/kotlin/idea/script/AbstractScriptConfigurationTest.kt.193 +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.idea.script - -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.extensions.Extensions -import com.intellij.openapi.module.JavaModuleType -import com.intellij.openapi.module.Module -import com.intellij.openapi.projectRoots.ProjectJdkTable -import com.intellij.openapi.roots.ModuleRootModificationUtil -import com.intellij.openapi.roots.ProjectRootManager -import com.intellij.openapi.util.io.FileUtil -import com.intellij.openapi.util.text.StringUtil -import com.intellij.openapi.vfs.LocalFileSystem -import com.intellij.openapi.vfs.VfsUtil -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.testFramework.PlatformTestCase -import com.intellij.testFramework.PlatformTestUtil -import com.intellij.testFramework.PsiTestUtil -import com.intellij.util.ui.UIUtil -import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime -import org.jetbrains.kotlin.idea.completion.test.KotlinCompletionTestCase -import org.jetbrains.kotlin.idea.core.script.IdeScriptReportSink -import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager.Companion.updateScriptDependenciesSynchronously -import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionContributor -import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionsManager -import org.jetbrains.kotlin.idea.core.script.isScriptDependenciesUpdaterDisabled -import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingUtil -import org.jetbrains.kotlin.idea.test.PluginTestCaseBase -import org.jetbrains.kotlin.idea.util.application.runWriteAction -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition -import org.jetbrains.kotlin.test.KotlinTestUtils -import org.jetbrains.kotlin.test.MockLibraryUtil -import org.jetbrains.kotlin.test.TestJdkKind -import org.jetbrains.kotlin.test.util.addDependency -import org.jetbrains.kotlin.test.util.projectLibrary -import org.jetbrains.kotlin.utils.PathUtil -import org.jetbrains.kotlin.utils.PathUtil.KOTLIN_JAVA_SCRIPT_RUNTIME_JAR -import org.jetbrains.kotlin.utils.PathUtil.KOTLIN_SCRIPTING_COMMON_JAR -import org.jetbrains.kotlin.utils.PathUtil.KOTLIN_SCRIPTING_JVM_JAR -import java.io.File -import java.util.regex.Pattern -import kotlin.script.dependencies.Environment -import kotlin.script.experimental.api.ScriptDiagnostic - -private val validKeys = setOf("javaHome", "sources", "classpath", "imports", "template-classes-names") -private const val useDefaultTemplate = "// DEPENDENCIES:" -private const val templatesSettings = "// TEMPLATES: " -// some bugs can only be reproduced when some module and script have intersecting library dependencies -private const val configureConflictingModule = "// CONFLICTING_MODULE" - -private fun String.splitOrEmpty(delimeters: String) = split(delimeters).takeIf { it.size > 1 } ?: emptyList() -internal val switches = listOf( - useDefaultTemplate, - configureConflictingModule -) - -abstract class AbstractScriptConfigurationTest : KotlinCompletionTestCase() { - companion object { - private const val SCRIPT_NAME = "script.kts" - } - - override fun setUpModule() { - // do not create default module - } - - private fun findMainScript(testDir: String): File { - val scriptFile = File(testDir).walkTopDown().find { it.name == SCRIPT_NAME } - if (scriptFile != null) return scriptFile - - return File(testDir).walkTopDown().singleOrNull { it.name.contains("script") } - ?: error("Couldn't find $SCRIPT_NAME file in $testDir") - } - - private val sdk by lazy { - val jdk = PluginTestCaseBase.jdk(TestJdkKind.MOCK_JDK) - runWriteAction { - ProjectJdkTable.getInstance().addJdk(jdk, testRootDisposable) - ProjectRootManager.getInstance(project).projectSdk = jdk - } - jdk - } - - protected fun configureScriptFile(path: String) { - val mainScriptFile = findMainScript(path) - val environment = createScriptEnvironment(mainScriptFile) - registerScriptTemplateProvider(environment) - - File(path, "mainModule").takeIf { it.exists() }?.let { - myModule = createTestModuleFromDir(it) - } - - File(path).listFiles { file -> file.name.startsWith("module") }.filter { it.exists() }.forEach { - val newModule = createTestModuleFromDir(it) - assert(myModule != null) { "Main module should exists" } - ModuleRootModificationUtil.addDependency(myModule, newModule) - } - - if (module != null) { - module.addDependency( - projectLibrary( - "script-runtime", - classesRoot = VfsUtil.findFileByIoFile(PathUtil.kotlinPathsForDistDirectory.scriptRuntimePath, true) - ) - ) - - if (environment["template-classes"] != null) { - module.addDependency( - projectLibrary( - "script-template-library", - classesRoot = VfsUtil.findFileByIoFile(environment["template-classes"] as File, true) - ) - ) - } - } - - if (configureConflictingModule in environment) { - val sharedLib = VfsUtil.findFileByIoFile(environment["lib-classes"] as File, true)!! - if (module == null) { - // Force create module if it doesn't exist - myModule = createTestModuleByName("mainModule") - } - module.addDependency(projectLibrary("sharedLib", classesRoot = sharedLib)) - } - - if (module != null) { - ModuleRootModificationUtil.updateModel(module) { model -> - model.sdk = sdk - } - } - - createFileAndSyncDependencies(mainScriptFile) - } - - private val oldScripClasspath: String? = System.getProperty("kotlin.script.classpath") - - override fun setUp() { - super.setUp() - ApplicationManager.getApplication().isScriptDependenciesUpdaterDisabled = true - } - - override fun tearDown() { - ApplicationManager.getApplication().isScriptDependenciesUpdaterDisabled = false - - System.setProperty("kotlin.script.classpath", oldScripClasspath ?: "") - - super.tearDown() - } - - private fun createTestModuleByName(name: String): Module { - val newModuleDir = runWriteAction { VfsUtil.createDirectoryIfMissing(project.baseDir, name) } - val newModule = createModuleAt(name, project, JavaModuleType.getModuleType(), newModuleDir.path) - - // Return type was changed, but it's not used. BUNCH: 183 - @Suppress("MissingRecentApi") - PsiTestUtil.addSourceContentToRoots(newModule, newModuleDir) - return newModule - } - - private fun createTestModuleFromDir(dir: File): Module { - return createTestModuleByName(dir.name).apply { - PlatformTestCase.copyDirContentsTo(LocalFileSystem.getInstance().findFileByIoFile(dir)!!, moduleFile!!.parent) - } - } - - private fun createScriptEnvironment(scriptFile: File): Environment { - val defaultEnvironment = defaultEnvironment(scriptFile.parent + File.separator) - val env = mutableMapOf() - scriptFile.forEachLine { line -> - - fun iterateKeysInLine(prefix: String) { - if (line.contains(prefix)) { - line.trim().substringAfter(prefix).split(";").forEach { entry -> - val (key, values) = entry.splitOrEmpty(":").map { it.trim() } - assert(key in validKeys) { "Unexpected key: $key" } - env[key] = values.split(",").map { - val str = it.trim() - defaultEnvironment[str] ?: str - } - } - } - } - - iterateKeysInLine(useDefaultTemplate) - iterateKeysInLine(templatesSettings) - - switches.forEach { - if (it in line) { - env[it] = true - } - } - } - - if (env[useDefaultTemplate] != true && env["template-classes-names"] == null) { - env["template-classes-names"] = listOf("custom.scriptDefinition.Template") - } - - if (env["javaHome"] != null) { - val jdkKind = when ((env["javaHome"] as? List)?.singleOrNull()) { - "9" -> TestJdkKind.FULL_JDK_9 - else -> TestJdkKind.MOCK_JDK - } - runWriteAction { - val jdk = PluginTestCaseBase.jdk(jdkKind) - ProjectJdkTable.getInstance().addJdk(jdk, testRootDisposable) - env["javaHome"] = File(jdk.homePath) - } - } - - env.putAll(defaultEnvironment) - return env - } - - private fun defaultEnvironment(path: String): Map { - val templateOutDir = File("${path}template").takeIf { it.isDirectory }?.let { - compileLibToDir(it, *scriptClasspath()) - } ?: File("idea/testData/script/definition/defaultTemplate").takeIf { it.isDirectory }?.let { - compileLibToDir(it, *scriptClasspath()) - } - - val libSrcDir = File("${path}lib").takeIf { it.isDirectory } - - val libClasses = libSrcDir?.let { compileLibToDir(it) } - - return mapOf( - "runtime-classes" to ForTestCompileRuntime.runtimeJarForTests(), - "runtime-source" to File("libraries/stdlib/src"), - "lib-classes" to libClasses, - "lib-source" to libSrcDir, - "template-classes" to templateOutDir - ) - } - - private fun scriptClasspath(): Array { - return with(PathUtil.kotlinPathsForDistDirectory) { - arrayOf( - File(libPath, KOTLIN_JAVA_SCRIPT_RUNTIME_JAR).path, - File(libPath, KOTLIN_SCRIPTING_COMMON_JAR).path, - File(libPath, KOTLIN_SCRIPTING_JVM_JAR).path - ) - } - } - - private fun createFileAndSyncDependencies(scriptFile: File) { - var script: VirtualFile? = null - if (module != null) { - script = module.moduleFile?.parent?.findChild(scriptFile.name) - } - - if (script == null) { - val target = File(project.basePath, scriptFile.name) - scriptFile.copyTo(target) - script = VfsUtil.findFileByIoFile(target, true) - } - - if (script == null) error("Test file with script couldn't be found in test project") - - configureByExistingFile(script) - updateScriptDependenciesSynchronously(myFile, project) - - VfsUtil.markDirtyAndRefresh(false, true, true, project.baseDir) - // This is needed because updateScriptDependencies invalidates psiFile that was stored in myFile field - myFile = psiManager.findFile(script) - - val ktFile = myFile as KtFile - val reports = IdeScriptReportSink.getReports(ktFile) - val isFatalErrorPresent = reports.any { it.severity == ScriptDiagnostic.Severity.FATAL } - assert(isFatalErrorPresent || KotlinHighlightingUtil.shouldHighlight(myFile)) { - "Highlighting is switched off for ${myFile.virtualFile.path}\n" + - "reports=$reports\n" + - "scriptDefinition=${ktFile.findScriptDefinition()}" - } - } - - private fun compileLibToDir(srcDir: File, vararg classpath: String): File { - //TODO: tmpDir would be enough, but there is tricky fail under AS otherwise - val outDir = KotlinTestUtils.tmpDirForReusableFolder("${getTestName(false)}${srcDir.name}Out") - - val kotlinSourceFiles = FileUtil.findFilesByMask(Pattern.compile(".+\\.kt$"), srcDir) - if (kotlinSourceFiles.isNotEmpty()) { - MockLibraryUtil.compileKotlin(srcDir.path, outDir, extraClasspath = *classpath) - } - - val javaSourceFiles = FileUtil.findFilesByMask(Pattern.compile(".+\\.java$"), srcDir) - if (javaSourceFiles.isNotEmpty()) { - KotlinTestUtils.compileJavaFiles( - javaSourceFiles, - listOf("-cp", StringUtil.join(listOf(*classpath, outDir), File.pathSeparator), "-d", outDir.path) - ) - } - return outDir - } - - private fun registerScriptTemplateProvider(environment: Environment) { - val provider = if (environment[useDefaultTemplate] == true) { - FromTextTemplateProvider(environment) - } else { - CustomScriptTemplateProvider(environment) - } - - ScriptDefinitionContributor.EP_NAME.getPoint(null).registerExtension(provider) - - ScriptDefinitionsManager.getInstance(project).reloadScriptDefinitions() - - UIUtil.dispatchAllInvocationEvents() - } -} diff --git a/idea/tests/org/jetbrains/kotlin/idea/script/extensionsUtil.kt b/idea/tests/org/jetbrains/kotlin/idea/script/extensionsUtil.kt new file mode 100644 index 00000000000..6959dea0ab0 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/script/extensionsUtil.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.script + +import com.intellij.openapi.Disposable +import com.intellij.openapi.extensions.ExtensionPointName +import com.intellij.openapi.extensions.Extensions +import com.intellij.openapi.project.Project +import com.intellij.testFramework.PlatformTestUtil + +fun addExtensionPointInTest( + pointName: ExtensionPointName, + project: Project, + provider: T, + testRootDisposable: Disposable +) { + PlatformTestUtil.registerExtension( + Extensions.getArea(project), + pointName, + provider, + testRootDisposable + ) +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/script/extensionsUtil.kt.193 b/idea/tests/org/jetbrains/kotlin/idea/script/extensionsUtil.kt.193 new file mode 100644 index 00000000000..6847ecc0ee7 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/script/extensionsUtil.kt.193 @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.script + +import com.intellij.openapi.Disposable +import com.intellij.openapi.extensions.ExtensionPointName +import com.intellij.openapi.project.Project + +fun addExtensionPointInTest( + pointName: ExtensionPointName, + project: Project, + provider: T, + testRootDisposable: Disposable +) { + pointName.getPoint(null).registerExtension(provider) +} \ No newline at end of file