diff --git a/idea/idea-test-framework/test/org/jetbrains/kotlin/idea/test/KotlinLightCodeInsightFixtureTestCaseBase.java.as42 b/idea/idea-test-framework/test/org/jetbrains/kotlin/idea/test/KotlinLightCodeInsightFixtureTestCaseBase.java.as42 new file mode 100644 index 00000000000..d55001ae243 --- /dev/null +++ b/idea/idea-test-framework/test/org/jetbrains/kotlin/idea/test/KotlinLightCodeInsightFixtureTestCaseBase.java.as42 @@ -0,0 +1,95 @@ +/* + * Copyright 2010-2020 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.test; + +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiFile; +import com.intellij.testFramework.TempFiles; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import gnu.trove.THashSet; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.WithMutedInDatabaseRunTest; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.util.Collection; + +@WithMutedInDatabaseRunTest +public abstract class KotlinLightCodeInsightFixtureTestCaseBase extends LightCodeInsightFixtureTestCase { + @NotNull + @Override + public Project getProject() { + return super.getProject(); + } + + @NotNull + @Override + public Editor getEditor() { + return super.getEditor(); + } + + @Override + public PsiFile getFile() { + return super.getFile(); + } + + protected final Collection myFilesToDelete = new THashSet<>(); + private final TempFiles myTempFiles = new TempFiles(myFilesToDelete); + + @Override + protected void tearDown() throws Exception { + myTempFiles.deleteAll(); + super.tearDown(); + } + + @NotNull + public VirtualFile createTempFile( + @NonNls @NotNull String ext, + @Nullable byte[] bom, + @NonNls @NotNull String content, + @NotNull Charset charset + ) throws IOException { + File temp = FileUtil.createTempFile("copy", "." + ext); + setContentOnDisk(temp, bom, content, charset); + + myFilesToDelete.add(temp.toPath()); + final VirtualFile file = getVirtualFile(temp); + assert file != null : temp; + return file; + } + + public static void setContentOnDisk(@NotNull File file, @Nullable byte[] bom, @NotNull String content, @NotNull Charset charset) + throws IOException { + FileOutputStream stream = new FileOutputStream(file); + if (bom != null) { + stream.write(bom); + } + try (OutputStreamWriter writer = new OutputStreamWriter(stream, charset)) { + writer.write(content); + } + } + + protected static VirtualFile getVirtualFile(@NotNull File file) { + return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file); + } + + @Override + protected void runTest() throws Throwable { + //noinspection Convert2MethodRef + KotlinTestUtils.runTestWithThrowable(this, () -> super.runTest()); + } +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinInTempDirTest.kt.as42 b/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinInTempDirTest.kt.as42 new file mode 100644 index 00000000000..f294dc05192 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinInTempDirTest.kt.as42 @@ -0,0 +1,38 @@ +/* + * 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.configuration + +import com.intellij.openapi.util.io.FileUtil +import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime +import org.junit.Assert +import java.io.File +import java.nio.file.Path + +abstract class AbstractConfigureKotlinInTempDirTest : AbstractConfigureKotlinTest() { + override fun getProjectDirOrFile(): Path { + val tempDir = FileUtil.generateRandomTemporaryPath() + FileUtil.createTempDirectory("temp", null) + myFilesToDelete.add(tempDir.toPath()) + + FileUtil.copyDir(File(projectRoot), tempDir) + + val kotlinRuntime = File(tempDir, "lib/kotlin-stdlib.jar") + if (getTestName(true).toLowerCase().contains("latestruntime") && kotlinRuntime.exists()) { + ForTestCompileRuntime.runtimeJarForTests().copyTo(kotlinRuntime, overwrite = true) + } + + val projectRoot = tempDir.path + + val projectFilePath = projectRoot + "/projectFile.ipr" + if (!File(projectFilePath).exists()) { + val dotIdeaPath = projectRoot + "/.idea" + Assert.assertTrue("Project file or '.idea' dir should exists in " + projectRoot, File(dotIdeaPath).exists()) + return File(projectRoot).toPath() + } + + return File(projectFilePath).toPath() + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinTest.kt.as42 b/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinTest.kt.as42 new file mode 100644 index 00000000000..c5f8ab57c16 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinTest.kt.as42 @@ -0,0 +1,257 @@ +/* + * 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.configuration + +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.application.PathMacros +import com.intellij.openapi.module.Module +import com.intellij.openapi.module.ModuleManager +import com.intellij.openapi.project.Project +import com.intellij.openapi.projectRoots.Sdk +import com.intellij.openapi.roots.ProjectRootManager +import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.util.io.FileUtilRt +import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess +import com.intellij.testFramework.PlatformTestCase +import com.intellij.testFramework.UsefulTestCase +import junit.framework.TestCase +import org.jetbrains.kotlin.idea.configuration.KotlinWithLibraryConfigurator.FileState +import org.jetbrains.kotlin.idea.framework.KotlinSdkType +import org.jetbrains.kotlin.idea.test.PluginTestCaseBase +import org.jetbrains.kotlin.idea.test.PluginTestCaseBase.* +import org.jetbrains.kotlin.idea.util.getProjectJdkTableSafe +import org.jetbrains.kotlin.test.KotlinTestUtils +import org.jetbrains.kotlin.test.WithMutedInDatabaseRunTest +import org.jetbrains.kotlin.test.isIgnoredInDatabaseWithLog +import org.jetbrains.kotlin.test.runTest +import org.jetbrains.kotlin.utils.PathUtil +import java.io.File +import java.nio.file.Path + +@WithMutedInDatabaseRunTest +abstract class AbstractConfigureKotlinTest : PlatformTestCase() { + override fun setUp() { + super.setUp() + + VfsRootAccess.allowRootAccess(KotlinTestUtils.getHomeDirectory()) + } + + @Throws(Exception::class) + override fun tearDown() { + VfsRootAccess.disallowRootAccess(KotlinTestUtils.getHomeDirectory()) + PathMacros.getInstance().removeMacro(TEMP_DIR_MACRO_KEY) + + super.tearDown() + } + + @Throws(Exception::class) + override fun initApplication() { + super.initApplication() + + KotlinSdkType.setUpIfNeeded(testRootDisposable) + + ApplicationManager.getApplication().runWriteAction { + addJdk(testRootDisposable, ::mockJdk6) + addJdk(testRootDisposable, ::mockJdk8) + addJdk(testRootDisposable, ::mockJdk9) + } + + val tempLibDir = FileUtil.createTempDirectory("temp", null) + PathMacros.getInstance().setMacro(TEMP_DIR_MACRO_KEY, FileUtilRt.toSystemDependentName(tempLibDir.absolutePath)) + } + + protected fun doTestConfigureModulesWithNonDefaultSetup(configurator: KotlinWithLibraryConfigurator) { + assertNoFilesInDefaultPaths() + + val modules = modules + for (module in modules) { + assertNotConfigured(module, configurator) + } + + configurator.configure(myProject, emptyList()) + + assertNoFilesInDefaultPaths() + + for (module in modules) { + assertProperlyConfigured(module, configurator) + } + } + + protected fun doTestOneJavaModule(jarState: FileState) { + doTestOneModule(jarState, JAVA_CONFIGURATOR) + } + + protected fun doTestOneJsModule(jarState: FileState) { + doTestOneModule(jarState, JS_CONFIGURATOR) + } + + private fun doTestOneModule(jarState: FileState, configurator: KotlinWithLibraryConfigurator) { + val module = module + + assertNotConfigured(module, configurator) + configure(module, jarState, configurator) + assertProperlyConfigured(module, configurator) + } + + override fun getModule(): Module { + val modules = ModuleManager.getInstance(myProject).modules + assert(modules.size == 1) { "One module should be loaded " + modules.size } + myModule = modules[0] + return super.getModule() + } + + val modules: Array + get() = ModuleManager.getInstance(myProject).modules + + override fun getProjectDirOrFile(): Path { + val projectFilePath = projectRoot + "/projectFile.ipr" + TestCase.assertTrue("Project file should exists " + projectFilePath, File(projectFilePath).exists()) + return File(projectFilePath).toPath() + } + + override fun doCreateProject(projectFile: Path): Project { + return loadProjectCompat(projectFile) + } + + private val projectName: String + get() { + val testName = getTestName(true) + return if (testName.contains("_")) { + testName.substring(0, testName.indexOf("_")) + } else + testName + } + + protected val projectRoot: String + get() = BASE_PATH + projectName + + override fun setUpModule() {} + + private fun assertNoFilesInDefaultPaths() { + UsefulTestCase.assertDoesntExist(File(JAVA_CONFIGURATOR.getDefaultPathToJarFile(project))) + UsefulTestCase.assertDoesntExist(File(JS_CONFIGURATOR.getDefaultPathToJarFile(project))) + } + + override fun runTest() { + return runTest { super.runTest() } + } + + companion object { + private val BASE_PATH = "idea/testData/configuration/" + private val TEMP_DIR_MACRO_KEY = "TEMP_TEST_DIR" + protected val JAVA_CONFIGURATOR: KotlinJavaModuleConfigurator by lazy { + object : KotlinJavaModuleConfigurator() { + override fun getDefaultPathToJarFile(project: Project) = getPathRelativeToTemp("default_jvm_lib") + } + } + + protected val JS_CONFIGURATOR: KotlinJsModuleConfigurator by lazy { + object : KotlinJsModuleConfigurator() { + override fun getDefaultPathToJarFile(project: Project) = getPathRelativeToTemp("default_js_lib") + } + } + + private fun configure( + modules: List, + runtimeState: FileState, + configurator: KotlinWithLibraryConfigurator, + jarFromDist: String, + jarFromTemp: String + ) { + val project = modules.first().project + val collector = createConfigureKotlinNotificationCollector(project) + + val pathToJar = getPathToJar(runtimeState, jarFromDist, jarFromTemp) + for (module in modules) { + configurator.configureModule(module, pathToJar, pathToJar, collector, runtimeState) + } + collector.showNotification() + } + + private fun getPathToJar(runtimeState: FileState, jarFromDist: String, jarFromTemp: String) = when (runtimeState) { + FileState.EXISTS -> jarFromDist + FileState.COPY -> jarFromTemp + FileState.DO_NOT_COPY -> jarFromDist + } + + + private val pathToExistentRuntimeJar: String + get() = PathUtil.kotlinPathsForDistDirectory.stdlibPath.parent + + private val pathToExistentJsJar: String + get() = PathUtil.kotlinPathsForDistDirectory.jsStdLibJarPath.parent + + protected fun assertNotConfigured(module: Module, configurator: KotlinWithLibraryConfigurator) { + TestCase.assertFalse( + String.format("Module %s should not be configured as %s Module", module.name, configurator.presentableText), + configurator.isConfigured(module) + ) + } + + protected fun assertConfigured(module: Module, configurator: KotlinWithLibraryConfigurator) { + TestCase.assertTrue( + String.format( + "Module %s should be configured with configurator '%s'", module.name, + configurator.presentableText + ), + configurator.isConfigured(module) + ) + } + + protected fun assertProperlyConfigured(module: Module, configurator: KotlinWithLibraryConfigurator) { + assertConfigured(module, configurator) + assertNotConfigured(module, getOppositeConfigurator(configurator)) + } + + private fun getOppositeConfigurator(configurator: KotlinWithLibraryConfigurator): KotlinWithLibraryConfigurator { + if (configurator === JAVA_CONFIGURATOR) return JS_CONFIGURATOR + if (configurator === JS_CONFIGURATOR) return JAVA_CONFIGURATOR + + throw IllegalArgumentException("Only JS_CONFIGURATOR and JAVA_CONFIGURATOR are supported") + } + + private fun getPathRelativeToTemp(relativePath: String): String { + val tempPath = PathMacros.getInstance().getValue(TEMP_DIR_MACRO_KEY) + return tempPath + '/' + relativePath + } + } + + protected fun configure(module: Module, jarState: FileState, configurator: KotlinProjectConfigurator) { + if (configurator is KotlinJavaModuleConfigurator) { + configure( + listOf(module), jarState, + configurator as KotlinWithLibraryConfigurator, + pathToExistentRuntimeJar, pathToNonexistentRuntimeJar + ) + } + if (configurator is KotlinJsModuleConfigurator) { + configure( + listOf(module), jarState, + configurator as KotlinWithLibraryConfigurator, + pathToExistentJsJar, pathToNonexistentJsJar + ) + } + } + + private val pathToNonexistentRuntimeJar: String + get() { + val pathToTempKotlinRuntimeJar = FileUtil.getTempDirectory() + "/" + PathUtil.KOTLIN_JAVA_STDLIB_JAR + myFilesToDelete.add(File(pathToTempKotlinRuntimeJar).toPath()) + return pathToTempKotlinRuntimeJar + } + + private val pathToNonexistentJsJar: String + get() { + val pathToTempKotlinRuntimeJar = FileUtil.getTempDirectory() + "/" + PathUtil.JS_LIB_JAR_NAME + myFilesToDelete.add(File(pathToTempKotlinRuntimeJar).toPath()) + return pathToTempKotlinRuntimeJar + } + + override fun getTestProjectJdk(): Sdk { + val projectRootManager = ProjectRootManager.getInstance(project) + return projectRootManager.projectSdk ?: throw IllegalStateException("SDK ${projectRootManager.projectSdkName} was not found") + } +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/QuickDocInHierarchyTest.kt.as42 b/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/QuickDocInHierarchyTest.kt.as42 new file mode 100644 index 00000000000..b72366c2c05 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/QuickDocInHierarchyTest.kt.as42 @@ -0,0 +1,50 @@ +/* + * 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.editor.quickDoc + +import com.intellij.codeInsight.CodeInsightTestCase +import com.intellij.ide.hierarchy.HierarchyBrowserBaseEx +import com.intellij.ide.hierarchy.LanguageTypeHierarchy +import com.intellij.ide.hierarchy.actions.BrowseHierarchyActionBase +import com.intellij.ide.hierarchy.type.TypeHierarchyNodeDescriptor +import com.intellij.ide.hierarchy.type.TypeHierarchyTreeStructure +import com.intellij.openapi.actionSystem.CommonDataKeys +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiElement +import com.intellij.testFramework.MapDataContext +import junit.framework.TestCase +import org.jetbrains.kotlin.idea.KotlinDocumentationProvider +import org.jetbrains.kotlin.idea.test.PluginTestCaseBase +import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner +import org.junit.runner.RunWith + +@RunWith(JUnit3WithIdeaConfigurationRunner::class) +class QuickDocInHierarchyTest() : CodeInsightTestCase() { + override fun getTestDataPath(): String { + return PluginTestCaseBase.getTestDataPathBase() + "/kdoc/inTypeHierarchy/" + } + + fun testSimple() { + configureByFile(getTestName(true) + ".kt") + + val context = MapDataContext() + context.put(CommonDataKeys.PROJECT, project) + context.put(CommonDataKeys.EDITOR, editor) + + val provider = BrowseHierarchyActionBase.findProvider(LanguageTypeHierarchy.INSTANCE, file, file, context)!! + val hierarchyTreeStructure = TypeHierarchyTreeStructure( + project, + provider.getTarget(context) as PsiClass, + HierarchyBrowserBaseEx.SCOPE_PROJECT + ) + val hierarchyNodeDescriptor = hierarchyTreeStructure.baseDescriptor as TypeHierarchyNodeDescriptor + val doc = KotlinDocumentationProvider().generateDoc(hierarchyNodeDescriptor.psiClass as PsiElement, null)!! + + TestCase.assertTrue("Invalid doc\n: $doc", doc.contains("Very special class")) + } +} \ No newline at end of file