182: compilation fix: PlatformTestCase.myFilesToDelete made non-static in Platform

some code from `PlatformTestCase` were copy-pasted to `KotlinLightCodeInsightFixtureTestCaseBase` because `PlatformTestCase` is not in it's type hierarchy, and thus we cant use these methods from `PlatformTestCase` when they became non-static
This commit is contained in:
Nicolay Mitropolsky
2018-03-12 11:18:14 +03:00
committed by Nikolay Krasko
parent 22186c05b4
commit 44605580f3
6 changed files with 1357 additions and 0 deletions
@@ -0,0 +1,131 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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.util.io.FileUtilRt;
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 java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.util.Collection;
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<File> myFilesToDelete = new THashSet<>();
private final TempFiles myTempFiles = new TempFiles(myFilesToDelete);
@Override
protected void tearDown() throws Exception {
myTempFiles.deleteAll();
super.tearDown();
}
@NotNull
protected File createTempFile(@NotNull String name, @Nullable String text) throws IOException {
File directory = createTempDirectory();
File file = new File(directory, name);
if (!file.createNewFile()) {
throw new IOException("Can't create " + file);
}
if (text != null) {
FileUtil.writeToFile(file, text);
}
return file;
}
@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);
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);
}
}
@NotNull
protected File createTempDirectory() throws IOException {
return createTempDir("");
}
@NotNull
public File createTempDir(@NonNls @NotNull String prefix) throws IOException {
return createTempDir(prefix, true);
}
@NotNull
public File createTempDir(@NonNls @NotNull String prefix, final boolean refresh) throws IOException {
final File tempDirectory = FileUtilRt.createTempDirectory("idea_test_" + prefix, null, false);
myFilesToDelete.add(tempDirectory);
if (refresh) {
getVirtualFile(tempDirectory);
}
return tempDirectory;
}
protected static VirtualFile getVirtualFile(@NotNull File file) {
return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
}
}
@@ -0,0 +1,268 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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.ProjectJdkTable
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.utils.PathUtil
import java.io.File
import java.nio.file.Path
abstract class AbstractConfigureKotlinTest : PlatformTestCase() {
override fun setUp() {
super.setUp()
val distPaths = with(PathUtil.kotlinPathsForIdeaPlugin) {
listOf(
stdlibPath,
stdlibSourcesPath,
reflectPath,
kotlinTestPath,
jsKotlinTestJarPath,
jsStdLibJarPath,
jsStdLibSrcJarPath
)
}
for (path in distPaths) {
VfsRootAccess.allowRootAccess(testRootDisposable, path.absolutePath)
}
}
@Throws(Exception::class)
override fun tearDown() {
PathMacros.getInstance().removeMacro(TEMP_DIR_MACRO_KEY)
super.tearDown()
}
@Throws(Exception::class)
override fun initApplication() {
super.initApplication()
KotlinSdkType.setUpIfNeeded()
ApplicationManager.getApplication().runWriteAction {
ProjectJdkTable.getInstance().addJdk(PluginTestCaseBase.mockJdk6())
ProjectJdkTable.getInstance().addJdk(PluginTestCaseBase.mockJdk8())
ProjectJdkTable.getInstance().addJdk(PluginTestCaseBase.mockJdk9())
}
PluginTestCaseBase.clearSdkTable(testRootDisposable)
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<Module>
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 myProjectManager.loadProject(projectFile.toFile().path)!!
}
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)))
}
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<Module>,
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) {
KotlinWithLibraryConfigurator.FileState.EXISTS -> jarFromDist
KotlinWithLibraryConfigurator.FileState.COPY -> jarFromTemp
KotlinWithLibraryConfigurator.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() + "/kotlin-runtime.jar"
myFilesToDelete.add(File(pathToTempKotlinRuntimeJar))
return pathToTempKotlinRuntimeJar
}
private val pathToNonexistentJsJar: String
get() {
val pathToTempKotlinRuntimeJar = FileUtil.getTempDirectory() + "/" + PathUtil.JS_LIB_JAR_NAME
myFilesToDelete.add(File(pathToTempKotlinRuntimeJar))
return pathToTempKotlinRuntimeJar
}
override fun getTestProjectJdk(): Sdk {
val projectRootManager = ProjectRootManager.getInstance(project)
return projectRootManager.projectSdk ?: throw IllegalStateException("SDK ${projectRootManager.projectSdkName} was not found")
}
}
@@ -0,0 +1,357 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.configuration;
import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProviderImpl;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.LibraryOrderEntry;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.RootPolicy;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiJavaModule;
import com.intellij.psi.PsiRequiresStatement;
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments;
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments;
import org.jetbrains.kotlin.config.*;
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCommonCompilerArgumentsHolder;
import org.jetbrains.kotlin.idea.facet.FacetUtilsKt;
import org.jetbrains.kotlin.idea.facet.KotlinFacet;
import org.jetbrains.kotlin.idea.framework.JsLibraryStdDetectionUtil;
import org.jetbrains.kotlin.idea.project.PlatformKt;
import org.jetbrains.kotlin.idea.util.Java9StructureUtilKt;
import org.jetbrains.kotlin.idea.versions.KotlinRuntimeLibraryUtilKt;
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleKt;
import org.jetbrains.kotlin.utils.PathUtil;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.stream.StreamSupport;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
public class ConfigureKotlinTest extends AbstractConfigureKotlinTest {
public void testNewLibrary_copyJar() {
doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.COPY);
ModuleRootManager.getInstance(getModule()).orderEntries().forEachLibrary(library -> {
assertSameElements(
Arrays.stream(library.getRootProvider().getFiles(OrderRootType.CLASSES)).map(VirtualFile::getName).toArray(),
PathUtil.KOTLIN_JAVA_STDLIB_JAR, PathUtil.KOTLIN_JAVA_REFLECT_JAR, PathUtil.KOTLIN_TEST_JAR);
assertSameElements(
Arrays.stream(library.getRootProvider().getFiles(OrderRootType.SOURCES)).map(VirtualFile::getName).toArray(),
PathUtil.KOTLIN_JAVA_STDLIB_SRC_JAR, PathUtil.KOTLIN_REFLECT_SRC_JAR, PathUtil.KOTLIN_TEST_SRC_JAR);
return true;
});
}
public void testNewLibrary_doNotCopyJar() {
doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY);
}
public void testLibraryWithoutPaths_jarExists() {
doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.EXISTS);
}
public void testNewLibrary_jarExists() {
doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.EXISTS);
}
public void testLibraryWithoutPaths_copyJar() {
doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.COPY);
}
public void testLibraryWithoutPaths_doNotCopyJar() {
doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY);
}
@SuppressWarnings("ConstantConditions")
public void testTwoModules_exists() {
Module[] modules = getModules();
for (Module module : modules) {
if (module.getName().equals("module1")) {
configure(module, KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY, Companion.getJAVA_CONFIGURATOR());
Companion.assertConfigured(module, Companion.getJAVA_CONFIGURATOR());
}
else if (module.getName().equals("module2")) {
Companion.assertNotConfigured(module, Companion.getJAVA_CONFIGURATOR());
configure(module, KotlinWithLibraryConfigurator.FileState.EXISTS, Companion.getJAVA_CONFIGURATOR());
Companion.assertConfigured(module, Companion.getJAVA_CONFIGURATOR());
}
}
}
public void testLibraryNonDefault_libExistInDefault() throws IOException {
Module module = getModule();
// Move fake runtime jar to default library path to pretend library is already configured
FileUtil.copy(
new File(getProject().getBasePath() + "/lib/kotlin-runtime.jar"),
new File(Companion.getJAVA_CONFIGURATOR().getDefaultPathToJarFile(getProject()) + "/kotlin-runtime.jar"));
Companion.assertNotConfigured(module, Companion.getJAVA_CONFIGURATOR());
Companion.getJAVA_CONFIGURATOR().configure(myProject, Collections.<Module>emptyList());
Companion.assertProperlyConfigured(module, Companion.getJAVA_CONFIGURATOR());
}
public void testTwoModulesWithNonDefaultPath_doNotCopyInDefault() throws IOException {
doTestConfigureModulesWithNonDefaultSetup(Companion.getJAVA_CONFIGURATOR());
assertEmpty(ConfigureKotlinInProjectUtilsKt.getCanBeConfiguredModules(myProject, Companion.getJS_CONFIGURATOR()));
}
public void testTwoModulesWithJSNonDefaultPath_doNotCopyInDefault() throws IOException {
doTestConfigureModulesWithNonDefaultSetup(Companion.getJS_CONFIGURATOR());
assertEmpty(ConfigureKotlinInProjectUtilsKt.getCanBeConfiguredModules(myProject, Companion.getJAVA_CONFIGURATOR()));
}
public void testNewLibrary_jarExists_js() {
doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.EXISTS);
}
public void testNewLibrary_copyJar_js() {
doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.COPY);
}
public void testNewLibrary_doNotCopyJar_js() {
doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY);
}
public void testJsLibraryWithoutPaths_jarExists() {
doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.EXISTS);
}
public void testJsLibraryWithoutPaths_copyJar() {
doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.COPY);
}
public void testJsLibraryWithoutPaths_doNotCopyJar() {
doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY);
}
public void testJsLibraryWrongKind() {
doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.EXISTS);
assertEquals(1, ModuleRootManager.getInstance(getModule()).orderEntries().process(new LibraryCountingRootPolicy(), 0).intValue());
}
public void testProjectWithoutFacetWithRuntime106WithoutLanguageLevel() {
assertEquals(LanguageVersion.KOTLIN_1_0, PlatformKt.getLanguageVersionSettings(myProject, null).getLanguageVersion());
assertEquals(LanguageVersion.KOTLIN_1_0, PlatformKt.getLanguageVersionSettings(getModule()).getLanguageVersion());
}
public void testProjectWithoutFacetWithRuntime11WithoutLanguageLevel() {
assertEquals(LanguageVersion.LATEST_STABLE, PlatformKt.getLanguageVersionSettings(myProject, null).getLanguageVersion());
assertEquals(LanguageVersion.LATEST_STABLE, PlatformKt.getLanguageVersionSettings(getModule()).getLanguageVersion());
}
public void testProjectWithoutFacetWithRuntime11WithLanguageLevel10() {
assertEquals(LanguageVersion.KOTLIN_1_0, PlatformKt.getLanguageVersionSettings(myProject, null).getLanguageVersion());
assertEquals(LanguageVersion.KOTLIN_1_0, PlatformKt.getLanguageVersionSettings(getModule()).getLanguageVersion());
}
public void testProjectWithFacetWithRuntime11WithLanguageLevel10() {
assertEquals(LanguageVersion.LATEST_STABLE, PlatformKt.getLanguageVersionSettings(myProject, null).getLanguageVersion());
assertEquals(LanguageVersion.KOTLIN_1_0, PlatformKt.getLanguageVersionSettings(getModule()).getLanguageVersion());
}
public void testJsLibraryVersion11() {
Library jsRuntime = KotlinRuntimeLibraryUtilKt.findAllUsedLibraries(myProject).keySet().iterator().next();
String version = JsLibraryStdDetectionUtil.INSTANCE.getJsLibraryStdVersion(jsRuntime);
assertEquals("1.1.0", version);
}
public void testJsLibraryVersion106() {
Library jsRuntime = KotlinRuntimeLibraryUtilKt.findAllUsedLibraries(myProject).keySet().iterator().next();
String version = JsLibraryStdDetectionUtil.INSTANCE.getJsLibraryStdVersion(jsRuntime);
assertEquals("1.0.6", version);
}
@SuppressWarnings("ConstantConditions")
public void testJvmProjectWithV1FacetConfig() {
KotlinFacetSettings settings = KotlinFacetSettingsProvider.Companion.getInstance(myProject).getInitializedSettings(getModule());
K2JVMCompilerArguments arguments = (K2JVMCompilerArguments) settings.getCompilerArguments();
assertEquals(false, settings.getUseProjectSettings());
assertEquals("1.1", settings.getLanguageLevel().getDescription());
assertEquals("1.0", settings.getApiLevel().getDescription());
assertEquals(TargetPlatformKind.Jvm.Companion.get(JvmTarget.JVM_1_8), settings.getTargetPlatformKind());
assertEquals("1.1", arguments.getLanguageVersion());
assertEquals("1.0", arguments.getApiVersion());
assertEquals(LanguageFeature.State.ENABLED_WITH_WARNING, CoroutineSupport.byCompilerArguments(arguments));
assertEquals("1.7", arguments.getJvmTarget());
assertEquals("-version -Xallow-kotlin-package -Xskip-metadata-version-check", settings.getCompilerSettings().getAdditionalArguments());
}
@SuppressWarnings("ConstantConditions")
public void testJsProjectWithV1FacetConfig() {
KotlinFacetSettings settings = KotlinFacetSettingsProvider.Companion.getInstance(myProject).getInitializedSettings(getModule());
K2JSCompilerArguments arguments = (K2JSCompilerArguments) settings.getCompilerArguments();
assertEquals(false, settings.getUseProjectSettings());
assertEquals("1.1", settings.getLanguageLevel().getDescription());
assertEquals("1.0", settings.getApiLevel().getDescription());
assertEquals(TargetPlatformKind.JavaScript.INSTANCE, settings.getTargetPlatformKind());
assertEquals("1.1", arguments.getLanguageVersion());
assertEquals("1.0", arguments.getApiVersion());
assertEquals(LanguageFeature.State.ENABLED_WITH_WARNING, CoroutineSupport.byCompilerArguments(arguments));
assertEquals("amd", arguments.getModuleKind());
assertEquals("-version -meta-info", settings.getCompilerSettings().getAdditionalArguments());
}
@SuppressWarnings("ConstantConditions")
public void testJvmProjectWithV2FacetConfig() {
KotlinFacetSettings settings = KotlinFacetSettingsProvider.Companion.getInstance(myProject).getInitializedSettings(getModule());
K2JVMCompilerArguments arguments = (K2JVMCompilerArguments) settings.getCompilerArguments();
assertEquals(false, settings.getUseProjectSettings());
assertEquals("1.1", settings.getLanguageLevel().getDescription());
assertEquals("1.0", settings.getApiLevel().getDescription());
assertEquals(TargetPlatformKind.Jvm.Companion.get(JvmTarget.JVM_1_8), settings.getTargetPlatformKind());
assertEquals("1.1", arguments.getLanguageVersion());
assertEquals("1.0", arguments.getApiVersion());
assertEquals(LanguageFeature.State.ENABLED, CoroutineSupport.byCompilerArguments(arguments));
assertEquals("1.7", arguments.getJvmTarget());
assertEquals("-version -Xallow-kotlin-package -Xskip-metadata-version-check", settings.getCompilerSettings().getAdditionalArguments());
}
@SuppressWarnings("ConstantConditions")
public void testJsProjectWithV2FacetConfig() {
KotlinFacetSettings settings = KotlinFacetSettingsProvider.Companion.getInstance(myProject).getInitializedSettings(getModule());
K2JSCompilerArguments arguments = (K2JSCompilerArguments) settings.getCompilerArguments();
assertEquals(false, settings.getUseProjectSettings());
assertEquals("1.1", settings.getLanguageLevel().getDescription());
assertEquals("1.0", settings.getApiLevel().getDescription());
assertEquals(TargetPlatformKind.JavaScript.INSTANCE, settings.getTargetPlatformKind());
assertEquals("1.1", arguments.getLanguageVersion());
assertEquals("1.0", arguments.getApiVersion());
assertEquals(LanguageFeature.State.ENABLED_WITH_ERROR, CoroutineSupport.byCompilerArguments(arguments));
assertEquals("amd", arguments.getModuleKind());
assertEquals("-version -meta-info", settings.getCompilerSettings().getAdditionalArguments());
}
@SuppressWarnings("ConstantConditions")
public void testJvmProjectWithV3FacetConfig() {
KotlinFacetSettings settings = KotlinFacetSettingsProvider.Companion.getInstance(myProject).getInitializedSettings(getModule());
K2JVMCompilerArguments arguments = (K2JVMCompilerArguments) settings.getCompilerArguments();
assertEquals(false, settings.getUseProjectSettings());
assertEquals("1.1", settings.getLanguageLevel().getDescription());
assertEquals("1.0", settings.getApiLevel().getDescription());
assertEquals(TargetPlatformKind.Jvm.Companion.get(JvmTarget.JVM_1_8), settings.getTargetPlatformKind());
assertEquals("1.1", arguments.getLanguageVersion());
assertEquals("1.0", arguments.getApiVersion());
assertEquals(LanguageFeature.State.ENABLED, CoroutineSupport.byCompilerArguments(arguments));
assertEquals("1.7", arguments.getJvmTarget());
assertEquals("-version -Xallow-kotlin-package -Xskip-metadata-version-check", settings.getCompilerSettings().getAdditionalArguments());
}
public void testImplementsDependency() {
ModuleManager moduleManager = ModuleManager.getInstance(myProject);
Module module1 = moduleManager.findModuleByName("module1");
assert module1 != null;
Module module2 = moduleManager.findModuleByName("module2");
assert module2 != null;
assertEquals(KotlinFacet.Companion.get(module1).getConfiguration().getSettings().getImplementedModuleNames(), emptyList());
assertEquals(KotlinFacet.Companion.get(module2).getConfiguration().getSettings().getImplementedModuleNames(), singletonList("module1"));
}
public void testJava9WithModuleInfo() {
checkAddStdlibModule();
}
public void testJava9WithModuleInfoWithStdlibAlready() {
checkAddStdlibModule();
}
public void testProjectWithFreeArgs() {
assertEquals(
Collections.singletonList("true"),
KotlinCommonCompilerArgumentsHolder.Companion.getInstance(myProject).getSettings().getFreeArgs()
);
}
private void checkAddStdlibModule() {
doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.COPY);
Module module = getModule();
Sdk moduleSdk = ModuleRootManager.getInstance(getModule()).getSdk();
assertNotNull("Module SDK is not defined", moduleSdk);
PsiJavaModule javaModule = Java9StructureUtilKt.findFirstPsiJavaModule(module);
assertNotNull(javaModule);
PsiRequiresStatement stdlibDirective =
Java9StructureUtilKt.findRequireDirective(javaModule, JavaModuleKt.KOTLIN_STDLIB_MODULE_NAME);
assertNotNull("Require directive for " + JavaModuleKt.KOTLIN_STDLIB_MODULE_NAME + " is expected",
stdlibDirective);
long numberOfStdlib = StreamSupport.stream(javaModule.getRequires().spliterator(), false)
.filter((statement) -> JavaModuleKt.KOTLIN_STDLIB_MODULE_NAME.equals(statement.getModuleName()))
.count();
assertTrue("Only one standard library directive is expected", numberOfStdlib == 1);
}
private void configureFacetAndCheckJvm(JvmTarget jvmTarget) {
IdeModifiableModelsProviderImpl modelsProvider = new IdeModifiableModelsProviderImpl(getProject());
try {
KotlinFacet facet = FacetUtilsKt.getOrCreateFacet(getModule(), modelsProvider, false, false);
TargetPlatformKind.Jvm platformKind = TargetPlatformKind.Jvm.Companion.get(jvmTarget);
FacetUtilsKt.configureFacet(
facet,
"1.1",
LanguageFeature.State.ENABLED,
platformKind,
modelsProvider
);
assertEquals(platformKind, facet.getConfiguration().getSettings().getTargetPlatformKind());
assertEquals(jvmTarget.getDescription(),
((K2JVMCompilerArguments) facet.getConfiguration().getSettings().getCompilerArguments()).getJvmTarget());
}
finally {
modelsProvider.dispose();
}
}
@SuppressWarnings("ConstantConditions")
public void testJvm8InProjectJvm6InModule() {
configureFacetAndCheckJvm(JvmTarget.JVM_1_6);
}
@SuppressWarnings("ConstantConditions")
public void testJvm6InProjectJvm8InModule() {
configureFacetAndCheckJvm(JvmTarget.JVM_1_8);
}
public void testProjectWithoutFacetWithJvmTarget18() {
assertEquals(TargetPlatformKind.Jvm.Companion.get(JvmTarget.JVM_1_8), PlatformKt.getTargetPlatform(getModule()));
}
private static class LibraryCountingRootPolicy extends RootPolicy<Integer> {
@Override
public Integer visitLibraryOrderEntry(LibraryOrderEntry libraryOrderEntry, Integer value) {
return value + 1;
}
}
}
@@ -0,0 +1,119 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.folding;
import com.intellij.codeInsight.folding.JavaCodeFoldingSettings;
import com.intellij.codeInsight.folding.impl.JavaCodeFoldingSettingsImpl;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCaseBase;
import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor;
import org.jetbrains.kotlin.test.SettingsConfigurator;
import org.junit.Assert;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.function.Consumer;
public abstract class AbstractKotlinFoldingTest extends KotlinLightCodeInsightFixtureTestCaseBase {
protected void doTest(@NotNull String path) {
myFixture.testFolding(path);
}
protected void doSettingsFoldingTest(@NotNull String path) throws IOException{
String fileText = FileUtil.loadFile(new File(path), true);
String directText = fileText.replaceAll("~true~", "true").replaceAll("~false~", "false");
directText += "\n\n// Generated from: " + path;
Consumer<String> doExpandSettingsTestFunction = this::doExpandSettingsTest;
doTestWithSettings(directText, doExpandSettingsTestFunction);
String invertedText = fileText
.replaceAll("~false~", "true").replaceAll("~true~", "false")
.replaceAll(SettingsConfigurator.SET_TRUE_DIRECTIVE, "~TEMP_TRUE_DIRECTIVE~")
.replaceAll(SettingsConfigurator.SET_FALSE_DIRECTIVE, SettingsConfigurator.SET_TRUE_DIRECTIVE)
.replaceAll("~TEMP_TRUE_DIRECTIVE~", SettingsConfigurator.SET_FALSE_DIRECTIVE);
invertedText += "\n\n// Generated from: " + path + " with !INVERTED! settings";
doTestWithSettings(invertedText, doExpandSettingsTestFunction);
}
protected static void doTestWithSettings(@NotNull String fileText, @NotNull Consumer<String> runnable) {
JavaCodeFoldingSettings settings = JavaCodeFoldingSettings.getInstance();
JavaCodeFoldingSettingsImpl restoreSettings = new JavaCodeFoldingSettingsImpl();
restoreSettings.loadState((JavaCodeFoldingSettingsImpl) settings);
try {
SettingsConfigurator configurator = new SettingsConfigurator(fileText, settings);
configurator.configureSettings();
runnable.accept(fileText);
}
finally {
((JavaCodeFoldingSettingsImpl) JavaCodeFoldingSettings.getInstance()).loadState(restoreSettings);
}
}
private void doExpandSettingsTest(String fileText) {
try {
VirtualFile tempFile = createTempFile("kt", null, fileText, Charset.defaultCharset());
assertFoldingRegionsForFile(tempFile.getPath());
}
catch (IOException e) {
throw new IllegalStateException(e);
}
}
// Rewritten version of CodeInsightTestFixtureImpl.testFoldingRegions(verificationFileName, true).
// Configure test with custom file name to force creating different editors for normal and inverted tests.
private void assertFoldingRegionsForFile(String verificationFileName) {
String START_FOLD = "<fold\\stext=\'[^\']*\'(\\sexpand=\'[^\']*\')*>";
String END_FOLD = "</fold>";
String expectedContent;
File file = new File(verificationFileName);
try {
expectedContent = FileUtil.loadFile(file);
}
catch (IOException e) {
throw new RuntimeException(e);
}
Assert.assertNotNull(expectedContent);
expectedContent = StringUtil.replace(expectedContent, "\r", "");
String cleanContent = expectedContent.replaceAll(START_FOLD, "").replaceAll(END_FOLD, "");
myFixture.configureByText(file.getName(), cleanContent);
String actual = ((CodeInsightTestFixtureImpl)myFixture).getFoldingDescription(true);
Assert.assertEquals(expectedContent, actual);
}
@NotNull
@Override
protected LightProjectDescriptor getProjectDescriptor() {
return KotlinLightProjectDescriptor.INSTANCE;
}
}
@@ -0,0 +1,205 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.refactoring.move
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
import com.intellij.testFramework.PsiTestUtil
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.MoveKotlinDeclarationsHandler
import org.jetbrains.kotlin.idea.refactoring.toPsiDirectory
import org.jetbrains.kotlin.idea.refactoring.toPsiFile
import org.jetbrains.kotlin.idea.test.KotlinMultiFileTestCase
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.idea.test.extractMultipleMarkerOffsets
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
class MoveKotlinDeclarationsHandlerTest : KotlinMultiFileTestCase() {
override fun getTestDataPath() = PluginTestCaseBase.getTestDataPathBase()
override fun getTestRoot() = "/refactoring/moveHandler/declarations"
private fun doTest(action: (rootDir: VirtualFile, handler: MoveKotlinDeclarationsHandler) -> Unit) {
val path = "$testDataPath$testRoot/${getTestName(true)}"
val rootDir = PsiTestUtil.createTestProjectStructure(myProject, myModule, path, myFilesToDelete, false)
prepareProject(rootDir)
PsiDocumentManager.getInstance(myProject).commitAllDocuments()
action(rootDir, MoveKotlinDeclarationsHandler())
}
private fun getPsiDirectory(rootDir: VirtualFile, path: String) = rootDir.findFileByRelativePath(path)!!.toPsiDirectory(project)!!
private fun getPsiFile(rootDir: VirtualFile, path: String) = rootDir.findFileByRelativePath(path)!!.toPsiFile(project)!!
private fun getElementAtCaret(rootDir: VirtualFile, path: String) = getElementsAtCarets(rootDir, path).single()
private fun getElementsAtCarets(rootDir: VirtualFile, path: String): List<PsiElement> {
val file = getPsiFile(rootDir, path)
val document = FileDocumentManager.getInstance().getDocument(file.virtualFile)!!
return document.extractMultipleMarkerOffsets(project).map { file.findElementAt(it)!! }
}
fun testObjectLiteral() = doTest { rootDir, handler ->
val objectDeclaration = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtObjectDeclaration>()!!
assert(!handler.canMove(arrayOf<PsiElement>(objectDeclaration), null))
}
fun testLocalClass() = doTest { rootDir, handler ->
val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!
assert(!handler.canMove(arrayOf<PsiElement>(klass), null))
}
fun testLocalFun() = doTest { rootDir, handler ->
val function = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtNamedFunction>()!!
assert(!handler.canMove(arrayOf<PsiElement>(function), null))
}
fun testLocalVal() = doTest { rootDir, handler ->
val property = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtProperty>()!!
assert(!handler.canMove(arrayOf<PsiElement>(property), null))
}
fun testMemberFun() = doTest { rootDir, handler ->
val function = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtNamedFunction>()!!
assert(!handler.canMove(arrayOf<PsiElement>(function), null))
}
fun testMemberVal() = doTest { rootDir, handler ->
val property = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtProperty>()!!
assert(!handler.canMove(arrayOf<PsiElement>(property), null))
}
fun testNestedClass() = doTest { rootDir, handler ->
val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!
assert(handler.canMove(arrayOf<PsiElement>(klass), null))
}
fun testInnerClass() = doTest { rootDir, handler ->
val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!
assert(handler.canMove(arrayOf<PsiElement>(klass), null))
}
fun testTopLevelClass() = doTest { rootDir, handler ->
val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!
assert(handler.canMove(arrayOf<PsiElement>(klass), null))
}
fun testTopLevelFun() = doTest { rootDir, handler ->
val function = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtNamedFunction>()!!
assert(handler.canMove(arrayOf<PsiElement>(function), null))
}
fun testTopLevelVal() = doTest { rootDir, handler ->
val property = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtProperty>()!!
assert(handler.canMove(arrayOf<PsiElement>(property), null))
}
fun testMultipleNestedClasses() = doTest { rootDir, handler ->
val classes = getElementsAtCarets(rootDir, "test.kt").map { it.getNonStrictParentOfType<KtClass>()!! }
assert(handler.canMove(classes.toTypedArray(), null))
}
fun testNestedAndTopLevelClass() = doTest { rootDir, handler ->
val classes = getElementsAtCarets(rootDir, "test.kt").map { it.getNonStrictParentOfType<KtClass>()!! }
assert(!handler.canMove(classes.toTypedArray(), null))
}
fun testMultipleTopLevelDeclarations() = doTest { rootDir, handler ->
val declarations = getElementsAtCarets(rootDir, "test.kt").map { it.getNonStrictParentOfType<KtNamedDeclaration>()!! }
assert(handler.canMove(declarations.toTypedArray(), null))
}
fun testMultipleTopLevelDeclarationsInDifferentFiles() = doTest { rootDir, handler ->
val declarations = listOf("test.kt", "test2.kt")
.flatMap { getElementsAtCarets(rootDir, it) }
.map { it.getNonStrictParentOfType<KtNamedDeclaration>()!! }
assert(handler.canMove(declarations.toTypedArray(), null))
val files = listOf("test.kt", "test2.kt").map { getPsiFile(rootDir, it) }
assert(handler.canMove(files.toTypedArray(), null))
}
fun testMultipleTopLevelDeclarationsInDifferentDirs() = doTest { rootDir, handler ->
val declarations = listOf("test1/test.kt", "test2/test2.kt")
.flatMap { getElementsAtCarets(rootDir, it) }
.map { it.getNonStrictParentOfType<KtNamedDeclaration>()!! }
assert(!handler.canMove(declarations.toTypedArray(), null))
val files = listOf("test1/test.kt", "test2/test2.kt").map { getPsiFile(rootDir, it) }
assert(!handler.canMove(files.toTypedArray(), null))
}
fun testFileAndTopLevelDeclarations() = doTest { rootDir, handler ->
val elements = getElementsAtCarets(rootDir, "test.kt").map { it.getNonStrictParentOfType<KtNamedDeclaration>()!! } +
getPsiFile(rootDir, "test2.kt")
assert(!handler.canMove(elements.toTypedArray(), null))
}
fun testCommonTargets() = doTest { rootDir, handler ->
val elementsToMove = arrayOf<PsiElement>(getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!)
val targetPackage = JavaPsiFacade.getInstance(project).findPackage("pack")!!
assert(handler.canMove(elementsToMove, targetPackage))
val targetDirectory = getPsiDirectory(rootDir, "pack")
assert(handler.canMove(elementsToMove, targetDirectory))
val targetFile = getPsiFile(rootDir, "pack/test2.kt")
assert(handler.canMove(elementsToMove, targetFile))
}
fun testTopLevelClassToClass() = doTest { rootDir, handler ->
val elementsToMove = arrayOf<PsiElement>(getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!)
val targetFile = getPsiFile(rootDir, "test2.kt") as KtFile
val topLevelTarget = targetFile.declarations.firstIsInstance<KtClass>()
assert(topLevelTarget.name == "B")
assert(!handler.canMove(elementsToMove, topLevelTarget))
val annotationTarget = targetFile.declarations.first { it.name == "Ann" } as KtClass
assert(!handler.canMove(elementsToMove, annotationTarget))
val nestedTarget = topLevelTarget.declarations.firstIsInstance<KtClass>()
assert(nestedTarget.name == "C")
assert(!handler.canMove(elementsToMove, nestedTarget))
}
fun testNestedClassToClass() = doTest { rootDir, handler ->
val elementsToMove = arrayOf<PsiElement>(getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!)
val targetFile = getPsiFile(rootDir, "test2.kt") as KtFile
val topLevelTarget = targetFile.declarations.firstIsInstance<KtClass>()
assert(topLevelTarget.name == "B")
assert(handler.canMove(elementsToMove, topLevelTarget))
val annotationTarget = targetFile.declarations.first { it.name == "Ann" } as KtClass
assert(!handler.canMove(elementsToMove, annotationTarget))
val nestedTarget = topLevelTarget.declarations.firstIsInstance<KtClass>()
assert(nestedTarget.name == "C")
assert(handler.canMove(elementsToMove, nestedTarget))
}
fun testTypeAlias() = doTest { rootDir, handler ->
val typeAlias = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtTypeAlias>()!!
assert(handler.canMove(arrayOf<PsiElement>(typeAlias), null))
}
}
@@ -0,0 +1,277 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.run
import com.intellij.execution.Location
import com.intellij.execution.PsiLocation
import com.intellij.execution.actions.ConfigurationContext
import com.intellij.openapi.module.Module
import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.roots.ModuleRootModificationUtil
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiComment
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiManager
import com.intellij.refactoring.RefactoringFactory
import com.intellij.testFramework.MapDataContext
import com.intellij.testFramework.PsiTestUtil
import org.jetbrains.kotlin.idea.MainFunctionDetector
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.search.allScope
import org.jetbrains.kotlin.idea.stubindex.KotlinFullClassNameIndex
import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelFunctionFqnNameIndex
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
import org.jetbrains.kotlin.idea.test.KotlinCodeInsightTestCase
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase.*
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.allChildren
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.junit.Assert
import java.io.File
import java.util.*
private val RUN_PREFIX = "// RUN:"
class RunConfigurationTest: KotlinCodeInsightTestCase() {
fun getTestProject() = myProject!!
override fun getModule() = myModule!!
fun testMainInTest() {
val createResult = configureModule(moduleDirPath("module"), getTestProject().baseDir!!)
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(createResult.module, addJdk(testRootDisposable, ::mockJdk))
val runConfiguration = createConfigurationFromMain("some.main")
val javaParameters = getJavaRunParameters(runConfiguration)
Assert.assertTrue(javaParameters.classPath.rootDirs.contains(createResult.srcOutputDir))
Assert.assertTrue(javaParameters.classPath.rootDirs.contains(createResult.testOutputDir))
fun functionVisitor(function: KtNamedFunction) {
val options = function.bodyExpression?.allChildren?.filterIsInstance<PsiComment>()?.map { it.text.trim().replace("//", "").trim() }?.filter { it.isNotBlank() }?.toList() ?: emptyList()
if (options.isNotEmpty()) {
val assertIsMain = "yes" in options
val assertIsNotMain = "no" in options
val bindingContext = function.analyze(BodyResolveMode.FULL)
val isMainFunction = MainFunctionDetector(bindingContext).isMain(function)
if (assertIsMain) {
Assert.assertTrue("The function ${function.fqName?.asString()} should be main", isMainFunction)
}
if (assertIsNotMain) {
Assert.assertFalse("The function ${function.fqName?.asString()} should NOT be main", isMainFunction)
}
if (isMainFunction) {
createConfigurationFromMain(function.fqName?.asString()!!).checkConfiguration()
Assert.assertNotNull("Kotlin configuration producer should produce configuration for ${function.fqName?.asString()}",
KotlinRunConfigurationProducer.getEntryPointContainer(function))
} else {
try {
createConfigurationFromMain(function.fqName?.asString()!!).checkConfiguration()
Assert.fail("configuration for function ${function.fqName?.asString()} at least shouldn't pass checkConfiguration()")
} catch (expected: Throwable) {
}
Assert.assertNull("Kotlin configuration producer shouldN'T produce configuration for ${function.fqName?.asString()}",
KotlinRunConfigurationProducer.getEntryPointContainer(function))
}
}
}
createResult.srcDir.children.filter { it.extension == "kt" }.forEach {
val psiFile = PsiManager.getInstance(createResult.module.project).findFile(it)
if (psiFile is KtFile) {
psiFile.acceptChildren(object : KtVisitorVoid() {
override fun visitNamedFunction(function: KtNamedFunction) {
functionVisitor(function)
}
})
}
}
}
fun testDependencyModuleClasspath() {
val dependencyModuleSrcDir = configureModule(moduleDirPath("module"), getTestProject().baseDir!!).srcOutputDir
val moduleWithDependencyDir = runWriteAction { getTestProject().baseDir!!.createChildDirectory(this, "moduleWithDependency") }
val moduleWithDependency = createModule("moduleWithDependency")
ModuleRootModificationUtil.setModuleSdk(moduleWithDependency, testProjectJdk)
val moduleWithDependencySrcDir = configureModule(
moduleDirPath("moduleWithDependency"), moduleWithDependencyDir, configModule = moduleWithDependency).srcOutputDir
ModuleRootModificationUtil.addDependency(moduleWithDependency, module)
val kotlinRunConfiguration = createConfigurationFromMain("some.test.main")
kotlinRunConfiguration.setModule(moduleWithDependency)
val javaParameters = getJavaRunParameters(kotlinRunConfiguration)
Assert.assertTrue(javaParameters.classPath.rootDirs.contains(dependencyModuleSrcDir))
Assert.assertTrue(javaParameters.classPath.rootDirs.contains(moduleWithDependencySrcDir))
}
fun testClassesAndObjects() {
doTest(ConfigLibraryUtil::configureKotlinRuntimeAndSdk)
}
fun testInJsModule() {
doTest(ConfigLibraryUtil::configureKotlinJsRuntimeAndSdk)
}
fun testUpdateOnClassRename() {
val createModuleResult = configureModule(moduleDirPath("module"), getTestProject().baseDir!!)
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(createModuleResult.module, addJdk(testRootDisposable, ::mockJdk))
val runConfiguration = createConfigurationFromObject("renameTest.Foo", save = true)
val obj = KotlinFullClassNameIndex.getInstance().get("renameTest.Foo", getTestProject(), getTestProject().allScope()).single()
val rename = RefactoringFactory.getInstance(getTestProject()).createRename(obj, "Bar")
rename.run()
Assert.assertEquals("renameTest.Bar", runConfiguration.MAIN_CLASS_NAME)
}
fun testUpdateOnPackageRename() {
val createModuleResult = configureModule(moduleDirPath("module"), getTestProject().baseDir!!)
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(createModuleResult.module, addJdk(testRootDisposable, ::mockJdk))
val runConfiguration = createConfigurationFromObject("renameTest.Foo", save = true)
val pkg = JavaPsiFacade.getInstance(getTestProject()).findPackage("renameTest")!!
val rename = RefactoringFactory.getInstance(getTestProject()).createRename(pkg, "afterRenameTest")
rename.run()
Assert.assertEquals("afterRenameTest.Foo", runConfiguration.MAIN_CLASS_NAME)
}
fun testWithModuleForJdk6() {
checkModuleInfoName(null, addJdk(testRootDisposable, ::mockJdk))
}
fun testWithModuleForJdk9() {
checkModuleInfoName("MAIN", addJdk(testRootDisposable, ::mockJdk9))
}
fun testWithModuleForJdk9WithoutModuleInfo() {
checkModuleInfoName(null, addJdk(testRootDisposable, ::mockJdk9))
}
private fun checkModuleInfoName(moduleName: String?, sdk: Sdk) {
val module = configureModule(moduleDirPath("module"), getTestProject().baseDir!!).module
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(module, sdk)
val javaParameters = getJavaRunParameters(createConfigurationFromMain("some.main"))
Assert.assertEquals(moduleName, javaParameters.moduleName)
}
private fun doTest(configureRuntime: (Module, Sdk) -> Unit) {
val baseDir = getTestProject().baseDir!!
val createModuleResult = configureModule(moduleDirPath("module"), baseDir)
val srcDir = createModuleResult.srcDir
configureRuntime(createModuleResult.module, addJdk(testRootDisposable, ::mockJdk))
try {
val expectedClasses = ArrayList<String>()
val actualClasses = ArrayList<String>()
val testFile = PsiManager.getInstance(getTestProject()).findFile(srcDir.findFileByRelativePath("test.kt")!!)!!
testFile.accept(
object : KtTreeVisitorVoid() {
override fun visitComment(comment: PsiComment) {
val declaration = comment.getStrictParentOfType<KtNamedDeclaration>()!!
val text = comment.text ?: return
if (!text.startsWith(RUN_PREFIX)) return
val expectedClass = text.substring(RUN_PREFIX.length).trim()
if (expectedClass.isNotEmpty()) expectedClasses.add(expectedClass)
val dataContext = MapDataContext()
dataContext.put(Location.DATA_KEY, PsiLocation(getTestProject(), declaration))
val context = ConfigurationContext.getFromContext(dataContext)
val actualClass = (context.configuration?.configuration as? KotlinRunConfiguration)?.runClass
if (actualClass != null) {
actualClasses.add(actualClass)
}
}
}
)
Assert.assertEquals(expectedClasses, actualClasses)
}
finally {
ConfigLibraryUtil.unConfigureKotlinRuntimeAndSdk(createModuleResult.module, mockJdk())
}
}
private fun createConfigurationFromMain(mainFqn: String): KotlinRunConfiguration {
val mainFunction = KotlinTopLevelFunctionFqnNameIndex.getInstance().get(mainFqn, getTestProject(), getTestProject().allScope()).first()
return createConfigurationFromElement(mainFunction) as KotlinRunConfiguration
}
private fun createConfigurationFromObject(objectFqn: String, save: Boolean = false): KotlinRunConfiguration {
val obj = KotlinFullClassNameIndex.getInstance().get(objectFqn, getTestProject(), getTestProject().allScope()).single()
val mainFunction = obj.declarations.single { it is KtFunction && it.getName() == "main" }
return createConfigurationFromElement(mainFunction, save) as KotlinRunConfiguration
}
private fun configureModule(moduleDir: String, outputParentDir: VirtualFile, configModule: Module = module): CreateModuleResult {
val srcPath = moduleDir + "/src"
val srcDir = PsiTestUtil.createTestProjectStructure(project, configModule, srcPath, myFilesToDelete, true)
val testPath = moduleDir + "/test"
if (File(testPath).exists()) {
val testDir = PsiTestUtil.createTestProjectStructure(project, configModule, testPath, myFilesToDelete, false)
PsiTestUtil.addSourceRoot(module, testDir, true)
}
val (srcOutDir, testOutDir) = runWriteAction {
val outDir = outputParentDir.createChildDirectory(this, "out")
val srcOutDir = outDir.createChildDirectory(this, "production")
val testOutDir = outDir.createChildDirectory(this, "test")
PsiTestUtil.setCompilerOutputPath(configModule, srcOutDir.url, false)
PsiTestUtil.setCompilerOutputPath(configModule, testOutDir.url, true)
Pair(srcOutDir, testOutDir)
}
PsiDocumentManager.getInstance(getTestProject()).commitAllDocuments()
return CreateModuleResult(configModule, srcDir, srcOutDir, testOutDir)
}
private fun moduleDirPath(moduleName: String) = "${testDataPath}${getTestName(false)}/$moduleName"
override fun getTestDataPath() = getTestDataPathBase() + "/run/"
override fun getTestProjectJdk() = mockJdk()
private class CreateModuleResult(
val module: Module,
val srcDir: VirtualFile,
val srcOutputDir: VirtualFile,
val testOutputDir: VirtualFile
)
}