203: Fix compilation
This commit is contained in:
+1
-1
@@ -357,7 +357,7 @@ fun Task.listConfigurationContents(configName: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val defaultJvmTarget = "1.8"
|
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)
|
val ignoreTestFailures by extra(project.kotlinBuildProperties.ignoreTestFailures)
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* 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.
|
* 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
|
package org.jetbrains.kotlin.codegen.inline.coroutines
|
||||||
|
|
||||||
import com.intellij.util.ArrayUtil
|
import com.intellij.util.ArrayUtil
|
||||||
|
|||||||
+5
-4
@@ -2,14 +2,16 @@
|
|||||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* 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.
|
* 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
|
package org.jetbrains.kotlin.daemon.common.experimental.socketInfrastructure
|
||||||
|
|
||||||
import io.ktor.network.sockets.Socket
|
import io.ktor.network.sockets.*
|
||||||
import kotlinx.coroutines.channels.*
|
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
|
import kotlinx.coroutines.channels.*
|
||||||
import org.jetbrains.kotlin.daemon.common.LoopbackNetworkInterface
|
import org.jetbrains.kotlin.daemon.common.LoopbackNetworkInterface
|
||||||
import org.jetbrains.kotlin.daemon.common.experimental.LoopbackNetworkInterfaceKtor
|
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 sun.net.ConnectionResetException
|
||||||
import java.beans.Transient
|
import java.beans.Transient
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
@@ -17,7 +19,6 @@ import java.io.ObjectInputStream
|
|||||||
import java.io.ObjectOutputStream
|
import java.io.ObjectOutputStream
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.util.logging.Logger
|
import java.util.logging.Logger
|
||||||
import org.jetbrains.kotlin.daemon.common.experimental.socketInfrastructure.Server.*
|
|
||||||
|
|
||||||
interface Client<ServerType : ServerBase> : Serializable, AutoCloseable {
|
interface Client<ServerType : ServerBase> : Serializable, AutoCloseable {
|
||||||
|
|
||||||
|
|||||||
-1
@@ -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.isInlineClassThatRequiresMangling
|
||||||
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForParameterTypes
|
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForParameterTypes
|
||||||
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
|
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
|
||||||
import javax.rmi.CORBA.ClassDesc
|
|
||||||
|
|
||||||
class LocalFunInlineChecker : DeclarationChecker {
|
class LocalFunInlineChecker : DeclarationChecker {
|
||||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||||
|
|||||||
+28
@@ -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.
|
* 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.
|
* 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
|
package org.jetbrains.kotlin.fir
|
||||||
|
|
||||||
import org.jetbrains.kotlin.daemon.common.threadCpuTime
|
import org.jetbrains.kotlin.daemon.common.threadCpuTime
|
||||||
|
|||||||
+1
-2
@@ -19,14 +19,13 @@ abstract public class KotlinCompletionTestCase extends CompletionTestCase {
|
|||||||
@Override
|
@Override
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
VfsRootAccess.allowRootAccess(KotlinTestUtils.getHomeDirectory());
|
VfsRootAccess.allowRootAccess(getTestRootDisposable(), KotlinTestUtils.getHomeDirectory());
|
||||||
CodeInsightSettings.getInstance().EXCLUDED_PACKAGES = new String[]{"excludedPackage", "somePackage.ExcludedClass"};
|
CodeInsightSettings.getInstance().EXCLUDED_PACKAGES = new String[]{"excludedPackage", "somePackage.ExcludedClass"};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void tearDown() throws Exception {
|
protected void tearDown() throws Exception {
|
||||||
CodeInsightSettings.getInstance().EXCLUDED_PACKAGES = ArrayUtil.EMPTY_STRING_ARRAY;
|
CodeInsightSettings.getInstance().EXCLUDED_PACKAGES = ArrayUtil.EMPTY_STRING_ARRAY;
|
||||||
VfsRootAccess.disallowRootAccess(KotlinTestUtils.getHomeDirectory());
|
|
||||||
super.tearDown();
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-7
@@ -20,16 +20,10 @@ import org.jetbrains.kotlin.test.WithMutedInDatabaseRunTest;
|
|||||||
public abstract class KotlinCodeInsightTestCase extends CodeInsightTestCase {
|
public abstract class KotlinCodeInsightTestCase extends CodeInsightTestCase {
|
||||||
@Override
|
@Override
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
VfsRootAccess.allowRootAccess(KotlinTestUtils.getHomeDirectory());
|
VfsRootAccess.allowRootAccess(getTestRootDisposable(), KotlinTestUtils.getHomeDirectory());
|
||||||
super.setUp();
|
super.setUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
super.tearDown();
|
|
||||||
VfsRootAccess.disallowRootAccess(KotlinTestUtils.getHomeDirectory());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void runTestRunnable(@NotNull ThrowableRunnable<Throwable> testRunnable) throws Throwable {
|
protected void runTestRunnable(@NotNull ThrowableRunnable<Throwable> testRunnable) throws Throwable {
|
||||||
KotlinTestUtils.runTestWithThrowable(this, () -> super.runTestRunnable(testRunnable));
|
KotlinTestUtils.runTestWithThrowable(this, () -> super.runTestRunnable(testRunnable));
|
||||||
|
|||||||
+44
@@ -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()
|
||||||
|
}
|
||||||
+76
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
@file:Suppress("JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE")
|
||||||
package org.jetbrains.kotlin.idea.debugger.evaluate.classLoading
|
package org.jetbrains.kotlin.idea.debugger.evaluate.classLoading
|
||||||
|
|
||||||
import com.sun.jdi.ArrayReference
|
import com.sun.jdi.ArrayReference
|
||||||
|
|||||||
+376
@@ -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())
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-2
@@ -36,12 +36,11 @@ abstract class AbstractConfigureKotlinTest : PlatformTestCase() {
|
|||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
|
|
||||||
VfsRootAccess.allowRootAccess(KotlinTestUtils.getHomeDirectory())
|
VfsRootAccess.allowRootAccess(testRootDisposable, KotlinTestUtils.getHomeDirectory())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
override fun tearDown() {
|
override fun tearDown() {
|
||||||
VfsRootAccess.disallowRootAccess(KotlinTestUtils.getHomeDirectory())
|
|
||||||
PathMacros.getInstance().removeMacro(TEMP_DIR_MACRO_KEY)
|
PathMacros.getInstance().removeMacro(TEMP_DIR_MACRO_KEY)
|
||||||
|
|
||||||
super.tearDown()
|
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.
|
* 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.
|
* 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
|
package org.jetbrains.kotlin.js.engine
|
||||||
|
|
||||||
import jdk.nashorn.api.scripting.NashornScriptEngineFactory
|
import jdk.nashorn.api.scripting.NashornScriptEngineFactory
|
||||||
|
|||||||
Reference in New Issue
Block a user