203: Fix compilation

This commit is contained in:
Florian Kistner
2020-08-31 17:10:20 +02:00
parent 9d12df28c1
commit 9775a2148a
26 changed files with 2709 additions and 21 deletions
+1 -1
View File
@@ -357,7 +357,7 @@ fun Task.listConfigurationContents(configName: String) {
}
val defaultJvmTarget = "1.8"
val defaultJavaHome = jdkPath(defaultJvmTarget)
val defaultJavaHome = jdkPath(if (Platform[203].orHigher()) "11" else defaultJvmTarget)
val ignoreTestFailures by extra(project.kotlinBuildProperties.ignoreTestFailures)
allprojects {
@@ -2,7 +2,7 @@
* 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.
*/
@file:Suppress("JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE")
package org.jetbrains.kotlin.codegen.inline.coroutines
import com.intellij.util.ArrayUtil
@@ -2,14 +2,16 @@
* 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.
*/
@file:Suppress("JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE")
package org.jetbrains.kotlin.daemon.common.experimental.socketInfrastructure
import io.ktor.network.sockets.Socket
import kotlinx.coroutines.channels.*
import io.ktor.network.sockets.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import org.jetbrains.kotlin.daemon.common.LoopbackNetworkInterface
import org.jetbrains.kotlin.daemon.common.experimental.LoopbackNetworkInterfaceKtor
import org.jetbrains.kotlin.daemon.common.experimental.socketInfrastructure.Server.AnyMessage
import org.jetbrains.kotlin.daemon.common.experimental.socketInfrastructure.Server.ServerDownMessage
import sun.net.ConnectionResetException
import java.beans.Transient
import java.io.IOException
@@ -17,7 +19,6 @@ import java.io.ObjectInputStream
import java.io.ObjectOutputStream
import java.io.Serializable
import java.util.logging.Logger
import org.jetbrains.kotlin.daemon.common.experimental.socketInfrastructure.Server.*
interface Client<ServerType : ServerBase> : Serializable, AutoCloseable {
@@ -44,7 +44,6 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
import org.jetbrains.kotlin.resolve.jvm.isInlineClassThatRequiresMangling
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForParameterTypes
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
import javax.rmi.CORBA.ClassDesc
class LocalFunInlineChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
@@ -0,0 +1,28 @@
/*
* 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.psi.stubs.elements
import com.intellij.psi.PsiElement
import com.intellij.psi.stubs.StubElement
import com.intellij.psi.stubs.StubInputStream
import com.intellij.psi.stubs.StubOutputStream
import org.jetbrains.kotlin.psi.KtContractEffect
import org.jetbrains.kotlin.psi.stubs.KotlinContractEffectStub
import org.jetbrains.kotlin.psi.stubs.impl.KotlinContractEffectStubImpl
class KtContractEffectElementType(debugName: String, psiClass: Class<KtContractEffect>) :
KtStubElementType<KotlinContractEffectStub, KtContractEffect>(debugName, psiClass, KotlinContractEffectStub::class.java) {
override fun serialize(stub: KotlinContractEffectStub, dataStream: StubOutputStream) {
}
override fun deserialize(dataStream: StubInputStream, parentStub: StubElement<PsiElement>?): KotlinContractEffectStub {
return KotlinContractEffectStubImpl(parentStub, this)
}
override fun createStub(psi: KtContractEffect, parentStub: StubElement<*>?): KotlinContractEffectStub {
return KotlinContractEffectStubImpl(parentStub, this)
}
}
@@ -2,7 +2,7 @@
* 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.
*/
@file:Suppress("JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE")
package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.daemon.common.threadCpuTime
@@ -19,14 +19,13 @@ abstract public class KotlinCompletionTestCase extends CompletionTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
VfsRootAccess.allowRootAccess(KotlinTestUtils.getHomeDirectory());
VfsRootAccess.allowRootAccess(getTestRootDisposable(), KotlinTestUtils.getHomeDirectory());
CodeInsightSettings.getInstance().EXCLUDED_PACKAGES = new String[]{"excludedPackage", "somePackage.ExcludedClass"};
}
@Override
protected void tearDown() throws Exception {
CodeInsightSettings.getInstance().EXCLUDED_PACKAGES = ArrayUtil.EMPTY_STRING_ARRAY;
VfsRootAccess.disallowRootAccess(KotlinTestUtils.getHomeDirectory());
super.tearDown();
}
@@ -0,0 +1,82 @@
/*
* 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.scratch.ui
import com.intellij.core.JavaPsiBundle
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.DefaultActionGroup
import com.intellij.openapi.actionSystem.Presentation
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.module.ModuleType
import com.intellij.openapi.project.DumbAwareAction
import com.intellij.openapi.vcs.changes.committed.LabeledComboBoxAction
import com.intellij.util.ui.UIUtil
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.idea.KotlinJvmBundle
import org.jetbrains.kotlin.idea.caches.project.productionSourceInfo
import org.jetbrains.kotlin.idea.caches.project.testSourceInfo
import org.jetbrains.kotlin.idea.scratch.ScratchFile
import org.jetbrains.kotlin.idea.scratch.isKotlinWorksheet
import java.util.function.Supplier
import javax.swing.JComponent
class ModulesComboBoxAction(private val scratchFile: ScratchFile) :
LabeledComboBoxAction(KotlinJvmBundle.message("scratch.module.combobox"))
{
override fun createPopupActionGroup(button: JComponent): DefaultActionGroup {
val actionGroup = DefaultActionGroup()
actionGroup.add(ModuleIsNotSelectedAction(JavaPsiBundle.messagePointer("list.item.no.module")))
val modules = ModuleManager.getInstance(scratchFile.project).modules.filter {
it.productionSourceInfo() != null || it.testSourceInfo() != null
}
actionGroup.addAll(modules.map { SelectModuleAction(it) })
return actionGroup
}
/**
* By default this action uses big font for label, so we have to decrease it
* to make it look the same as in [CheckboxAction].
*/
override fun createCustomComponent(presentation: Presentation, place: String): JComponent {
val customComponent = super.createCustomComponent(presentation, place)
customComponent.components.forEach { it.font = UIUtil.getFont(UIUtil.FontSize.SMALL, it.font) }
return customComponent
}
override fun update(e: AnActionEvent) {
super.update(e)
val selectedModule = scratchFile.module?.takeIf { !it.isDisposed }
e.presentation.apply {
icon = selectedModule?.let { ModuleType.get(it).icon }
text = selectedModule?.name ?: JavaPsiBundle.message("list.item.no.module")
}
e.presentation.isVisible = isModuleSelectorVisible()
}
@TestOnly
fun isModuleSelectorVisible(): Boolean {
return !scratchFile.file.isKotlinWorksheet
}
private inner class ModuleIsNotSelectedAction(placeholder: Supplier<String>) : DumbAwareAction(placeholder) {
override fun actionPerformed(e: AnActionEvent) {
scratchFile.setModule(null)
}
}
private inner class SelectModuleAction(private val module: Module) :
DumbAwareAction(module.name, null, ModuleType.get(module).icon) {
override fun actionPerformed(e: AnActionEvent) {
scratchFile.setModule(module)
}
}
}
@@ -0,0 +1,584 @@
/*
* 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.maven;
import com.intellij.compiler.server.BuildManager;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.progress.EmptyProgressIndicator;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.TestDialog;
import com.intellij.openapi.util.AsyncResult;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.util.Consumer;
import com.intellij.util.PathUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.maven.execution.MavenExecutor;
import org.jetbrains.idea.maven.execution.MavenRunnerParameters;
import org.jetbrains.idea.maven.execution.MavenRunnerSettings;
import org.jetbrains.idea.maven.execution.SoutMavenConsole;
import org.jetbrains.idea.maven.model.MavenArtifact;
import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.project.*;
import org.jetbrains.jps.model.java.JavaResourceRootType;
import org.jetbrains.jps.model.java.JavaSourceRootProperties;
import org.jetbrains.jps.model.java.JavaSourceRootType;
import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
import org.jetbrains.kotlin.idea.test.KotlinSdkCreationChecker;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.WithMutedInDatabaseRunTest;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
@WithMutedInDatabaseRunTest
public abstract class MavenImportingTestCase extends MavenTestCase {
protected MavenProjectsTree myProjectsTree;
protected MavenProjectsManager myProjectsManager;
private File myGlobalSettingsFile;
protected KotlinSdkCreationChecker sdkCreationChecker;
@Override
protected void setUp() throws Exception {
VfsRootAccess.allowRootAccess(getTestRootDisposable(), PathManager.getConfigPath());
super.setUp();
myGlobalSettingsFile =
MavenWorkspaceSettingsComponent.getInstance(myProject).getSettings().generalSettings.getEffectiveGlobalSettingsIoFile();
if (myGlobalSettingsFile != null) {
VfsRootAccess.allowRootAccess(getTestRootDisposable(), myGlobalSettingsFile.getAbsolutePath());
}
sdkCreationChecker = new KotlinSdkCreationChecker();
}
@Override
protected void setUpInWriteAction() throws Exception {
super.setUpInWriteAction();
myProjectsManager = MavenProjectsManager.getInstance(myProject);
removeFromLocalRepository("test");
}
@Override
protected void tearDown() throws Exception {
try {
JavaAwareProjectJdkTableImpl.removeInternalJdkInTests();
Messages.setTestDialog(TestDialog.DEFAULT);
removeFromLocalRepository("test");
FileUtil.delete(BuildManager.getInstance().getBuildSystemDirectory().toFile());
sdkCreationChecker.removeNewKotlinSdk();
}
finally {
super.tearDown();
}
}
@Override
protected void runTest() throws Throwable {
KotlinTestUtils.runTestWithThrowable(this, () -> super.runTest());
}
protected void assertModules(String... expectedNames) {
Module[] actual = ModuleManager.getInstance(myProject).getModules();
List<String> actualNames = new ArrayList<String>();
for (Module m : actual) {
actualNames.add(m.getName());
}
assertUnorderedElementsAreEqual(actualNames, expectedNames);
}
protected void assertContentRoots(String moduleName, String... expectedRoots) {
List<String> actual = new ArrayList<String>();
for (ContentEntry e : getContentRoots(moduleName)) {
actual.add(e.getUrl());
}
for (int i = 0; i < expectedRoots.length; i++) {
expectedRoots[i] = VfsUtil.pathToUrl(expectedRoots[i]);
}
assertUnorderedPathsAreEqual(actual, Arrays.asList(expectedRoots));
}
protected void assertSources(String moduleName, String... expectedSources) {
assertContentFolders(moduleName, JavaSourceRootType.SOURCE, expectedSources);
}
protected void assertGeneratedSources(String moduleName, String... expectedSources) {
ContentEntry contentRoot = getContentRoot(moduleName);
List<ContentFolder> folders = new ArrayList<ContentFolder>();
for (SourceFolder folder : contentRoot.getSourceFolders(JavaSourceRootType.SOURCE)) {
JavaSourceRootProperties properties = folder.getJpsElement().getProperties(JavaSourceRootType.SOURCE);
assertNotNull(properties);
if (properties.isForGeneratedSources()) {
folders.add(folder);
}
}
doAssertContentFolders(contentRoot, folders, expectedSources);
}
protected void assertResources(String moduleName, String... expectedSources) {
assertContentFolders(moduleName, JavaResourceRootType.RESOURCE, expectedSources);
}
protected void assertTestSources(String moduleName, String... expectedSources) {
assertContentFolders(moduleName, JavaSourceRootType.TEST_SOURCE, expectedSources);
}
protected void assertTestResources(String moduleName, String... expectedSources) {
assertContentFolders(moduleName, JavaResourceRootType.TEST_RESOURCE, expectedSources);
}
protected void assertExcludes(String moduleName, String... expectedExcludes) {
ContentEntry contentRoot = getContentRoot(moduleName);
doAssertContentFolders(contentRoot, Arrays.asList(contentRoot.getExcludeFolders()), expectedExcludes);
}
protected void assertContentRootExcludes(String moduleName, String contentRoot, String... expectedExcudes) {
ContentEntry root = getContentRoot(moduleName, contentRoot);
doAssertContentFolders(root, Arrays.asList(root.getExcludeFolders()), expectedExcudes);
}
protected void assertContentFolders(String moduleName, @NotNull JpsModuleSourceRootType<?> rootType, String... expected) {
ContentEntry contentRoot = getContentRoot(moduleName);
doAssertContentFolders(contentRoot, contentRoot.getSourceFolders(rootType), expected);
}
private static void doAssertContentFolders(ContentEntry e, final List<? extends ContentFolder> folders, String... expected) {
List<String> actual = new ArrayList<String>();
for (ContentFolder f : folders) {
String rootUrl = e.getUrl();
String folderUrl = f.getUrl();
if (folderUrl.startsWith(rootUrl)) {
int length = rootUrl.length() + 1;
folderUrl = folderUrl.substring(Math.min(length, folderUrl.length()));
}
actual.add(folderUrl);
}
assertOrderedElementsAreEqual(actual, Arrays.asList(expected));
}
protected void assertModuleOutput(String moduleName, String output, String testOutput) {
CompilerModuleExtension e = getCompilerExtension(moduleName);
assertFalse(e.isCompilerOutputPathInherited());
assertEquals(output, getAbsolutePath(e.getCompilerOutputUrl()));
assertEquals(testOutput, getAbsolutePath(e.getCompilerOutputUrlForTests()));
}
private static String getAbsolutePath(String path) {
path = VfsUtil.urlToPath(path);
path = PathUtil.getCanonicalPath(path);
return FileUtil.toSystemIndependentName(path);
}
protected void assertProjectOutput(String module) {
assertTrue(getCompilerExtension(module).isCompilerOutputPathInherited());
}
protected CompilerModuleExtension getCompilerExtension(String module) {
ModuleRootManager m = getRootManager(module);
return CompilerModuleExtension.getInstance(m.getModule());
}
protected void assertModuleLibDep(String moduleName, String depName) {
assertModuleLibDep(moduleName, depName, null);
}
protected void assertModuleLibDep(String moduleName, String depName, String classesPath) {
assertModuleLibDep(moduleName, depName, classesPath, null, null);
}
protected void assertModuleLibDep(String moduleName, String depName, String classesPath, String sourcePath, String javadocPath) {
LibraryOrderEntry lib = getModuleLibDep(moduleName, depName);
assertModuleLibDepPath(lib, OrderRootType.CLASSES, classesPath == null ? null : Collections.singletonList(classesPath));
assertModuleLibDepPath(lib, OrderRootType.SOURCES, sourcePath == null ? null : Collections.singletonList(sourcePath));
assertModuleLibDepPath(lib, JavadocOrderRootType.getInstance(),
javadocPath == null ? null : Collections.singletonList(javadocPath));
}
protected void assertModuleLibDep(
String moduleName,
String depName,
List<String> classesPaths,
List<String> sourcePaths,
List<String> javadocPaths
) {
LibraryOrderEntry lib = getModuleLibDep(moduleName, depName);
assertModuleLibDepPath(lib, OrderRootType.CLASSES, classesPaths);
assertModuleLibDepPath(lib, OrderRootType.SOURCES, sourcePaths);
assertModuleLibDepPath(lib, JavadocOrderRootType.getInstance(), javadocPaths);
}
private static void assertModuleLibDepPath(LibraryOrderEntry lib, OrderRootType type, List<String> paths) {
if (paths == null) return;
assertUnorderedPathsAreEqual(Arrays.asList(lib.getRootUrls(type)), paths);
// also check the library because it may contain slight different set of urls (e.g. with duplicates)
assertUnorderedPathsAreEqual(Arrays.asList(lib.getLibrary().getUrls(type)), paths);
}
protected void assertModuleLibDepScope(String moduleName, String depName, DependencyScope scope) {
LibraryOrderEntry dep = getModuleLibDep(moduleName, depName);
assertEquals(scope, dep.getScope());
}
private LibraryOrderEntry getModuleLibDep(String moduleName, String depName) {
return getModuleDep(moduleName, depName, LibraryOrderEntry.class);
}
protected void assertModuleLibDeps(String moduleName, String... expectedDeps) {
assertModuleDeps(moduleName, LibraryOrderEntry.class, expectedDeps);
}
protected void assertExportedDeps(String moduleName, String... expectedDeps) {
final List<String> actual = new ArrayList<String>();
getRootManager(moduleName).orderEntries().withoutSdk().withoutModuleSourceEntries().exportedOnly()
.process(new RootPolicy<Object>() {
@Override
public Object visitModuleOrderEntry(ModuleOrderEntry e, Object value) {
actual.add(e.getModuleName());
return null;
}
@Override
public Object visitLibraryOrderEntry(LibraryOrderEntry e, Object value) {
actual.add(e.getLibraryName());
return null;
}
}, null);
assertOrderedElementsAreEqual(actual, expectedDeps);
}
protected void assertModuleModuleDeps(String moduleName, String... expectedDeps) {
assertModuleDeps(moduleName, ModuleOrderEntry.class, expectedDeps);
}
private void assertModuleDeps(String moduleName, Class clazz, String... expectedDeps) {
assertOrderedElementsAreEqual(collectModuleDepsNames(moduleName, clazz), expectedDeps);
}
protected void assertModuleModuleDepScope(String moduleName, String depName, DependencyScope scope) {
ModuleOrderEntry dep = getModuleModuleDep(moduleName, depName);
assertEquals(scope, dep.getScope());
}
private ModuleOrderEntry getModuleModuleDep(String moduleName, String depName) {
return getModuleDep(moduleName, depName, ModuleOrderEntry.class);
}
private List<String> collectModuleDepsNames(String moduleName, Class clazz) {
List<String> actual = new ArrayList<String>();
for (OrderEntry e : getRootManager(moduleName).getOrderEntries()) {
if (clazz.isInstance(e)) {
actual.add(e.getPresentableName());
}
}
return actual;
}
private <T> T getModuleDep(String moduleName, String depName, Class<T> clazz) {
T dep = null;
for (OrderEntry e : getRootManager(moduleName).getOrderEntries()) {
if (clazz.isInstance(e) && e.getPresentableName().equals(depName)) {
dep = (T) e;
}
}
assertNotNull("Dependency not found: " + depName
+ "\namong: " + collectModuleDepsNames(moduleName, clazz),
dep);
return dep;
}
public void assertProjectLibraries(String... expectedNames) {
List<String> actualNames = new ArrayList<String>();
for (Library each : ProjectLibraryTable.getInstance(myProject).getLibraries()) {
String name = each.getName();
actualNames.add(name == null ? "<unnamed>" : name);
}
assertUnorderedElementsAreEqual(actualNames, expectedNames);
}
protected void assertModuleGroupPath(String moduleName, String... expected) {
String[] path = ModuleManager.getInstance(myProject).getModuleGroupPath(getModule(moduleName));
if (expected.length == 0) {
assertNull(path);
}
else {
assertNotNull(path);
assertOrderedElementsAreEqual(Arrays.asList(path), expected);
}
}
protected Module getModule(final String name) {
AccessToken accessToken = ApplicationManager.getApplication().acquireReadActionLock();
try {
Module m = ModuleManager.getInstance(myProject).findModuleByName(name);
assertNotNull("Module " + name + " not found", m);
return m;
}
finally {
accessToken.finish();
}
}
private ContentEntry getContentRoot(String moduleName) {
ContentEntry[] ee = getContentRoots(moduleName);
List<String> roots = new ArrayList<String>();
for (ContentEntry e : ee) {
roots.add(e.getUrl());
}
String message = "Several content roots found: [" + StringUtil.join(roots, ", ") + "]";
assertEquals(message, 1, ee.length);
return ee[0];
}
private ContentEntry getContentRoot(String moduleName, String path) {
for (ContentEntry e : getContentRoots(moduleName)) {
if (e.getUrl().equals(VfsUtil.pathToUrl(path))) return e;
}
throw new AssertionError("content root not found");
}
public ContentEntry[] getContentRoots(String moduleName) {
return getRootManager(moduleName).getContentEntries();
}
private ModuleRootManager getRootManager(String module) {
return ModuleRootManager.getInstance(getModule(module));
}
protected void importProject(@NonNls String xml) throws IOException {
createProjectPom(xml);
importProject();
}
protected void importProject() {
importProjectWithProfiles();
}
protected void importProjectWithProfiles(String... profiles) {
doImportProjects(Collections.singletonList(myProjectPom), profiles);
}
protected void importProjects(VirtualFile... files) {
doImportProjects(Arrays.asList(files));
}
private void doImportProjects(List<VirtualFile> files, String... profiles) {
initProjectsManager(false);
readProjects(files, profiles);
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
myProjectsManager.waitForResolvingCompletion();
myProjectsManager.scheduleImportInTests(files);
myProjectsManager.importProjects();
}
});
for (MavenProject each : myProjectsTree.getProjects()) {
if (each.hasReadingProblems()) {
System.out.println(each + " has problems: " + each.getProblems());
}
}
}
protected void readProjects(List<VirtualFile> files, String... profiles) {
myProjectsManager.resetManagedFilesAndProfilesInTests(files, new MavenExplicitProfiles(Arrays.asList(profiles)));
waitForReadingCompletion();
}
protected void updateProjectsAndImport(VirtualFile... files) {
readProjects(files);
myProjectsManager.performScheduledImportInTests();
}
protected void initProjectsManager(boolean enableEventHandling) {
myProjectsManager.initForTests();
myProjectsTree = myProjectsManager.getProjectsTreeForTests();
if (enableEventHandling) myProjectsManager.listenForExternalChanges();
}
protected void scheduleResolveAll() {
myProjectsManager.scheduleResolveAllInTests();
}
protected void waitForReadingCompletion() {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
try {
myProjectsManager.waitForReadingCompletion();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}
protected void readProjects() {
readProjects(myProjectsManager.getProjectsFiles());
}
protected void readProjects(VirtualFile... files) {
List<MavenProject> projects = new ArrayList<MavenProject>();
for (VirtualFile each : files) {
projects.add(myProjectsManager.findProject(each));
}
myProjectsManager.forceUpdateProjects(projects);
waitForReadingCompletion();
}
protected void resolveDependenciesAndImport() {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
myProjectsManager.waitForResolvingCompletion();
myProjectsManager.performScheduledImportInTests();
}
});
}
protected void resolveFoldersAndImport() {
myProjectsManager.scheduleFoldersResolveForAllProjects();
myProjectsManager.waitForFoldersResolvingCompletion();
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
myProjectsManager.performScheduledImportInTests();
}
});
}
protected void resolvePlugins() {
myProjectsManager.waitForPluginsResolvingCompletion();
}
protected void downloadArtifacts() {
downloadArtifacts(myProjectsManager.getProjects(), null);
}
protected MavenArtifactDownloader.DownloadResult downloadArtifacts(
Collection<MavenProject> projects,
List<MavenArtifact> artifacts
) {
final MavenArtifactDownloader.DownloadResult[] unresolved = new MavenArtifactDownloader.DownloadResult[1];
AsyncResult<MavenArtifactDownloader.DownloadResult> result = new AsyncResult<MavenArtifactDownloader.DownloadResult>();
result.doWhenDone(new Consumer<MavenArtifactDownloader.DownloadResult>() {
@Override
public void consume(MavenArtifactDownloader.DownloadResult unresolvedArtifacts) {
unresolved[0] = unresolvedArtifacts;
}
});
myProjectsManager.scheduleArtifactsDownloading(projects, artifacts, true, true, result);
myProjectsManager.waitForArtifactsDownloadingCompletion();
return unresolved[0];
}
protected void performPostImportTasks() {
myProjectsManager.waitForPostImportTasksCompletion();
}
protected void executeGoal(String relativePath, String goal) {
VirtualFile dir = myProjectRoot.findFileByRelativePath(relativePath);
MavenRunnerParameters rp = new MavenRunnerParameters(true, dir.getPath(), Arrays.asList(goal), Collections.<String>emptyList());
MavenRunnerSettings rs = new MavenRunnerSettings();
MavenExecutor e = new MavenExternalExecutor(myProject, rp, getMavenGeneralSettings(), rs, new SoutMavenConsole());
e.execute(new EmptyProgressIndicator());
}
protected void removeFromLocalRepository(String relativePath) throws IOException {
FileUtil.delete(new File(getRepositoryPath(), relativePath));
}
protected void setupJdkForModules(String... moduleNames) {
for (String each : moduleNames) {
setupJdkForModule(each);
}
}
protected Sdk setupJdkForModule(final String moduleName) {
final Sdk sdk = JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk();
ModuleRootModificationUtil.setModuleSdk(getModule(moduleName), sdk);
return sdk;
}
protected static Sdk createJdk(String versionName) {
return IdeaTestUtil.getMockJdk17(versionName);
}
protected static AtomicInteger configConfirmationForYesAnswer() {
final AtomicInteger counter = new AtomicInteger();
Messages.setTestDialog(new TestDialog() {
@Override
public int show(String message) {
counter.set(counter.get() + 1);
return 0;
}
});
return counter;
}
protected static AtomicInteger configConfirmationForNoAnswer() {
final AtomicInteger counter = new AtomicInteger();
Messages.setTestDialog(new TestDialog() {
@Override
public int show(String message) {
counter.set(counter.get() + 1);
return 1;
}
});
return counter;
}
}
@@ -20,16 +20,10 @@ import org.jetbrains.kotlin.test.WithMutedInDatabaseRunTest;
public abstract class KotlinCodeInsightTestCase extends CodeInsightTestCase {
@Override
protected void setUp() throws Exception {
VfsRootAccess.allowRootAccess(KotlinTestUtils.getHomeDirectory());
VfsRootAccess.allowRootAccess(getTestRootDisposable(), KotlinTestUtils.getHomeDirectory());
super.setUp();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
VfsRootAccess.disallowRootAccess(KotlinTestUtils.getHomeDirectory());
}
@Override
protected void runTestRunnable(@NotNull ThrowableRunnable<Throwable> testRunnable) throws Throwable {
KotlinTestUtils.runTestWithThrowable(this, () -> super.runTestRunnable(testRunnable));
@@ -0,0 +1,44 @@
/*
* 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.vfs.newvfs.impl.VfsRootAccess
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase
import com.intellij.util.ThrowableRunnable
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.TestMetadata
import java.io.File
import kotlin.reflect.full.findAnnotation
abstract class KotlinLightPlatformCodeInsightFixtureTestCase : LightPlatformCodeInsightFixtureTestCase() {
protected open fun isFirPlugin(): Boolean = false
override fun setUp() {
super.setUp()
enableKotlinOfficialCodeStyle(project)
runPostStartupActivitiesOnce(project)
VfsRootAccess.allowRootAccess(testRootDisposable, KotlinTestUtils.getHomeDirectory())
if (!isFirPlugin()) {
invalidateLibraryCache(project)
}
}
override fun tearDown() = runAll(
ThrowableRunnable { disableKotlinOfficialCodeStyle(project) },
ThrowableRunnable { super.tearDown() },
)
protected fun testDataFile(fileName: String): File = File(testDataPath, fileName)
protected fun testDataFile(): File = testDataFile(fileName())
protected fun testPath(fileName: String = fileName()): String = testDataFile(fileName).toString()
protected fun testPath(): String = testPath(fileName())
protected open fun fileName(): String = KotlinTestUtils.getTestDataFileName(this::class.java, this.name) ?: (getTestName(false) + ".kt")
override fun getTestDataPath(): String = this::class.findAnnotation<TestMetadata>()?.value ?: super.getTestDataPath()
}
@@ -0,0 +1,76 @@
/*
* 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.test
import com.intellij.ide.highlighter.ModuleFileType
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileVisitor
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess
import com.intellij.psi.PsiDocumentManager
import com.intellij.refactoring.MultiFileTestCase
import com.intellij.testFramework.PsiTestUtil
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.test.KotlinTestUtils
abstract class KotlinMultiFileTestCase : MultiFileTestCase() {
protected var isMultiModule = false
override fun setUp() {
super.setUp()
VfsRootAccess.allowRootAccess(testRootDisposable, KotlinTestUtils.getHomeDirectory())
runWriteAction {
PluginTestCaseBase.addJdk(testRootDisposable, PluginTestCaseBase::mockJdk6)
ProjectRootManager.getInstance(project).projectSdk = PluginTestCaseBase.mockJdk6()
}
}
protected fun getTestDirName(lowercaseFirstLetter: Boolean): String {
val testName = getTestName(lowercaseFirstLetter)
val endIndex = testName.lastIndexOf('_')
if (endIndex < 0) return testName
return testName.substring(0, endIndex).replace('_', '/')
}
protected fun doTestCommittingDocuments(action: (VirtualFile, VirtualFile?) -> Unit) {
super.doTest(
{ rootDir, rootAfter ->
action(rootDir, rootAfter)
PsiDocumentManager.getInstance(project!!).commitAllDocuments()
FileDocumentManager.getInstance().saveAllDocuments()
}, getTestDirName(true)
)
}
override fun prepareProject(rootDir: VirtualFile) {
if (isMultiModule) {
val model = ModuleManager.getInstance(project).modifiableModel
VfsUtilCore.visitChildrenRecursively(
rootDir,
object : VirtualFileVisitor<Any>() {
override fun visitFile(file: VirtualFile): Boolean {
if (!file.isDirectory && file.name.endsWith(ModuleFileType.DOT_DEFAULT_EXTENSION)) {
model.loadModule(file.path)
return false
}
return true
}
}
)
runWriteAction { model.commit() }
} else {
PsiTestUtil.addSourceContentToRoots(myModule, rootDir)
}
}
}
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@file:Suppress("JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE")
package org.jetbrains.kotlin.idea.debugger.evaluate.classLoading
import com.sun.jdi.ArrayReference
@@ -0,0 +1,376 @@
/*
* 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.scratch
import com.intellij.ide.scratch.ScratchFileService
import com.intellij.ide.scratch.ScratchRootType
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.module.Module
import com.intellij.openapi.roots.CompilerModuleExtension
import com.intellij.openapi.roots.ModuleRootModificationUtil
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess
import com.intellij.testFramework.FileEditorManagerTestCase
import com.intellij.testFramework.MapDataContext
import com.intellij.testFramework.PsiTestUtil
import com.intellij.testFramework.TestActionEvent
import com.intellij.util.ui.UIUtil
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.idea.actions.KOTLIN_WORKSHEET_EXTENSION
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager
import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingUtil
import org.jetbrains.kotlin.idea.scratch.actions.ClearScratchAction
import org.jetbrains.kotlin.idea.scratch.actions.RunScratchAction
import org.jetbrains.kotlin.idea.scratch.actions.ScratchCompilationSupport
import org.jetbrains.kotlin.idea.scratch.output.InlayScratchFileRenderer
import org.jetbrains.kotlin.idea.scratch.ui.KtScratchFileEditorWithPreview
import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.parsing.KotlinParserDefinition.Companion.STD_SCRIPT_SUFFIX
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.MockLibraryUtil
import org.jetbrains.kotlin.utils.PathUtil
import org.junit.Assert
import java.io.File
abstract class AbstractScratchRunActionTest : FileEditorManagerTestCase() {
fun doRightPreviewPanelOutputTest(fileName: String) {
doRightPreviewPanelOutputTest(fileName = fileName, isRepl = false)
}
fun doWorksheetReplTest(fileName: String) {
doInlayOutputTest(fileName = fileName, isRepl = true, isWorksheet = true)
}
fun doScratchReplTest(fileName: String) {
doInlayOutputTest(fileName = fileName, isRepl = true, isWorksheet = false)
}
fun doWorksheetCompilingTest(fileName: String) {
doInlayOutputTest(fileName = fileName, isRepl = false, isWorksheet = true)
}
fun doScratchCompilingTest(fileName: String) {
doInlayOutputTest(fileName = fileName, isRepl = false, isWorksheet = false)
}
fun doWorksheetMultiFileTest(dirName: String) {
doMultiFileTest(dirName, isWorksheet = true)
}
fun doScratchMultiFileTest(dirName: String) {
doMultiFileTest(dirName, isWorksheet = false)
}
private fun doMultiFileTest(dirName: String, isWorksheet: Boolean) {
val mainFileExtension = if (isWorksheet) KOTLIN_WORKSHEET_EXTENSION else STD_SCRIPT_SUFFIX
val javaFiles = arrayListOf<File>()
val kotlinFiles = arrayListOf<File>()
val baseDir = File(testDataPath, dirName)
baseDir.walk().forEach {
if (it.isFile) {
if (it.extension == "java") javaFiles.add(it)
if (it.extension == "kt") kotlinFiles.add(it)
}
}
val testDataPathFile = File(myFixture.testDataPath)
javaFiles.forEach {
myFixture.copyFileToProject(
FileUtil.getRelativePath(testDataPathFile, it)!!,
FileUtil.getRelativePath(baseDir, it)!!
)
}
kotlinFiles.forEach {
myFixture.copyFileToProject(
FileUtil.getRelativePath(testDataPathFile, it)!!,
FileUtil.getRelativePath(baseDir, it)!!
)
}
val outputDir = FileUtil.createTempDirectory(dirName, "")
if (javaFiles.isNotEmpty()) {
val options = listOf("-d", outputDir.path)
KotlinTestUtils.compileJavaFiles(javaFiles, options)
}
MockLibraryUtil.compileKotlin(baseDir.path, outputDir)
PsiTestUtil.setCompilerOutputPath(myFixture.module, outputDir.path, false)
val mainFileName = "$dirName/${getTestName(true)}.$mainFileExtension"
doInlayOutputTest(mainFileName, isRepl = false, isWorksheet = isWorksheet)
launchAction(ClearScratchAction())
doInlayOutputTest(mainFileName, isRepl = true, isWorksheet = isWorksheet)
ModuleRootModificationUtil.updateModel(myFixture.module) { model ->
model.getModuleExtension(CompilerModuleExtension::class.java).inheritCompilerOutputPath(true)
}
}
private fun doInlayOutputTest(fileName: String, isRepl: Boolean, isWorksheet: Boolean) {
configureAndLaunchScratch(fileName = fileName, isRepl = isRepl, isWorksheet = isWorksheet)
val actualOutput = getFileTextWithInlays()
val expectedFile = getExpectedFile(fileName, isRepl, suffix = "after")
KotlinTestUtils.assertEqualsToFile(expectedFile, actualOutput)
}
private fun doRightPreviewPanelOutputTest(fileName: String, isRepl: Boolean) {
configureAndLaunchScratch(fileName = fileName, isRepl = isRepl, isWorksheet = false)
val previewTextWithFoldings = getPreviewTextWithFoldings()
val expectedFile = getExpectedFile(fileName, isRepl, suffix = "preview")
KotlinTestUtils.assertEqualsToFile(expectedFile, previewTextWithFoldings)
}
private fun configureAndLaunchScratch(fileName: String, isRepl: Boolean, isWorksheet: Boolean) {
val sourceFile = File(testDataPath, fileName)
val fileText = sourceFile.readText().inlinePropertiesValues(isRepl)
if (isWorksheet) {
configureWorksheetByText(sourceFile.name, fileText)
} else {
configureScratchByText(sourceFile.name, fileText)
}
if (!KotlinHighlightingUtil.shouldHighlight(myFixture.file)) error("Highlighting for scratch file is switched off")
launchScratch()
waitUntilScratchFinishes(isRepl)
}
private fun getExpectedFile(fileName: String, isRepl: Boolean, suffix: String): File {
val expectedFileName = if (isRepl) {
fileName.replace(".kts", ".repl.$suffix")
} else {
fileName.replace(".kts", ".comp.$suffix")
}
return File(testDataPath, expectedFileName)
}
protected fun String.inlinePropertiesValues(
isRepl: Boolean = false,
isInteractiveMode: Boolean = false
): String {
return replace("~REPL_MODE~", isRepl.toString()).replace("~INTERACTIVE_MODE~", isInteractiveMode.toString())
}
protected fun getFileTextWithInlays(): String {
val doc = myFixture.getDocument(myFixture.file) ?: error("Document for ${myFixture.file.name} is null")
val actualOutput = StringBuilder(myFixture.file.text)
for (line in doc.lineCount - 1 downTo 0) {
getInlays(doc.getLineStartOffset(line), doc.getLineEndOffset(line))
.forEach { inlay ->
val str = inlay.toString()
val offset = doc.getLineEndOffset(line)
actualOutput.insert(
offset,
"${str.takeWhile { it.isWhitespace() }}// ${str.trim()}"
)
}
}
return actualOutput.toString().trim()
}
private fun getPreviewTextWithFoldings(): String {
val scratchFileEditor = getScratchEditorForSelectedFile(myManager, myFixture.file.virtualFile)
?: error("Couldn't find scratch panel")
val previewEditor = scratchFileEditor.getPreviewEditor()
return getFoldingData(previewEditor.editor, withCollapseStatus = false)
}
protected fun getInlays(start: Int = 0, end: Int = myFixture.file.textLength): List<InlayScratchFileRenderer> {
val inlineElementsInRange = myFixture.editor.inlayModel
.getAfterLineEndElementsInRange(start, end)
.filter { it.renderer is InlayScratchFileRenderer }
return inlineElementsInRange.map { it.renderer as InlayScratchFileRenderer }
}
protected fun configureScratchByText(name: String, text: String): ScratchFile {
val scratchVirtualFile = ScratchRootType.getInstance().createScratchFile(
project,
name,
KotlinLanguage.INSTANCE,
text,
ScratchFileService.Option.create_if_missing
) ?: error("Couldn't create scratch file")
myFixture.openFileInEditor(scratchVirtualFile)
ScriptConfigurationManager.updateScriptDependenciesSynchronously(myFixture.file)
val scratchFileEditor = getScratchEditorForSelectedFile(myManager, myFixture.file.virtualFile)
?: error("Couldn't find scratch file")
configureOptions(scratchFileEditor, text, myFixture.module)
return scratchFileEditor.scratchFile
}
protected fun configureWorksheetByText(name: String, text: String): ScratchFile {
val worksheetFile = myFixture.configureByText(name, text).virtualFile
ScriptConfigurationManager.updateScriptDependenciesSynchronously(myFixture.file)
val scratchFileEditor = getScratchEditorForSelectedFile(myManager, myFixture.file.virtualFile)
?: error("Couldn't find scratch panel")
// We want to check that correct module is selected automatically,
// that's why we set `module` to null so it wouldn't be changed
configureOptions(scratchFileEditor, text, null)
return scratchFileEditor.scratchFile
}
protected fun launchScratch() {
val action = RunScratchAction()
launchAction(action)
}
protected fun launchAction(action: AnAction) {
val e = getActionEvent(myFixture.file.virtualFile, action)
action.beforeActionPerformedUpdate(e)
Assert.assertTrue(e.presentation.isEnabled && e.presentation.isVisible)
action.actionPerformed(e)
}
protected fun waitUntilScratchFinishes(shouldStopRepl: Boolean = true) {
UIUtil.dispatchAllInvocationEvents()
val start = System.currentTimeMillis()
// wait until output is displayed in editor or for 1 minute
while (ScratchCompilationSupport.isAnyInProgress()) {
if ((System.currentTimeMillis() - start) > TIME_OUT) {
LOG.warn("Waiting timeout $TIME_OUT ms is exceed")
break
}
Thread.sleep(100)
}
if (shouldStopRepl) stopReplProcess()
UIUtil.dispatchAllInvocationEvents()
}
protected fun stopReplProcess() {
if (myFixture.file != null) {
val scratchFile = getScratchEditorForSelectedFile(myManager, myFixture.file.virtualFile)?.scratchFile
?: error("Couldn't find scratch panel")
scratchFile.replScratchExecutor?.stopAndWait()
}
UIUtil.dispatchAllInvocationEvents()
}
private fun getActionEvent(virtualFile: VirtualFile, action: AnAction): TestActionEvent {
val context = MapDataContext()
context.put(CommonDataKeys.VIRTUAL_FILE_ARRAY, arrayOf(virtualFile))
context.put(CommonDataKeys.PROJECT, project)
context.put(CommonDataKeys.EDITOR, myFixture.editor)
return TestActionEvent(context, action)
}
protected fun testScratchText(): String {
return File(testDataPath, "idea/scripting-support/testData/scratch/custom/test_scratch.kts").readText()
}
override fun getTestDataPath() = KotlinTestUtils.getHomeDirectory()
override fun getProjectDescriptor(): com.intellij.testFramework.LightProjectDescriptor {
val testName = getTestName(false)
return when {
testName.endsWith("WithKotlinTest") -> INSTANCE_WITH_KOTLIN_TEST
testName.endsWith("NoRuntime") -> INSTANCE_WITHOUT_RUNTIME
testName.endsWith("ScriptRuntime") -> INSTANCE_WITH_SCRIPT_RUNTIME
else -> KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE_FULL_JDK
}
}
override fun setUp() {
super.setUp()
VfsRootAccess.allowRootAccess(getTestRootDisposable(), KotlinTestUtils.getHomeDirectory())
PluginTestCaseBase.addJdk(myFixture.projectDisposable) { PluginTestCaseBase.fullJdk() }
}
override fun tearDown() {
super.tearDown()
ScratchFileService.getInstance().scratchesMapping.mappings.forEach { file, _ ->
runWriteAction { file.delete(this) }
}
}
companion object {
private const val TIME_OUT = 60000 // 1 min
private val INSTANCE_WITH_KOTLIN_TEST = object : KotlinWithJdkAndRuntimeLightProjectDescriptor(
arrayListOf(
ForTestCompileRuntime.runtimeJarForTests(),
PathUtil.kotlinPathsForDistDirectory.kotlinTestPath
)
) {
override fun getSdk() = PluginTestCaseBase.fullJdk()
}
private val INSTANCE_WITHOUT_RUNTIME = object : KotlinLightProjectDescriptor() {
override fun getSdk() = PluginTestCaseBase.fullJdk()
}
private val INSTANCE_WITH_SCRIPT_RUNTIME = object : KotlinWithJdkAndRuntimeLightProjectDescriptor(
arrayListOf(
ForTestCompileRuntime.runtimeJarForTests(),
ForTestCompileRuntime.scriptRuntimeJarForTests()
)
) {
override fun getSdk() = PluginTestCaseBase.fullJdk()
}
fun configureOptions(
scratchFileEditor: KtScratchFileEditorWithPreview,
fileText: String,
module: Module?
) {
val scratchFile = scratchFileEditor.scratchFile
if (InTextDirectivesUtils.getPrefixedBoolean(fileText, "// INTERACTIVE_MODE: ") != true) {
scratchFile.saveOptions { copy(isInteractiveMode = false) }
}
if (InTextDirectivesUtils.getPrefixedBoolean(fileText, "// REPL_MODE: ") == true) {
scratchFile.saveOptions { copy(isRepl = true) }
}
if (module != null && !InTextDirectivesUtils.isDirectiveDefined(fileText, "// NO_MODULE")) {
scratchFile.setModule(module)
}
val isPreviewEnabled = InTextDirectivesUtils.getPrefixedBoolean(fileText, "// PREVIEW_ENABLED: ") == true
scratchFileEditor.setPreviewEnabled(isPreviewEnabled)
}
}
}
@@ -0,0 +1,39 @@
/*
* 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
import com.intellij.codeInsight.javadoc.JavaDocExternalFilter
import com.intellij.psi.PsiDocCommentBase
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtFile
import java.util.function.Consumer
// FIX ME WHEN BUNCH 201 REMOVED
class KotlinDocumentationProvider : KotlinDocumentationProviderCompatBase() {
override fun collectDocComments(file: PsiFile, sink: Consumer<in PsiDocCommentBase>) {
if (file !is KtFile) return
PsiTreeUtil.processElements(file) {
val comment = (it as? KtDeclaration)?.docComment
if (comment != null) sink.accept(comment)
true
}
}
override fun generateRenderedDoc(element: PsiElement): String? {
val docComment = (element as? KtDeclaration)?.docComment ?: return null
val result = StringBuilder().also {
it.renderKDoc(docComment.getDefaultSection(), docComment.getAllSections())
}
return JavaDocExternalFilter.filterInternalDocInfo(result.toString())
}
}
@@ -0,0 +1,90 @@
/*
* Copyright 2000-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.framework
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.projectRoots.*
import com.intellij.openapi.projectRoots.impl.ProjectJdkImpl
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil
import com.intellij.util.Consumer
import org.jdom.Element
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.KotlinIcons
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion
import org.jetbrains.kotlin.utils.PathUtil
import javax.swing.JComponent
class KotlinSdkType : SdkType("KotlinSDK") {
companion object {
@JvmField
val INSTANCE = KotlinSdkType()
val defaultHomePath: String
get() = PathUtil.kotlinPathsForIdeaPlugin.homePath.absolutePath
@JvmOverloads
fun setUpIfNeeded(disposable: Disposable? = null, checkIfNeeded: () -> Boolean = { true }) {
val projectSdks: Array<Sdk> = ProjectJdkTable.getInstance().allJdks
if (projectSdks.any { it.sdkType is KotlinSdkType }) return
if (!checkIfNeeded()) return // do not create Kotlin SDK
val newSdkName = SdkConfigurationUtil.createUniqueSdkName(INSTANCE, defaultHomePath, projectSdks.toList())
val newJdk = ProjectJdkImpl(newSdkName, INSTANCE)
newJdk.homePath = defaultHomePath
INSTANCE.setupSdkPaths(newJdk)
ApplicationManager.getApplication().invokeAndWait {
runWriteAction {
if (ProjectJdkTable.getInstance().allJdks.any { it.sdkType is KotlinSdkType }) return@runWriteAction
if (disposable != null) {
ProjectJdkTable.getInstance().addJdk(newJdk, disposable)
} else {
ProjectJdkTable.getInstance().addJdk(newJdk)
}
}
}
}
}
override fun getPresentableName() = KotlinBundle.message("framework.name.kotlin.sdk")
override fun getIcon() = KotlinIcons.SMALL_LOGO
override fun isValidSdkHome(path: String?) = true
override fun suggestSdkName(currentSdkName: String?, sdkHome: String?) = "Kotlin SDK"
override fun suggestHomePath() = null
override fun sdkHasValidPath(sdk: Sdk) = true
override fun getVersionString(sdk: Sdk) = bundledRuntimeVersion()
override fun supportsCustomCreateUI() = true
override fun showCustomCreateUI(sdkModel: SdkModel, parentComponent: JComponent, selectedSdk: Sdk?, sdkCreatedCallback: Consumer<in Sdk>) {
sdkCreatedCallback.consume(createSdkWithUniqueName(sdkModel.sdks.toList()))
}
fun createSdkWithUniqueName(existingSdks: Collection<Sdk>): ProjectJdkImpl {
val sdkName = suggestSdkName(SdkConfigurationUtil.createUniqueSdkName(this, "", existingSdks), "")
return ProjectJdkImpl(sdkName, this).apply {
homePath = defaultHomePath
}
}
override fun createAdditionalDataConfigurable(sdkModel: SdkModel, sdkModificator: SdkModificator) = null
override fun saveAdditionalData(additionalData: SdkAdditionalData, additional: Element) {
}
override fun allowCreationByUser(): Boolean {
return false
}
}
@@ -0,0 +1,33 @@
/*
* 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.reporter
import com.intellij.diagnostic.ITNReporter
import com.intellij.openapi.diagnostic.IdeaLoggingEvent
import com.intellij.openapi.diagnostic.SubmittedReportInfo
import com.intellij.util.Consumer
import java.awt.Component
abstract class ITNReporterCompat : ITNReporter() {
final override fun submit(
events: Array<IdeaLoggingEvent>,
additionalInfo: String?,
parentComponent: Component,
consumer: Consumer<in SubmittedReportInfo>
): Boolean {
return submitCompat(events, additionalInfo, parentComponent, consumer)
}
open fun submitCompat(
events: Array<IdeaLoggingEvent>,
additionalInfo: String?,
parentComponent: Component?,
consumer: Consumer<in SubmittedReportInfo>
): Boolean {
@Suppress("IncompatibleAPI")
return super.submit(events, additionalInfo, parentComponent ?: error("Should never happen in Intellij Idea"), consumer)
}
}
@@ -0,0 +1,298 @@
/*
* 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.reporter
import com.intellij.diagnostic.ReportMessages
import com.intellij.ide.DataManager
import com.intellij.ide.util.PropertiesComponent
import com.intellij.notification.NotificationType
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.diagnostic.IdeaLoggingEvent
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.diagnostic.SubmittedReportInfo
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.Messages
import com.intellij.util.Consumer
import com.intellij.util.ThreeState
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.KotlinPluginUpdater
import org.jetbrains.kotlin.idea.KotlinPluginUtil
import org.jetbrains.kotlin.idea.PluginUpdateStatus
import org.jetbrains.kotlin.idea.util.isEap
import java.awt.Component
import java.io.IOException
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.time.format.DateTimeParseException
import java.time.temporal.ChronoUnit
import javax.swing.Icon
/**
* We need to wrap ITNReporter for force showing or errors from kotlin plugin even from released version of IDEA.
*/
class KotlinReportSubmitter : ITNReporterCompat() {
companion object {
private const val KOTLIN_FATAL_ERROR_NOTIFICATION_PROPERTY = "kotlin.fatal.error.notification"
private const val IDEA_FATAL_ERROR_NOTIFICATION_PROPERTY = "idea.fatal.error.notification"
private const val DISABLED_VALUE = "disabled"
private const val ENABLED_VALUE = "enabled"
private const val KOTLIN_PLUGIN_RELEASE_DATE = "kotlin.plugin.releaseDate"
private val LOG = Logger.getInstance(KotlinReportSubmitter::class.java)
@Volatile
private var isFatalErrorReportingDisabledInRelease = ThreeState.UNSURE
private val isIdeaAndKotlinRelease by lazy {
// Disabled in released version of IDEA and Android Studio
// Enabled in EAPs, Canary and Beta
val isReleaseLikeIdea = DISABLED_VALUE == System.getProperty(IDEA_FATAL_ERROR_NOTIFICATION_PROPERTY, ENABLED_VALUE)
val isKotlinRelease =
!(KotlinPluginUtil.isSnapshotVersion() || KotlinPluginUtil.isDevVersion() || isEap(KotlinPluginUtil.getPluginVersion()))
isReleaseLikeIdea && isKotlinRelease
}
private const val NUMBER_OF_REPORTING_DAYS_FROM_RELEASE = 7
fun setupReportingFromRelease() {
if (ApplicationManager.getApplication().isUnitTestMode) {
return
}
if (!isIdeaAndKotlinRelease) {
return
}
val currentPluginReleaseDate = readStoredPluginReleaseDate()
if (currentPluginReleaseDate != null) {
isFatalErrorReportingDisabledInRelease =
if (isFatalErrorReportingDisabled(currentPluginReleaseDate)) ThreeState.YES else ThreeState.NO
return
}
ApplicationManager.getApplication().executeOnPooledThread {
val releaseDate =
try {
KotlinPluginUpdater.fetchPluginReleaseDate(
KotlinPluginUtil.KOTLIN_PLUGIN_ID,
KotlinPluginUtil.getPluginVersion(),
null
)
} catch (e: IOException) {
LOG.warn(e)
null
} catch (e: KotlinPluginUpdater.Companion.ResponseParseException) {
// Exception won't be shown, but will be logged
LOG.error(e)
return@executeOnPooledThread
}
if (releaseDate != null) {
writePluginReleaseValue(releaseDate)
} else {
// Will try to fetch the same release date on IDE restart
}
isFatalErrorReportingDisabledInRelease = isFatalErrorReportingWithDefault(releaseDate)
}
}
private fun isFatalErrorReportingWithDefault(releaseDate: LocalDate?): ThreeState {
return if (releaseDate != null) {
if (isFatalErrorReportingDisabled(releaseDate)) ThreeState.YES else ThreeState.NO
} else {
// Disable reporting by default until we obtain a valid release date.
// We might fail reporting exceptions that happened before initialization but after successful release date fetching
// such exceptions maybe be reported after restart.
ThreeState.YES
}
}
private fun isFatalErrorReportingDisabledWithUpdate(): Boolean {
val currentPluginReleaseDate = readStoredPluginReleaseDate()
isFatalErrorReportingDisabledInRelease = isFatalErrorReportingWithDefault(currentPluginReleaseDate)
return isFatalErrorReportingDisabledInRelease == ThreeState.YES
}
private fun isFatalErrorReportingDisabled(releaseDate: LocalDate): Boolean {
return ChronoUnit.DAYS.between(releaseDate, LocalDate.now()) > NUMBER_OF_REPORTING_DAYS_FROM_RELEASE
}
private val RELEASE_DATE_FORMATTER: DateTimeFormatter by lazy {
DateTimeFormatter.ofPattern("yyyy-MM-dd")
}
private fun readStoredPluginReleaseDate(): LocalDate? {
val pluginVersionToReleaseDate = PropertiesComponent.getInstance().getValue(KOTLIN_PLUGIN_RELEASE_DATE) ?: return null
val parsedDate = fun(): LocalDate? {
val parts = pluginVersionToReleaseDate.split(":")
if (parts.size != 2) {
return null
}
val pluginVersion = parts[0]
if (pluginVersion != KotlinPluginUtil.getPluginVersion()) {
// Stored for some other plugin version
return null
}
return try {
val dateString = parts[1]
LocalDate.parse(dateString, RELEASE_DATE_FORMATTER)
} catch (e: DateTimeParseException) {
null
}
}.invoke()
if (parsedDate == null) {
PropertiesComponent.getInstance().setValue(KOTLIN_PLUGIN_RELEASE_DATE, null)
}
return parsedDate
}
private fun writePluginReleaseValue(date: LocalDate) {
val currentKotlinVersion = KotlinPluginUtil.getPluginVersion()
val dateStr = RELEASE_DATE_FORMATTER.format(date)
PropertiesComponent.getInstance().setValue(KOTLIN_PLUGIN_RELEASE_DATE, "$currentKotlinVersion:$dateStr")
}
}
private var hasUpdate = false
private var hasLatestVersion = false
override fun showErrorInRelease(event: IdeaLoggingEvent): Boolean {
if (ApplicationManager.getApplication().isInternal) {
// Reporting is always enabled for internal mode in the platform
return true
}
if (ApplicationManager.getApplication().isUnitTestMode) {
return true
}
if (hasUpdate) {
return false
}
val kotlinNotificationEnabled = DISABLED_VALUE != System.getProperty(KOTLIN_FATAL_ERROR_NOTIFICATION_PROPERTY, ENABLED_VALUE)
if (!kotlinNotificationEnabled) {
// Kotlin notifications are explicitly disabled
return false
}
if (!isIdeaAndKotlinRelease) {
return true
}
return when (isFatalErrorReportingDisabledInRelease) {
ThreeState.YES ->
false
ThreeState.NO -> {
// Reiterate the check for the case when there was no restart for long and reporting decision might expire
!isFatalErrorReportingDisabledWithUpdate()
}
ThreeState.UNSURE -> {
// There might be an exception while initialization isn't complete.
// Decide urgently based on previously stored release version if already fetched.
!isFatalErrorReportingDisabledWithUpdate()
}
}
}
override fun submitCompat(
events: Array<IdeaLoggingEvent>,
additionalInfo: String?,
parentComponent: Component?,
consumer: Consumer<in SubmittedReportInfo>
): Boolean {
if (hasUpdate) {
if (ApplicationManager.getApplication().isInternal) {
return super.submitCompat(events, additionalInfo, parentComponent, consumer)
}
// TODO: What happens here? User clicks report but no report is send?
return true
}
if (hasLatestVersion) {
return super.submitCompat(events, additionalInfo, parentComponent, consumer)
}
val project: Project? = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(parentComponent))
if (KotlinPluginUtil.isPatched()) {
ReportMessages.GROUP
.createNotification(
ReportMessages.ERROR_REPORT,
KotlinBundle.message("reporter.text.can.t.report.exception.from.patched.plugin"),
NotificationType.INFORMATION,
null
)
.setImportant(false)
.notify(project)
return true
}
KotlinPluginUpdater.getInstance().runUpdateCheck { status ->
if (status is PluginUpdateStatus.Update) {
hasUpdate = true
if (ApplicationManager.getApplication().isInternal) {
super.submitCompat(events, additionalInfo, parentComponent, consumer)
}
val rc = showDialog(
parentComponent,
KotlinBundle.message(
"reporter.message.text.you.re.running.kotlin.plugin.version",
KotlinPluginUtil.getPluginVersion(),
status.pluginDescriptor.version
),
KotlinBundle.message("reporter.title.update.kotlin.plugin"),
arrayOf(KotlinBundle.message("reporter.button.text.update"), KotlinBundle.message("reporter.button.text.ignore")),
0, Messages.getInformationIcon()
)
if (rc == 0) {
KotlinPluginUpdater.getInstance().installPluginUpdate(status)
}
} else {
hasLatestVersion = true
super.submitCompat(events, additionalInfo, parentComponent, consumer)
}
false
}
return true
}
fun showDialog(parent: Component?, message: String, title: String, options: Array<String>, defaultOptionIndex: Int, icon: Icon?): Int {
return if (parent != null) {
Messages.showDialog(parent, message, title, options, defaultOptionIndex, icon)
} else {
Messages.showDialog(message, title, options, defaultOptionIndex, icon)
}
}
}
@@ -0,0 +1,18 @@
/*
* 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;
import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase;
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess;
import org.jetbrains.kotlin.test.KotlinTestUtils;
abstract public class KotlinDaemonAnalyzerTestCase extends DaemonAnalyzerTestCase {
@Override
protected void setUp() throws Exception {
VfsRootAccess.allowRootAccess(getTestRootDisposable(), KotlinTestUtils.getHomeDirectory());
super.setUp();
}
}
@@ -0,0 +1,488 @@
/*
* 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.caches.resolve
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.StdModuleTypes
import com.intellij.openapi.roots.DependencyScope
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.ModuleRootModificationUtil
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.openapi.roots.impl.libraries.LibraryEx
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess
import com.intellij.psi.PsiManager
import com.intellij.testFramework.ModuleTestCase
import com.intellij.testFramework.PsiTestUtil
import com.intellij.testFramework.UsefulTestCase
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
import org.jetbrains.kotlin.idea.caches.project.*
import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo
import org.jetbrains.kotlin.idea.caches.project.ModuleTestSourceInfo
import org.jetbrains.kotlin.idea.framework.CommonLibraryKind
import org.jetbrains.kotlin.idea.framework.JSLibraryKind
import org.jetbrains.kotlin.idea.framework.platform
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase.*
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.idea.util.getProjectJdkTableSafe
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.util.addDependency
import org.jetbrains.kotlin.test.util.jarRoot
import org.jetbrains.kotlin.test.util.projectLibrary
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
import org.junit.Assert
import org.junit.runner.RunWith
@RunWith(JUnit3WithIdeaConfigurationRunner::class)
class IdeaModuleInfoTest : ModuleTestCase() {
fun testSimpleModuleDependency() {
val (a, b) = modules()
b.addDependency(a)
b.production.assertDependenciesEqual(b.production, a.production)
UsefulTestCase.assertDoesntContain(a.production.dependencies(), b.production)
}
fun testCircularDependency() {
val (a, b) = modules()
b.addDependency(a)
a.addDependency(b)
a.production.assertDependenciesEqual(a.production, b.production)
b.production.assertDependenciesEqual(b.production, a.production)
}
fun testExportedDependency() {
val (a, b, c) = modules()
b.addDependency(a, exported = true)
c.addDependency(b)
a.production.assertDependenciesEqual(a.production)
b.production.assertDependenciesEqual(b.production, a.production)
c.production.assertDependenciesEqual(c.production, b.production, a.production)
}
fun testRedundantExportedDependency() {
val (a, b, c) = modules()
b.addDependency(a, exported = true)
c.addDependency(a)
c.addDependency(b)
a.production.assertDependenciesEqual(a.production)
b.production.assertDependenciesEqual(b.production, a.production)
c.production.assertDependenciesEqual(c.production, a.production, b.production)
}
fun testCircularExportedDependency() {
val (a, b, c) = modules()
b.addDependency(a, exported = true)
c.addDependency(b, exported = true)
a.addDependency(c, exported = true)
a.production.assertDependenciesEqual(a.production, c.production, b.production)
b.production.assertDependenciesEqual(b.production, a.production, c.production)
c.production.assertDependenciesEqual(c.production, b.production, a.production)
}
fun testSimpleLibDependency() {
val a = module("a")
val lib = projectLibrary()
a.addDependency(lib)
a.production.assertDependenciesEqual(a.production, lib.classes)
}
fun testCircularExportedDependencyWithLib() {
val (a, b, c) = modules()
val lib = projectLibrary()
a.addDependency(lib)
b.addDependency(a, exported = true)
c.addDependency(b, exported = true)
a.addDependency(c, exported = true)
b.addDependency(lib)
c.addDependency(lib)
a.production.assertDependenciesEqual(a.production, lib.classes, c.production, b.production)
b.production.assertDependenciesEqual(b.production, a.production, c.production, lib.classes)
c.production.assertDependenciesEqual(c.production, b.production, a.production, lib.classes)
}
fun testSeveralModulesExportLibs() {
val (a, b, c) = modules()
val lib1 = projectLibrary("lib1")
val lib2 = projectLibrary("lib2")
a.addDependency(lib1, exported = true)
b.addDependency(lib2, exported = true)
c.addDependency(a)
c.addDependency(b)
c.production.assertDependenciesEqual(c.production, a.production, lib1.classes, b.production, lib2.classes)
}
fun testSeveralModulesExportSameLib() {
val (a, b, c) = modules()
val lib = projectLibrary()
a.addDependency(lib, exported = true)
b.addDependency(lib, exported = true)
c.addDependency(a)
c.addDependency(b)
c.production.assertDependenciesEqual(c.production, a.production, lib.classes, b.production)
}
fun testRuntimeDependency() {
val (a, b) = modules()
b.addDependency(a, dependencyScope = DependencyScope.RUNTIME)
b.addDependency(projectLibrary(), dependencyScope = DependencyScope.RUNTIME)
b.production.assertDependenciesEqual(b.production)
}
fun testProvidedDependency() {
val (a, b) = modules()
val lib = projectLibrary()
b.addDependency(a, dependencyScope = DependencyScope.PROVIDED)
b.addDependency(lib, dependencyScope = DependencyScope.PROVIDED)
b.production.assertDependenciesEqual(b.production, a.production, lib.classes)
}
fun testSimpleTestDependency() {
val (a, b) = modules()
b.addDependency(a, dependencyScope = DependencyScope.TEST)
a.production.assertDependenciesEqual(a.production)
a.test.assertDependenciesEqual(a.test, a.production)
b.production.assertDependenciesEqual(b.production)
b.test.assertDependenciesEqual(b.test, b.production, a.test, a.production)
}
fun testLibTestDependency() {
val a = module("a")
val lib = projectLibrary()
a.addDependency(lib, dependencyScope = DependencyScope.TEST)
a.production.assertDependenciesEqual(a.production)
a.test.assertDependenciesEqual(a.test, a.production, lib.classes)
}
fun testExportedTestDependency() {
val (a, b, c) = modules()
b.addDependency(a, exported = true)
c.addDependency(b, dependencyScope = DependencyScope.TEST)
c.production.assertDependenciesEqual(c.production)
c.test.assertDependenciesEqual(c.test, c.production, b.test, b.production, a.test, a.production)
}
fun testDependents() {
//NOTE: we do not differ between dependency kinds
val (a, b, c) = modules(name1 = "a", name2 = "b", name3 = "c")
val (d, e, f) = modules(name1 = "d", name2 = "e", name3 = "f")
b.addDependency(a, exported = true)
c.addDependency(a)
d.addDependency(c, exported = true)
e.addDependency(b)
f.addDependency(d)
f.addDependency(e)
a.test.assertDependentsEqual(a.test, b.test, c.test, e.test)
a.production.assertDependentsEqual(a.production, a.test, b.production, b.test, c.production, c.test, e.production, e.test)
b.test.assertDependentsEqual(b.test, e.test)
b.production.assertDependentsEqual(b.production, b.test, e.production, e.test)
c.test.assertDependentsEqual(c.test, d.test, f.test)
c.production.assertDependentsEqual(c.production, c.test, d.production, d.test, f.production, f.test)
d.test.assertDependentsEqual(d.test, f.test)
d.production.assertDependentsEqual(d.production, d.test, f.production, f.test)
e.test.assertDependentsEqual(e.test, f.test)
e.production.assertDependentsEqual(e.production, e.test, f.production, f.test)
f.test.assertDependentsEqual(f.test)
f.production.assertDependentsEqual(f.production, f.test)
}
fun testLibraryDependency1() {
val lib1 = projectLibrary("lib1")
val lib2 = projectLibrary("lib2")
val module = module("module")
module.addDependency(lib1)
module.addDependency(lib2)
lib1.classes.assertAdditionalLibraryDependencies(lib2.classes)
lib2.classes.assertAdditionalLibraryDependencies(lib1.classes)
}
fun testLibraryDependency2() {
val lib1 = projectLibrary("lib1")
val lib2 = projectLibrary("lib2")
val lib3 = projectLibrary("lib3")
val (a, b, c) = modules()
a.addDependency(lib1)
b.addDependency(lib2)
c.addDependency(lib3)
c.addDependency(a)
c.addDependency(b)
lib1.classes.assertAdditionalLibraryDependencies()
lib2.classes.assertAdditionalLibraryDependencies()
lib3.classes.assertAdditionalLibraryDependencies(lib1.classes, lib2.classes)
}
fun testLibraryDependency3() {
val lib1 = projectLibrary("lib1")
val lib2 = projectLibrary("lib2")
val lib3 = projectLibrary("lib3")
val (a, b) = modules()
a.addDependency(lib1)
b.addDependency(lib2)
a.addDependency(lib3)
b.addDependency(lib3)
lib1.classes.assertAdditionalLibraryDependencies(lib3.classes)
lib2.classes.assertAdditionalLibraryDependencies(lib3.classes)
lib3.classes.assertAdditionalLibraryDependencies(lib1.classes, lib2.classes)
}
fun testRoots() {
val a = module("a", hasProductionRoot = true, hasTestRoot = false)
val empty = module("empty", hasProductionRoot = false, hasTestRoot = false)
a.addDependency(empty)
val b = module("b", hasProductionRoot = false, hasTestRoot = true)
b.addDependency(a)
val c = module("c")
c.addDependency(b)
c.addDependency(a)
assertNotNull(a.productionSourceInfo())
assertNull(a.testSourceInfo())
assertNull(empty.productionSourceInfo())
assertNull(empty.testSourceInfo())
assertNull(b.productionSourceInfo())
assertNotNull(b.testSourceInfo())
b.test.assertDependenciesEqual(b.test, a.production)
c.test.assertDependenciesEqual(c.test, c.production, b.test, a.production)
c.production.assertDependenciesEqual(c.production, a.production)
}
fun testCommonLibraryDoesNotDependOnPlatform() {
val stdlibCommon = stdlibCommon()
val stdlibJvm = stdlibJvm()
val stdlibJs = stdlibJs()
val a = module("a")
a.addDependency(stdlibCommon)
a.addDependency(stdlibJvm)
val b = module("b")
b.addDependency(stdlibCommon)
b.addDependency(stdlibJs)
stdlibCommon.classes.assertAdditionalLibraryDependencies()
stdlibJvm.classes.assertAdditionalLibraryDependencies(stdlibCommon.classes)
stdlibJs.classes.assertAdditionalLibraryDependencies(stdlibCommon.classes)
}
fun testScriptDependenciesForModule() {
val a = module("a")
val b = module("b")
with(createFileInModule(a, "script.kts").moduleInfo) {
dependencies().contains(a.production)
dependencies().contains(a.test)
!dependencies().contains(b.production)
}
}
fun testScriptDependenciesForProject() {
val a = module("a")
val script = createFileInProject("script.kts").moduleInfo
!script.dependencies().contains(a.production)
!script.dependencies().contains(a.test)
script.dependencies().firstIsInstance<ScriptDependenciesInfo.ForFile>()
}
fun testSdkForScript() {
// The first known jdk will be used for scripting if there is no jdk in the project
runWriteAction {
addJdk(testRootDisposable, ::mockJdk6)
addJdk(testRootDisposable, ::mockJdk9)
ProjectRootManager.getInstance(project).projectSdk = null
}
val firstSDK = getProjectJdkTableSafe().allJdks.first()
with(createFileInProject("script.kts").moduleInfo) {
dependencies().filterIsInstance<SdkInfo>().single { it.sdk == firstSDK }
}
}
fun testSdkForScriptProjectSdk() {
runWriteAction {
addJdk(testRootDisposable, ::mockJdk6)
addJdk(testRootDisposable, ::mockJdk9)
ProjectRootManager.getInstance(project).projectSdk = mockJdk9()
}
with(createFileInProject("script.kts").moduleInfo) {
dependencies().filterIsInstance<SdkInfo>().single { it.sdk == mockJdk9() }
}
}
fun testSdkForScriptModuleSdk() {
val a = module("a")
runWriteAction {
addJdk(testRootDisposable, ::mockJdk6)
addJdk(testRootDisposable, ::mockJdk9)
ProjectRootManager.getInstance(project).projectSdk = mockJdk6()
with(ModuleRootManager.getInstance(a).modifiableModel) {
sdk = mockJdk9()
commit()
}
}
with(createFileInModule(a, "script.kts").moduleInfo) {
dependencies().filterIsInstance<SdkInfo>().first { it.sdk == mockJdk9() }
}
}
private fun createFileInModule(module: Module, fileName: String, inTests: Boolean = false): VirtualFile {
val fileToCopyIO = createTempFile(fileName, "")
for (contentEntry in ModuleRootManager.getInstance(module).contentEntries) {
for (sourceFolder in contentEntry.sourceFolders) {
if (((!inTests && !sourceFolder.isTestSource) || (inTests && sourceFolder.isTestSource)) && sourceFolder.file != null) {
return runWriteAction {
getVirtualFile(fileToCopyIO).copy(this, sourceFolder.file!!, fileName)
}
}
}
}
error("Couldn't find source folder in ${module.name}")
}
private fun createFileInProject(fileName: String): VirtualFile {
return runWriteAction {
getVirtualFile(createTempFile(fileName, "")).copy(this, project.baseDir, fileName)
}
}
private fun Module.addDependency(
other: Module,
dependencyScope: DependencyScope = DependencyScope.COMPILE,
exported: Boolean = false
) = ModuleRootModificationUtil.addDependency(this, other, dependencyScope, exported)
private val VirtualFile.moduleInfo: IdeaModuleInfo
get() {
return PsiManager.getInstance(project).findFile(this)!!.getModuleInfo()
}
private val Module.production: ModuleProductionSourceInfo
get() = productionSourceInfo()!!
private val Module.test: ModuleTestSourceInfo
get() = testSourceInfo()!!
private val LibraryEx.classes: LibraryInfo
get() = object : LibraryInfo(project!!, this) {
override val platform: TargetPlatform
get() = kind.platform
}
private fun module(name: String, hasProductionRoot: Boolean = true, hasTestRoot: Boolean = true): Module {
return createModuleFromTestData(createTempDirectory().absolutePath, name, StdModuleTypes.JAVA, false).apply {
if (hasProductionRoot)
PsiTestUtil.addSourceContentToRoots(this, dir(), false)
if (hasTestRoot)
PsiTestUtil.addSourceContentToRoots(this, dir(), true)
}
}
private fun dir() = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(createTempDirectory())!!
private fun modules(name1: String = "a", name2: String = "b", name3: String = "c") = Triple(module(name1), module(name2), module(name3))
private fun IdeaModuleInfo.assertDependenciesEqual(vararg expected: IdeaModuleInfo) {
Assert.assertEquals(expected.toList(), this.dependencies())
}
private fun LibraryInfo.assertAdditionalLibraryDependencies(vararg expected: IdeaModuleInfo) {
Assert.assertEquals(this, dependencies().first())
val dependenciesWithoutSelf = this.dependencies().drop(1)
UsefulTestCase.assertSameElements(dependenciesWithoutSelf, expected.toList())
}
private fun ModuleSourceInfo.assertDependentsEqual(vararg expected: ModuleSourceInfo) {
UsefulTestCase.assertSameElements(this.getDependentModules(), expected.toList())
}
private fun stdlibCommon(): LibraryEx = projectLibrary(
"kotlin-stdlib-common",
ForTestCompileRuntime.stdlibCommonForTests().jarRoot,
kind = CommonLibraryKind
)
private fun stdlibJvm(): LibraryEx = projectLibrary("kotlin-stdlib", ForTestCompileRuntime.runtimeJarForTests().jarRoot)
private fun stdlibJs(): LibraryEx = projectLibrary(
"kotlin-stdlib-js",
ForTestCompileRuntime.runtimeJarForTests().jarRoot,
kind = JSLibraryKind
)
override fun setUp() {
super.setUp()
VfsRootAccess.allowRootAccess(testRootDisposable, KotlinTestUtils.getHomeDirectory())
}
}
@@ -36,12 +36,11 @@ abstract class AbstractConfigureKotlinTest : PlatformTestCase() {
override fun setUp() {
super.setUp()
VfsRootAccess.allowRootAccess(KotlinTestUtils.getHomeDirectory())
VfsRootAccess.allowRootAccess(testRootDisposable, KotlinTestUtils.getHomeDirectory())
}
@Throws(Exception::class)
override fun tearDown() {
VfsRootAccess.disallowRootAccess(KotlinTestUtils.getHomeDirectory())
PathMacros.getInstance().removeMacro(TEMP_DIR_MACRO_KEY)
super.tearDown()
@@ -0,0 +1,71 @@
/*
* 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.repl
import com.intellij.codeInsight.completion.CompletionType
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess
import com.intellij.psi.PsiDocumentManager
import com.intellij.testFramework.LightProjectDescriptor
import org.jetbrains.kotlin.console.KotlinConsoleKeeper
import org.jetbrains.kotlin.console.KotlinConsoleRunner
import org.jetbrains.kotlin.idea.completion.test.KotlinFixtureCompletionBaseTestCase
import org.jetbrains.kotlin.idea.completion.test.testCompletion
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File
abstract class AbstractIdeReplCompletionTest : KotlinFixtureCompletionBaseTestCase() {
private var consoleRunner: KotlinConsoleRunner? = null
override fun setUp() {
super.setUp()
consoleRunner = KotlinConsoleKeeper.getInstance(project).run(module)!!
ScriptConfigurationManager.updateScriptDependenciesSynchronously(consoleRunner!!.consoleFile)
VfsRootAccess.allowRootAccess(testRootDisposable, KotlinTestUtils.getHomeDirectory())
}
override fun tearDown() {
consoleRunner?.dispose()
consoleRunner = null
super.tearDown()
}
override fun getPlatform() = JvmPlatforms.unspecifiedJvmPlatform
override fun defaultCompletionType() = CompletionType.BASIC
override fun doTest(testPath: String) {
val runner = consoleRunner!!
val file = File(testPath)
val lines = file.readLines()
lines.prefixedWith(">> ").forEach { runner.successfulLine(it) } // not actually executing anything, only simulating
val codeSample = lines.prefixedWith("-- ").joinToString("\n")
runWriteAction {
val editor = runner.consoleView.editorDocument
editor.setText(codeSample)
FileDocumentManager.getInstance().saveDocument(runner.consoleView.editorDocument)
PsiDocumentManager.getInstance(project).commitAllDocuments()
}
myFixture.configureFromExistingVirtualFile(runner.consoleFile.virtualFile)
myFixture.editor.caretModel.moveToOffset(myFixture.editor.document.getLineEndOffset(0))
testCompletion(file.readText(), getPlatform(), { completionType, count -> myFixture.complete(completionType, count) })
}
private fun List<String>.prefixedWith(prefix: String) = filter { it.startsWith(prefix) }.map { it.removePrefix(prefix) }
override fun getProjectDescriptor(): LightProjectDescriptor = FullJdkProjectDescriptor
}
private object FullJdkProjectDescriptor : KotlinWithJdkAndRuntimeLightProjectDescriptor() {
override fun getSdk() = PluginTestCaseBase.fullJdk()
}
@@ -0,0 +1,186 @@
/*
* 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.repl
import com.intellij.execution.console.LanguageConsoleImpl
import com.intellij.openapi.roots.ModuleRootModificationUtil
import com.intellij.testFramework.PlatformTestCase
import com.intellij.util.ThrowableRunnable
import com.intellij.util.ui.UIUtil
import org.jetbrains.kotlin.console.KotlinConsoleKeeper
import org.jetbrains.kotlin.console.KotlinConsoleRunner
import org.jetbrains.kotlin.idea.run.createLibraryWithLongPaths
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner
import org.jetbrains.kotlin.test.WithMutedInDatabaseRunTest
import org.jetbrains.kotlin.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
import kotlin.reflect.KMutableProperty0
import kotlin.test.assertFalse
import kotlin.test.assertTrue
@RunWith(JUnit3WithIdeaConfigurationRunner::class)
@WithMutedInDatabaseRunTest
class IdeReplExecutionTest : PlatformTestCase() {
private lateinit var consoleRunner: KotlinConsoleRunner
private var commandsSent = 0
override fun setUp() {
super.setUp()
consoleRunner = KotlinConsoleKeeper.getInstance(project).run(module)!!
}
override fun tearDown() {
consoleRunner.dispose()
(this::consoleRunner as KMutableProperty0<KotlinConsoleRunner?>).set(null)
super.tearDown()
}
override fun runTestRunnable(testRunnable: ThrowableRunnable<Throwable>) {
runTest {
super.runTestRunnable(testRunnable)
}
}
private fun sendCommand(command: String) {
runWriteAction { consoleRunner.consoleView.editorDocument.setText(command) }
consoleRunner.executor.executeCommand()
commandsSent++
}
private fun checkOutput(expectedOutput: String) {
val output = getReplOutput(textOnTimeOut = {
"Only ${consoleRunner.commandHistory.processedEntriesCount} commands were processed"
}) { consoleRunner.commandHistory.processedEntriesCount >= commandsSent }
assertTrue(output.trim().endsWith(expectedOutput), "'$expectedOutput' should be printed but document text is:\n$output")
}
private fun getReplOutput(
maxIterations: Int = 50,
sleepTime: Long = 500,
textOnTimeOut: () -> String,
predicate: () -> Boolean
): String {
for (i in 1..maxIterations) {
UIUtil.dispatchAllInvocationEvents()
if (predicate()) {
return refreshAndGetHistoryEditorText()
}
Thread.sleep(sleepTime)
}
return textOnTimeOut()
}
private fun refreshAndGetHistoryEditorText(): String {
val consoleView = consoleRunner.consoleView as LanguageConsoleImpl
consoleView.flushDeferredText()
return consoleView.historyViewer.document.text
}
private fun testSimpleCommand(command: String, expectedOutput: String) {
sendCommand(command)
checkOutput(expectedOutput)
}
@Test
fun testRunPossibility() {
val allOk = { x: String -> x.contains(":help for help") }
val hasErrors = { x: String ->
x.contains("Process finished with exit code 1") || x.contains("Exception in") || x.contains("Error")
}
val output = getReplOutput(textOnTimeOut = { "Repl startup timed out" }) {
val editorText = refreshAndGetHistoryEditorText()
hasErrors(editorText) || allOk(editorText)
}
assertFalse(hasErrors(output), "Cannot run kotlin repl")
assertTrue(allOk(output), "Successful run should contain text: ':help for help'")
assertFalse(consoleRunner.processHandler.isProcessTerminated, "Process accidentally terminated")
}
@Test
fun testLongCommandLine() {
ModuleRootModificationUtil.addDependency(module, createLibraryWithLongPaths(project))
consoleRunner.dispose()
consoleRunner = KotlinConsoleKeeper.getInstance(project).run(module)!!
testRunPossibility()
}
@Test
fun testOnePlusOne() = testSimpleCommand("1 + 1", "2")
@Test
fun testPrintlnText() = "Hello, console world!".let { testSimpleCommand("println(\"$it\")", it) }
@Test
fun testDivisionByZeroException() = testSimpleCommand("1 / 0", "java.lang.ArithmeticException: / by zero")
@Test
fun testMultilineSupport() {
val printText = "Print in multiline!"
sendCommand(
"fun f() {\n" +
" println(\"$printText\")\n" +
"}\n"
)
sendCommand("f()")
checkOutput(printText)
}
@Test
fun testReadLineSingle() {
val readLineText = "ReadMe!"
sendCommand("val a = readLine()")
sendCommand(readLineText)
sendCommand("a")
checkOutput(readLineText)
}
@Test
fun testReadLineMultiple() {
val readLineTextA = "ReadMe A!"
val readLineTextB = "ReadMe B!"
sendCommand(
"val a = readLine()\n" +
"val b = readLine()"
)
sendCommand(readLineTextA)
sendCommand(readLineTextB)
sendCommand("a")
checkOutput(readLineTextA)
sendCommand("b")
checkOutput(readLineTextB)
}
@Test
fun testCorrectAfterError() {
val message = "MyMessage"
sendCommand("fun f() { println(x)\n println(y) ")
sendCommand("println(\"$message\")")
checkOutput(message)
}
@Test
fun testMultipleErrorsHandling() {
val veryLongTextWithErrors = "println($);".repeat(30)
sendCommand(veryLongTextWithErrors)
sendCommand(veryLongTextWithErrors)
sendCommand(veryLongTextWithErrors)
sendCommand("println(\"OK\")")
checkOutput("OK")
}
}
@@ -0,0 +1,203 @@
/*
* 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.stubs
import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase
import com.intellij.openapi.application.WriteAction
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProviderImpl
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleType
import com.intellij.openapi.module.StdModuleTypes
import com.intellij.openapi.roots.DependencyScope
import com.intellij.openapi.roots.ModuleRootModificationUtil
import com.intellij.openapi.roots.OrderRootType
import com.intellij.openapi.roots.libraries.PersistentLibraryKind
import com.intellij.openapi.roots.ui.configuration.libraryEditor.NewLibraryEditor
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess
import com.intellij.psi.PsiFile
import com.intellij.testFramework.PsiTestUtil
import com.intellij.util.ThrowableRunnable
import org.jetbrains.kotlin.config.CompilerSettings
import org.jetbrains.kotlin.config.KotlinFacetSettings
import org.jetbrains.kotlin.config.KotlinFacetSettingsProvider
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.idea.facet.getOrCreateFacet
import org.jetbrains.kotlin.idea.facet.initializeIfNeeded
import org.jetbrains.kotlin.idea.test.*
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.TestJdkKind
import org.jetbrains.kotlin.test.WithMutedInDatabaseRunTest
import org.jetbrains.kotlin.test.runTest
import org.junit.Assert
import java.io.File
@WithMutedInDatabaseRunTest
abstract class AbstractMultiModuleTest : DaemonAnalyzerTestCase() {
abstract override fun getTestDataPath(): String
override fun setUp() {
super.setUp()
enableKotlinOfficialCodeStyle(project)
VfsRootAccess.allowRootAccess(testRootDisposable, KotlinTestUtils.getHomeDirectory())
}
fun module(name: String, jdk: TestJdkKind = TestJdkKind.MOCK_JDK, hasTestRoot: Boolean = false): Module {
val srcDir = testDataPath + "${getTestName(true)}/$name"
val moduleWithSrcRootSet = createModuleFromTestData(srcDir, name, StdModuleTypes.JAVA, true)
if (hasTestRoot) {
addRoot(
moduleWithSrcRootSet,
File(testDataPath + "${getTestName(true)}/${name}Test"),
true
)
}
ConfigLibraryUtil.configureSdk(moduleWithSrcRootSet, PluginTestCaseBase.addJdk(testRootDisposable) { PluginTestCaseBase.jdk(jdk) })
return moduleWithSrcRootSet
}
override fun tearDown() = runAll(
ThrowableRunnable { disableKotlinOfficialCodeStyle(project) },
ThrowableRunnable { super.tearDown() },
)
public override fun createModule(path: String, moduleType: ModuleType<*>): Module {
return super.createModule(path, moduleType)
}
override fun runTestRunnable(testRunnable: ThrowableRunnable<Throwable>) {
runTest { super.runTestRunnable(testRunnable) }
}
fun addRoot(module: Module, sourceDirInTestData: File, isTestRoot: Boolean, transformContainedFiles: ((File) -> Unit)? = null) {
val tmpDir = createTempDirectory()
// Preserve original root name. This might be useful for later matching of copied files to original ones
val tmpRootDir = File(tmpDir, sourceDirInTestData.name).also { it.mkdir() }
FileUtil.copyDir(sourceDirInTestData, tmpRootDir)
if (transformContainedFiles != null) {
tmpRootDir.listFiles().forEach(transformContainedFiles)
}
val virtualTempDir = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(tmpRootDir)!!
object : WriteCommandAction.Simple<Unit>(project) {
override fun run() {
virtualTempDir.refresh(false, isTestRoot)
}
}.execute().throwException()
PsiTestUtil.addSourceRoot(module, virtualTempDir, isTestRoot)
}
fun Module.addDependency(
other: Module,
dependencyScope: DependencyScope = DependencyScope.COMPILE,
exported: Boolean = false
): Module = this.apply { ModuleRootModificationUtil.addDependency(this, other, dependencyScope, exported) }
fun Module.addLibrary(
jar: File,
name: String = KotlinJdkAndLibraryProjectDescriptor.LIBRARY_NAME,
kind: PersistentLibraryKind<*>? = null
) {
ConfigLibraryUtil.addLibrary(NewLibraryEditor().apply {
this.name = name
addRoot(VfsUtil.getUrlForLibraryRoot(jar), OrderRootType.CLASSES)
}, this, kind)
}
fun Module.enableMultiPlatform(additionalCompilerArguments: String = "") {
createFacet()
val facetSettings = KotlinFacetSettingsProvider.getInstance(project)?.getInitializedSettings(this)
?: error("Facet settings are not found")
facetSettings.useProjectSettings = false
facetSettings.compilerSettings = CompilerSettings().apply {
additionalArguments += " -Xmulti-platform $additionalCompilerArguments"
}
}
fun Module.enableCoroutines() {
createFacet()
val facetSettings = KotlinFacetSettingsProvider.getInstance(project)?.getInitializedSettings(this)
?: error("Facet settings are not found")
facetSettings.useProjectSettings = false
facetSettings.coroutineSupport = LanguageFeature.State.ENABLED
}
protected fun checkFiles(
findFiles: () -> List<PsiFile>,
check: () -> Unit
) {
var atLeastOneFile = false
findFiles().forEach { file ->
configureByExistingFile(file.virtualFile!!)
atLeastOneFile = true
check()
}
Assert.assertTrue(atLeastOneFile)
}
}
fun Module.createFacet(
platformKind: TargetPlatform? = null,
useProjectSettings: Boolean = true
) {
createFacetWithAdditionalSetup(platformKind, useProjectSettings) { }
}
fun Module.createMultiplatformFacetM1(
platformKind: TargetPlatform? = null,
useProjectSettings: Boolean = true,
implementedModuleNames: List<String>,
pureKotlinSourceFolders: List<String>
) {
createFacetWithAdditionalSetup(platformKind, useProjectSettings) {
this.implementedModuleNames = implementedModuleNames
this.pureKotlinSourceFolders = pureKotlinSourceFolders
}
}
fun Module.createMultiplatformFacetM3(
platformKind: TargetPlatform? = null,
useProjectSettings: Boolean = true,
dependsOnModuleNames: List<String>,
pureKotlinSourceFolders: List<String>
) {
createFacetWithAdditionalSetup(platformKind, useProjectSettings) {
this.dependsOnModuleNames = dependsOnModuleNames
this.isHmppEnabled = true
this.pureKotlinSourceFolders = pureKotlinSourceFolders
}
}
private fun Module.createFacetWithAdditionalSetup(
platformKind: TargetPlatform?,
useProjectSettings: Boolean,
additionalSetup: KotlinFacetSettings.() -> Unit
) {
WriteAction.run<Throwable> {
val modelsProvider = IdeModifiableModelsProviderImpl(project)
with(getOrCreateFacet(modelsProvider, useProjectSettings).configuration.settings) {
initializeIfNeeded(
this@createFacetWithAdditionalSetup,
modelsProvider.getModifiableRootModel(this@createFacetWithAdditionalSetup),
platformKind
)
additionalSetup()
}
modelsProvider.commit()
}
}
@@ -0,0 +1,80 @@
/*
* 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.j2k
import com.intellij.openapi.roots.LanguageLevelProjectExtension
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess
import com.intellij.pom.java.LanguageLevel
import com.intellij.testFramework.LightPlatformTestCase
import org.jetbrains.kotlin.idea.caches.PerModulePackageCacheService.Companion.DEBUG_LOG_ENABLE_PerModulePackageCache
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.invalidateLibraryCache
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File
abstract class AbstractJavaToKotlinConverterTest : KotlinLightCodeInsightFixtureTestCase() {
override fun setUp() {
super.setUp()
project.DEBUG_LOG_ENABLE_PerModulePackageCache = true
val testName = getTestName(false)
if (testName.contains("Java8") || testName.contains("java8")) {
LanguageLevelProjectExtension.getInstance(project).languageLevel = LanguageLevel.JDK_1_8
}
VfsRootAccess.allowRootAccess(getTestRootDisposable(), KotlinTestUtils.getHomeDirectory())
invalidateLibraryCache(project)
addFile("KotlinApi.kt", "kotlinApi")
addFile("JavaApi.java", "javaApi")
}
override fun tearDown() {
project.DEBUG_LOG_ENABLE_PerModulePackageCache = false
super.tearDown()
}
protected fun addFile(fileName: String, dirName: String? = null) {
addFile(File("j2k/testData/$fileName"), dirName)
}
protected fun addFile(file: File, dirName: String?): VirtualFile {
return addFile(FileUtil.loadFile(file, true), file.name, dirName)
}
protected fun addFile(text: String, fileName: String, dirName: String?): VirtualFile {
return runWriteAction {
val root = LightPlatformTestCase.getSourceRoot()!!
val virtualDir = dirName?.let {
root.findChild(it) ?: root.createChildDirectory(null, it)
} ?: root
val virtualFile = virtualDir.createChildData(null, fileName)
virtualFile.getOutputStream(null)!!.writer().use { it.write(text) }
virtualFile
}
}
protected fun deleteFile(virtualFile: VirtualFile) {
runWriteAction { virtualFile.delete(this) }
}
}
@@ -2,7 +2,7 @@
* 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.
*/
@file:Suppress("JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE")
package org.jetbrains.kotlin.js.engine
import jdk.nashorn.api.scripting.NashornScriptEngineFactory