Cleanup 192 patchset files (KTI-315)

This commit is contained in:
Yunir Salimzyanov
2020-08-13 19:00:06 +03:00
parent 73aa21aab6
commit 42da9e62db
126 changed files with 0 additions and 11671 deletions
@@ -1,64 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.cli.jvm.compiler;
import com.intellij.codeInsight.ContainerProvider;
import com.intellij.codeInsight.runner.JavaMainMethodProvider;
import com.intellij.core.CoreApplicationEnvironment;
import com.intellij.core.JavaCoreApplicationEnvironment;
import com.intellij.lang.MetaLanguage;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.extensions.ExtensionsArea;
import com.intellij.openapi.fileTypes.FileTypeExtensionPoint;
import com.intellij.openapi.vfs.VirtualFileSystem;
import com.intellij.psi.FileContextProvider;
import com.intellij.psi.augment.PsiAugmentProvider;
import com.intellij.psi.augment.TypeAnnotationModifier;
import com.intellij.psi.compiled.ClassFileDecompilers;
import com.intellij.psi.meta.MetaDataContributor;
import com.intellij.psi.stubs.BinaryFileStubBuilders;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem;
// Mostly a placeholder for the functionality added to the bunch 193
public class KotlinCoreApplicationEnvironment extends JavaCoreApplicationEnvironment {
public static KotlinCoreApplicationEnvironment create(@NotNull Disposable parentDisposable, boolean unitTestMode) {
Extensions.cleanRootArea(parentDisposable);
registerExtensionPoints();
return new KotlinCoreApplicationEnvironment(parentDisposable, unitTestMode);
}
private KotlinCoreApplicationEnvironment(@NotNull Disposable parentDisposable, boolean unitTestMode) {
super(parentDisposable, unitTestMode);
}
private static void registerExtensionPoints() {
ExtensionsArea area = Extensions.getRootArea();
CoreApplicationEnvironment.registerExtensionPoint(area, BinaryFileStubBuilders.EP_NAME, FileTypeExtensionPoint.class);
CoreApplicationEnvironment.registerExtensionPoint(area, FileContextProvider.EP_NAME, FileContextProvider.class);
CoreApplicationEnvironment.registerExtensionPoint(area, MetaDataContributor.EP_NAME, MetaDataContributor.class);
CoreApplicationEnvironment.registerExtensionPoint(area, PsiAugmentProvider.EP_NAME, PsiAugmentProvider.class);
CoreApplicationEnvironment.registerExtensionPoint(area, JavaMainMethodProvider.EP_NAME, JavaMainMethodProvider.class);
CoreApplicationEnvironment.registerExtensionPoint(area, ContainerProvider.EP_NAME, ContainerProvider.class);
CoreApplicationEnvironment.registerExtensionPoint(area, ClassFileDecompilers.EP_NAME, ClassFileDecompilers.Decompiler.class);
CoreApplicationEnvironment.registerExtensionPoint(area, TypeAnnotationModifier.EP_NAME, TypeAnnotationModifier.class);
CoreApplicationEnvironment.registerExtensionPoint(area, MetaLanguage.EP_NAME, MetaLanguage.class);
IdeaExtensionPoints.INSTANCE.registerVersionSpecificAppExtensionPoints(area);
}
@Nullable
@Override
protected VirtualFileSystem createJrtFileSystem() {
return new CoreJrtFileSystem();
}
}
@@ -1,332 +0,0 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.test.testFramework;
import com.intellij.core.CoreASTFactory;
import com.intellij.lang.*;
import com.intellij.lang.impl.PsiBuilderFactoryImpl;
import com.intellij.mock.*;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
import com.intellij.openapi.fileTypes.FileTypeFactory;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.progress.EmptyProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.impl.CoreProgressManager;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.pom.PomModel;
import com.intellij.pom.core.impl.PomModelImpl;
import com.intellij.pom.tree.TreeAspect;
import com.intellij.psi.*;
import com.intellij.psi.impl.*;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.testFramework.LightVirtualFile;
import com.intellij.testFramework.TestDataFile;
import com.intellij.util.CachedValuesManagerImpl;
import com.intellij.util.Function;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.messages.MessageBusFactory;
import junit.framework.TestCase;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.picocontainer.ComponentAdapter;
import org.picocontainer.MutablePicoContainer;
import java.io.File;
import java.io.IOException;
import java.util.Set;
@SuppressWarnings("ALL")
public abstract class KtParsingTestCase extends KtPlatformLiteFixture {
public static final Key<Document> HARD_REF_TO_DOCUMENT_KEY = Key.create("HARD_REF_TO_DOCUMENT_KEY");
protected String myFilePrefix = "";
protected String myFileExt;
protected final String myFullDataPath;
protected PsiFile myFile;
private MockPsiManager myPsiManager;
private PsiFileFactoryImpl myFileFactory;
protected Language myLanguage;
private final ParserDefinition[] myDefinitions;
private final boolean myLowercaseFirstLetter;
protected KtParsingTestCase(@NonNls @NotNull String dataPath, @NotNull String fileExt, @NotNull ParserDefinition... definitions) {
this(dataPath, fileExt, false, definitions);
}
protected KtParsingTestCase(@NonNls @NotNull String dataPath, @NotNull String fileExt, boolean lowercaseFirstLetter, @NotNull ParserDefinition... definitions) {
myDefinitions = definitions;
myFullDataPath = getTestDataPath() + "/" + dataPath;
myFileExt = fileExt;
myLowercaseFirstLetter = lowercaseFirstLetter;
}
@Override
protected void setUp() throws Exception {
super.setUp();
initApplication();
ComponentAdapter component = getApplication().getPicoContainer().getComponentAdapter(ProgressManager.class.getName());
Extensions.registerAreaClass("IDEA_PROJECT", null);
myProject = new MockProjectEx(getTestRootDisposable());
myPsiManager = new MockPsiManager(myProject);
myFileFactory = new PsiFileFactoryImpl(myPsiManager);
MutablePicoContainer appContainer = getApplication().getPicoContainer();
registerComponentInstance(appContainer, MessageBus.class, MessageBusFactory.newMessageBus(getApplication()));
final MockEditorFactory editorFactory = new MockEditorFactory();
registerComponentInstance(appContainer, EditorFactory.class, editorFactory);
registerComponentInstance(appContainer, FileDocumentManager.class, new MockFileDocumentManagerImpl(new Function<CharSequence, Document>() {
@Override
public Document fun(CharSequence charSequence) {
return editorFactory.createDocument(charSequence);
}
}, HARD_REF_TO_DOCUMENT_KEY));
registerComponentInstance(appContainer, PsiDocumentManager.class, new MockPsiDocumentManager());
registerApplicationService(PsiBuilderFactory.class, new PsiBuilderFactoryImpl());
registerApplicationService(DefaultASTFactory.class, new CoreASTFactory());
registerApplicationService(ProgressManager.class, new CoreProgressManager());
myProject.registerService(CachedValuesManager.class, new CachedValuesManagerImpl(myProject, new PsiCachedValuesFactory(myPsiManager)));
myProject.registerService(PsiManager.class, myPsiManager);
this.registerExtensionPoint(FileTypeFactory.FILE_TYPE_FACTORY_EP, FileTypeFactory.class);
registerExtensionPoint(MetaLanguage.EP_NAME, MetaLanguage.class);
for (ParserDefinition definition : myDefinitions) {
addExplicitExtension(LanguageParserDefinitions.INSTANCE, definition.getFileNodeType().getLanguage(), definition);
}
if (myDefinitions.length > 0) {
configureFromParserDefinition(myDefinitions[0], myFileExt);
}
// That's for reparse routines
final PomModelImpl pomModel = new PomModelImpl(myProject);
myProject.registerService(PomModel.class, pomModel);
new TreeAspect(pomModel);
}
public void configureFromParserDefinition(ParserDefinition definition, String extension) {
myLanguage = definition.getFileNodeType().getLanguage();
myFileExt = extension;
addExplicitExtension(LanguageParserDefinitions.INSTANCE, this.myLanguage, definition);
registerComponentInstance(
getApplication().getPicoContainer(), FileTypeManager.class,
new MockFileTypeManager(new MockLanguageFileType(myLanguage, myFileExt)));
}
protected <T> void addExplicitExtension(final LanguageExtension<T> instance, final Language language, final T object) {
instance.addExplicitExtension(language, object);
Disposer.register(myProject, new Disposable() {
@Override
public void dispose() {
instance.removeExplicitExtension(language, object);
}
});
}
@Override
protected <T> void registerExtensionPoint(final ExtensionPointName<T> extensionPointName, Class<T> aClass) {
super.registerExtensionPoint(extensionPointName, aClass);
Disposer.register(myProject, new Disposable() {
@Override
public void dispose() {
Extensions.getRootArea().unregisterExtensionPoint(extensionPointName.getName());
}
});
}
protected <T> void registerApplicationService(final Class<T> aClass, T object) {
getApplication().registerService(aClass, object);
Disposer.register(myProject, new Disposable() {
@Override
public void dispose() {
getApplication().getPicoContainer().unregisterComponent(aClass.getName());
}
});
}
public MockProjectEx getProject() {
return myProject;
}
public MockPsiManager getPsiManager() {
return myPsiManager;
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
myFile = null;
myProject = null;
myPsiManager = null;
}
protected String getTestDataPath() {
return PathManager.getHomePath();
}
@NotNull
public final String getTestName() {
return getTestName(myLowercaseFirstLetter);
}
protected boolean includeRanges() {
return false;
}
protected boolean skipSpaces() {
return false;
}
protected boolean checkAllPsiRoots() {
return true;
}
protected void doTest(boolean checkResult) {
String name = getTestName();
try {
String text = loadFile(name + "." + myFileExt);
myFile = createPsiFile(name, text);
ensureParsed(myFile);
assertEquals("light virtual file text mismatch", text, ((LightVirtualFile)myFile.getVirtualFile()).getContent().toString());
assertEquals("virtual file text mismatch", text, LoadTextUtil.loadText(myFile.getVirtualFile()));
assertEquals("doc text mismatch", text, myFile.getViewProvider().getDocument().getText());
assertEquals("psi text mismatch", text, myFile.getText());
ensureCorrectReparse(myFile);
if (checkResult){
checkResult(name, myFile);
}
else{
toParseTreeText(myFile, skipSpaces(), includeRanges());
}
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
protected void doTest(String suffix) throws IOException {
String name = getTestName();
String text = loadFile(name + "." + myFileExt);
myFile = createPsiFile(name, text);
ensureParsed(myFile);
assertEquals(text, myFile.getText());
checkResult(name + suffix, myFile);
}
protected void doCodeTest(String code) throws IOException {
String name = getTestName();
myFile = createPsiFile("a", code);
ensureParsed(myFile);
assertEquals(code, myFile.getText());
checkResult(myFilePrefix + name, myFile);
}
protected PsiFile createPsiFile(String name, String text) {
return createFile(name + "." + myFileExt, text);
}
protected PsiFile createFile(@NonNls String name, String text) {
LightVirtualFile virtualFile = new LightVirtualFile(name, myLanguage, text);
virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET);
return createFile(virtualFile);
}
protected PsiFile createFile(LightVirtualFile virtualFile) {
return myFileFactory.trySetupPsiForFile(virtualFile, myLanguage, true, false);
}
protected void checkResult(@NonNls @TestDataFile String targetDataName, final PsiFile file) throws IOException {
doCheckResult(myFullDataPath, file, checkAllPsiRoots(), targetDataName, skipSpaces(), includeRanges());
}
public static void doCheckResult(String testDataDir,
PsiFile file,
boolean checkAllPsiRoots,
String targetDataName,
boolean skipSpaces,
boolean printRanges) throws IOException {
FileViewProvider provider = file.getViewProvider();
Set<Language> languages = provider.getLanguages();
if (!checkAllPsiRoots || languages.size() == 1) {
doCheckResult(testDataDir, targetDataName + ".txt", toParseTreeText(file, skipSpaces, printRanges).trim());
return;
}
for (Language language : languages) {
PsiFile root = provider.getPsi(language);
String expectedName = targetDataName + "." + language.getID() + ".txt";
doCheckResult(testDataDir, expectedName, toParseTreeText(root, skipSpaces, printRanges).trim());
}
}
protected void checkResult(String actual) throws IOException {
String name = getTestName();
doCheckResult(myFullDataPath, myFilePrefix + name + ".txt", actual);
}
protected void checkResult(@TestDataFile @NonNls String targetDataName, String actual) throws IOException {
doCheckResult(myFullDataPath, targetDataName, actual);
}
public static void doCheckResult(String fullPath, String targetDataName, String actual) throws IOException {
String expectedFileName = fullPath + File.separatorChar + targetDataName;
KtUsefulTestCase.assertSameLinesWithFile(expectedFileName, actual);
}
protected static String toParseTreeText(PsiElement file, boolean skipSpaces, boolean printRanges) {
return DebugUtil.psiToString(file, skipSpaces, printRanges);
}
protected String loadFile(@NonNls @TestDataFile String name) throws IOException {
return loadFileDefault(myFullDataPath, name);
}
public static String loadFileDefault(String dir, String name) throws IOException {
return FileUtil.loadFile(new File(dir, name), CharsetToolkit.UTF8, true).trim();
}
public static void ensureParsed(PsiFile file) {
file.accept(new PsiElementVisitor() {
@Override
public void visitElement(PsiElement element) {
element.acceptChildren(this);
}
});
}
public static void ensureCorrectReparse(@NotNull PsiFile file) {
String psiToStringDefault = DebugUtil.psiToString(file, false, false);
String fileText = file.getText();
DiffLog diffLog = (new BlockSupportImpl(file.getProject())).reparseRange(
file, file.getNode(), TextRange.allOf(fileText), fileText, new EmptyProgressIndicator(), fileText);
diffLog.performActualPsiChange(file);
TestCase.assertEquals(psiToStringDefault, DebugUtil.psiToString(file, false, false));
}
}
@@ -1,80 +0,0 @@
/*
* Copyright 2000-2014 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.test.testFramework;
import com.intellij.core.CoreEncodingProjectManager;
import com.intellij.mock.MockApplicationEx;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.extensions.ExtensionPoint;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.extensions.ExtensionsArea;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.vfs.encoding.EncodingManager;
import org.picocontainer.MutablePicoContainer;
import java.lang.reflect.Modifier;
public abstract class KtPlatformLiteFixture extends KtUsefulTestCase {
protected MockProjectEx myProject;
@Override
protected void setUp() throws Exception {
super.setUp();
Extensions.cleanRootArea(getTestRootDisposable());
}
public static MockApplicationEx getApplication() {
return (MockApplicationEx)ApplicationManager.getApplication();
}
public void initApplication() {
MockApplicationEx instance = new MockApplicationEx(getTestRootDisposable());
ApplicationManager.setApplication(instance, FileTypeManager::getInstance, getTestRootDisposable());
getApplication().registerService(EncodingManager.class, CoreEncodingProjectManager.class);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
clearFields(this);
myProject = null;
}
protected <T> void registerExtensionPoint(ExtensionPointName<T> extensionPointName, Class<T> aClass) {
registerExtensionPoint(Extensions.getRootArea(), extensionPointName, aClass);
}
private static <T> void registerExtensionPoint(
ExtensionsArea area, ExtensionPointName<T> extensionPointName,
Class<? extends T> aClass
) {
String name = extensionPointName.getName();
if (!area.hasExtensionPoint(name)) {
ExtensionPoint.Kind kind = aClass.isInterface() || (aClass.getModifiers() & Modifier.ABSTRACT) != 0 ? ExtensionPoint.Kind.INTERFACE : ExtensionPoint.Kind.BEAN_CLASS;
area.registerExtensionPoint(name, aClass.getName(), kind);
}
}
@SuppressWarnings("unchecked")
public static <T> T registerComponentInstance(MutablePicoContainer container, Class<T> key, T implementation) {
Object old = container.getComponentInstance(key);
container.unregisterComponent(key);
container.registerComponentInstance(key, implementation);
return (T)old;
}
}
File diff suppressed because it is too large Load Diff
-17
View File
@@ -1,17 +0,0 @@
versions.intellijSdk=192.7142.36
versions.androidBuildTools=r23.0.1
versions.idea.NodeJS=181.3494.12
versions.jar.asm-all=7.0.1
versions.jar.guava=25.1-jre
versions.jar.groovy-all=2.4.17
versions.jar.lombok-ast=0.2.3
versions.jar.swingx-core=1.6.2-2
versions.jar.kxml2=2.3.0
versions.jar.streamex=0.6.8
versions.jar.gson=2.8.5
versions.jar.oro=2.0.8
versions.jar.picocontainer=1.2
versions.jar.lz4-java=1.6.0
ignore.jar.snappy-in-java=true
versions.gradle-api=4.5.1
versions.shadow=5.2.0
@@ -1,420 +0,0 @@
/*
* 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.caches
import com.intellij.ProjectTopics
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.module.Module
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.rootManager
import com.intellij.openapi.roots.ModuleRootEvent
import com.intellij.openapi.roots.ModuleRootListener
import com.intellij.openapi.util.Key
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.openapi.vfs.newvfs.BulkFileListener
import com.intellij.openapi.vfs.newvfs.events.*
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiManager
import com.intellij.psi.impl.PsiManagerEx
import com.intellij.psi.impl.PsiTreeChangeEventImpl
import com.intellij.psi.impl.PsiTreeChangePreprocessor
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.caches.PerModulePackageCacheService.Companion.DEBUG_LOG_ENABLE_PerModulePackageCache
import org.jetbrains.kotlin.idea.caches.PerModulePackageCacheService.Companion.FULL_DROP_THRESHOLD
import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo
import org.jetbrains.kotlin.idea.caches.project.getModuleInfoByVirtualFile
import org.jetbrains.kotlin.idea.caches.project.getNullableModuleInfo
import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil
import org.jetbrains.kotlin.idea.util.getSourceRoot
import org.jetbrains.kotlin.idea.util.sourceRoot
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtPackageDirective
import org.jetbrains.kotlin.psi.NotNullableUserDataProperty
import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ConcurrentMap
class KotlinPackageContentModificationListener(private val project: Project) : Disposable {
val connection = project.messageBus.connect()
companion object {
val LOG = Logger.getInstance(this::class.java)
}
init {
connection.subscribe(VirtualFileManager.VFS_CHANGES, object : BulkFileListener {
override fun before(events: MutableList<out VFileEvent>) = onEvents(events, false)
override fun after(events: List<VFileEvent>) = onEvents(events, true)
private fun isRelevant(event: VFileEvent): Boolean = when (event) {
is VFilePropertyChangeEvent -> false
is VFileCreateEvent -> true
is VFileMoveEvent -> true
is VFileDeleteEvent -> true
is VFileContentChangeEvent -> true
is VFileCopyEvent -> true
else -> {
LOG.warn("Unknown vfs event: ${event.javaClass}")
false
}
}
fun onEvents(events: List<VFileEvent>, isAfter: Boolean) {
val service = PerModulePackageCacheService.getInstance(project)
val fileManager = PsiManagerEx.getInstanceEx(project).fileManager
if (events.size >= FULL_DROP_THRESHOLD) {
service.onTooComplexChange()
} else {
events.asSequence()
.filter(::isRelevant)
.filter {
(it.isValid || it !is VFileCreateEvent) && it.file != null
}
.filter {
val vFile = it.file!!
vFile.isDirectory || vFile.fileType == KotlinFileType.INSTANCE
}
.filter {
// It expected that content change events will be duplicated with more precise PSI events and processed
// in KotlinPackageStatementPsiTreeChangePreprocessor, but events might have been missing if PSI view provider
// is absent.
if (it is VFileContentChangeEvent) {
isAfter && fileManager.findCachedViewProvider(it.file) == null
} else {
true
}
}
.filter {
when (val origin = it.requestor) {
is Project -> origin == project
is PsiManager -> origin.project == project
else -> true
}
}
.forEach { event -> service.notifyPackageChange(event) }
}
}
})
connection.subscribe(ProjectTopics.PROJECT_ROOTS, object : ModuleRootListener {
override fun rootsChanged(event: ModuleRootEvent) {
PerModulePackageCacheService.getInstance(project).onTooComplexChange()
}
})
}
override fun dispose() {
connection.disconnect()
}
}
class KotlinPackageStatementPsiTreeChangePreprocessor(private val project: Project) : PsiTreeChangePreprocessor {
override fun treeChanged(event: PsiTreeChangeEventImpl) {
val eFile = event.file ?: event.child as? PsiFile
if (eFile == null) {
LOG.debugIfEnabled(project, true) { "Got PsiEvent: $event without file" }
}
val file = eFile as? KtFile ?: return
when (event.code) {
PsiTreeChangeEventImpl.PsiEventType.CHILD_ADDED,
PsiTreeChangeEventImpl.PsiEventType.CHILD_MOVED,
PsiTreeChangeEventImpl.PsiEventType.CHILD_REPLACED,
PsiTreeChangeEventImpl.PsiEventType.CHILD_REMOVED -> {
val child = event.child ?: run {
LOG.debugIfEnabled(project, true) { "Got PsiEvent: $event without child" }
return
}
if (child.getParentOfType<KtPackageDirective>(false) != null)
ServiceManager.getService(project, PerModulePackageCacheService::class.java).notifyPackageChange(file)
}
PsiTreeChangeEventImpl.PsiEventType.CHILDREN_CHANGED -> {
val parent = event.parent ?: run {
LOG.debugIfEnabled(project, true) { "Got PsiEvent: $event without parent" }
return
}
val childrenOfType = parent.getChildrenOfType<KtPackageDirective>()
if (
(!event.isGenericChange && (childrenOfType.any() || parent is KtPackageDirective)) ||
(childrenOfType.any { it.name.isEmpty() } && parent is KtFile)
) {
ServiceManager.getService(project, PerModulePackageCacheService::class.java).notifyPackageChange(file)
}
}
else -> {
}
}
}
companion object {
val LOG = Logger.getInstance(this::class.java)
}
}
private typealias ImplicitPackageData = MutableMap<FqName, MutableList<VirtualFile>>
class ImplicitPackagePrefixCache(private val project: Project) {
private val implicitPackageCache = ConcurrentHashMap<VirtualFile, ImplicitPackageData>()
fun getPrefix(sourceRoot: VirtualFile): FqName {
val implicitPackageMap = implicitPackageCache.getOrPut(sourceRoot) { analyzeImplicitPackagePrefixes(sourceRoot) }
return implicitPackageMap.keys.singleOrNull() ?: FqName.ROOT
}
internal fun clear() {
implicitPackageCache.clear()
}
private fun analyzeImplicitPackagePrefixes(sourceRoot: VirtualFile): MutableMap<FqName, MutableList<VirtualFile>> {
val result = mutableMapOf<FqName, MutableList<VirtualFile>>()
val ktFiles = sourceRoot.children.filter { it.fileType == KotlinFileType.INSTANCE }
for (ktFile in ktFiles) {
result.addFile(ktFile)
}
return result
}
private fun ImplicitPackageData.addFile(ktFile: VirtualFile) {
synchronized(this) {
val psiFile = PsiManager.getInstance(project).findFile(ktFile) as? KtFile ?: return
addPsiFile(psiFile, ktFile)
}
}
private fun ImplicitPackageData.addPsiFile(
psiFile: KtFile,
ktFile: VirtualFile
) = getOrPut(psiFile.packageFqName) { mutableListOf() }.add(ktFile)
private fun ImplicitPackageData.removeFile(file: VirtualFile) {
synchronized(this) {
for ((key, value) in this) {
if (value.remove(file)) {
if (value.isEmpty()) remove(key)
break
}
}
}
}
private fun ImplicitPackageData.updateFile(file: KtFile) {
synchronized(this) {
removeFile(file.virtualFile)
addPsiFile(file, file.virtualFile)
}
}
internal fun update(event: VFileEvent) {
when (event) {
is VFileCreateEvent -> checkNewFileInSourceRoot(event.file)
is VFileDeleteEvent -> checkDeletedFileInSourceRoot(event.file)
is VFileCopyEvent -> {
val newParent = event.newParent
if (newParent.isValid) {
checkNewFileInSourceRoot(newParent.findChild(event.newChildName))
}
}
is VFileMoveEvent -> {
checkNewFileInSourceRoot(event.file)
if (event.oldParent.getSourceRoot(project) == event.oldParent) {
implicitPackageCache[event.oldParent]?.removeFile(event.file)
}
}
}
}
private fun checkNewFileInSourceRoot(file: VirtualFile?) {
if (file == null) return
if (file.getSourceRoot(project) == file.parent) {
implicitPackageCache[file.parent]?.addFile(file)
}
}
private fun checkDeletedFileInSourceRoot(file: VirtualFile?) {
val directory = file?.parent
if (directory == null || !directory.isValid) return
if (directory.getSourceRoot(project) == directory) {
implicitPackageCache[directory]?.removeFile(file)
}
}
internal fun update(ktFile: KtFile) {
val parent = ktFile.virtualFile?.parent ?: return
if (ktFile.sourceRoot == parent) {
implicitPackageCache[parent]?.updateFile(ktFile)
}
}
}
class PerModulePackageCacheService(private val project: Project) : Disposable {
/*
* Actually an WeakMap<Module, SoftMap<ModuleSourceInfo, SoftMap<FqName, Boolean>>>
*/
private val cache = ContainerUtil.createConcurrentWeakMap<Module, ConcurrentMap<ModuleSourceInfo, ConcurrentMap<FqName, Boolean>>>()
private val implicitPackagePrefixCache = ImplicitPackagePrefixCache(project)
private val pendingVFileChanges: MutableSet<VFileEvent> = mutableSetOf()
private val pendingKtFileChanges: MutableSet<KtFile> = mutableSetOf()
private val projectScope = GlobalSearchScope.projectScope(project)
internal fun onTooComplexChange() {
clear()
}
private fun clear() {
synchronized(this) {
pendingVFileChanges.clear()
pendingKtFileChanges.clear()
cache.clear()
implicitPackagePrefixCache.clear()
}
}
internal fun notifyPackageChange(file: VFileEvent): Unit = synchronized(this) {
pendingVFileChanges += file
}
internal fun notifyPackageChange(file: KtFile): Unit = synchronized(this) {
pendingKtFileChanges += file
}
private fun invalidateCacheForModuleSourceInfo(moduleSourceInfo: ModuleSourceInfo) {
LOG.debugIfEnabled(project) { "Invalidated cache for $moduleSourceInfo" }
val perSourceInfoData = cache[moduleSourceInfo.module] ?: return
val dataForSourceInfo = perSourceInfoData[moduleSourceInfo] ?: return
dataForSourceInfo.clear()
}
private fun checkPendingChanges() = synchronized(this) {
if (pendingVFileChanges.size + pendingKtFileChanges.size >= FULL_DROP_THRESHOLD) {
onTooComplexChange()
} else {
pendingVFileChanges.processPending { event ->
val vfile = event.file ?: return@processPending
// When VirtualFile !isValid (deleted for example), it impossible to use getModuleInfoByVirtualFile
// For directory we must check both is it in some sourceRoot, and is it contains some sourceRoot
if (vfile.isDirectory || !vfile.isValid) {
for ((module, data) in cache) {
val sourceRootUrls = module.rootManager.sourceRootUrls
if (sourceRootUrls.any { url ->
vfile.containedInOrContains(url)
}) {
LOG.debugIfEnabled(project) { "Invalidated cache for $module" }
data.clear()
}
}
} else {
val infoByVirtualFile = getModuleInfoByVirtualFile(project, vfile)
if (infoByVirtualFile == null || infoByVirtualFile !is ModuleSourceInfo) {
LOG.debugIfEnabled(project) { "Skip $vfile as it has mismatched ModuleInfo=$infoByVirtualFile" }
}
(infoByVirtualFile as? ModuleSourceInfo)?.let {
invalidateCacheForModuleSourceInfo(it)
}
}
implicitPackagePrefixCache.update(event)
}
pendingKtFileChanges.processPending { file ->
if (file.virtualFile != null && file.virtualFile !in projectScope) {
LOG.debugIfEnabled(project) {
"Skip $file without vFile, or not in scope: ${file.virtualFile?.let { it !in projectScope }}"
}
return@processPending
}
val nullableModuleInfo = file.getNullableModuleInfo()
(nullableModuleInfo as? ModuleSourceInfo)?.let { invalidateCacheForModuleSourceInfo(it) }
if (nullableModuleInfo == null || nullableModuleInfo !is ModuleSourceInfo) {
LOG.debugIfEnabled(project) { "Skip $file as it has mismatched ModuleInfo=$nullableModuleInfo" }
}
implicitPackagePrefixCache.update(file)
}
}
}
private inline fun <T> MutableCollection<T>.processPending(crossinline body: (T) -> Unit) {
this.removeIf { value ->
try {
body(value)
} catch (pce: ProcessCanceledException) {
throw pce
} catch (exc: Exception) {
// Log and proceed. Otherwise pending object processing won't be cleared and exception will be thrown forever.
LOG.error(exc)
}
return@removeIf true
}
}
private fun VirtualFile.containedInOrContains(root: String) =
(VfsUtilCore.isEqualOrAncestor(url, root)
|| isDirectory && VfsUtilCore.isEqualOrAncestor(root, url))
fun packageExists(packageFqName: FqName, moduleInfo: ModuleSourceInfo): Boolean {
val module = moduleInfo.module
checkPendingChanges()
val perSourceInfoCache = cache.getOrPut(module) {
ContainerUtil.createConcurrentSoftMap()
}
val cacheForCurrentModuleInfo = perSourceInfoCache.getOrPut(moduleInfo) {
ContainerUtil.createConcurrentSoftMap()
}
return cacheForCurrentModuleInfo.getOrPut(packageFqName) {
val packageExists = PackageIndexUtil.packageExists(packageFqName, moduleInfo.contentScope(), project)
LOG.debugIfEnabled(project) { "Computed cache value for $packageFqName in $moduleInfo is $packageExists" }
packageExists
}
}
fun getImplicitPackagePrefix(sourceRoot: VirtualFile): FqName {
checkPendingChanges()
return implicitPackagePrefixCache.getPrefix(sourceRoot)
}
override fun dispose() {
clear()
}
companion object {
const val FULL_DROP_THRESHOLD = 1000
private val LOG = Logger.getInstance(this::class.java)
fun getInstance(project: Project): PerModulePackageCacheService =
ServiceManager.getService(project, PerModulePackageCacheService::class.java)
var Project.DEBUG_LOG_ENABLE_PerModulePackageCache: Boolean
by NotNullableUserDataProperty<Project, Boolean>(Key.create("debug.PerModulePackageCache"), false)
}
}
private fun Logger.debugIfEnabled(project: Project, withCurrentTrace: Boolean = false, message: () -> String) {
if (ApplicationManager.getApplication().isUnitTestMode && project.DEBUG_LOG_ENABLE_PerModulePackageCache) {
val msg = message()
if (withCurrentTrace) {
val e = Exception().apply { fillInStackTrace() }
this.debug(msg, e)
} else {
this.debug(msg)
}
}
}
@@ -1,148 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.highlighter
import com.intellij.codeHighlighting.Pass
import com.intellij.codeHighlighting.TextEditorHighlightingPass
import com.intellij.codeHighlighting.TextEditorHighlightingPassFactory
import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar
import com.intellij.codeInsight.daemon.impl.HighlightInfo
import com.intellij.codeInsight.daemon.impl.UpdateHighlightersUtil
import com.intellij.lang.annotation.Annotation
import com.intellij.lang.annotation.HighlightSeverity
import com.intellij.lang.annotation.HighlightSeverity.*
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.ProjectComponent
import com.intellij.openapi.editor.Document
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.project.DumbAware
import com.intellij.openapi.ui.MessageType
import com.intellij.openapi.wm.WindowManager
import com.intellij.openapi.wm.ex.StatusBarEx
import com.intellij.psi.PsiFile
import com.intellij.util.ui.UIUtil
import org.jetbrains.kotlin.idea.core.script.IdeScriptReportSink
import org.jetbrains.kotlin.idea.script.ScriptDiagnosticFixProvider
import org.jetbrains.kotlin.psi.KtFile
import kotlin.script.experimental.api.ScriptDiagnostic
import kotlin.script.experimental.api.SourceCode
class ScriptExternalHighlightingPass(
private val file: KtFile,
document: Document
) : TextEditorHighlightingPass(file.project, document), DumbAware {
override fun doCollectInformation(progress: ProgressIndicator) = Unit
override fun doApplyInformationToEditor() {
val document = document ?: return
if (!file.isScript()) return
val reports = IdeScriptReportSink.getReports(file)
val annotations = reports.mapNotNull { scriptDiagnostic ->
val (startOffset, endOffset) = scriptDiagnostic.location?.let { computeOffsets(document, it) } ?: 0 to 0
val exception = scriptDiagnostic.exception
val exceptionMessage = if (exception != null) " ($exception)" else ""
val message = scriptDiagnostic.message + exceptionMessage
val annotation = Annotation(
startOffset,
endOffset,
scriptDiagnostic.severity.convertSeverity() ?: return@mapNotNull null,
message,
message
)
// if range is empty, show notification panel in editor
annotation.isFileLevelAnnotation = startOffset == endOffset
for (provider in ScriptDiagnosticFixProvider.EP_NAME.extensions) {
provider.provideFixes(scriptDiagnostic).forEach {
annotation.registerFix(it)
}
}
annotation
}
val infos = annotations.map { HighlightInfo.fromAnnotation(it) }
UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument!!, 0, file.textLength, infos, colorsScheme, id)
}
private fun computeOffsets(document: Document, position: SourceCode.Location): Pair<Int, Int> {
val startLine = position.start.line.coerceLineIn(document)
val startOffset = document.offsetBy(startLine, position.start.col)
val endLine = position.end?.line?.coerceAtLeast(startLine)?.coerceLineIn(document) ?: startLine
val endOffset = document.offsetBy(
endLine,
position.end?.col ?: document.getLineEndOffset(endLine)
).coerceAtLeast(startOffset)
return startOffset to endOffset
}
private fun Int.coerceLineIn(document: Document) = coerceIn(0, document.lineCount - 1)
private fun Document.offsetBy(line: Int, col: Int): Int {
return (getLineStartOffset(line) + col).coerceIn(getLineStartOffset(line), getLineEndOffset(line))
}
private fun ScriptDiagnostic.Severity.convertSeverity(): HighlightSeverity? {
return when (this) {
ScriptDiagnostic.Severity.FATAL -> ERROR
ScriptDiagnostic.Severity.ERROR -> ERROR
ScriptDiagnostic.Severity.WARNING -> WARNING
ScriptDiagnostic.Severity.INFO -> INFORMATION
ScriptDiagnostic.Severity.DEBUG -> if (ApplicationManager.getApplication().isInternal) INFORMATION else null
}
}
private fun showNotification(file: KtFile, message: String) {
UIUtil.invokeLaterIfNeeded {
val ideFrame = WindowManager.getInstance().getIdeFrame(file.project)
if (ideFrame != null) {
val statusBar = ideFrame.statusBar as StatusBarEx
statusBar.notifyProgressByBalloon(
MessageType.WARNING,
message,
null,
null
)
}
}
}
class Factory(registrar: TextEditorHighlightingPassRegistrar) : ProjectComponent,
TextEditorHighlightingPassFactory {
init {
registrar.registerTextEditorHighlightingPass(
this,
TextEditorHighlightingPassRegistrar.Anchor.BEFORE,
Pass.UPDATE_FOLDING,
false,
false
)
}
override fun createHighlightingPass(file: PsiFile, editor: Editor): TextEditorHighlightingPass? {
if (file !is KtFile) return null
return ScriptExternalHighlightingPass(file, editor.document)
}
}
}
@@ -1,20 +0,0 @@
/*
* 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.klib
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.BaseComponent
// FIX ME WHEN BUNCH 192 REMOVED
class KlibLoadingMetadataCache : KlibLoadingMetadataCacheCompat(), BaseComponent {
companion object {
@JvmStatic
fun getInstance(): KlibLoadingMetadataCache =
ApplicationManager.getApplication().getComponent(KlibLoadingMetadataCache::class.java)
}
}
@@ -1,114 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.modules;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.PsiJavaModule;
import com.intellij.psi.PsiManager;
import com.intellij.psi.impl.light.LightJavaModule;
import kotlin.collections.ArraysKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.idea.core.FileIndexUtilsKt;
import java.io.IOException;
import java.io.InputStream;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import static com.intellij.psi.PsiJavaModule.MODULE_INFO_FILE;
// Copied from com.intellij.codeInsight.daemon.impl.analysis.ModuleHighlightUtil
public class ModuleHighlightUtil2 {
private static final Attributes.Name MULTI_RELEASE = new Attributes.Name("Multi-Release");
@Nullable
static PsiJavaModule getModuleDescriptor(@NotNull VirtualFile file, @NotNull Project project) {
ProjectFileIndex index = ProjectFileIndex.SERVICE.getInstance(project);
if (index.isInLibrary(file)) {
VirtualFile root;
if ((root = index.getClassRootForFile(file)) != null) {
VirtualFile descriptorFile = root.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE);
if (descriptorFile == null) {
VirtualFile alt = root.findFileByRelativePath("META-INF/versions/9/" + PsiJavaModule.MODULE_INFO_CLS_FILE);
if (alt != null && isMultiReleaseJar(root)) {
descriptorFile = alt;
}
}
if (descriptorFile != null) {
PsiFile psiFile = PsiManager.getInstance(project).findFile(descriptorFile);
if (psiFile instanceof PsiJavaFile) {
return ((PsiJavaFile) psiFile).getModuleDeclaration();
}
}
else if (root.getFileSystem() instanceof JarFileSystem && "jar".equalsIgnoreCase(root.getExtension())) {
return LightJavaModule.getModule(PsiManager.getInstance(project), root);
}
}
else if ((root = index.getSourceRootForFile(file)) != null) {
VirtualFile descriptorFile = root.findChild(MODULE_INFO_FILE);
if (descriptorFile != null) {
PsiFile psiFile = PsiManager.getInstance(project).findFile(descriptorFile);
if (psiFile instanceof PsiJavaFile) {
return ((PsiJavaFile) psiFile).getModuleDeclaration();
}
}
}
}
else {
Module module = index.getModuleForFile(file);
if (module != null) {
boolean isTest = FileIndexUtilsKt.isInTestSourceContentKotlinAware(index, file);
VirtualFile modularRoot = ArraysKt.singleOrNull(ModuleRootManager.getInstance(module).getSourceRoots(isTest),
root -> root.findChild(MODULE_INFO_FILE) != null);
if (modularRoot != null) {
VirtualFile moduleInfo = modularRoot.findChild(MODULE_INFO_FILE);
assert moduleInfo != null : modularRoot;
PsiFile psiFile = PsiManager.getInstance(project).findFile(moduleInfo);
if (psiFile instanceof PsiJavaFile) {
return ((PsiJavaFile) psiFile).getModuleDeclaration();
}
}
}
}
return null;
}
private static boolean isMultiReleaseJar(VirtualFile root) {
if (root.getFileSystem() instanceof JarFileSystem) {
VirtualFile manifest = root.findFileByRelativePath(JarFile.MANIFEST_NAME);
if (manifest != null) {
try (InputStream stream = manifest.getInputStream()) {
return Boolean.valueOf(new Manifest(stream).getMainAttributes().getValue(MULTI_RELEASE));
}
catch (IOException ignored) {
}
}
}
return false;
}
}
@@ -1,19 +0,0 @@
/*
* 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.completion
typealias LookupCancelService = LookupCancelWatcher
@@ -1,158 +0,0 @@
/*
* 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.completion
import com.intellij.application.subscribe
import com.intellij.codeInsight.completion.CompletionPhaseListener
import com.intellij.codeInsight.lookup.Lookup
import com.intellij.codeInsight.lookup.LookupEvent
import com.intellij.codeInsight.lookup.LookupListener
import com.intellij.codeInsight.lookup.LookupManager
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.ProjectComponent
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.EditorFactory
import com.intellij.openapi.editor.RangeMarker
import com.intellij.openapi.editor.event.CaretEvent
import com.intellij.openapi.editor.event.CaretListener
import com.intellij.openapi.editor.event.EditorFactoryEvent
import com.intellij.openapi.editor.event.EditorFactoryListener
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Key
import org.jetbrains.kotlin.idea.statistics.CompletionFUSCollector
import org.jetbrains.kotlin.idea.statistics.CompletionFUSCollector.completionStatsData
import org.jetbrains.kotlin.idea.statistics.FinishReasonStats
class LookupCancelWatcher(val project: Project) : ProjectComponent {
private class Reminiscence(editor: Editor, offset: Int) {
var editor: Editor? = editor
private var marker: RangeMarker? = editor.document.createRangeMarker(offset, offset)
// forget about auto-popup cancellation when the caret is moved to the start or before it
private var editorListener: CaretListener? = object : CaretListener {
override fun caretPositionChanged(e: CaretEvent) {
if (marker != null && (!marker!!.isValid || editor.logicalPositionToOffset(e.newPosition) <= offset)) {
dispose()
}
}
}
init {
ApplicationManager.getApplication()!!.assertIsDispatchThread()
editor.caretModel.addCaretListener(editorListener!!)
}
fun matches(editor: Editor, offset: Int): Boolean {
return editor == this.editor && marker?.startOffset == offset
}
fun dispose() {
ApplicationManager.getApplication()!!.assertIsDispatchThread()
if (marker != null) {
editor!!.caretModel.removeCaretListener(editorListener!!)
marker = null
editor = null
editorListener = null
}
}
}
private var lastReminiscence: Reminiscence? = null
companion object {
fun getInstance(project: Project): LookupCancelWatcher = project.getComponent(LookupCancelWatcher::class.java)!!
val AUTO_POPUP_AT = Key<Int>("LookupCancelWatcher.AUTO_POPUP_AT")
}
fun wasAutoPopupRecentlyCancelled(editor: Editor, offset: Int): Boolean {
return lastReminiscence?.matches(editor, offset) ?: false
}
private val lookupCancelListener = object : LookupListener {
override fun lookupCanceled(event: LookupEvent) {
val lookup = event.lookup
if (event.isCanceledExplicitly && lookup.isCompletion) {
val offset = lookup.currentItem?.getUserData(AUTO_POPUP_AT)
if (offset != null) {
lastReminiscence?.dispose()
if (offset <= lookup.editor.document.textLength) {
lastReminiscence = Reminiscence(lookup.editor, offset)
}
}
}
}
}
override fun initComponent() {
CompletionPhaseListener.TOPIC.subscribe(project, CompletionPhaseListener { isCompletionRunning ->
if (isCompletionRunning) {
if (completionStatsData != null) {
completionStatsData = completionStatsData?.copy(finishReason = FinishReasonStats.INTERRUPTED)
CompletionFUSCollector.log(completionStatsData)
completionStatsData = null
}
completionStatsData = CompletionFUSCollector.CompletionStatsData(System.currentTimeMillis())
}
if (!isCompletionRunning) {
completionStatsData = completionStatsData?.copy(finishTime = System.currentTimeMillis())
}
})
EditorFactory.getInstance().addEditorFactoryListener(
object : EditorFactoryListener {
override fun editorReleased(event: EditorFactoryEvent) {
if (lastReminiscence?.editor == event.editor) {
lastReminiscence!!.dispose()
}
}
},
project
)
LookupManager.getInstance(project).addPropertyChangeListener { event ->
if (event.propertyName == LookupManager.PROP_ACTIVE_LOOKUP) {
val lookup = event.newValue as Lookup?
lookup?.addLookupListener(lookupCancelListener)
lookup?.addLookupListener(object : LookupListener {
override fun lookupShown(event: LookupEvent) {
completionStatsData = completionStatsData?.copy(shownTime = System.currentTimeMillis())
}
override fun lookupCanceled(event: LookupEvent) {
completionStatsData = completionStatsData?.copy(
finishReason = if (event.isCanceledExplicitly) FinishReasonStats.CANCELLED else FinishReasonStats.HIDDEN
)
CompletionFUSCollector.log(completionStatsData)
completionStatsData = null
}
override fun itemSelected(event: LookupEvent) {
val eventLookup = event.lookup
val lookupIndex = eventLookup.items.indexOf(eventLookup.currentItem)
if (lookupIndex >= 0) completionStatsData = completionStatsData?.copy(selectedItem = lookupIndex)
completionStatsData = completionStatsData?.copy(finishReason = FinishReasonStats.DONE)
CompletionFUSCollector.log(completionStatsData)
completionStatsData = null
}
})
}
}
}
}
@@ -1,11 +0,0 @@
public class Testing {
public static void test() {
DefaultImpl<caret>
}
}
// EXIST: { lookupString: "DefaultImpls", tailText: " (defaultImpls.NonAbstractFun)" }
// EXIST: { lookupString: "DefaultImpls", tailText: " (defaultImpls.NonAbstractFunWithExpressionBody)" }
// EXIST: { lookupString: "DefaultImpls", tailText: " (defaultImpls.NonAbstractProperty)" }
// EXIST: { lookupString: "DefaultImpls", tailText: " (defaultImpls.NonAbstractPropertyWithBody)" }
// ABSENT: { lookupString: "DefaultImpls", tailText: " (defaultImpls.AllAbstract)" }
@@ -1,9 +0,0 @@
public class Testing {
public static void test() {
List<caret>
}
}
// EXIST: EmptyList
// EXIST: { lookupString:List,tailText:"<E> (java.util)" }
// ABSENT: { lookupString:List,tailText:"<E> (kotlin.collections)" }
@@ -1,41 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.completion.test
import com.intellij.codeInsight.completion.CompletionType
import com.intellij.openapi.util.io.FileUtil
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import java.io.File
abstract class AbstractKotlinSourceInJavaCompletionTest : KotlinFixtureCompletionBaseTestCase() {
override fun getPlatform() = JvmPlatforms.unspecifiedJvmPlatform
override fun doTest(testPath: String) {
val mockPath = RELATIVE_COMPLETION_TEST_DATA_BASE_PATH + "/injava/mockLib"
val mockLibDir = File(mockPath)
fun collectPaths(dir: File): List<String> {
return dir.listFiles()!!.flatMap {
if (it.isDirectory) {
collectPaths(it)
} else listOf(FileUtil.toSystemIndependentName(it.path))
}
}
val paths = collectPaths(mockLibDir).toTypedArray()
paths.forEach { path ->
val vFile = myFixture.copyFileToProject(path, path.substring(mockPath.length))
myFixture.configureFromExistingVirtualFile(vFile)
}
LightClassComputationControl.testWithControl(project, FileUtil.loadFile(File(testPath))) {
super.doTest(testPath)
}
}
override fun getProjectDescriptor() = LightCodeInsightFixtureTestCase.JAVA_LATEST
override fun defaultCompletionType() = CompletionType.BASIC
}
@@ -1,83 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.highlighter
import com.intellij.codeHighlighting.Pass
import com.intellij.codeHighlighting.TextEditorHighlightingPass
import com.intellij.codeHighlighting.TextEditorHighlightingPassFactory
import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar
import com.intellij.codeInsight.daemon.impl.AnnotationHolderImpl
import com.intellij.codeInsight.daemon.impl.HighlightInfo
import com.intellij.codeInsight.daemon.impl.UpdateHighlightersUtil
import com.intellij.lang.annotation.AnnotationSession
import com.intellij.lang.annotation.AnnotationHolder
import com.intellij.openapi.components.ProjectComponent
import com.intellij.openapi.editor.Document
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.project.DumbAware
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiRecursiveElementVisitor
import org.jetbrains.kotlin.psi.KtFile
class KotlinBeforeResolveHighlightingPass(
private val file: KtFile,
document: Document
) : TextEditorHighlightingPass(file.project, document), DumbAware {
@Volatile
private var annotationHolder: AnnotationHolderImpl? = null
override fun doCollectInformation(progress: ProgressIndicator) {
val annotationHolder = AnnotationHolderImpl(AnnotationSession(file))
val visitor = BeforeResolveHighlightingVisitor(annotationHolder)
val extensions = EP_NAME.extensionList.map { it.createVisitor(annotationHolder) }
file.accept(object : PsiRecursiveElementVisitor() {
override fun visitElement(element: PsiElement) {
super.visitElement(element)
element.accept(visitor)
extensions.forEach(element::accept)
}
})
this.annotationHolder = annotationHolder
}
override fun doApplyInformationToEditor() {
if (annotationHolder == null) return
val infos = annotationHolder!!.map { HighlightInfo.fromAnnotation(it) }
UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument!!, 0, file.textLength, infos, colorsScheme, id)
annotationHolder = null
}
class Factory(registrar: TextEditorHighlightingPassRegistrar) : ProjectComponent, TextEditorHighlightingPassFactory {
init {
registrar.registerTextEditorHighlightingPass(
this,
TextEditorHighlightingPassRegistrar.Anchor.BEFORE,
Pass.UPDATE_FOLDING,
false,
false
)
}
override fun createHighlightingPass(file: PsiFile, editor: Editor): TextEditorHighlightingPass? {
if (file !is KtFile) return null
return KotlinBeforeResolveHighlightingPass(file, editor.document)
}
}
companion object {
val EP_NAME = ExtensionPointName.create<BeforeResolveHighlightingExtension>("org.jetbrains.kotlin.beforeResolveHighlightingVisitor")
}
}
interface BeforeResolveHighlightingExtension {
fun createVisitor(holder: AnnotationHolder): HighlightingVisitor
}
@@ -1,61 +0,0 @@
/*
* 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.util.application
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.progress.ProgressIndicatorProvider
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.Project
fun <T> runReadAction(action: () -> T): T {
return ApplicationManager.getApplication().runReadAction<T>(action)
}
fun <T> runWriteAction(action: () -> T): T {
return ApplicationManager.getApplication().runWriteAction<T>(action)
}
fun Project.executeWriteCommand(name: String, command: () -> Unit) {
CommandProcessor.getInstance().executeCommand(this, { runWriteAction(command) }, name, null)
}
fun <T> Project.executeWriteCommand(name: String, groupId: Any? = null, command: () -> T): T {
return executeCommand<T>(name, groupId) { runWriteAction(command) }
}
fun <T> Project.executeCommand(name: String, groupId: Any? = null, command: () -> T): T {
@Suppress("UNCHECKED_CAST") var result: T = null as T
CommandProcessor.getInstance().executeCommand(this, { result = command() }, name, groupId)
@Suppress("USELESS_CAST")
return result as T
}
fun <T> runWithCancellationCheck(block: () -> T): T = block()
inline fun executeOnPooledThread(crossinline action: () -> Unit) =
ApplicationManager.getApplication().executeOnPooledThread { action() }
inline fun invokeLater(crossinline action: () -> Unit) =
ApplicationManager.getApplication().invokeLater { action() }
inline fun isUnitTestMode(): Boolean = ApplicationManager.getApplication().isUnitTestMode
inline fun <reified T : Any> Project.getServiceSafe(): T =
ServiceManager.getService(this, T::class.java) ?: error("Unable to locate service ${T::class.java.name}")
@@ -1,56 +0,0 @@
/*
* Copyright 2010-2018 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.git
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Couple
import com.intellij.openapi.util.registry.Registry
import com.intellij.openapi.vcs.FilePath
import git4idea.checkin.GitCheckinExplicitMovementProvider
import org.jetbrains.kotlin.idea.actions.pathBeforeJ2K
import org.jetbrains.kotlin.idea.git.KotlinGitBundle
import java.util.*
class KotlinExplicitMovementProvider : GitCheckinExplicitMovementProvider() {
init {
Registry.get("git.explicit.commit.renames.prohibit.multiple.calls").setValue(false)
}
override fun isEnabled(project: Project): Boolean {
return true
}
override fun getDescription(): String {
return KotlinGitBundle.message("j2k.extra.commit.description")
}
override fun getCommitMessage(oldCommitMessage: String): String {
return KotlinGitBundle.message("j2k.extra.commit.commit.message")
}
override fun collectExplicitMovements(
project: Project,
beforePaths: List<FilePath>,
afterPaths: List<FilePath>
): Collection<Movement> {
val movedChanges = ArrayList<Movement>()
for (after in afterPaths) {
val pathBeforeJ2K = after.virtualFile?.pathBeforeJ2K
if (pathBeforeJ2K != null) {
val before = beforePaths.firstOrNull { it.path == pathBeforeJ2K }
if (before != null) {
movedChanges.add(Movement(before, after))
}
}
}
return movedChanges
}
override fun afterMovementsCommitted(project: Project, movedPaths: MutableList<Couple<FilePath>>) {
movedPaths.forEach { it.second.virtualFile?.pathBeforeJ2K = null }
}
}
@@ -1,227 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ide.konan
import com.intellij.ProjectTopics
import com.intellij.notification.Notification
import com.intellij.notification.NotificationType
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.*
import com.intellij.openapi.application.ReadAction.nonBlocking
import com.intellij.openapi.components.ProjectComponent
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.guessProjectDir
import com.intellij.openapi.roots.ModuleRootEvent
import com.intellij.openapi.roots.ModuleRootListener
import com.intellij.openapi.util.text.StringUtilRt
import com.intellij.util.PathUtilRt
import com.intellij.util.concurrency.AppExecutorUtil
import org.jetbrains.concurrency.CancellablePromise
import org.jetbrains.kotlin.idea.caches.project.getModuleInfosFromIdeaModel
import org.jetbrains.kotlin.idea.configuration.klib.KotlinNativeLibraryNameUtil.isGradleLibraryName
import org.jetbrains.kotlin.idea.configuration.klib.KotlinNativeLibraryNameUtil.parseIDELibraryName
import org.jetbrains.kotlin.idea.versions.UnsupportedAbiVersionNotificationPanelProvider
import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion
import org.jetbrains.kotlin.konan.library.KONAN_STDLIB_NAME
import org.jetbrains.kotlin.idea.klib.KlibCompatibilityInfo.IncompatibleMetadata
// FIX ME WHEN BUNCH 192 REMOVED
/** TODO: merge [KotlinNativeABICompatibilityChecker] in the future with [UnsupportedAbiVersionNotificationPanelProvider], KT-34525 */
class KotlinNativeABICompatibilityChecker(private val project: Project) : ProjectComponent, Disposable {
private sealed class LibraryGroup(private val ordinal: Int) : Comparable<LibraryGroup> {
override fun compareTo(other: LibraryGroup) = when {
this == other -> 0
this is FromDistribution && other is FromDistribution -> kotlinVersion.compareTo(other.kotlinVersion)
else -> ordinal.compareTo(other.ordinal)
}
data class FromDistribution(val kotlinVersion: String) : LibraryGroup(0)
object ThirdParty : LibraryGroup(1)
object User : LibraryGroup(2)
}
private val cachedIncompatibleLibraries = HashSet<String>()
@Volatile
private var backgroundJob: CancellablePromise<*>? = null
init {
project.messageBus.connect().subscribe(ProjectTopics.PROJECT_ROOTS, object : ModuleRootListener {
override fun rootsChanged(event: ModuleRootEvent) {
// run when project roots are changes, e.g. on project import
validateKotlinNativeLibraries()
}
})
}
override fun projectOpened() {
// run when project is opened
validateKotlinNativeLibraries()
}
private fun validateKotlinNativeLibraries() {
if (ApplicationManager.getApplication().isUnitTestMode || project.isDisposed)
return
backgroundJob = nonBlocking<List<Notification>> {
val librariesToNotify = getLibrariesToNotifyAbout()
prepareNotifications(librariesToNotify)
}
.finishOnUiThread(ModalityState.defaultModalityState()) { notifications ->
notifications.forEach {
it.notify(project)
}
}
.expireWith(project) // cancel job when project is disposed
.withDocumentsCommitted(project)
.submit(AppExecutorUtil.getAppExecutorService())
.also {
it.onProcessed {
backgroundJob = null
}
}
}
private fun getLibrariesToNotifyAbout(): Map<String, NativeKlibLibraryInfo> {
val incompatibleLibraries = getModuleInfosFromIdeaModel(project)
.filterIsInstance<NativeKlibLibraryInfo>()
.filter { !it.compatibilityInfo.isCompatible }
.associateBy { it.libraryRoot }
val newEntries = if (cachedIncompatibleLibraries.isNotEmpty())
incompatibleLibraries.filterKeys { it !in cachedIncompatibleLibraries }
else
incompatibleLibraries
cachedIncompatibleLibraries.clear()
cachedIncompatibleLibraries.addAll(incompatibleLibraries.keys)
return newEntries
}
private fun prepareNotifications(librariesToNotify: Map<String, NativeKlibLibraryInfo>): List<Notification> {
if (librariesToNotify.isEmpty())
return emptyList()
val librariesByGroups = HashMap<Pair<LibraryGroup, Boolean>, MutableList<Pair<String, String>>>()
librariesToNotify.forEach { (libraryRoot, libraryInfo) ->
val isOldMetadata = (libraryInfo.compatibilityInfo as? IncompatibleMetadata)?.isOlder ?: true
val (libraryName, libraryGroup) = parseIDELibraryName(libraryInfo)
librariesByGroups.computeIfAbsent(libraryGroup to isOldMetadata) { mutableListOf() } += libraryName to libraryRoot
}
return librariesByGroups.keys.sortedWith(
compareBy(
{ (libraryGroup, _) -> libraryGroup },
{ (_, isOldMetadata) -> isOldMetadata }
)
).map { key ->
val (libraryGroup, isOldMetadata) = key
val libraries =
librariesByGroups.getValue(key).sortedWith(compareBy(LIBRARY_NAME_COMPARATOR) { (libraryName, _) -> libraryName })
val message = when (libraryGroup) {
is LibraryGroup.FromDistribution -> {
val libraryNamesInOneLine = libraries
.joinToString(limit = MAX_LIBRARY_NAMES_IN_ONE_LINE) { (libraryName, _) -> libraryName }
val text = KotlinGradleNativeBundle.message(
"error.incompatible.libraries",
libraries.size, libraryGroup.kotlinVersion, libraryNamesInOneLine
)
val explanation = when (isOldMetadata) {
true -> KotlinGradleNativeBundle.message("error.incompatible.libraries.older")
false -> KotlinGradleNativeBundle.message("error.incompatible.libraries.newer")
}
val recipe = KotlinGradleNativeBundle.message("error.incompatible.libraries.recipe", bundledRuntimeVersion())
"$text\n\n$explanation\n$recipe"
}
is LibraryGroup.ThirdParty -> {
val text = when (isOldMetadata) {
true -> KotlinGradleNativeBundle.message("error.incompatible.3p.libraries.older", libraries.size)
false -> KotlinGradleNativeBundle.message("error.incompatible.3p.libraries.newer", libraries.size)
}
val librariesLineByLine = libraries.joinToString(separator = "\n") { (libraryName, _) -> libraryName }
val recipe = KotlinGradleNativeBundle.message("error.incompatible.3p.libraries.recipe", bundledRuntimeVersion())
"$text\n$librariesLineByLine\n\n$recipe"
}
is LibraryGroup.User -> {
val projectRoot = project.guessProjectDir()?.canonicalPath
fun getLibraryTextToPrint(libraryNameAndRoot: Pair<String, String>): String {
val (libraryName, libraryRoot) = libraryNameAndRoot
val relativeRoot = projectRoot?.let {
libraryRoot.substringAfter(projectRoot)
.takeIf { it != libraryRoot }
?.trimStart('/', '\\')
?.let { "${'$'}project/$it" }
} ?: libraryRoot
return KotlinGradleNativeBundle.message("library.name.0.at.1.relative.root", libraryName, relativeRoot)
}
val text = when (isOldMetadata) {
true -> KotlinGradleNativeBundle.message("error.incompatible.user.libraries.older", libraries.size)
false -> KotlinGradleNativeBundle.message("error.incompatible.user.libraries.newer", libraries.size)
}
val librariesLineByLine = libraries.joinToString(separator = "\n", transform = ::getLibraryTextToPrint)
val recipe = KotlinGradleNativeBundle.message("error.incompatible.user.libraries.recipe", bundledRuntimeVersion())
"$text\n$librariesLineByLine\n\n$recipe"
}
}
Notification(
NOTIFICATION_GROUP_ID,
NOTIFICATION_TITLE,
StringUtilRt.convertLineSeparators(message, "<br/>"),
NotificationType.ERROR,
null
)
}
}
// returns pair of library name and library group
private fun parseIDELibraryName(libraryInfo: NativeKlibLibraryInfo): Pair<String, LibraryGroup> {
val ideLibraryName = libraryInfo.library.name?.takeIf(String::isNotEmpty)
if (ideLibraryName != null) {
parseIDELibraryName(ideLibraryName)?.let { (kotlinVersion, libraryName) ->
return libraryName to LibraryGroup.FromDistribution(kotlinVersion)
}
if (isGradleLibraryName(ideLibraryName))
return ideLibraryName to LibraryGroup.ThirdParty
}
return (ideLibraryName ?: PathUtilRt.getFileName(libraryInfo.libraryRoot)) to LibraryGroup.User
}
override fun dispose() {
backgroundJob?.let(CancellablePromise<*>::cancel)
backgroundJob = null
cachedIncompatibleLibraries.clear()
}
companion object {
private val LIBRARY_NAME_COMPARATOR = Comparator<String> { libraryName1, libraryName2 ->
when {
libraryName1 == libraryName2 -> 0
libraryName1 == KONAN_STDLIB_NAME -> -1 // stdlib must go the first
libraryName2 == KONAN_STDLIB_NAME -> 1
else -> libraryName1.compareTo(libraryName2)
}
}
private const val MAX_LIBRARY_NAMES_IN_ONE_LINE = 5
private val NOTIFICATION_TITLE get() = KotlinGradleNativeBundle.message("error.incompatible.libraries.title")
private const val NOTIFICATION_GROUP_ID = "Incompatible Kotlin/Native libraries"
}
}
@@ -1,6 +0,0 @@
#if (${MODULE_GROUP} && ${MODULE_GROUP} != "")
group = "${MODULE_GROUP}"
#end
#if (${MODULE_VERSION} && ${MODULE_VERSION} != "")
version = "${MODULE_VERSION}"
#end
@@ -1,20 +0,0 @@
#if (${PROJECT_NAME} && ${PROJECT_NAME} != "")
#if (((!${MODULE_PATH} || ${MODULE_PATH} == "")) && (${MODULE_NAME} && ${MODULE_NAME} != ""))
rootProject.name = '${MODULE_NAME}'
#else
rootProject.name = '${PROJECT_NAME}'
#end
#end
#if (${MODULE_PATH} && ${MODULE_PATH} != "")
#if (${MODULE_FLAT_DIR} == "true")includeFlat '${MODULE_PATH}'
#else
include '${MODULE_PATH}'
#end
#if (${MODULE_NAME} && ${MODULE_NAME} != "" && ${MODULE_PATH} != ${MODULE_NAME})
findProject(':${MODULE_PATH}')?.name = '${MODULE_NAME}'
#end
#end
#if (${BUILD_FILE_NAME} && ${BUILD_FILE_NAME} != "")
rootProject.buildFileName = '${BUILD_FILE_NAME}'
#end
@@ -1,87 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.actions
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.ide.actions.ShowFilePathAction
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.DumbAware
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.MessageType
import com.intellij.openapi.ui.popup.JBPopupFactory
import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.wm.WindowManager
import com.intellij.psi.PsiFile
import com.intellij.ui.BrowserHyperlinkListener
import org.jetbrains.kotlin.idea.KotlinIdeaGradleBundle
import java.io.File
class ShowKotlinGradleDslLogs : IntentionAction, AnAction(), DumbAware {
override fun invoke(project: Project, editor: Editor?, file: PsiFile?) {
openLogsDirIfPresent(project)
}
override fun actionPerformed(e: AnActionEvent) {
openLogsDirIfPresent(e.project)
}
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile?) = ShowFilePathAction.isSupported()
override fun update(e: AnActionEvent) {
val presentation = e.presentation
presentation.isVisible = ShowFilePathAction.isSupported()
presentation.text = NAME
}
private fun openLogsDirIfPresent(project: Project?) {
val logsDir = findLogsDir()
if (logsDir != null) {
ShowFilePathAction.openDirectory(logsDir)
} else {
val parent = WindowManager.getInstance().getStatusBar(project)?.component
?: WindowManager.getInstance().findVisibleFrame().rootPane
JBPopupFactory.getInstance()
.createHtmlTextBalloonBuilder(
KotlinIdeaGradleBundle.message(
"text.gradle.dsl.logs.cannot.be.found.automatically.see.how.to.find.logs",
gradleTroubleshootingLink
),
MessageType.ERROR,
BrowserHyperlinkListener.INSTANCE
)
.setFadeoutTime(5000)
.createBalloon()
.showInCenterOf(parent)
}
}
/** The way how to find Gradle logs is described here
* @see org.jetbrains.kotlin.idea.actions.ShowKotlinGradleDslLogs.gradleTroubleshootingLink
*/
private fun findLogsDir(): File? {
val userHome = System.getProperty("user.home")
return when {
SystemInfo.isMac -> File("$userHome/Library/Logs/gradle-kotlin-dsl")
SystemInfo.isLinux -> File("$userHome/.gradle-kotlin-dsl/logs")
SystemInfo.isWindows -> File("$userHome/AppData/Local/gradle-kotlin-dsl/log")
else -> null
}.takeIf { it?.exists() == true }
}
override fun startInWriteAction() = false
override fun getText() = NAME
override fun getFamilyName() = NAME
companion object {
private const val gradleTroubleshootingLink = "https://docs.gradle.org/current/userguide/kotlin_dsl.html#troubleshooting"
val NAME = KotlinIdeaGradleBundle.message("action.text.show.kotlin.gradle.dsl.logs.in", ShowFilePathAction.getFileManagerName())
}
}
@@ -1,38 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.configuration
import com.intellij.ide.plugins.PluginManager
import com.intellij.notification.Notification
import com.intellij.notification.NotificationAction
import com.intellij.notification.NotificationType
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.extensions.PluginId
import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.PluginsAdvertiser
import com.intellij.util.PlatformUtils
import org.jetbrains.kotlin.idea.KotlinIdeaGradleBundle
const val NATIVE_DEBUG_ID = "com.intellij.nativeDebug"
fun suggestNativeDebug(projectPath: String) {
if (!PlatformUtils.isIdeaUltimate() ||
PluginManager.isPluginInstalled(PluginId.getId(NATIVE_DEBUG_ID))) {
return
}
val project = ProjectManager.getInstance().openProjects.firstOrNull { it.basePath == projectPath } ?: return
PluginsAdvertiser.NOTIFICATION_GROUP.createNotification(
KotlinIdeaGradleBundle.message("title.plugin.suggestion"),
KotlinIdeaGradleBundle.message("notification.text.native.debug.provides.debugger.for.kotlin.native"),
NotificationType.INFORMATION, null
).addAction(object : NotificationAction(KotlinIdeaGradleBundle.message("action.text.install")) {
override fun actionPerformed(e: AnActionEvent, notification: Notification) {
PluginsAdvertiser.installAndEnablePlugins(setOf(NATIVE_DEBUG_ID)) { notification.expire() }
}
}).notify(project)
}
@@ -1,366 +0,0 @@
/*
* Copyright 2010-2018 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.gradle.execution;
import com.intellij.build.BuildViewManager;
import com.intellij.compiler.impl.CompilerUtil;
import com.intellij.execution.executors.DefaultRunExecutor;
import com.intellij.openapi.compiler.ex.CompilerPathsEx;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.ProjectKeys;
import com.intellij.openapi.externalSystem.model.execution.ExternalSystemTaskExecutionSettings;
import com.intellij.openapi.externalSystem.model.project.ModuleData;
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode;
import com.intellij.openapi.externalSystem.task.TaskCallback;
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootModificationTracker;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.task.*;
import com.intellij.task.impl.JpsProjectTaskRunner;
import com.intellij.util.SmartList;
import com.intellij.util.SystemProperties;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.FactoryMap;
import com.intellij.util.containers.MultiMap;
import org.intellij.lang.annotations.Language;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.config.KotlinFacetSettings;
import org.jetbrains.kotlin.idea.KotlinIdeaGradleBundle;
import org.jetbrains.kotlin.idea.facet.KotlinFacet;
import org.jetbrains.kotlin.platform.TargetPlatformKt;
import org.jetbrains.kotlin.platform.TargetPlatform;
import org.jetbrains.kotlin.platform.konan.NativePlatformKt;
import org.jetbrains.plugins.gradle.execution.build.CachedModuleDataFinder;
import org.jetbrains.plugins.gradle.execution.build.GradleProjectTaskRunner;
import org.jetbrains.plugins.gradle.service.project.GradleBuildSrcProjectsResolver;
import org.jetbrains.plugins.gradle.service.project.GradleProjectResolverUtil;
import org.jetbrains.plugins.gradle.service.task.GradleTaskManager;
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings;
import org.jetbrains.plugins.gradle.settings.GradleSettings;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import java.io.File;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import static com.intellij.openapi.externalSystem.service.execution.ExternalSystemRunConfiguration.PROGRESS_LISTENER_KEY;
import static com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil.*;
import static com.intellij.openapi.util.text.StringUtil.*;
import static org.jetbrains.plugins.gradle.execution.GradleRunnerUtil.resolveProjectPath;
/**
* This is a modified copy of {@link GradleProjectTaskRunner} that allows building Kotlin Common and Kotlin Native modules
* in IDEA by delegating to Gradle builder ("Delegate IDE build/run actions to gradle"). See #KT-27295, #KT-27296.
*
* TODO: Refactor this class to remove duplicated logic when {@link GradleProjectTaskRunner} will allow extending it to
* collect custom Gradle tasks. See #IDEA-204372, #KT-28880.
*/
class KotlinMPPGradleProjectTaskRunner extends ProjectTaskRunner
{
@Language("Groovy")
private static final String FORCE_COMPILE_TASKS_INIT_SCRIPT_TEMPLATE = "projectsEvaluated { \n" +
" rootProject.findProject('%s')?.tasks?.withType(AbstractCompile) { \n" +
" outputs.upToDateWhen { false } \n" +
" } \n" +
"}\n";
@Override
public void run(@NotNull Project project,
@NotNull ProjectTaskContext context,
@Nullable ProjectTaskNotification callback,
@NotNull Collection<? extends ProjectTask> tasks) {
MultiMap<String, String> buildTasksMap = MultiMap.createLinkedSet();
MultiMap<String, String> cleanTasksMap = MultiMap.createLinkedSet();
MultiMap<String, String> initScripts = MultiMap.createLinkedSet();
Map<Class<? extends ProjectTask>, List<ProjectTask>> taskMap = JpsProjectTaskRunner.groupBy(tasks);
List<Module> modules = addModulesBuildTasks(taskMap.get(ModuleBuildTask.class), buildTasksMap, initScripts);
// TODO there should be 'gradle' way to build files instead of related modules entirely
List<Module> modulesOfFiles = addModulesBuildTasks(taskMap.get(ModuleFilesBuildTask.class), buildTasksMap, initScripts);
// TODO send a message if nothing to build
Set<String> rootPaths = buildTasksMap.keySet();
AtomicInteger successCounter = new AtomicInteger();
AtomicInteger errorCounter = new AtomicInteger();
TaskCallback taskCallback = callback == null ? null : new TaskCallback() {
@Override
public void onSuccess() {
handle(true);
}
@Override
public void onFailure() {
handle(false);
}
private void handle(boolean success) {
int successes = success ? successCounter.incrementAndGet() : successCounter.get();
int errors = success ? errorCounter.get() : errorCounter.incrementAndGet();
if (successes + errors == rootPaths.size()) {
if (!project.isDisposed()) {
// refresh on output roots is required in order for the order enumerator to see all roots via VFS
final List<Module> affectedModules = ContainerUtil.concat(modules, modulesOfFiles);
// have to refresh in case of errors too, because run configuration may be set to ignore errors
Collection<String> affectedRoots = ContainerUtil.newHashSet(
CompilerPathsEx.getOutputPaths(affectedModules.toArray(Module.EMPTY_ARRAY)));
if (!affectedRoots.isEmpty()) {
CompilerUtil.refreshOutputRoots(affectedRoots);
}
}
callback.finished(new ProjectTaskResult(false, errors, 0));
}
}
};
// TODO compiler options should be configurable
@Language("Groovy")
String compilerOptionsInitScript = "allprojects {\n" +
" tasks.withType(JavaCompile) {\n" +
" options.compilerArgs += [\"-Xlint:deprecation\"]\n" +
" }" +
"}\n";
String gradleVmOptions = GradleSettings.getInstance(project).getGradleVmOptions();
for (String rootProjectPath : rootPaths) {
Collection<String> buildTasks = buildTasksMap.get(rootProjectPath);
if (buildTasks.isEmpty()) continue;
Collection<String> cleanTasks = cleanTasksMap.get(rootProjectPath);
ExternalSystemTaskExecutionSettings settings = new ExternalSystemTaskExecutionSettings();
File projectFile = new File(rootProjectPath);
final String projectName;
if (projectFile.isFile()) {
projectName = projectFile.getParentFile().getName();
}
else {
projectName = projectFile.getName();
}
String executionName = KotlinIdeaGradleBundle.message("build.0.project", projectName);
settings.setExecutionName(executionName);
settings.setExternalProjectPath(rootProjectPath);
settings.setTaskNames(ContainerUtil.collect(ContainerUtil.concat(cleanTasks, buildTasks).iterator()));
//settings.setScriptParameters(scriptParameters);
settings.setVmOptions(gradleVmOptions);
settings.setExternalSystemIdString(GradleConstants.SYSTEM_ID.getId());
UserDataHolderBase userData = new UserDataHolderBase();
userData.putUserData(PROGRESS_LISTENER_KEY, BuildViewManager.class);
Collection<String> scripts = initScripts.getModifiable(rootProjectPath);
scripts.add(compilerOptionsInitScript);
userData.putUserData(GradleTaskManager.INIT_SCRIPT_KEY, join(scripts, SystemProperties.getLineSeparator()));
userData.putUserData(GradleTaskManager.INIT_SCRIPT_PREFIX_KEY, executionName);
ExternalSystemUtil.runTask(settings, DefaultRunExecutor.EXECUTOR_ID, project, GradleConstants.SYSTEM_ID,
taskCallback, ProgressExecutionMode.IN_BACKGROUND_ASYNC, false, userData);
}
}
@Override
public boolean canRun(@NotNull ProjectTask projectTask) {
if (projectTask instanceof ModuleBuildTask) {
final ModuleBuildTask moduleBuildTask = (ModuleBuildTask) projectTask;
final Module module = moduleBuildTask.getModule();
if (module.getProject().getPresentableUrl() == null || !GradleProjectSettings.isDelegatedBuildEnabled(module)) {
return false;
}
if (!isExternalSystemAwareModule(GradleConstants.SYSTEM_ID, module)) return false;
// ---------------------------------------- //
// TODO BEGIN: Extract custom Kotlin logic. //
// ---------------------------------------- //
if (isProjectWithNativeSourceOrCommonProductionSourceModules(module.getProject())) return true;
// ---------------------------------------- //
// TODO END: Extract custom Kotlin logic. //
// ---------------------------------------- //
}
return false;
}
private static List<Module> addModulesBuildTasks(@Nullable Collection<? extends ProjectTask> projectTasks,
@NotNull MultiMap<String, String> buildTasksMap,
@NotNull MultiMap<String, String> initScripts) {
if (ContainerUtil.isEmpty(projectTasks)) return Collections.emptyList();
List<Module> affectedModules = new SmartList<>();
Map<Module, String> rootPathsMap = FactoryMap.create(module -> notNullize(resolveProjectPath(module)));
final CachedModuleDataFinder moduleDataFinder = new CachedModuleDataFinder();
for (ProjectTask projectTask : projectTasks) {
if (!(projectTask instanceof ModuleBuildTask)) continue;
ModuleBuildTask moduleBuildTask = (ModuleBuildTask)projectTask;
Module module = moduleBuildTask.getModule();
affectedModules.add(module);
final String rootProjectPath = rootPathsMap.get(module);
if (isEmpty(rootProjectPath)) continue;
final String projectId = getExternalProjectId(module);
if (projectId == null) continue;
final String externalProjectPath = getExternalProjectPath(module);
if (externalProjectPath == null || endsWith(externalProjectPath, "buildSrc")) continue;
final DataNode<? extends ModuleData> moduleDataNode = moduleDataFinder.findMainModuleData(module);
if (moduleDataNode == null) continue;
// all buildSrc runtime projects will be built by gradle implicitly
if (Boolean.parseBoolean(moduleDataNode.getData().getProperty(GradleBuildSrcProjectsResolver.BUILD_SRC_MODULE_PROPERTY))) {
continue;
}
String gradlePath = GradleProjectResolverUtil.getGradlePath(module);
if (gradlePath == null) continue;
String taskPrefix = endsWithChar(gradlePath, ':') ? gradlePath : (gradlePath + ':');
List<String> gradleTasks = ContainerUtil.mapNotNull(
findAll(moduleDataNode, ProjectKeys.TASK), node ->
node.getData().isInherited() ? null : trimStart(node.getData().getName(), taskPrefix));
Collection<String> projectInitScripts = initScripts.getModifiable(rootProjectPath);
Collection<String> buildRootTasks = buildTasksMap.getModifiable(rootProjectPath);
final String moduleType = getExternalModuleType(module);
if (!moduleBuildTask.isIncrementalBuild()) {
projectInitScripts.add(String.format(FORCE_COMPILE_TASKS_INIT_SCRIPT_TEMPLATE, gradlePath));
}
String assembleTask = "assemble";
if (GradleConstants.GRADLE_SOURCE_SET_MODULE_TYPE_KEY.equals(moduleType)) {
String sourceSetName = GradleProjectResolverUtil.getSourceSetName(module);
String gradleTask = isEmpty(sourceSetName) || "main".equals(sourceSetName) ? "classes" : sourceSetName + "Classes";
if (gradleTasks.contains(gradleTask)) {
buildRootTasks.add(taskPrefix + gradleTask);
}
else if ("main".equals(sourceSetName) || "test".equals(sourceSetName)) {
buildRootTasks.add(taskPrefix + assembleTask);
}
// ---------------------------------------- //
// TODO BEGIN: Extract custom Kotlin logic. //
// ---------------------------------------- //
else if (isNativeSourceModule(module)) {
// Add tasks for Kotlin/Native.
buildRootTasks.addAll(addPrefix(findNativeGradleBuildTasks(gradleTasks, sourceSetName), taskPrefix));
}
else if (isCommonProductionSourceModule(module)) {
// Add tasks for compiling metadata.
buildRootTasks.addAll(addPrefix(findMetadataBuildTasks(gradleTasks, sourceSetName), taskPrefix));
}
// ---------------------------------------- //
// TODO END: Extract custom Kotlin logic. //
// ---------------------------------------- //
}
else {
if (gradleTasks.contains("classes")) {
buildRootTasks.add(taskPrefix + "classes");
buildRootTasks.add(taskPrefix + "testClasses");
}
else if (gradleTasks.contains(assembleTask)) {
buildRootTasks.add(taskPrefix + assembleTask);
}
}
}
return affectedModules;
}
// ---------------------------------------- //
// TODO BEGIN: Extract custom Kotlin logic. //
// ---------------------------------------- //
private static boolean isProjectWithNativeSourceOrCommonProductionSourceModules(Project project) {
return CachedValuesManager.getManager(project).getCachedValue(
project,
() -> new CachedValueProvider.Result<>(
Arrays.stream(ModuleManager.getInstance(project).getModules()).anyMatch(
module -> isNativeSourceModule(module) || isCommonProductionSourceModule(module)
),
ProjectRootModificationTracker.getInstance(project)
));
}
private static boolean isNativeSourceModule(Module module) {
final KotlinFacet kotlinFacet = KotlinFacet.Companion.get(module);
if (kotlinFacet == null) return false;
final TargetPlatform platform = kotlinFacet.getConfiguration().getSettings().getTargetPlatform();
if (platform == null) return false;
return NativePlatformKt.isNative(platform);
}
private static boolean isCommonProductionSourceModule(Module module) {
final KotlinFacet kotlinFacet = KotlinFacet.Companion.get(module);
if (kotlinFacet == null) return false;
final KotlinFacetSettings facetSettings = kotlinFacet.getConfiguration().getSettings();
if (facetSettings.isTestModule()) return false;
final TargetPlatform platform = facetSettings.getTargetPlatform();
if (platform == null) return false;
return TargetPlatformKt.isCommon(platform);
}
private static Collection<String> findNativeGradleBuildTasks(Collection<String> gradleTasks, String sourceSetName) {
// First, attempt to find Kotlin/Native convention Gradle task that unites all outputType-specific build tasks.
final String conventionGradleTask = sourceSetName + "Binaries";
if (gradleTasks.contains(conventionGradleTask)) {
return Collections.singletonList(conventionGradleTask);
}
// If convention task not found, then attempt to find all appropriate build tasks for the given source set.
final Collection<String> linkPrefixes;
final String targetName;
if (sourceSetName.endsWith("Main")) {
targetName = StringUtil.substringBeforeLast(sourceSetName,"Main");
linkPrefixes = ContainerUtil.newArrayList("link", "linkMain");
}
else if (sourceSetName.endsWith("Test")) {
targetName = StringUtil.substringBeforeLast(sourceSetName,"Test");
linkPrefixes = Collections.singletonList("linkTest");
}
else {
targetName = sourceSetName;
linkPrefixes = Collections.singletonList("link");
}
return linkPrefixes.stream()
// get base task name (without disambiguation classifier)
.map(linkPrefix -> linkPrefix + capitalize(targetName))
// find all Gradle tasks that start with base task name
.flatMap(nativeTaskName -> gradleTasks.stream().filter(taskName -> taskName.startsWith(nativeTaskName)))
.collect(Collectors.toList());
}
private static Collection<String> findMetadataBuildTasks(Collection<String> gradleTasks, String sourceSetName) {
if ("commonMain".equals(sourceSetName)) {
final String metadataTaskName = "metadataMainClasses";
if (gradleTasks.contains(metadataTaskName)) {
return Collections.singletonList(metadataTaskName);
}
}
return Collections.emptyList();
}
private static Collection<String> addPrefix(Collection<String> tasks, String taskPrefix) {
return tasks.stream().map(task -> taskPrefix + task).collect(Collectors.toList());
}
// ---------------------------------------- //
// TODO END: Extract custom Kotlin logic. //
// ---------------------------------------- //
}
@@ -1,124 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.gradle.testing
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.externalSystem.model.DataNode
import com.intellij.openapi.externalSystem.model.ProjectKeys
import com.intellij.openapi.externalSystem.model.project.ModuleData
import com.intellij.openapi.externalSystem.model.project.ProjectData
import com.intellij.openapi.externalSystem.model.task.TaskData
import com.intellij.openapi.externalSystem.util.Order
import com.intellij.openapi.util.registry.Registry
import com.intellij.util.Consumer
import org.gradle.tooling.model.idea.IdeaModule
import org.jetbrains.kotlin.gradle.KotlinMPPGradleModel
import org.jetbrains.kotlin.gradle.KotlinMPPGradleModelBuilder
import org.jetbrains.kotlin.idea.configuration.getMppModel
import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension
@Order(Int.MIN_VALUE)
open class KotlinTestTasksResolver : AbstractProjectResolverExtension() {
companion object {
private const val ENABLED_REGISTRY_KEY = "kotlin.gradle.testing.enabled"
}
private val LOG by lazy { Logger.getInstance(KotlinTestTasksResolver::class.java) }
override fun getToolingExtensionsClasses(): Set<Class<out Any>> {
return setOf(KotlinMPPGradleModelBuilder::class.java, Unit::class.java)
}
override fun populateModuleTasks(
gradleModule: IdeaModule,
ideModule: DataNode<ModuleData>,
ideProject: DataNode<ProjectData>
): MutableCollection<TaskData> {
if (!Registry.`is`(ENABLED_REGISTRY_KEY))
return super.populateModuleTasks(gradleModule, ideModule, ideProject)
val mppModel = resolverCtx.getMppModel(gradleModule)
?: return super.populateModuleTasks(gradleModule, ideModule, ideProject)
return postprocessTaskData(mppModel, ideModule, nextResolver.populateModuleTasks(gradleModule, ideModule, ideProject))
}
private fun postprocessTaskData(
mppModel: KotlinMPPGradleModel,
ideModule: DataNode<ModuleData>,
originalTaskData: MutableCollection<TaskData>
): MutableCollection<TaskData> {
val testTaskNames = mutableSetOf<String>().apply {
mppModel.targets.forEach { target ->
target.testRunTasks.forEach { testTaskModel ->
add(testTaskModel.taskName)
}
}
}
fun buildNewTaskDataMarkedAsTest(original: TaskData): TaskData =
TaskData(original.owner, original.name, original.linkedExternalProjectPath, original.description).apply {
group = original.group
type = original.type
isInherited = original.isInherited
isTest = true
}
val replacementMap: Map<TaskData, TaskData> = mutableMapOf<TaskData, TaskData>().apply {
originalTaskData.forEach {
if (it.name in testTaskNames && !it.isTest) {
put(it, buildNewTaskDataMarkedAsTest(it))
}
}
}
ideModule.children.filter { it.data in replacementMap }.forEach { it.clear(true) }
replacementMap.values.forEach { ideModule.createChild(ProjectKeys.TASK, it) }
return originalTaskData.mapTo(arrayListOf<TaskData>()) { replacementMap[it] ?: it }
}
override fun enhanceTaskProcessing(
taskNames: MutableList<String>,
jvmParametersSetup: String?,
initScriptConsumer: Consumer<String>,
testExecutionExpected: kotlin.Boolean
) {
if (!Registry.`is`(ENABLED_REGISTRY_KEY))
return
if (testExecutionExpected) {
try {
val addTestListenerScript = javaClass
.getResourceAsStream("/org/jetbrains/kotlin/idea/gradle/testing/addKotlinMppTestListener.groovy")
.bufferedReader()
.readText()
initScriptConsumer.consume(addTestListenerScript)
} catch (e: Exception) {
LOG.error(e)
}
}
enhanceTaskProcessing(taskNames, jvmParametersSetup, initScriptConsumer)
}
override fun enhanceTaskProcessing(taskNames: MutableList<String>, jvmAgentSetup: String?, initScriptConsumer: Consumer<String>) {
if (!Registry.`is`(ENABLED_REGISTRY_KEY))
return
try {
val testLoggerScript = javaClass
.getResourceAsStream("/org/jetbrains/kotlin/idea/gradle/testing/KotlinMppTestLogger.groovy")
.bufferedReader()
.readText()
initScriptConsumer.consume(testLoggerScript)
} catch (e: Exception) {
LOG.error(e)
}
}
}
@@ -1,62 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.run
import com.intellij.execution.Location
import com.intellij.execution.actions.ConfigurationFromContext
import com.intellij.execution.junit.JUnitConfigurationProducer
import com.intellij.execution.testframework.AbstractPatternBasedConfigurationProducer
import com.intellij.ide.plugins.PluginManager
import com.intellij.openapi.extensions.PluginId.getId
import com.intellij.openapi.util.component1
import com.intellij.openapi.util.component2
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiMethod
import org.jetbrains.kotlin.idea.KotlinLanguage
private val isJUnitEnabled by lazy { isPluginEnabled("JUnit") }
private val isTestNgEnabled by lazy { isPluginEnabled("TestNG-J") }
private fun isPluginEnabled(id: String): Boolean {
return PluginManager.isPluginInstalled(getId(id)) && id !in PluginManager.getDisabledPlugins()
}
internal fun ConfigurationFromContext.isJpsJunitConfiguration(): Boolean {
return isProducedBy(JUnitConfigurationProducer::class.java)
|| isProducedBy(AbstractPatternBasedConfigurationProducer::class.java)
}
internal fun canRunJvmTests() = isJUnitEnabled || isTestNgEnabled
internal fun getTestClassForJvm(location: Location<*>): PsiClass? {
val leaf = location.psiElement ?: return null
if (leaf.language != KotlinLanguage.INSTANCE) return null
if (isJUnitEnabled) {
KotlinJUnitRunConfigurationProducer.getTestClass(leaf)?.let { return it }
}
if (isTestNgEnabled) {
KotlinTestNgConfigurationProducer.getTestClassAndMethod(leaf)?.let { (testClass, testMethod) ->
return if (testMethod == null) testClass else null
}
}
return null
}
internal fun getTestMethodForJvm(location: Location<*>): PsiMethod? {
val leaf = location.psiElement ?: return null
if (leaf.language != KotlinLanguage.INSTANCE) return null
if (isJUnitEnabled) {
KotlinJUnitRunConfigurationProducer.getTestMethod(leaf)?.let { return it }
}
if (isTestNgEnabled) {
KotlinTestNgConfigurationProducer.getTestClassAndMethod(leaf)?.second?.let { return it }
}
return null
}
@@ -1,55 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.scripting.gradle.importing
import com.intellij.openapi.externalSystem.model.DataNode
import com.intellij.openapi.externalSystem.model.project.ProjectData
import org.gradle.tooling.model.idea.IdeaProject
import org.gradle.tooling.model.kotlin.dsl.KotlinDslScriptsModel
import org.jetbrains.kotlin.gradle.KotlinDslScriptAdditionalTask
import org.jetbrains.kotlin.gradle.KotlinDslScriptModelProvider
import org.jetbrains.kotlin.idea.scripting.gradle.kotlinDslScriptsModelImportSupported
import org.jetbrains.plugins.gradle.model.ProjectImportModelProvider
import org.jetbrains.plugins.gradle.model.ClassSetBuildImportModelProvider
class KotlinDslScriptModelResolver : KotlinDslScriptModelResolverCommon() {
override fun requiresTaskRunning() = true
override fun getModelProvider() = KotlinDslScriptModelProvider()
override fun getProjectsLoadedModelProvider(): ProjectImportModelProvider? {
return ClassSetBuildImportModelProvider(
setOf(KotlinDslScriptAdditionalTask::class.java)
)
}
override fun populateProjectExtraModels(gradleProject: IdeaProject, ideProject: DataNode<ProjectData>) {
super.populateProjectExtraModels(gradleProject, ideProject)
populateBuildModels(gradleProject, ideProject)
resolverCtx.models.includedBuilds.forEach { includedRoot ->
populateBuildModels(includedRoot, ideProject)
}
}
private fun populateBuildModels(
root: IdeaProject,
ideProject: DataNode<ProjectData>
) {
root.modules.forEach {
if (it.gradleProject.parent == null) {
if (kotlinDslScriptsModelImportSupported(resolverCtx.projectGradleVersion)) {
resolverCtx.getExtraProject(it, KotlinDslScriptsModel::class.java)?.let { model ->
processScriptModel(resolverCtx, model, it.name)
}
}
saveGradleBuildEnvironment(resolverCtx)
}
}
}
}
@@ -1,11 +0,0 @@
/*
* 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.scripting.gradle.settings
import com.intellij.openapi.project.Project
class StandaloneScriptsUIComponent(val project: Project) : StandaloneScriptsUIComponentCompat(project) {
}
@@ -1,29 +0,0 @@
/*
* 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.codeInsight.gradle;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.task.ProjectTaskManager;
//BUNCH 193
class ExternalSystemTestCaseBunch {
protected static boolean isDefaultRefreshCallback(Object callback) {
return false;
}
protected static void build(Object[] buildableElements, Project myProject) {
if (buildableElements instanceof Module[]) {
ProjectTaskManager.getInstance(myProject).build((Module[])buildableElements);
}
else if (buildableElements instanceof Artifact[]) {
ProjectTaskManager.getInstance(myProject).build((Artifact[])buildableElements);
}
}
}
@@ -1,30 +0,0 @@
/*
* 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
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.BaseComponent
import org.jetbrains.kotlin.idea.ThreadTrackerPatcherForTeamCityTesting.patchThreadTracker
import org.jetbrains.kotlin.idea.debugger.filter.addKotlinStdlibDebugFilterIfNeeded
import org.jetbrains.kotlin.idea.util.application.isUnitTestMode
// FIX ME WHEN BUNCH 192 REMOVED
class JvmPluginStartupComponent : BaseComponent {
override fun getComponentName(): String = JvmPluginStartupComponent::class.java.name
override fun initComponent() {
if (isUnitTestMode()) {
patchThreadTracker()
}
addKotlinStdlibDebugFilterIfNeeded()
}
override fun disposeComponent() {}
companion object {
fun getInstance(): JvmPluginStartupComponent =
ApplicationManager.getApplication().getComponent(JvmPluginStartupComponent::class.java)
}
}
@@ -1,99 +0,0 @@
/*
* 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.compiler
import com.intellij.diagnostic.PluginException
import com.intellij.ide.plugins.PluginManagerCore
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.compiler.CompilationStatusListener
import com.intellij.openapi.compiler.CompileContext
import com.intellij.openapi.compiler.CompilerManager
import com.intellij.openapi.compiler.CompilerMessageCategory
import com.intellij.openapi.components.ProjectComponent
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.io.FileUtilRt
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.kotlin.config.CompilerRunnerConstants
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.js.JavaScript
import java.io.PrintStream
import java.io.PrintWriter
// FIX ME WHEN BUNCH 192 REMOVED
class KotlinCompilerManager(project: Project, manager: CompilerManager) : ProjectComponent {
// Extending PluginException ensures that Exception Analyzer recognizes this as a Kotlin exception
private class KotlinCompilerException(private val text: String) :
PluginException("", PluginManagerCore.getPluginByClassName(KotlinCompilerManager::class.java.name)) {
override fun printStackTrace(s: PrintWriter) {
s.print(text)
}
override fun printStackTrace(s: PrintStream) {
s.print(text)
}
@Synchronized
override fun fillInStackTrace(): Throwable {
return this
}
override fun getStackTrace(): Array<StackTraceElement> {
LOG.error("Somebody called getStackTrace() on KotlinCompilerException")
// Return some stack trace that originates in Kotlin
return UnsupportedOperationException().stackTrace
}
override val message: String
get() = "<Exception from standalone Kotlin compiler>"
}
companion object {
private val LOG = Logger.getInstance(KotlinCompilerManager::class.java)
// Comes from external make
private const val PREFIX_WITH_COMPILER_NAME =
CompilerRunnerConstants.KOTLIN_COMPILER_NAME + ": " + CompilerRunnerConstants.INTERNAL_ERROR_PREFIX
private val FILE_EXTS_WHICH_NEEDS_REFRESH = ContainerUtil.immutableSet(JavaScript.DOT_EXTENSION, ".map")
}
init {
manager.addCompilableFileType(KotlinFileType.INSTANCE)
manager.addCompilationStatusListener(object : CompilationStatusListener {
override fun compilationFinished(aborted: Boolean, errors: Int, warnings: Int, compileContext: CompileContext) {
for (error in compileContext.getMessages(CompilerMessageCategory.ERROR)) {
val message = error.message
if (message.startsWith(CompilerRunnerConstants.INTERNAL_ERROR_PREFIX) || message.startsWith(PREFIX_WITH_COMPILER_NAME)) {
LOG.error(KotlinCompilerException(message))
}
}
}
override fun fileGenerated(outputRoot: String, relativePath: String) {
if (ApplicationManager.getApplication().isUnitTestMode) return
val ext = FileUtilRt.getExtension(relativePath).toLowerCase()
if (FILE_EXTS_WHICH_NEEDS_REFRESH.contains(ext)) {
val outFile = "$outputRoot/$relativePath"
val virtualFile = LocalFileSystem.getInstance().findFileByPath(outFile)
?: error("Virtual file not found for generated file path: $outFile")
virtualFile.refresh( /*async =*/false, /*recursive =*/false)
}
}
}, project)
}
}
@@ -1,39 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.compiler.configuration
import com.intellij.compiler.server.BuildProcessParametersProvider
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.registry.Registry
import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.idea.PluginStartupComponent
class KotlinBuildProcessParametersProvider(private val project: Project) : BuildProcessParametersProvider() {
override fun getVMArguments(): MutableList<String> {
val compilerWorkspaceSettings = KotlinCompilerWorkspaceSettings.getInstance(project)
val res = arrayListOf<String>()
if (compilerWorkspaceSettings.preciseIncrementalEnabled) {
res.add("-D" + IncrementalCompilation.INCREMENTAL_COMPILATION_JVM_PROPERTY + "=true")
}
if (compilerWorkspaceSettings.incrementalCompilationForJsEnabled) {
res.add("-D" + IncrementalCompilation.INCREMENTAL_COMPILATION_JS_PROPERTY + "=true")
}
if (compilerWorkspaceSettings.enableDaemon) {
res.add("-Dkotlin.daemon.enabled")
}
if (Registry.`is`("kotlin.jps.instrument.bytecode", false)) {
res.add("-Dkotlin.jps.instrument.bytecode=true")
}
PluginStartupComponent.getInstance().aliveFlagPath.let {
if (!it.isBlank()) {
// TODO: consider taking the property name from compiler/daemon/common (check whether dependency will be not too heavy)
res.add("-Dkotlin.daemon.client.alive.path=\"$it\"")
}
}
return res
}
}
@@ -1,27 +0,0 @@
/*
* 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.configuration
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.application.ReadAction.nonBlocking
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.util.concurrency.AppExecutorUtil
import org.jetbrains.kotlin.idea.configuration.ui.notifications.ConfigureKotlinNotification
import java.util.concurrent.Callable
fun notify(manager: ConfigureKotlinNotificationManager, project: Project, excludeModules: List<Module>) {
nonBlocking(Callable {
ConfigureKotlinNotification.getNotificationState(project, excludeModules)
})
.expireWith(project)
.finishOnUiThread(ModalityState.any()) { notificationState ->
notificationState?.let {
manager.notify(project, ConfigureKotlinNotification(project, excludeModules, it))
}
}
.submit(AppExecutorUtil.getAppExecutorService())
}
@@ -1,94 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.configuration.ui
import com.intellij.notification.NotificationDisplayType
import com.intellij.notification.NotificationsConfiguration
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.runReadAction
import com.intellij.openapi.components.ProjectComponent
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataImportListener
import com.intellij.openapi.project.Project
import com.intellij.openapi.startup.StartupManager
import org.jetbrains.kotlin.idea.configuration.getModulesWithKotlinFiles
import org.jetbrains.kotlin.idea.configuration.notifyOutdatedBundledCompilerIfNecessary
import org.jetbrains.kotlin.idea.configuration.ui.notifications.notifyKotlinStyleUpdateIfNeeded
import org.jetbrains.kotlin.idea.project.getAndCacheLanguageLevelByDependencies
import org.jetbrains.kotlin.idea.util.runReadActionInSmartMode
import java.util.concurrent.atomic.AtomicInteger
class KotlinConfigurationCheckerComponent(val project: Project) : ProjectComponent {
private val syncDepth = AtomicInteger()
init {
NotificationsConfiguration.getNotificationsConfiguration()
.register(CONFIGURE_NOTIFICATION_GROUP_ID, NotificationDisplayType.STICKY_BALLOON, true)
val connection = project.messageBus.connect(project)
connection.subscribe(ProjectDataImportListener.TOPIC, ProjectDataImportListener {
notifyOutdatedBundledCompilerIfNecessary(project)
})
notifyKotlinStyleUpdateIfNeeded(project)
}
override fun projectOpened() {
super.projectOpened()
StartupManager.getInstance(project).registerPostStartupActivity {
performProjectPostOpenActions()
}
}
fun performProjectPostOpenActions() {
ApplicationManager.getApplication().executeOnPooledThread {
val modulesWithKotlinFiles = project.runReadActionInSmartMode {
getModulesWithKotlinFiles(project)
}
for (module in modulesWithKotlinFiles) {
runReadAction {
if (project.isDisposed) return@runReadAction
module.getAndCacheLanguageLevelByDependencies()
}
}
}
}
val isSyncing: Boolean get() = syncDepth.get() > 0
fun syncStarted() {
syncDepth.incrementAndGet()
}
fun syncDone() {
syncDepth.decrementAndGet()
}
companion object {
const val CONFIGURE_NOTIFICATION_GROUP_ID = "Configure Kotlin in Project"
fun getInstance(project: Project): KotlinConfigurationCheckerComponent =
project.getComponent(KotlinConfigurationCheckerComponent::class.java)
?: error("Can't find ${KotlinConfigurationCheckerComponent::class} component")
fun getInstanceIfNotDisposed(project: Project): KotlinConfigurationCheckerComponent? {
return runReadAction {
if (!project.isDisposed) getInstance(project) else null
}
}
}
}
@@ -1,19 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.configuration.ui
typealias KotlinConfigurationCheckerService = KotlinConfigurationCheckerComponent
@@ -1,190 +0,0 @@
/*
* 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.internal.makeBackup
import com.intellij.compiler.server.BuildManager
import com.intellij.history.core.RevisionsCollector
import com.intellij.history.integration.LocalHistoryImpl
import com.intellij.history.integration.patches.PatchCreator
import com.intellij.ide.actions.ShowFilePathAction
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.application.PathManager
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.progress.Task
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vcs.changes.Change
import com.intellij.util.WaitForProgressToShow
import com.intellij.util.io.ZipUtil
import org.jetbrains.kotlin.idea.KotlinJvmBundle
import org.jetbrains.kotlin.idea.util.application.runReadAction
import java.io.File
import java.io.FileOutputStream
import java.text.SimpleDateFormat
import java.util.*
import java.util.zip.ZipOutputStream
class CreateIncrementalCompilationBackup : AnAction(KotlinJvmBundle.message("create.backup.for.debugging.kotlin.incremental.compilation")) {
companion object {
const val BACKUP_DIR_NAME = ".backup"
const val PATCHES_TO_CREATE = 5
const val PATCHES_FRACTION = .25
const val LOGS_FRACTION = .05
const val PROJECT_SYSTEM_FRACTION = .05
const val ZIP_FRACTION = 1.0 - PATCHES_FRACTION - LOGS_FRACTION - PROJECT_SYSTEM_FRACTION
}
override fun actionPerformed(e: AnActionEvent) {
val project = e.project!!
val projectBaseDir = File(project.baseDir!!.path)
val backupDir = File(FileUtil.createTempDirectory("makeBackup", null), BACKUP_DIR_NAME)
ProgressManager.getInstance().run(
object : Task.Backgroundable(
project,
KotlinJvmBundle.message("creating.backup.for.debugging.kotlin.incremental.compilation"),
true
) {
override fun run(indicator: ProgressIndicator) {
createPatches(backupDir, project, indicator)
copyLogs(backupDir, indicator)
copyProjectSystemDir(backupDir, project, indicator)
zipProjectDir(backupDir, project, projectBaseDir, indicator)
}
}
)
}
private fun createPatches(backupDir: File, project: Project, indicator: ProgressIndicator) {
runReadAction {
val localHistoryImpl = LocalHistoryImpl.getInstanceImpl()!!
val gateway = localHistoryImpl.gateway!!
val localHistoryFacade = localHistoryImpl.facade
val revisionsCollector = RevisionsCollector(
localHistoryFacade,
gateway.createTransientRootEntry(),
project.baseDir!!.path,
project.locationHash,
null
)
var patchesCreated = 0
val patchesDir = File(backupDir, "patches")
patchesDir.mkdirs()
val revisions = revisionsCollector.result!!
for (rev in revisions) {
val label = rev.label
if (label != null && label.startsWith(HISTORY_LABEL_PREFIX)) {
val patchFile = File(patchesDir, label.removePrefix(HISTORY_LABEL_PREFIX) + ".patch")
indicator.text = KotlinJvmBundle.message("creating.patch.0", patchFile)
indicator.fraction = PATCHES_FRACTION * patchesCreated / PATCHES_TO_CREATE
val differences = revisions[0].getDifferencesWith(rev)!!
val changes = differences.map { d ->
Change(d.getLeftContentRevision(gateway), d.getRightContentRevision(gateway))
}
PatchCreator.create(project, changes, patchFile.path, false, null)
if (++patchesCreated >= PATCHES_TO_CREATE) {
break
}
}
}
}
}
private fun copyLogs(backupDir: File, indicator: ProgressIndicator) {
indicator.text = KotlinJvmBundle.message("copying.logs")
indicator.fraction = PATCHES_FRACTION
val logsDir = File(backupDir, "logs")
FileUtil.copyDir(File(PathManager.getLogPath()), logsDir)
indicator.fraction = PATCHES_FRACTION + LOGS_FRACTION
}
private fun copyProjectSystemDir(backupDir: File, project: Project, indicator: ProgressIndicator) {
indicator.text = KotlinJvmBundle.message("copying.project.s.system.dir")
indicator.fraction = PATCHES_FRACTION
val projectSystemDir = File(backupDir, "project-system")
FileUtil.copyDir(BuildManager.getInstance().getProjectSystemDirectory(project)!!, projectSystemDir)
indicator.fraction = PATCHES_FRACTION + LOGS_FRACTION + PROJECT_SYSTEM_FRACTION
}
private fun zipProjectDir(backupDir: File, project: Project, projectDir: File, indicator: ProgressIndicator) {
// files and relative paths
val files = ArrayList<Pair<File, String>>() // files and relative paths
var totalBytes = 0L
for (dir in listOf(projectDir, backupDir.parentFile!!)) {
FileUtil.processFilesRecursively(
dir,
/*processor*/ {
if (it!!.isFile
&& !it.name.endsWith(".hprof")
&& !(it.name.startsWith("make_backup_") && it.name.endsWith(".zip"))
) {
indicator.text = KotlinJvmBundle.message("scanning.project.dir.0", it)
files.add(Pair(it, FileUtil.getRelativePath(dir, it)!!))
totalBytes += it.length()
}
true
},
/*directoryFilter*/ {
val name = it!!.name
name != ".git" && name != "out"
}
)
}
val backupFile = File(projectDir, "make_backup_" + SimpleDateFormat("yyyy-MM-dd_HH-mm-ss").format(Date()) + ".zip")
val zos = ZipOutputStream(FileOutputStream(backupFile))
var processedBytes = 0L
zos.use {
for ((file, relativePath) in files) {
indicator.text = KotlinJvmBundle.message("adding.file.to.backup.0", relativePath)
indicator.fraction = PATCHES_FRACTION + LOGS_FRACTION + processedBytes.toDouble() / totalBytes * ZIP_FRACTION
ZipUtil.addFileToZip(zos, file, relativePath, null, null)
processedBytes += file.length()
}
}
FileUtil.delete(backupDir)
WaitForProgressToShow.runOrInvokeLaterAboveProgress(
{
ShowFilePathAction.showDialog(
project,
KotlinJvmBundle.message("successfully.created.backup.0", backupFile.absolutePath),
KotlinJvmBundle.message("created.backup"),
backupFile,
null
)
}, null, project
)
}
}
@@ -1,64 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.scratch
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
import com.intellij.openapi.components.ProjectComponent
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesModificationTracker
import org.jetbrains.kotlin.idea.core.script.scriptRelatedModuleName
import org.jetbrains.kotlin.idea.util.projectStructure.getModule
import org.jetbrains.kotlin.parsing.KotlinParserDefinition.Companion.STD_SCRIPT_SUFFIX
import org.jetbrains.kotlin.psi.KtFile
// FIX ME WHEN BUNCH 192 REMOVED
class ScratchFileModuleInfoProvider(val project: Project) : ProjectComponent {
private val LOG = Logger.getInstance(this.javaClass)
override fun projectOpened() {
project.messageBus.connect().subscribe(ScratchFileListener.TOPIC, object : ScratchFileListener {
override fun fileCreated(scratchFile: ScratchFile) {
val ktFile = scratchFile.getPsiFile() as? KtFile ?: return
val file = ktFile.virtualFile ?: return
if (file.extension != STD_SCRIPT_SUFFIX) {
LOG.error("Kotlin Scratch file should have .kts extension. Cannot add scratch panel for ${file.path}")
return
}
scratchFile.addModuleListener { psiFile, module ->
psiFile.virtualFile.scriptRelatedModuleName = module?.name
// Drop caches for old module
ScriptDependenciesModificationTracker.getInstance(project).incModificationCount()
// Force re-highlighting
DaemonCodeAnalyzer.getInstance(project).restart(psiFile)
}
if (file.isKotlinWorksheet) {
val module = file.getModule(project) ?: return
scratchFile.setModule(module)
} else {
val module = file.scriptRelatedModuleName?.let { ModuleManager.getInstance(project).findModuleByName(it) } ?: return
scratchFile.setModule(module)
}
}
})
}
}
@@ -1,110 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.scratch.actions
import com.intellij.icons.AllIcons
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.keymap.KeymapManager
import com.intellij.openapi.keymap.KeymapUtil
import com.intellij.openapi.project.DumbService
import com.intellij.task.ProjectTaskManager
import org.jetbrains.kotlin.idea.KotlinJvmBundle
import org.jetbrains.kotlin.idea.scratch.*
import org.jetbrains.kotlin.idea.scratch.printDebugMessage
import org.jetbrains.kotlin.idea.scratch.LOG as log
class RunScratchAction : ScratchAction(
KotlinJvmBundle.message("scratch.run.button"),
AllIcons.Actions.Execute
) {
init {
KeymapManager.getInstance().activeKeymap.getShortcuts("Kotlin.RunScratch").firstOrNull()?.let {
templatePresentation.text += " (${KeymapUtil.getShortcutText(it)})"
}
}
override fun actionPerformed(e: AnActionEvent) {
val project = e.project ?: return
val scratchFile = getScratchFileFromSelectedEditor(project) ?: return
doAction(scratchFile, false)
}
companion object {
fun doAction(scratchFile: ScratchFile, isAutoRun: Boolean) {
val isRepl = scratchFile.options.isRepl
val executor = (if (isRepl) scratchFile.replScratchExecutor else scratchFile.compilingScratchExecutor) ?: return
log.printDebugMessage("Run Action: isRepl = $isRepl")
fun executeScratch() {
try {
if (isAutoRun && executor is SequentialScratchExecutor) {
executor.executeNew()
} else {
executor.execute()
}
} catch (ex: Throwable) {
executor.errorOccurs(KotlinJvmBundle.message("exception.occurs.during.run.scratch.action"), ex, true)
}
}
val isMakeBeforeRun = scratchFile.options.isMakeBeforeRun
log.printDebugMessage("Run Action: isMakeBeforeRun = $isMakeBeforeRun")
val module = scratchFile.module
log.printDebugMessage("Run Action: module = ${module?.name}")
if (!isAutoRun && module != null && isMakeBeforeRun) {
val project = scratchFile.project
ProjectTaskManager.getInstance(project).build(arrayOf(module)) { result ->
if (result.isAborted || result.errors > 0) {
executor.errorOccurs(KotlinJvmBundle.message("there.were.compilation.errors.in.module.0", module.name))
}
if (DumbService.isDumb(project)) {
DumbService.getInstance(project).smartInvokeLater {
executeScratch()
}
} else {
executeScratch()
}
}
} else {
executeScratch()
}
}
}
override fun update(e: AnActionEvent) {
super.update(e)
e.presentation.isEnabled = !ScratchCompilationSupport.isAnyInProgress()
if (e.presentation.isEnabled) {
e.presentation.text = templatePresentation.text
} else {
e.presentation.text = KotlinJvmBundle.message("other.scratch.file.execution.is.in.progress")
}
val project = e.project ?: return
val scratchFile = getScratchFileFromSelectedEditor(project) ?: return
e.presentation.isVisible = !ScratchCompilationSupport.isInProgress(scratchFile)
}
}
@@ -1,139 +0,0 @@
/*
* 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.vcs
import com.intellij.BundleBase.replaceMnemonicAmpersand
import com.intellij.CommonBundle
import com.intellij.ide.plugins.PluginManager
import com.intellij.openapi.extensions.PluginId
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.Messages
import com.intellij.openapi.ui.Messages.NO
import com.intellij.openapi.ui.Messages.YES
import com.intellij.openapi.util.Key
import com.intellij.openapi.vcs.CheckinProjectPanel
import com.intellij.openapi.vcs.changes.CommitContext
import com.intellij.openapi.vcs.changes.CommitExecutor
import com.intellij.openapi.vcs.checkin.CheckinHandler
import com.intellij.openapi.vcs.checkin.CheckinHandlerFactory
import com.intellij.openapi.vcs.ui.RefreshableOnComponent
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.ui.NonFocusableCheckBox
import com.intellij.util.PairConsumer
import org.jetbrains.kotlin.idea.KotlinJvmBundle
import org.jetbrains.kotlin.psi.NotNullableUserDataProperty
import java.awt.GridLayout
import java.io.File
import javax.swing.JComponent
import javax.swing.JPanel
private val BUNCH_PLUGIN_ID = PluginId.getId("org.jetbrains.bunch.tool.idea.plugin")
private var Project.bunchFileCheckEnabled: Boolean
by NotNullableUserDataProperty(Key.create("IS_BUNCH_FILE_CHECK_ENABLED_KOTLIN"), !PluginManager.isPluginInstalled(BUNCH_PLUGIN_ID))
class BunchFileCheckInHandlerFactory : CheckinHandlerFactory() {
override fun createHandler(panel: CheckinProjectPanel, commitContext: CommitContext): CheckinHandler {
return BunchCheckInHandler(panel)
}
class BunchCheckInHandler(private val checkInProjectPanel: CheckinProjectPanel) : CheckinHandler() {
private val project get() = checkInProjectPanel.project
override fun getBeforeCheckinConfigurationPanel(): RefreshableOnComponent? {
if (PluginManager.isPluginInstalled(BUNCH_PLUGIN_ID)) return null
BunchFileUtils.bunchFile(project) ?: return null
val bunchFilesCheckBox = NonFocusableCheckBox(replaceMnemonicAmpersand(KotlinJvmBundle.message("check.bunch.files")))
return object : RefreshableOnComponent {
override fun getComponent(): JComponent {
val panel = JPanel(GridLayout(1, 0))
panel.add(bunchFilesCheckBox)
return panel
}
override fun refresh() {}
override fun saveState() {
project.bunchFileCheckEnabled = bunchFilesCheckBox.isSelected
}
override fun restoreState() {
bunchFilesCheckBox.isSelected = project.bunchFileCheckEnabled
}
}
}
override fun beforeCheckin(
executor: CommitExecutor?,
additionalDataConsumer: PairConsumer<Any, Any>?
): ReturnResult {
if (!project.bunchFileCheckEnabled) return ReturnResult.COMMIT
val extensions = BunchFileUtils.bunchExtension(project)?.toSet() ?: return ReturnResult.COMMIT
val forgottenFiles = HashSet<File>()
val commitFiles = checkInProjectPanel.files.filter { it.isFile }.toSet()
for (file in commitFiles) {
if (file.extension in extensions) continue
val parent = file.parent ?: continue
val name = file.name
for (extension in extensions) {
val bunchFile = File(parent, "$name.$extension")
if (bunchFile !in commitFiles && bunchFile.exists()) {
forgottenFiles.add(bunchFile)
}
}
}
if (forgottenFiles.isEmpty()) return ReturnResult.COMMIT
val projectBaseFile = File(project.basePath)
var filePaths = forgottenFiles.map { it.relativeTo(projectBaseFile).path }.sorted()
if (filePaths.size > 15) {
filePaths = filePaths.take(15) + "..."
}
when (Messages.showYesNoCancelDialog(
project,
KotlinJvmBundle.message(
"several.bunch.files.haven.t.been.updated.0.do.you.want.to.review.them.before.commit",
filePaths.joinToString("\n")
),
KotlinJvmBundle.message("button.text.forgotten.bunch.files"),
KotlinJvmBundle.message("button.text.review"),
KotlinJvmBundle.message("button.text.commit"),
CommonBundle.getCancelButtonText(),
Messages.getWarningIcon()
)) {
YES -> {
return ReturnResult.CLOSE_WINDOW
}
NO -> return ReturnResult.COMMIT
}
return ReturnResult.CANCEL
}
}
}
object BunchFileUtils {
fun bunchFile(project: Project): VirtualFile? {
val baseDir = project.baseDir ?: return null
return baseDir.findChild(".bunch")
}
fun bunchExtension(project: Project): List<String>? {
val bunchFile: VirtualFile = bunchFile(project) ?: return null
val file = File(bunchFile.path)
if (!file.exists()) return null
val lines = file.readLines().map { it.trim() }.filter { it.isNotEmpty() }
if (lines.size <= 1) return null
return lines.drop(1).map { it.split('_').first() }
}
}
@@ -1,12 +0,0 @@
/*
* 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.maven
import com.intellij.openapi.module.Module
// FIX ME WHEN BUNCH 192 REMOVED
internal val Module.kotlinImporterComponent: KotlinImporterComponent
get() = getComponent(KotlinImporterComponent::class.java) ?: throw IllegalStateException("No maven importer state configured")
@@ -1,38 +0,0 @@
/*
* Copyright 2010-2018 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.maven
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import org.jetbrains.idea.maven.project.MavenImportListener
import org.jetbrains.idea.maven.project.MavenProject
import org.jetbrains.idea.maven.project.MavenProjectsManager
import org.jetbrains.kotlin.idea.configuration.KotlinMigrationProjectService
import org.jetbrains.kotlin.idea.configuration.notifyOutdatedBundledCompilerIfNecessary
import org.jetbrains.kotlin.idea.util.ProgressIndicatorUtils.runUnderDisposeAwareIndicator
// FIX ME WHEN BUNCH 192 REMOVED
class MavenImportListener(val project: Project) : MavenProjectsManager.Listener {
init {
project.messageBus.connect(project).subscribe(
MavenImportListener.TOPIC,
MavenImportListener { _: Collection<MavenProject>, _: List<Module> ->
runUnderDisposeAwareIndicator(project) {
notifyOutdatedBundledCompilerIfNecessary(project)
KotlinMigrationProjectService.getInstance(project).onImportFinished()
}
}
)
MavenProjectsManager.getInstance(project)?.addManagerListener(this)
}
override fun projectsScheduled() {
runUnderDisposeAwareIndicator(project) {
KotlinMigrationProjectService.getInstance(project).onImportAboutToStart()
}
}
}
@@ -1,23 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.tools.projectWizard.wizard.service
import com.intellij.ide.plugins.PluginManager
import com.intellij.openapi.extensions.PluginId
import org.jetbrains.kotlin.tools.projectWizard.core.service.BuildSystemAvailabilityWizardService
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemType
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.isGradle
class IdeaBuildSystemAvailabilityWizardService : BuildSystemAvailabilityWizardService, IdeaWizardService {
override fun isAvailable(buildSystemType: BuildSystemType): Boolean = when {
buildSystemType.isGradle -> isPluginEnabled("org.jetbrains.plugins.gradle")
buildSystemType == BuildSystemType.Maven -> isPluginEnabled("org.jetbrains.idea.maven")
else -> true
}
private fun isPluginEnabled(id: String) =
PluginManager.getPlugin(PluginId.getId(id))?.isEnabled == true
}
@@ -1,88 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.tools.projectWizard.wizard.service
import com.intellij.execution.executors.DefaultRunExecutor
import com.intellij.openapi.actionSystem.ActionPlaces
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.actionSystem.impl.SimpleDataContext
import com.intellij.openapi.externalSystem.model.execution.ExternalSystemTaskExecutionSettings
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.LocalFileSystem
import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.tools.projectWizard.core.Reader
import org.jetbrains.kotlin.tools.projectWizard.core.TaskResult
import org.jetbrains.kotlin.tools.projectWizard.core.andThen
import org.jetbrains.kotlin.tools.projectWizard.core.safe
import org.jetbrains.kotlin.tools.projectWizard.core.service.ProjectImportingWizardService
import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.ModuleIR
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemType
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.isGradle
import org.jetbrains.plugins.gradle.action.ImportProjectFromScriptAction
import org.jetbrains.plugins.gradle.util.GradleConstants
import java.nio.file.Path
// FIX ME WHEN BUNCH 192 REMOVED
class IdeaGradleWizardService(private val project: Project) : ProjectImportingWizardService,
IdeaWizardService {
override fun isSuitableFor(buildSystemType: BuildSystemType): Boolean =
buildSystemType.isGradle
// We have to call action directly as there is no common way
// to import Gradle project in all IDEAs from 183 to 193
override fun importProject(
reader: Reader,
path: Path,
modulesIrs: List<ModuleIR>,
buildSystem: BuildSystemType
): TaskResult<Unit> = performImport(path) andThen createGradleWrapper(path)
private fun performImport(path: Path) = safe {
val virtualFile = LocalFileSystem.getInstance().findFileByPath(path.toString())
?: error("No virtual file found for path $path")
val dataContext = SimpleDataContext.getSimpleContext(
mapOf(
CommonDataKeys.PROJECT.name to project,
CommonDataKeys.VIRTUAL_FILE.name to virtualFile
),
null
)
val action = ImportProjectFromScriptAction()
val event = AnActionEvent.createFromAnAction(
action,
/*event=*/ null,
ActionPlaces.UNKNOWN,
dataContext
)
action.actionPerformed(event)
}
private fun createGradleWrapper(path: Path) = safe {
val settings = ExternalSystemTaskExecutionSettings().apply {
externalProjectPath = path.toString()
taskNames = listOf(WRAPPER_TASK_NAME)
externalSystemIdString = GradleConstants.SYSTEM_ID.id
}
ExternalSystemUtil.runTask(
settings,
DefaultRunExecutor.EXECUTOR_ID,
project,
GradleConstants.SYSTEM_ID,
/*callback=*/ null,
ProgressExecutionMode.NO_PROGRESS_ASYNC
)
}
companion object {
@NonNls
private const val WRAPPER_TASK_NAME = "wrapper"
}
}
@@ -1,17 +0,0 @@
/*
* 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.tools.projectWizard.wizard.ui.firstStep
import com.intellij.openapi.actionSystem.ActionGroup
import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl
import com.intellij.openapi.keymap.ex.KeymapManagerEx
// needed for <=192 to work correctly
abstract class ActionToolbarImplWrapper(
place: String,
actionGroup: ActionGroup,
horizontal: Boolean
) : ActionToolbarImpl(place, actionGroup, horizontal, KeymapManagerEx.getInstanceEx())
@@ -1,49 +0,0 @@
/*
* 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.console
import com.intellij.execution.ExecutionManager
import com.intellij.execution.Executor
import com.intellij.execution.ui.RunContentDescriptor
import com.intellij.openapi.compiler.CompilerManager
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.task.ProjectTaskManager
class ConsoleCompilerHelper(
private val project: Project,
private val module: Module,
private val executor: Executor,
private val contentDescriptor: RunContentDescriptor
) {
fun moduleIsUpToDate(): Boolean {
val compilerManager = CompilerManager.getInstance(project)
val compilerScope = compilerManager.createModuleCompileScope(module, true)
return compilerManager.isUpToDate(compilerScope)
}
fun compileModule() {
if (ExecutionManager.getInstance(project).contentManager.removeRunContent(executor, contentDescriptor)) {
ProjectTaskManager.getInstance(project).build(arrayOf(module)) { result ->
if (!module.isDisposed) {
KotlinConsoleKeeper.getInstance(project).run(module, previousCompilationFailed = result.errors > 0)
}
}
}
}
}
@@ -1,51 +0,0 @@
/*
* 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.test;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.StdModuleTypes;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.testFramework.LightProjectDescriptor;
import org.jetbrains.annotations.NotNull;
public class KotlinLightProjectDescriptor extends LightProjectDescriptor {
protected KotlinLightProjectDescriptor() {
}
public static final KotlinLightProjectDescriptor INSTANCE = new KotlinLightProjectDescriptor();
@Override
public ModuleType getModuleType() {
return StdModuleTypes.JAVA;
}
@Override
public Sdk getSdk() {
return PluginTestCaseBase.mockJdk();
}
@Override
public void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, @NotNull ContentEntry contentEntry) {
configureModule(module, model);
}
public void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model) {
}
}
@@ -1,21 +0,0 @@
/*
* 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.codeInsight.daemon.impl.EditorTracker
import com.intellij.ide.startup.impl.StartupManagerImpl
import com.intellij.openapi.project.Project
import com.intellij.openapi.startup.StartupManager
// FIX ME WHEN BUNCH 192 REMOVED
fun editorTrackerProjectOpened(project: Project) {
project.getComponent(EditorTracker::class.java)?.projectOpened()
}
// FIX ME WHEN BUNCH 193 REMOVED
fun runPostStartupActivitiesOnce(project: Project) {
(StartupManager.getInstance(project) as StartupManagerImpl).runPostStartupActivities()
}
@@ -1,46 +0,0 @@
/*
* 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.debugger.stepping
import com.intellij.debugger.engine.SuspendContextImpl
import com.intellij.debugger.engine.events.SuspendContextCommandImpl
import com.intellij.debugger.ui.breakpoints.RunToCursorBreakpoint
import com.sun.jdi.Location
import com.sun.jdi.Method
import com.sun.jdi.event.LocatableEvent
import org.jetbrains.kotlin.idea.debugger.safeLocation
object CoroutineBreakpointFacility : AbstractCoroutineBreakpointFacility() {
override fun installCoroutineResumedBreakpoint(context: SuspendContextImpl, location: Location, method: Method): Boolean {
val debugProcess = context.debugProcess
val project = debugProcess.project
val methodLocation = method.location()
val position = debugProcess.positionManager.getSourcePosition(methodLocation) ?: return false
val breakpoint = object : RunToCursorBreakpoint(project, position, false) {
override fun processLocatableEvent(action: SuspendContextCommandImpl, event: LocatableEvent?): Boolean {
val result = super.processLocatableEvent(action, event)
if (result) {
stepOverSuspendSwitch(action, debugProcess)
}
return result
}
}
breakpoint.setSuspendPolicy(context)
applyEmptyThreadFilter(debugProcess)
breakpoint.createRequest(debugProcess)
debugProcess.setRunToCursorBreakpoint(breakpoint)
return true
}
}
fun SuspendContextImpl.getLocationCompat(): Location? {
return this.frameProxy?.safeLocation()
}
@@ -1,63 +0,0 @@
/*
* 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.testFramework
import com.intellij.openapi.Disposable
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationEvent
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener
import com.intellij.testFramework.PlatformTestUtil.maskExtensions
import org.jetbrains.kotlin.idea.framework.GRADLE_SYSTEM_ID
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import kotlin.test.assertNull
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener.EP_NAME as EP
interface GradleProcessOutputInterceptor {
companion object {
fun getInstance(): GradleProcessOutputInterceptor? = EP.extensions.firstIsInstanceOrNull()
fun install(parentDisposable: Disposable) {
val installedExtensions = EP.extensions
assertNull(
installedExtensions.firstIsInstanceOrNull<GradleProcessOutputInterceptor>(),
"Another ${GradleProcessOutputInterceptor::class.java.simpleName} is already installed"
)
maskExtensions(
EP,
listOf(GradleProcessOutputInterceptorImpl()) + installedExtensions,
parentDisposable
)
}
}
fun reset()
fun getOutput(): String
}
private class GradleProcessOutputInterceptorImpl : GradleProcessOutputInterceptor, ExternalSystemTaskNotificationListener {
private val buffer = StringBuilder()
override fun onTaskOutput(id: ExternalSystemTaskId, text: String, stdOut: Boolean) {
if (id.projectSystemId == GRADLE_SYSTEM_ID && text.isNotEmpty())
buffer.append(text)
}
override fun reset() = buffer.setLength(0)
override fun getOutput() = buffer.toString()
override fun onSuccess(id: ExternalSystemTaskId) = Unit
override fun onFailure(id: ExternalSystemTaskId, e: Exception) = Unit
override fun onStatusChange(event: ExternalSystemTaskNotificationEvent) = Unit
override fun onCancel(id: ExternalSystemTaskId) = Unit
override fun onEnd(id: ExternalSystemTaskId) = Unit
override fun beforeCancel(id: ExternalSystemTaskId) = Unit
override fun onQueued(id: ExternalSystemTaskId, workingDir: String?) = Unit
@Suppress("UnstableApiUsage")
override fun onStart(id: ExternalSystemTaskId) = Unit
}
@@ -1,104 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.testFramework
import com.intellij.ide.startup.impl.StartupManagerImpl
import com.intellij.lang.LanguageAnnotators
import com.intellij.lang.LanguageExtensionPoint
import com.intellij.lang.annotation.Annotator
import com.intellij.openapi.Disposable
import com.intellij.openapi.editor.Document
import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ex.ProjectManagerEx
import com.intellij.openapi.startup.StartupManager
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.impl.PsiDocumentManagerBase
import com.intellij.testFramework.PlatformTestUtil
import com.intellij.testFramework.runInEdtAndWait
import com.intellij.util.ui.UIUtil
import org.jetbrains.kotlin.idea.codeInsight.hints.HintType
import org.jetbrains.kotlin.idea.test.runPostStartupActivitiesOnce
fun commitAllDocuments() {
val fileDocumentManager = FileDocumentManager.getInstance()
runInEdtAndWait {
fileDocumentManager.saveAllDocuments()
}
ProjectManagerEx.getInstanceEx().openProjects.forEach { project ->
val psiDocumentManagerBase = PsiDocumentManager.getInstance(project) as PsiDocumentManagerBase
runInEdtAndWait {
psiDocumentManagerBase.clearUncommittedDocuments()
psiDocumentManagerBase.commitAllDocuments()
}
}
}
fun commitDocument(project: Project, document: Document) {
val psiDocumentManagerBase = PsiDocumentManager.getInstance(project) as PsiDocumentManagerBase
runInEdtAndWait {
psiDocumentManagerBase.commitDocument(document)
}
}
fun saveDocument(document: Document) {
val fileDocumentManager = FileDocumentManager.getInstance()
runInEdtAndWait {
fileDocumentManager.saveDocument(document)
}
}
fun enableHints(enable: Boolean) =
HintType.values().forEach { it.option.set(enable) }
fun dispatchAllInvocationEvents() {
runInEdtAndWait {
UIUtil.dispatchAllInvocationEvents()
}
}
fun loadProjectWithName(path: String, name: String): Project? =
ProjectManagerEx.getInstanceEx().loadProject(name, path)
fun TestApplicationManager.closeProject(project: Project) {
dispatchAllInvocationEvents()
val projectManagerEx = ProjectManagerEx.getInstanceEx()
projectManagerEx.forceCloseProjectEx(project, true)
}
fun runStartupActivities(project: Project) {
with(StartupManager.getInstance(project) as StartupManagerImpl) {
scheduleInitialVfsRefresh()
runStartupActivities()
}
runPostStartupActivitiesOnce(project)
}
fun waitForAllEditorsFinallyLoaded(project: Project) {
// routing is obsolete in 192
}
fun replaceWithCustomHighlighter(parentDisposable: Disposable, fromImplementationClass: String, toImplementationClass: String) {
val pointName = ExtensionPointName.create<LanguageExtensionPoint<Annotator>>(LanguageAnnotators.EP_NAME)
val extensionPoint = pointName.getPoint(null)
val point = LanguageExtensionPoint<Annotator>()
point.language = "kotlin"
point.implementationClass = toImplementationClass
val extensions = extensionPoint.extensions
val filteredExtensions =
extensions.filter { it.language != "kotlin" || it.implementationClass != fromImplementationClass }
.toList()
// custom highlighter is already registered if filteredExtensions has the same size as extensions
if (filteredExtensions.size < extensions.size) {
PlatformTestUtil.maskExtensions(pointName, filteredExtensions + listOf(point), parentDisposable)
}
}
@@ -1,165 +0,0 @@
<idea-plugin xmlns:xi="http://www.w3.org/2001/XInclude" version="2" url="http://kotlinlang.org" allow-bundled-update="true">
<id>org.jetbrains.kotlin</id>
<name>Kotlin</name>
<description><![CDATA[
The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
<br>
<a href="http://kotlinlang.org/docs/tutorials/getting-started.html">Getting Started in IntelliJ IDEA</a><br>
<a href="http://kotlinlang.org/docs/tutorials/kotlin-android.html">Getting Started in Android Studio</a><br>
<a href="http://slack.kotlinlang.org/">Public Slack</a><br>
<a href="https://youtrack.jetbrains.com/issues/KT">Issue tracker</a><br>
]]></description>
<version>@snapshot@</version>
<vendor url="http://www.jetbrains.com">JetBrains</vendor>
<idea-version since-build="192.7142.36" until-build="192.*"/>
<change-notes><![CDATA[
<h3>1.4.0</h3>
Released: <b>August 17, 2020</b>
<ul>
<li>New compiler with better type inference.</li>
<li>IR backends for JVM and JS in Alpha mode (<a href="https://kotlinlang.org/docs/reference/whatsnew14.html#unified-backends-and-extensibility">requires opt-in</a>).</li>
<li>A new flexible Kotlin Project Wizard for easy creation and configuration of different types of projects.</li>
<li>New IDE functionality to debug coroutines.</li>
<li>IDE performance improvements: many actions, such as project opening and autocomplete suggestions now complete up to 4 times faster.</li>
<li>New language features such as SAM conversions, trailing comma, and other.</li>
<li>Type annotations in the JVM bytecode and new modes for generating default interfaces in Kotlin/JVM.</li>
<li>New Gradle DSL for Kotlin/JS.</li>
<li>Improved performance and interop with Swift and Objective-C in Kotlin/Native.</li>
<li>Support for sharing code in several targets thanks to the hierarchical structure in multiplatform projects.</li>
<li>New collection operators, delegated properties improvements, the double-ended queue implementation ArrayDeque, and much more new things in the standard library.</li>
</ul>
For more details, see <a href="https://kotlinlang.org/docs/reference/whatsnew14.html?utm_source=product&utm_medium=link">Whats New in Kotlin 1.4.0</a> and <a href="http://blog.jetbrains.com/kotlin/2020/08/kotlin-1-4-released-with-a-focus-on-quality-and-performance/?utm_source=product&utm_medium=link">this blog post</a>.
<br><br>
To get the most out of the changes and improvements introduced in Kotlin 1.4, join our <a href="https://kotlinlang.org/lp/event-14/">Online Event</a> where you will be able to enjoy four days of Kotlin talks, Q&As with the Kotlin team, and more.
]]>
</change-notes>
<depends>com.intellij.modules.platform</depends>
<depends optional="true" config-file="junit.xml">JUnit</depends>
<depends optional="true" config-file="gradle.xml">org.jetbrains.plugins.gradle</depends>
<depends optional="true" config-file="gradle-java.xml">org.jetbrains.plugins.gradle.java</depends>
<depends optional="true" config-file="kotlin-gradle-testing.xml">org.jetbrains.plugins.gradle.java</depends>
<depends optional="true" config-file="gradle-groovy.xml">org.intellij.groovy</depends>
<depends optional="true" config-file="maven-common.xml">org.jetbrains.idea.maven</depends>
<depends optional="true" config-file="maven.xml">org.jetbrains.idea.maven</depends>
<depends optional="true" config-file="testng-j.xml">TestNG-J</depends>
<depends optional="true" config-file="coverage.xml">Coverage</depends>
<depends optional="true" config-file="i18n.xml">com.intellij.java-i18n</depends>
<depends optional="true" config-file="decompiler.xml">org.jetbrains.java.decompiler</depends>
<depends optional="true" config-file="git4idea.xml">Git4Idea</depends>
<depends optional="true" config-file="stream-debugger.xml">org.jetbrains.debugger.streams</depends>
<!-- ULTIMATE-PLUGIN-PLACEHOLDER -->
<!-- CIDR-PLUGIN-PLACEHOLDER-START -->
<depends>com.intellij.modules.idea</depends>
<depends>com.intellij.modules.java</depends>
<depends optional="true" config-file="javaScriptDebug.xml">JavaScriptDebugger</depends>
<depends optional="true" config-file="kotlin-copyright.xml">com.intellij.copyright</depends>
<depends optional="true" config-file="injection.xml">org.intellij.intelliLang</depends>
<!-- CIDR-PLUGIN-PLACEHOLDER-END -->
<xi:include href="plugin-common.xml" xpointer="xpointer(/idea-plugin/*)"/>
<!-- CIDR-PLUGIN-EXCLUDE-START -->
<xi:include href="jvm-common.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="jvm.xml" xpointer="xpointer(/idea-plugin/*)"/>
<!-- CIDR-PLUGIN-EXCLUDE-END -->
<xi:include href="native-common.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="native.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="tipsAndTricks.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="extensions/ide.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="kotlinx-serialization.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="scripting-support.xml" xpointer="xpointer(/idea-plugin/*)"/>
<application-components>
<component>
<implementation-class>org.jetbrains.kotlin.idea.versions.KotlinUpdatePluginComponent</implementation-class>
</component>
</application-components>
<project-components>
<component>
<implementation-class>org.jetbrains.kotlin.idea.completion.LookupCancelWatcher</implementation-class>
</component>
<component>
<implementation-class>org.jetbrains.kotlin.idea.caches.KotlinPackageContentModificationListener</implementation-class>
</component>
<component>
<implementation-class>org.jetbrains.kotlin.idea.configuration.KotlinMigrationProjectComponent</implementation-class>
</component>
<component>
<implementation-class>org.jetbrains.kotlin.idea.highlighter.KotlinBeforeResolveHighlightingPass$Factory</implementation-class>
</component>
<component>
<implementation-class>org.jetbrains.kotlin.idea.refactoring.cutPaste.MoveDeclarationsPassFactory</implementation-class>
<skipForDefaultProject/>
</component>
<component>
<implementation-class>org.jetbrains.kotlin.idea.highlighter.ScriptExternalHighlightingPass$Factory</implementation-class>
</component>
<component>
<implementation-class>org.jetbrains.kotlin.idea.caches.trackers.KotlinCodeBlockModificationListener</implementation-class>
</component>
</project-components>
<application-components>
<component>
<implementation-class>org.jetbrains.kotlin.idea.PluginStartupComponent</implementation-class>
</component>
</application-components>
<extensionPoints>
<xi:include href="extensions/compiler.xml" xpointer="xpointer(/idea-plugin/extensionPoints/*)"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.pluginUpdateVerifier"
interface="org.jetbrains.kotlin.idea.update.PluginUpdateVerifier"/>
</extensionPoints>
<xi:include href="plugin-kotlin-extensions.xml" xpointer="xpointer(/idea-plugin/*)"/>
<extensions defaultExtensionNs="com.intellij.jvm">
<declarationSearcher language="kotlin" implementationClass="org.jetbrains.kotlin.idea.jvm.KotlinDeclarationSearcher"/>
</extensions>
<extensions defaultExtensionNs="com.intellij">
<statistics.counterUsagesCollector groupId="kotlin.gradle.target" version="2"/>
<statistics.counterUsagesCollector groupId="kotlin.maven.target" version="3"/>
<statistics.counterUsagesCollector groupId="kotlin.jps.target" version="3"/>
<statistics.counterUsagesCollector groupId="kotlin.gradle.library" version="1"/>
<statistics.counterUsagesCollector groupId="kotlin.ide.refactoring" version="1"/>
<statistics.counterUsagesCollector groupId="kotlin.ide.newFileTempl" version="1"/>
<statistics.counterUsagesCollector groupId="kotlin.ide.npwizards" version="2"/>
<statistics.counterUsagesCollector groupId="kotlin.ide.debugger" version="2"/>
<statistics.counterUsagesCollector groupId="kotlin.ide.j2k" version="1"/>
<statistics.counterUsagesCollector groupId="kotlin.ide.editor" version="1"/>
<statistics.counterUsagesCollector groupId="kotlin.ide.migrationTool" version="1"/>
<statistics.counterUsagesCollector groupId="kotlin.ide.new.wizard" version="1"/>
<statistics.counterUsagesCollector groupId="kotlin.gradle.performance" version="1"/>
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.IDESettingsFUSCollector"/>
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.formatter.KotlinFormatterUsageCollector"/>
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.statistics.ProjectConfigurationCollector"/>
<fileTypeUsageSchemaDescriptor schema="Gradle Script" implementationClass="org.jetbrains.kotlin.idea.core.script.KotlinGradleScriptFileTypeSchemaDetector"/>
<defaultLiveTemplatesProvider implementation="org.jetbrains.kotlin.idea.liveTemplates.KotlinLiveTemplatesProvider"/>
<fileTypeFactory implementation="org.jetbrains.kotlin.idea.core.KotlinFileTypeFactory"/>
<fileTypeFactory implementation="org.jetbrains.kotlin.idea.KotlinJavaScriptMetaFileTypeFactory"/>
<fileTypeFactory implementation="org.jetbrains.kotlin.idea.KotlinBuiltInFileTypeFactory"/>
<fileTypeFactory implementation="org.jetbrains.kotlin.idea.KotlinModuleFileFactory"/>
</extensions>
<extensions defaultExtensionNs="com.intellij">
<focusModeProvider language="kotlin" implementationClass="org.jetbrains.kotlin.idea.core.KotlinFocusModeProvider" />
</extensions>
</idea-plugin>
-21
View File
@@ -1,21 +0,0 @@
<idea-plugin>
<application-components>
<component>
<implementation-class>org.jetbrains.kotlin.idea.JvmPluginStartupComponent</implementation-class>
</component>
</application-components>
<project-components>
<component>
<implementation-class>org.jetbrains.kotlin.idea.compiler.KotlinCompilerManager</implementation-class>
</component>
<component>
<implementation-class>org.jetbrains.kotlin.idea.scratch.ScratchFileModuleInfoProvider</implementation-class>
</component>
<component>
<implementation-class>org.jetbrains.kotlin.idea.configuration.ui.KotlinConfigurationCheckerComponent</implementation-class>
</component>
</project-components>
</idea-plugin>
-13
View File
@@ -1,13 +0,0 @@
<idea-plugin>
<project-components>
<component>
<implementation-class>org.jetbrains.kotlin.idea.maven.MavenImportListener</implementation-class>
</component>
</project-components>
<module-components>
<component>
<implementation-class>org.jetbrains.kotlin.idea.maven.KotlinImporterComponent</implementation-class>
</component>
</module-components>
</idea-plugin>
-19
View File
@@ -1,19 +0,0 @@
<idea-plugin xmlns:xi="http://www.w3.org/2001/XInclude">
<application-components>
<component>
<implementation-class>org.jetbrains.kotlin.idea.klib.KlibLoadingMetadataCache</implementation-class>
</component>
</application-components>
<project-components>
<component>
<implementation-class>org.jetbrains.kotlin.ide.konan.KotlinNativeABICompatibilityChecker</implementation-class>
</component>
</project-components>
<extensions defaultExtensionNs="com.intellij">
<fileTypeFactory implementation="org.jetbrains.kotlin.ide.konan.KotlinNativeFileTypeFactory"/>
</extensions>
<depends optional="true" config-file="native-run-configuration.xml">org.jetbrains.plugins.gradle</depends>
</idea-plugin>
@@ -1,386 +0,0 @@
/*
* 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
import com.google.gson.GsonBuilder
import com.google.gson.JsonIOException
import com.google.gson.JsonSyntaxException
import com.intellij.ide.actions.ShowFilePathAction
import com.intellij.ide.plugins.*
import com.intellij.ide.util.PropertiesComponent
import com.intellij.notification.NotificationDisplayType
import com.intellij.notification.NotificationGroup
import com.intellij.notification.NotificationListener
import com.intellij.notification.NotificationType
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.*
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.extensions.PluginId
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.progress.Task
import com.intellij.openapi.updateSettings.impl.PluginDownloader
import com.intellij.openapi.updateSettings.impl.UpdateSettings
import com.intellij.openapi.util.JDOMUtil
import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.vfs.CharsetToolkit
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.util.Alarm
import com.intellij.util.io.HttpRequests
import com.intellij.util.text.VersionComparatorUtil
import org.jetbrains.kotlin.idea.update.verify
import java.io.File
import java.io.IOException
import java.io.PrintWriter
import java.io.StringWriter
import java.net.URLEncoder
import java.time.DateTimeException
import java.time.Instant
import java.time.LocalDate
import java.time.ZoneOffset
import java.util.concurrent.TimeUnit
sealed class PluginUpdateStatus {
val timestamp = System.currentTimeMillis()
object LatestVersionInstalled : PluginUpdateStatus()
class Update(
val pluginDescriptor: IdeaPluginDescriptor,
val hostToInstallFrom: String?
) : PluginUpdateStatus()
class CheckFailed(val message: String, val detail: String? = null) : PluginUpdateStatus()
class Unverified(val verifierName: String, val reason: String?, val updateStatus: Update) : PluginUpdateStatus()
fun mergeWith(other: PluginUpdateStatus): PluginUpdateStatus {
if (other is Update) {
when (this) {
is LatestVersionInstalled -> {
return other
}
is Update -> {
if (VersionComparatorUtil.compare(other.pluginDescriptor.version, pluginDescriptor.version) > 0) {
return other
}
}
is CheckFailed, is Unverified -> {
// proceed to return this
}
}
}
return this
}
companion object {
fun fromException(message: String, e: Exception): PluginUpdateStatus {
val writer = StringWriter()
e.printStackTrace(PrintWriter(writer))
return CheckFailed(message, writer.toString())
}
}
}
class KotlinPluginUpdater : Disposable {
private var updateDelay = INITIAL_UPDATE_DELAY
private val alarm = Alarm(Alarm.ThreadToUse.POOLED_THREAD, this)
private val notificationGroup = NotificationGroup(
KotlinBundle.message("plugin.updater.notification.group"),
NotificationDisplayType.STICKY_BALLOON, true
)
@Volatile
private var checkQueued = false
@Volatile
private var lastUpdateStatus: PluginUpdateStatus? = null
fun kotlinFileEdited(file: VirtualFile) {
if (!file.isInLocalFileSystem) return
if (ApplicationManager.getApplication().isUnitTestMode || ApplicationManager.getApplication().isHeadlessEnvironment) return
if (!UpdateSettings.getInstance().isCheckNeeded) return
val lastUpdateTime = java.lang.Long.parseLong(PropertiesComponent.getInstance().getValue(PROPERTY_NAME, "0"))
if (lastUpdateTime == 0L || System.currentTimeMillis() - lastUpdateTime > CACHED_REQUEST_DELAY) {
queueUpdateCheck { updateStatus ->
when (updateStatus) {
is PluginUpdateStatus.Update -> notifyPluginUpdateAvailable(updateStatus)
is PluginUpdateStatus.CheckFailed -> LOG.info("Plugin update check failed: ${updateStatus.message}, details: ${updateStatus.detail}")
}
true
}
}
}
private fun queueUpdateCheck(callback: (PluginUpdateStatus) -> Boolean) {
ApplicationManager.getApplication().assertIsDispatchThread()
if (!checkQueued) {
checkQueued = true
alarm.addRequest({ updateCheck(callback) }, updateDelay)
updateDelay *= 2 // exponential backoff
}
}
fun runUpdateCheck(callback: (PluginUpdateStatus) -> Boolean) {
ApplicationManager.getApplication().executeOnPooledThread {
updateCheck(callback)
}
}
fun runCachedUpdate(callback: (PluginUpdateStatus) -> Boolean) {
ApplicationManager.getApplication().assertIsDispatchThread()
val cachedStatus = lastUpdateStatus
if (cachedStatus != null && System.currentTimeMillis() - cachedStatus.timestamp < CACHED_REQUEST_DELAY) {
if (cachedStatus !is PluginUpdateStatus.CheckFailed) {
callback(cachedStatus)
return
}
}
queueUpdateCheck(callback)
}
private fun updateCheck(callback: (PluginUpdateStatus) -> Boolean) {
var updateStatus: PluginUpdateStatus
if (KotlinPluginUtil.isSnapshotVersion() || KotlinPluginUtil.isPatched()) {
updateStatus = PluginUpdateStatus.LatestVersionInstalled
} else {
try {
updateStatus = checkUpdatesInMainRepository()
for (host in RepositoryHelper.getPluginHosts().filterNotNull()) {
val customUpdateStatus = checkUpdatesInCustomRepository(host)
updateStatus = updateStatus.mergeWith(customUpdateStatus)
}
} catch (e: Exception) {
updateStatus = PluginUpdateStatus.fromException(KotlinBundle.message("plugin.updater.error.check.failed"), e)
}
}
lastUpdateStatus = updateStatus
checkQueued = false
if (updateStatus is PluginUpdateStatus.Update) {
updateStatus = verify(updateStatus)
}
if (updateStatus !is PluginUpdateStatus.CheckFailed) {
recordSuccessfulUpdateCheck()
}
ApplicationManager.getApplication().invokeLater({
callback(updateStatus)
}, ModalityState.any())
}
private fun initPluginDescriptor(newVersion: String): IdeaPluginDescriptor {
val originalPlugin = PluginManager.getPlugin(KotlinPluginUtil.KOTLIN_PLUGIN_ID)!!
return PluginNode(KotlinPluginUtil.KOTLIN_PLUGIN_ID).apply {
version = newVersion
name = originalPlugin.name
description = originalPlugin.description
}
}
private fun checkUpdatesInMainRepository(): PluginUpdateStatus {
val buildNumber = ApplicationInfo.getInstance().apiVersion
val currentVersion = KotlinPluginUtil.getPluginVersion()
val os = URLEncoder.encode(SystemInfo.OS_NAME + " " + SystemInfo.OS_VERSION, CharsetToolkit.UTF8)
val uid = PermanentInstallationID.get()
val pluginId = KotlinPluginUtil.KOTLIN_PLUGIN_ID.idString
val url =
"https://plugins.jetbrains.com/plugins/list?pluginId=$pluginId&build=$buildNumber&pluginVersion=$currentVersion&os=$os&uuid=$uid"
val responseDoc = HttpRequests.request(url).connect {
JDOMUtil.load(it.inputStream)
}
if (responseDoc.name != "plugin-repository") {
return PluginUpdateStatus.CheckFailed(
KotlinBundle.message("plugin.updater.error.unexpected.repository.response"),
JDOMUtil.writeElement(responseDoc, "\n")
)
}
if (responseDoc.children.isEmpty()) {
// No plugin version compatible with current IDEA build; don't retry updates
return PluginUpdateStatus.LatestVersionInstalled
}
val newVersion = responseDoc.getChild("category")?.getChild("idea-plugin")?.getChild("version")?.text
?: return PluginUpdateStatus.CheckFailed(
KotlinBundle.message("plugin.updater.error.cant.find.plugin.version"),
JDOMUtil.writeElement(responseDoc, "\n")
)
val pluginDescriptor = initPluginDescriptor(newVersion)
return updateIfNotLatest(pluginDescriptor, null)
}
private fun checkUpdatesInCustomRepository(host: String): PluginUpdateStatus {
val plugins = try {
RepositoryHelper.loadPlugins(host, null)
} catch (e: Exception) {
return PluginUpdateStatus.fromException(KotlinBundle.message("plugin.updater.error.custom.repository", host), e)
}
val kotlinPlugin = plugins.find { pluginDescriptor ->
pluginDescriptor.pluginId == KotlinPluginUtil.KOTLIN_PLUGIN_ID && PluginManagerCore.isCompatible(pluginDescriptor)
} ?: return PluginUpdateStatus.LatestVersionInstalled
return updateIfNotLatest(kotlinPlugin, host)
}
private fun updateIfNotLatest(kotlinPlugin: IdeaPluginDescriptor, host: String?): PluginUpdateStatus {
if (VersionComparatorUtil.compare(kotlinPlugin.version, KotlinPluginUtil.getPluginVersion()) <= 0) {
return PluginUpdateStatus.LatestVersionInstalled
}
return PluginUpdateStatus.Update(kotlinPlugin, host)
}
private fun recordSuccessfulUpdateCheck() {
PropertiesComponent.getInstance().setValue(PROPERTY_NAME, System.currentTimeMillis().toString())
updateDelay = INITIAL_UPDATE_DELAY
}
private fun notifyPluginUpdateAvailable(update: PluginUpdateStatus.Update) {
val notification = notificationGroup.createNotification(
KotlinBundle.message("plugin.updater.notification.title"),
KotlinBundle.message("plugin.updater.notification.message", update.pluginDescriptor.version),
NotificationType.INFORMATION,
NotificationListener { notification, _ ->
notification.expire()
installPluginUpdate(update) {
notifyPluginUpdateAvailable(update)
}
})
notification.notify(null)
}
fun installPluginUpdate(
update: PluginUpdateStatus.Update,
successCallback: () -> Unit = {}, cancelCallback: () -> Unit = {}, errorCallback: () -> Unit = {}
) {
val descriptor = update.pluginDescriptor
val pluginDownloader = PluginDownloader.createDownloader(descriptor, update.hostToInstallFrom, null)
ProgressManager.getInstance().run(object : Task.Backgroundable(
null, KotlinBundle.message("plugin.updater.downloading"), true, PluginManagerUISettings.getInstance()
) {
override fun run(indicator: ProgressIndicator) {
var installed = false
var message: String? = null
val prepareResult = try {
pluginDownloader.prepareToInstall(indicator)
} catch (e: IOException) {
LOG.info(e)
message = e.message
false
}
if (prepareResult) {
installed = true
pluginDownloader.install()
ApplicationManager.getApplication().invokeLater {
PluginManagerMain.notifyPluginsUpdated(null)
}
}
ApplicationManager.getApplication().invokeLater {
if (!installed) {
errorCallback()
notifyNotInstalled(message)
} else {
successCallback()
}
}
}
override fun onCancel() {
cancelCallback()
}
})
}
private fun notifyNotInstalled(message: String?) {
val notification = notificationGroup.createNotification(
KotlinBundle.message("plugin.updater.notification.title"),
when (message) {
null -> KotlinBundle.message("plugin.updater.not.installed")
else -> KotlinBundle.message("plugin.updater.not.installed.misc", message)
},
NotificationType.INFORMATION,
NotificationListener { notification, _ ->
val logFile = File(PathManager.getLogPath(), "idea.log")
ShowFilePathAction.openFile(logFile)
notification.expire()
}
)
notification.notify(null)
}
override fun dispose() {
}
companion object {
private const val INITIAL_UPDATE_DELAY = 2000L
private val CACHED_REQUEST_DELAY = TimeUnit.DAYS.toMillis(1)
private const val PROPERTY_NAME = "kotlin.lastUpdateCheck"
private val LOG = Logger.getInstance(KotlinPluginUpdater::class.java)
fun getInstance(): KotlinPluginUpdater = ServiceManager.getService(KotlinPluginUpdater::class.java)
class ResponseParseException(message: String, cause: Exception? = null) : IllegalStateException(message, cause)
@Suppress("SpellCheckingInspection")
private class PluginDTO {
var cdate: String? = null
var channel: String? = null
// `true` if the version is seen in plugin site and available for download.
// Maybe be `false` if author requested version deletion.
var listed: Boolean = true
// `true` if version is approved and verified
var approve: Boolean = true
}
@Throws(IOException::class, ResponseParseException::class)
fun fetchPluginReleaseDate(pluginId: PluginId, version: String, channel: String?): LocalDate? {
val url = "https://plugins.jetbrains.com/api/plugins/${pluginId.idString}/updates?version=$version"
val pluginDTOs: Array<PluginDTO> = try {
HttpRequests.request(url).connect {
GsonBuilder().create().fromJson(it.inputStream.reader(), Array<PluginDTO>::class.java)
}
} catch (ioException: JsonIOException) {
throw IOException(ioException)
} catch (syntaxException: JsonSyntaxException) {
throw ResponseParseException("Can't parse json response", syntaxException)
}
val selectedPluginDTO = pluginDTOs
.firstOrNull {
it.listed && it.approve && (it.channel == channel || (it.channel == "" && channel == null))
}
?: return null
val dateString = selectedPluginDTO.cdate ?: throw ResponseParseException("Empty cdate")
return try {
val dateLong = dateString.toLong()
Instant.ofEpochMilli(dateLong).atZone(ZoneOffset.UTC).toLocalDate()
} catch (e: NumberFormatException) {
throw ResponseParseException("Can't parse long date", e)
} catch (e: DateTimeException) {
throw ResponseParseException("Can't convert to date", e)
}
}
}
}
@@ -1,23 +0,0 @@
/*
* Copyright 2010-2020 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;
public class PluginStartupActivity {
}
@@ -1,149 +0,0 @@
/*
* 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;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathMacros;
import com.intellij.openapi.components.BaseComponent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.event.DocumentListener;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.updateSettings.impl.UpdateChecker;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.search.searches.IndexPatternSearch;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory;
import org.jetbrains.kotlin.diagnostics.Errors;
import org.jetbrains.kotlin.idea.reporter.KotlinReportSubmitter;
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinTodoSearcher;
import org.jetbrains.kotlin.js.resolve.diagnostics.ErrorsJs;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm;
import org.jetbrains.kotlin.resolve.konan.diagnostics.ErrorsNative;
import org.jetbrains.kotlin.utils.PathUtil;
import java.io.File;
import java.io.IOException;
import static org.jetbrains.kotlin.idea.TestResourceBundleKt.registerAdditionalResourceBundleInTests;
public class PluginStartupComponent implements BaseComponent {
private static final Logger LOG = Logger.getInstance(PluginStartupComponent.class);
private static final String KOTLIN_BUNDLED = "KOTLIN_BUNDLED";
public static PluginStartupComponent getInstance() {
return ApplicationManager.getApplication().getComponent(PluginStartupComponent.class);
}
@Override
@NotNull
public String getComponentName() {
return PluginStartupComponent.class.getName();
}
@Override
public void initComponent() {
if (ApplicationManager.getApplication().isUnitTestMode()) {
registerAdditionalResourceBundleInTests();
}
registerPathVariable();
initializeDiagnostics();
try {
// API added in 15.0.2
UpdateChecker.INSTANCE.getExcludedFromUpdateCheckPlugins().add("org.jetbrains.kotlin");
}
catch (Throwable throwable) {
LOG.debug("Excluding Kotlin plugin updates using old API", throwable);
UpdateChecker.getDisabledToUpdatePlugins().add("org.jetbrains.kotlin");
}
EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new DocumentListener() {
@Override
public void documentChanged(@NotNull DocumentEvent e) {
VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(e.getDocument());
if (virtualFile != null && virtualFile.getFileType() == KotlinFileType.INSTANCE) {
KotlinPluginUpdater.Companion.getInstance().kotlinFileEdited(virtualFile);
}
}
});
ServiceManager.getService(IndexPatternSearch.class).registerExecutor(new KotlinTodoSearcher());
KotlinPluginCompatibilityVerifier.checkCompatibility();
KotlinReportSubmitter.Companion.setupReportingFromRelease();
//todo[Sedunov]: wait for fix in platform to avoid misunderstood from Java newbies (also ConfigureKotlinInTempDirTest)
//KotlinSdkType.Companion.setUpIfNeeded();
}
/*
Concurrent access to Errors may lead to the class loading dead lock because of non-trivial initialization in Errors.
As a work-around, all Error classes are initialized beforehand.
It doesn't matter what exact diagnostic factories are used here.
*/
private static void initializeDiagnostics() {
consumeFactory(Errors.DEPRECATION);
consumeFactory(ErrorsJvm.ACCIDENTAL_OVERRIDE);
consumeFactory(ErrorsJs.CALL_FROM_UMD_MUST_BE_JS_MODULE_AND_JS_NON_MODULE);
consumeFactory(ErrorsNative.INCOMPATIBLE_THROWS_INHERITED);
}
private static void consumeFactory(DiagnosticFactory<?> factory) {
//noinspection ResultOfMethodCallIgnored
factory.getClass();
}
private static void registerPathVariable() {
PathMacros macros = PathMacros.getInstance();
macros.setMacro(KOTLIN_BUNDLED, PathUtil.getKotlinPathsForIdeaPlugin().getHomePath().getPath());
}
private String aliveFlagPath;
public synchronized String getAliveFlagPath() {
if (this.aliveFlagPath == null) {
try {
File flagFile = File.createTempFile("kotlin-idea-", "-is-running");
flagFile.deleteOnExit();
this.aliveFlagPath = flagFile.getAbsolutePath();
}
catch (IOException e) {
this.aliveFlagPath = "";
}
}
return this.aliveFlagPath;
}
public synchronized void resetAliveFlag() {
if (this.aliveFlagPath != null) {
File flagFile = new File(this.aliveFlagPath);
if (flagFile.exists()) {
if (flagFile.delete()) {
this.aliveFlagPath = null;
}
}
}
}
@Override
public void disposeComponent() {}
}
@@ -1,27 +0,0 @@
/*
* Copyright 2010-2020 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;
import com.intellij.openapi.application.ApplicationManager;
import java.io.File;
import java.io.IOException;
public class PluginStartupService {
}
@@ -1,221 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.actions.internal.benchmark
import com.intellij.codeInsight.AutoPopupController
import com.intellij.codeInsight.completion.CompletionType
import com.intellij.codeInsight.navigation.NavigationUtil
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.editor.EditorFactory
import com.intellij.openapi.editor.ScrollType
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.MessageType
import com.intellij.openapi.ui.popup.JBPopupFactory
import com.intellij.openapi.wm.WindowManager
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.search.DelegatingGlobalSearchScope
import com.intellij.psi.search.FileTypeIndex
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.ui.components.JBLabel
import com.intellij.ui.components.JBTextField
import com.intellij.uiDesigner.core.GridConstraints
import kotlinx.coroutines.*
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.caches.project.ModuleOrigin
import org.jetbrains.kotlin.idea.caches.project.getNullableModuleInfo
import org.jetbrains.kotlin.idea.completion.CompletionBenchmarkSink
import org.jetbrains.kotlin.idea.core.moveCaret
import org.jetbrains.kotlin.idea.core.util.EDT
import org.jetbrains.kotlin.idea.core.util.getLineCount
import org.jetbrains.kotlin.idea.core.util.toPsiFile
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.psi.KtFile
import java.util.*
import javax.swing.JFileChooser
import javax.swing.JPanel
abstract class AbstractCompletionBenchmarkAction : AnAction() {
override fun actionPerformed(e: AnActionEvent) {
val project = e.project ?: return
val benchmarkSink = CompletionBenchmarkSink.enableAndGet()
val scenario = createBenchmarkScenario(project, benchmarkSink) ?: return
GlobalScope.launch(EDT) {
scenario.doBenchmark()
CompletionBenchmarkSink.disable()
}
}
internal abstract fun createBenchmarkScenario(
project: Project,
benchmarkSink: CompletionBenchmarkSink.Impl
): AbstractCompletionBenchmarkScenario?
companion object {
fun showPopup(project: Project, text: String) {
val statusBar = WindowManager.getInstance().getStatusBar(project)
JBPopupFactory.getInstance()
.createHtmlTextBalloonBuilder(text, MessageType.ERROR, null)
.setFadeoutTime(5000)
.createBalloon().showInCenterOf(statusBar.component)
}
internal fun <T> List<T>.randomElement(random: Random): T? = if (this.isNotEmpty()) this[random.nextInt(this.size)] else null
internal fun <T : Any> List<T>.shuffledSequence(random: Random): Sequence<T> =
generateSequence { this.randomElement(random) }.distinct()
internal fun collectSuitableKotlinFiles(project: Project, filePredicate: (KtFile) -> Boolean): MutableList<KtFile> {
val scope = object : DelegatingGlobalSearchScope(GlobalSearchScope.allScope(project)) {
override fun isSearchOutsideRootModel(): Boolean = false
}
fun KtFile.isUsableForBenchmark(): Boolean {
val moduleInfo = this.getNullableModuleInfo() ?: return false
if (this.isCompiled || !this.isWritable || this.isScript()) return false
return moduleInfo.moduleOrigin == ModuleOrigin.MODULE
}
val kotlinVFiles = FileTypeIndex.getFiles(KotlinFileType.INSTANCE, scope)
return kotlinVFiles
.asSequence()
.mapNotNull { vfile -> (vfile.toPsiFile(project) as? KtFile) }
.filterTo(mutableListOf()) { it.isUsableForBenchmark() && filePredicate(it) }
}
internal fun JPanel.addBoxWithLabel(tooltip: String, label: String = "$tooltip:", default: String, i: Int): JBTextField {
this.add(JBLabel(label), GridConstraints().apply { row = i; column = 0 })
val textField = JBTextField().apply {
text = default
toolTipText = tooltip
}
this.add(textField, GridConstraints().apply { row = i; column = 1; fill = GridConstraints.FILL_HORIZONTAL })
return textField
}
}
override fun update(e: AnActionEvent) {
e.presentation.isEnabledAndVisible = ApplicationManager.getApplication().isInternal
}
}
internal abstract class AbstractCompletionBenchmarkScenario(
val project: Project, private val benchmarkSink: CompletionBenchmarkSink.Impl,
val random: Random = Random(), private val timeout: Long = 15000
) {
sealed class Result {
abstract fun toCSV(stringBuilder: StringBuilder)
open class SuccessResult(val lines: Int, val filePath: String, val first: Long, val full: Long) : Result() {
override fun toCSV(stringBuilder: StringBuilder): Unit = with(stringBuilder) {
append(filePath)
append(", ")
append(lines)
append(", ")
append(first)
append(", ")
append(full)
}
}
class ErrorResult(val filePath: String) : Result() {
override fun toCSV(stringBuilder: StringBuilder): Unit = with(stringBuilder) {
append(filePath)
append(", ")
append(", ")
append(", ")
}
}
}
protected suspend fun typeAtOffsetAndGetResult(text: String, offset: Int, file: KtFile): Result {
NavigationUtil.openFileWithPsiElement(file.navigationElement, false, true)
val document =
PsiDocumentManager.getInstance(project).getDocument(file) ?: return Result.ErrorResult("${file.virtualFile.path}:O$offset")
val location = "${file.virtualFile.path}:${document.getLineNumber(offset)}"
val editor = EditorFactory.getInstance().getEditors(document, project).firstOrNull() ?: return Result.ErrorResult(location)
delay(500)
editor.moveCaret(offset, scrollType = ScrollType.CENTER)
delay(500)
CommandProcessor.getInstance().executeCommand(project, {
runWriteAction {
document.insertString(editor.caretModel.offset, "\n$text\n")
PsiDocumentManager.getInstance(project).commitDocument(document)
}
editor.moveCaret(editor.caretModel.offset + text.length + 1)
AutoPopupController.getInstance(project).scheduleAutoPopup(editor, CompletionType.BASIC, null)
}, "insertTextAndInvokeCompletion", "completionBenchmark")
val result = try {
withTimeout(timeout) { collectResult(file, location) }
} catch (_: CancellationException) {
Result.ErrorResult(location)
}
CommandProcessor.getInstance().executeCommand(project, {
runWriteAction {
document.deleteString(offset, offset + text.length + 2)
PsiDocumentManager.getInstance(project).commitDocument(document)
}
}, "revertToOriginal", "completionBenchmark")
delay(100)
return result
}
private suspend fun collectResult(file: KtFile, location: String): Result {
val results = benchmarkSink.channel.receive()
return Result.SuccessResult(file.getLineCount(), location, results.firstFlush, results.full)
}
protected fun saveResults(allResults: List<Result>) {
val jfc = JFileChooser()
val result = jfc.showSaveDialog(null)
if (result == JFileChooser.APPROVE_OPTION) {
val file = jfc.selectedFile
file.writeText(buildString {
appendLine("n, file, lines, ff, full")
var i = 0
allResults.forEach {
append(i++)
append(", ")
it.toCSV(this)
appendLine()
}
})
}
AbstractCompletionBenchmarkAction.showPopup(project, KotlinBundle.message("title.done"))
}
abstract suspend fun doBenchmark()
}
@@ -1,67 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.actions.internal.refactoringTesting
import com.intellij.ide.plugins.PluginManager
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.extensions.PluginId
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.gradle.getMethodOrNull
internal fun <T> lazyPub(initializer: () -> T) = lazy(LazyThreadSafetyMode.PUBLICATION, initializer)
internal fun gitReset(project: Project, projectRoot: VirtualFile) {
fun ClassLoader.loadClassOrThrow(name: String) =
loadClass(name) ?: error("$name not loaded")
fun Class<*>.loadMethodOrThrow(name: String, vararg arguments: Class<*>) =
getMethodOrNull(name, *arguments) ?: error("${this.name}::$name not loaded")
val loader = PluginManager.getPlugin(PluginId.getId("Git4Idea"))?.pluginClassLoader ?: error("Git plugin is not found")
val gitCls = loader.loadClassOrThrow("git4idea.commands.Git")
val gitLineHandlerCls = loader.loadClassOrThrow("git4idea.commands.GitLineHandler")
val gitCommandCls = loader.loadClassOrThrow("git4idea.commands.GitCommand")
val gitCommandResultCls = loader.loadClassOrThrow("git4idea.commands.GitCommandResult")
val gitLineHandlerCtor = gitLineHandlerCls.getConstructor(Project::class.java, VirtualFile::class.java, gitCommandCls) ?: error(
"git4idea.commands.GitLineHandler::ctor not loaded"
)
val runCommand = gitCls.loadMethodOrThrow("runCommand", gitLineHandlerCls)
val getExitCode = gitCommandResultCls.loadMethodOrThrow("getExitCode")
val gitLineHandlerAddParameters = gitLineHandlerCls.loadMethodOrThrow("addParameters", List::class.java)
val gitCommandReset = gitCommandCls.getField("RESET")?.get(null) ?: error("git4idea.commands.GitCommand.RESET not loaded")
val resetLineHandler = gitLineHandlerCtor.newInstance(project, projectRoot, gitCommandReset)
gitLineHandlerAddParameters.invoke(resetLineHandler, listOf("--hard", "HEAD"))
val gitService = ServiceManager.getService(gitCls)
val runCommandResult = runCommand.invoke(gitService, resetLineHandler)
val gitResetResultCode = getExitCode.invoke(runCommandResult) as Int
if (gitResetResultCode == 0) {
VfsUtil.markDirtyAndRefresh(false, true, false, projectRoot)
//GitRepositoryManager.getInstance(project).updateRepository(d.getGitRoot())
} else {
error("Git reset failed")
}
}
inline fun edtExecute(crossinline body: () -> Unit) {
ApplicationManager.getApplication().invokeAndWait {
body()
}
}
inline fun readAction(crossinline body: () -> Unit) {
ApplicationManager.getApplication().runReadAction {
body()
}
}
@@ -1,83 +0,0 @@
/*
* 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.codeInsight
import com.intellij.codeInsight.CodeInsightBundle
import com.intellij.codeInsight.CodeInsightSettings
import com.intellij.codeInsight.hint.HintManager
import com.intellij.codeInsight.hint.HintManagerImpl
import com.intellij.codeInsight.hint.HintUtil
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.application.ReadAction.nonBlocking
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.project.Project
import com.intellij.ui.LightweightHint
import com.intellij.util.ArrayUtil
import com.intellij.util.concurrency.AppExecutorUtil
import org.jetbrains.annotations.TestOnly
import org.jetbrains.concurrency.CancellablePromise
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.imports.KotlinImportOptimizer
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.ImportPath
import java.util.*
import javax.swing.event.HyperlinkEvent
import javax.swing.event.HyperlinkListener
// FIX ME WHEN BUNCH 192 REMOVED
object ReviewAddedImports {
@get:TestOnly
var importsToBeReviewed: Collection<String> = emptyList()
@get:TestOnly
var importsToBeDeleted: Collection<String> = emptyList()
fun reviewAddedImports(
project: Project,
editor: Editor,
file: KtFile,
imported: TreeSet<String>
) {
if (CodeInsightSettings.getInstance().ADD_IMPORTS_ON_PASTE == CodeInsightSettings.YES &&
!imported.isEmpty()
) {
if (ApplicationManager.getApplication().isUnitTestMode) {
importsToBeReviewed = imported
removeImports(project, file, importsToBeDeleted)
return
}
// there is actual no such functionality in 192
}
}
private fun removeImports(
project: Project,
file: KtFile,
importsToRemove: Collection<String>
) {
if (importsToRemove.isEmpty()) return
WriteCommandAction.runWriteCommandAction(project, KotlinBundle.message("revert.applied.imports"), null, Runnable {
val newImports = file.importDirectives.mapNotNull {
val importedFqName = it.importedFqName ?: return@mapNotNull null
if (importsToRemove.contains(importedFqName.asString())) return@mapNotNull null
ImportPath(importedFqName, it.isAllUnder, it.aliasName?.let { alias -> Name.identifier(alias) })
}
KotlinImportOptimizer.replaceImports(file, newImports)
})
}
}
internal fun <T> submitNonBlocking(project: Project, indicator: ProgressIndicator, block: () -> T): CancellablePromise<T> =
nonBlocking<T> {
return@nonBlocking block()
}
.withDocumentsCommitted(project)
.submit(AppExecutorUtil.getAppExecutorService())
@@ -1,34 +0,0 @@
/*
* 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.codeInsight.codevision
import com.intellij.codeInsight.hints.ChangeListener
import com.intellij.codeInsight.hints.ImmediateConfigurable
import com.intellij.codeInsight.hints.config.InlayHintsConfigurable
import com.intellij.internal.statistic.eventLog.FeatureUsageData
import com.intellij.internal.statistic.service.fus.collectors.FUCounterUsageLogger
import com.intellij.openapi.project.Project
import com.intellij.ui.components.JBCheckBox
import com.intellij.ui.layout.panel
import org.jetbrains.kotlin.idea.KotlinBundle
import javax.swing.JPanel
typealias CodeVisionInlayHintsConfigurable = InlayHintsConfigurable
fun logUsageStatistics(project: Project?, groupId: String, eventId: String) {
project?.let { FUCounterUsageLogger.getInstance().logEvent(project, groupId, eventId) }
}
fun logUsageStatistics(project: Project?, groupId: String, eventId: String, data: FeatureUsageData) {
project?.let { FUCounterUsageLogger.getInstance().logEvent(project, groupId, eventId, data) }
}
fun createImmediateConfigurable(): ImmediateConfigurable {
return object : ImmediateConfigurable {
override fun createComponent(listener: ChangeListener): JPanel = panel {}
}
}
@@ -1,73 +0,0 @@
/*
* 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.codeInsight.hints
import com.intellij.codeInsight.hints.ChangeListener
import com.intellij.codeInsight.hints.ImmediateConfigurable
import com.intellij.codeInsight.hints.config.InlayHintsConfigurable
import com.intellij.ui.components.JBCheckBox
import com.intellij.ui.layout.panel
import org.jetbrains.kotlin.idea.KotlinBundle
import javax.swing.JComponent
typealias CompatibleInlayHintsConfigurable = InlayHintsConfigurable
fun createLambdaHintsImmediateConfigurable(settings: KotlinLambdasHintsProvider.Settings): ImmediateConfigurable {
return object : ImmediateConfigurable {
private val returnExprField = JBCheckBox(KotlinBundle.message("hints.settings.lambda.return"), settings.returnExpressions)
private val receiversAndParamsField = JBCheckBox(
KotlinBundle.message("hints.settings.lambda.receivers.parameters"),
settings.implicitReceiversAndParams
)
override fun createComponent(listener: ChangeListener): JComponent {
returnExprField.isSelected = settings.returnExpressions
returnExprField.addActionListener { settings.returnExpressions = returnExprField.isSelected }
receiversAndParamsField.isSelected = settings.implicitReceiversAndParams
receiversAndParamsField.addActionListener { settings.implicitReceiversAndParams = receiversAndParamsField.isSelected }
return panel {
row { returnExprField(pushX) }
row { receiversAndParamsField(pushX) }
}
}
}
}
fun createTypeHintsImmediateConfigurable(settings: KotlinReferencesTypeHintsProvider.Settings): ImmediateConfigurable {
return object : ImmediateConfigurable {
private val propertyTypeField = JBCheckBox(KotlinBundle.message("hints.settings.types.property"), settings.propertyType)
private val variableTypeField = JBCheckBox(KotlinBundle.message("hints.settings.types.variable"), settings.localVariableType)
private val funReturnTypeField = JBCheckBox(KotlinBundle.message("hints.settings.types.return"), settings.functionReturnType)
private val paramTypeField = JBCheckBox(KotlinBundle.message("hints.settings.types.parameter"), settings.parameterType)
override fun createComponent(listener: ChangeListener): JComponent {
propertyTypeField.isSelected = settings.propertyType
propertyTypeField.addActionListener { settings.propertyType = propertyTypeField.isSelected }
variableTypeField.isSelected = settings.localVariableType
variableTypeField.addActionListener { settings.localVariableType = variableTypeField.isSelected }
funReturnTypeField.isSelected = settings.functionReturnType
funReturnTypeField.addActionListener { settings.functionReturnType = funReturnTypeField.isSelected }
paramTypeField.isSelected = settings.parameterType
paramTypeField.addActionListener { settings.parameterType = paramTypeField.isSelected }
return panel {
row { propertyTypeField(pushX) }
row { variableTypeField(pushX) }
row { funReturnTypeField(pushX) }
row { paramTypeField(pushX) }
}
}
}
}
@@ -1,752 +0,0 @@
/*
* Copyright 2000-2018 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.compiler.configuration;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.TextComponentAccessor;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.ListCellRendererWrapper;
import com.intellij.ui.RawCommandLineEditor;
import com.intellij.util.text.VersionComparatorUtil;
import com.intellij.util.ui.ThreeStateCheckBox;
import com.intellij.util.ui.UIUtil;
import kotlin.collections.ArraysKt;
import kotlin.collections.CollectionsKt;
import kotlin.jvm.functions.Function0;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments;
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments;
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments;
import org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants;
import org.jetbrains.kotlin.config.*;
import org.jetbrains.kotlin.idea.KotlinBundle;
import org.jetbrains.kotlin.idea.PluginStartupComponent;
import org.jetbrains.kotlin.idea.facet.DescriptionListCellRenderer;
import org.jetbrains.kotlin.idea.facet.KotlinFacet;
import org.jetbrains.kotlin.idea.roots.RootUtilsKt;
import org.jetbrains.kotlin.idea.util.CidrUtil;
import org.jetbrains.kotlin.idea.util.application.ApplicationUtilsKt;
import org.jetbrains.kotlin.platform.IdePlatformKind;
import org.jetbrains.kotlin.platform.PlatformUtilKt;
import org.jetbrains.kotlin.platform.TargetPlatform;
import org.jetbrains.kotlin.platform.impl.JsIdePlatformUtil;
import org.jetbrains.kotlin.platform.impl.JvmIdePlatformKind;
import org.jetbrains.kotlin.platform.impl.JvmIdePlatformUtil;
import org.jetbrains.kotlin.platform.jvm.JdkPlatform;
import javax.swing.*;
import java.util.*;
public class KotlinCompilerConfigurableTab implements SearchableConfigurable {
private static final Map<String, String> moduleKindDescriptions = new LinkedHashMap<>();
private static final Map<String, String> soruceMapSourceEmbeddingDescriptions = new LinkedHashMap<>();
private static final List<LanguageFeature.State> languageFeatureStates = Arrays.asList(
LanguageFeature.State.ENABLED, LanguageFeature.State.ENABLED_WITH_WARNING, LanguageFeature.State.ENABLED_WITH_ERROR
);
private static final int MAX_WARNING_SIZE = 75;
static {
moduleKindDescriptions.put(K2JsArgumentConstants.MODULE_PLAIN, KotlinBundle.message("configuration.description.plain.put.to.global.scope"));
moduleKindDescriptions.put(K2JsArgumentConstants.MODULE_AMD, KotlinBundle.message("configuration.description.amd"));
moduleKindDescriptions.put(K2JsArgumentConstants.MODULE_COMMONJS, KotlinBundle.message("configuration.description.commonjs"));
moduleKindDescriptions.put(K2JsArgumentConstants.MODULE_UMD, KotlinBundle.message("configuration.description.umd.detect.amd.or.commonjs.if.available.fallback.to.plain"));
soruceMapSourceEmbeddingDescriptions.put(K2JsArgumentConstants.SOURCE_MAP_SOURCE_CONTENT_NEVER, KotlinBundle.message("configuration.description.never"));
soruceMapSourceEmbeddingDescriptions.put(K2JsArgumentConstants.SOURCE_MAP_SOURCE_CONTENT_ALWAYS, KotlinBundle.message("configuration.description.always"));
soruceMapSourceEmbeddingDescriptions.put(K2JsArgumentConstants.SOURCE_MAP_SOURCE_CONTENT_INLINING, KotlinBundle.message("configuration.description.when.inlining.a.function.from.other.module.with.embedded.sources"));
}
@Nullable
private final KotlinCompilerWorkspaceSettings compilerWorkspaceSettings;
private final Project project;
private final boolean isProjectSettings;
private CommonCompilerArguments commonCompilerArguments;
private K2JSCompilerArguments k2jsCompilerArguments;
private K2JVMCompilerArguments k2jvmCompilerArguments;
private CompilerSettings compilerSettings;
private JPanel contentPane;
private ThreeStateCheckBox reportWarningsCheckBox;
private RawCommandLineEditor additionalArgsOptionsField;
private JLabel additionalArgsLabel;
private ThreeStateCheckBox generateSourceMapsCheckBox;
private TextFieldWithBrowseButton outputPrefixFile;
private TextFieldWithBrowseButton outputPostfixFile;
private JLabel labelForOutputDirectory;
private TextFieldWithBrowseButton outputDirectory;
private ThreeStateCheckBox copyRuntimeFilesCheckBox;
private ThreeStateCheckBox keepAliveCheckBox;
private JCheckBox enableIncrementalCompilationForJvmCheckBox;
private JCheckBox enableIncrementalCompilationForJsCheckBox;
private JComboBox moduleKindComboBox;
private JTextField scriptTemplatesField;
private JTextField scriptTemplatesClasspathField;
private JLabel scriptTemplatesLabel;
private JLabel scriptTemplatesClasspathLabel;
private JPanel k2jvmPanel;
private JPanel k2jsPanel;
private JComboBox jvmVersionComboBox;
private JComboBox<VersionView> languageVersionComboBox;
private JComboBox coroutineSupportComboBox;
private JComboBox<VersionView> apiVersionComboBox;
private JPanel scriptPanel;
private JLabel labelForOutputPrefixFile;
private JLabel labelForOutputPostfixFile;
private JLabel warningLabel;
private JTextField sourceMapPrefix;
private JLabel labelForSourceMapPrefix;
private JComboBox sourceMapEmbedSources;
private JPanel coroutinesPanel;
private boolean isEnabled = true;
public KotlinCompilerConfigurableTab(
Project project,
@NotNull CommonCompilerArguments commonCompilerArguments,
@NotNull K2JSCompilerArguments k2jsCompilerArguments,
@NotNull K2JVMCompilerArguments k2jvmCompilerArguments, CompilerSettings compilerSettings,
@Nullable KotlinCompilerWorkspaceSettings compilerWorkspaceSettings,
boolean isProjectSettings,
boolean isMultiEditor
) {
this.project = project;
this.commonCompilerArguments = commonCompilerArguments;
this.k2jsCompilerArguments = k2jsCompilerArguments;
this.compilerSettings = compilerSettings;
this.compilerWorkspaceSettings = compilerWorkspaceSettings;
this.k2jvmCompilerArguments = k2jvmCompilerArguments;
this.isProjectSettings = isProjectSettings;
warningLabel.setIcon(AllIcons.General.WarningDialog);
if (isProjectSettings) {
languageVersionComboBox.addActionListener(e -> onLanguageLevelChanged(getSelectedLanguageVersionView()));
}
additionalArgsOptionsField.attachLabel(additionalArgsLabel);
fillLanguageAndAPIVersionList();
fillCoroutineSupportList();
if (CidrUtil.isRunningInCidrIde()) {
keepAliveCheckBox.setVisible(false);
k2jvmPanel.setVisible(false);
k2jsPanel.setVisible(false);
}
else {
initializeNonCidrSettings(isMultiEditor);
}
reportWarningsCheckBox.setThirdStateEnabled(isMultiEditor);
if (isProjectSettings) {
List<String> modulesOverridingProjectSettings = ArraysKt.mapNotNull(
ModuleManager.getInstance(project).getModules(),
module -> {
KotlinFacet facet = KotlinFacet.Companion.get(module);
if (facet == null) return null;
KotlinFacetSettings facetSettings = facet.getConfiguration().getSettings();
if (facetSettings.getUseProjectSettings()) return null;
return module.getName();
}
);
CollectionsKt.sort(modulesOverridingProjectSettings);
if (!modulesOverridingProjectSettings.isEmpty()) {
warningLabel.setVisible(true);
warningLabel.setText(buildOverridingModulesWarning(modulesOverridingProjectSettings));
}
}
}
@SuppressWarnings("unused")
public KotlinCompilerConfigurableTab(Project project) {
this(project,
(CommonCompilerArguments) KotlinCommonCompilerArgumentsHolder.Companion.getInstance(project).getSettings().unfrozen(),
(K2JSCompilerArguments) Kotlin2JsCompilerArgumentsHolder.Companion.getInstance(project).getSettings().unfrozen(),
(K2JVMCompilerArguments) Kotlin2JvmCompilerArgumentsHolder.Companion.getInstance(project).getSettings().unfrozen(),
(CompilerSettings) KotlinCompilerSettings.Companion.getInstance(project).getSettings().unfrozen(),
KotlinCompilerWorkspaceSettings.getInstance(project),
true,
false);
}
private void initializeNonCidrSettings(boolean isMultiEditor) {
setupFileChooser(labelForOutputPrefixFile, outputPrefixFile,
KotlinBundle.message("configuration.title.kotlin.compiler.js.option.output.prefix.browse.title"),
true);
setupFileChooser(labelForOutputPostfixFile, outputPostfixFile,
KotlinBundle.message("configuration.title.kotlin.compiler.js.option.output.postfix.browse.title"),
true);
setupFileChooser(labelForOutputDirectory, outputDirectory,
KotlinBundle.message("configuration.title.choose.output.directory"),
false);
fillModuleKindList();
fillSourceMapSourceEmbeddingList();
fillJvmVersionList();
generateSourceMapsCheckBox.setThirdStateEnabled(isMultiEditor);
generateSourceMapsCheckBox.addActionListener(event -> sourceMapPrefix.setEnabled(generateSourceMapsCheckBox.isSelected()));
copyRuntimeFilesCheckBox.setThirdStateEnabled(isMultiEditor);
keepAliveCheckBox.setThirdStateEnabled(isMultiEditor);
if (compilerWorkspaceSettings == null) {
keepAliveCheckBox.setVisible(false);
k2jvmPanel.setVisible(false);
enableIncrementalCompilationForJsCheckBox.setVisible(false);
}
updateOutputDirEnabled();
}
private static int calculateNameCountToShowInWarning(List<String> allNames) {
int lengthSoFar = 0;
int size = allNames.size();
for (int i = 0; i < size; i++) {
lengthSoFar = (i > 0 ? lengthSoFar + 2 : 0) + allNames.get(i).length();
if (lengthSoFar > MAX_WARNING_SIZE) return i;
}
return size;
}
@NotNull
private static String buildOverridingModulesWarning(List<String> modulesOverridingProjectSettings) {
int nameCountToShow = calculateNameCountToShowInWarning(modulesOverridingProjectSettings);
int allNamesCount = modulesOverridingProjectSettings.size();
if (nameCountToShow == 0) {
return KotlinBundle.message("configuration.warning.text.modules.override.project.settings", String.valueOf(allNamesCount));
}
StringBuilder builder = new StringBuilder();
builder.append("<html>");
builder.append(KotlinBundle.message("configuration.warning.text.following.modules.override.project.settings")).append(" ");
CollectionsKt.joinTo(
modulesOverridingProjectSettings.subList(0, nameCountToShow),
builder,
", ",
"",
"",
-1,
"",
new Function1<String, CharSequence>() {
@Override
public CharSequence invoke(String s) {
return "<strong>" + s + "</strong>";
}
}
);
if (nameCountToShow < allNamesCount) {
builder.append(" ").append(KotlinBundle.message("configuration.text.and")).append(" ").append(allNamesCount - nameCountToShow).append(" ").append(KotlinBundle.message("configuration.text.other.s"));
}
return builder.toString();
}
@NotNull
private static String getModuleKindDescription(@Nullable String moduleKind) {
if (moduleKind == null) return "";
String result = moduleKindDescriptions.get(moduleKind);
assert result != null : "Module kind " + moduleKind + " was not added to combobox, therefore it should not be here";
return result;
}
@NotNull
private static String getSourceMapSourceEmbeddingDescription(@Nullable String sourceMapSourceEmbeddingId) {
if (sourceMapSourceEmbeddingId == null) return "";
String result = soruceMapSourceEmbeddingDescriptions.get(sourceMapSourceEmbeddingId);
assert result != null : "Source map source embedding mode " + sourceMapSourceEmbeddingId +
" was not added to combobox, therefore it should not be here";
return result;
}
@NotNull
private static String getModuleKindOrDefault(@Nullable String moduleKindId) {
if (moduleKindId == null) {
moduleKindId = K2JsArgumentConstants.MODULE_PLAIN;
}
return moduleKindId;
}
@NotNull
private static String getSourceMapSourceEmbeddingOrDefault(@Nullable String sourceMapSourceEmbeddingId) {
if (sourceMapSourceEmbeddingId == null) {
sourceMapSourceEmbeddingId = K2JsArgumentConstants.SOURCE_MAP_SOURCE_CONTENT_INLINING;
}
return sourceMapSourceEmbeddingId;
}
private static String getJvmVersionOrDefault(@Nullable String jvmVersion) {
return jvmVersion != null ? jvmVersion : JvmTarget.DEFAULT.getDescription();
}
private static void setupFileChooser(
@NotNull JLabel label,
@NotNull TextFieldWithBrowseButton fileChooser,
@NotNull String title,
boolean forFiles
) {
label.setLabelFor(fileChooser);
fileChooser.addBrowseFolderListener(title, null, null,
new FileChooserDescriptor(forFiles, !forFiles, false, false, false, false),
TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT);
}
private static boolean isModifiedWithNullize(@NotNull TextFieldWithBrowseButton chooser, @Nullable String currentValue) {
return !StringUtil.equals(
StringUtil.nullize(chooser.getText(), true),
StringUtil.nullize(currentValue, true));
}
private static boolean isModified(@NotNull TextFieldWithBrowseButton chooser, @NotNull String currentValue) {
return !StringUtil.equals(chooser.getText(), currentValue);
}
private void updateOutputDirEnabled() {
if (isEnabled && copyRuntimeFilesCheckBox != null) {
outputDirectory.setEnabled(copyRuntimeFilesCheckBox.isSelected());
labelForOutputDirectory.setEnabled(copyRuntimeFilesCheckBox.isSelected());
}
}
private boolean isLessOrEqual(LanguageVersion version, LanguageVersion upperBound) {
return VersionComparatorUtil.compare(version.getVersionString(), upperBound.getVersionString()) <= 0;
}
public void onLanguageLevelChanged(@Nullable VersionView languageLevel) {
if (languageLevel == null) return;
restrictAPIVersions(languageLevel);
coroutinesPanel.setVisible(languageLevel.getVersion().compareTo(LanguageVersion.KOTLIN_1_3) < 0);
}
@SuppressWarnings("unchecked")
private void restrictAPIVersions(VersionView upperBoundView) {
VersionView selectedAPIView = getSelectedAPIVersionView();
LanguageVersion selectedAPIVersion = selectedAPIView.getVersion();
LanguageVersion upperBound = upperBoundView.getVersion();
List<VersionView> permittedAPIVersions = new ArrayList<>(LanguageVersion.values().length + 1);
if (isLessOrEqual(VersionView.LatestStable.INSTANCE.getVersion(), upperBound)) {
permittedAPIVersions.add(VersionView.LatestStable.INSTANCE);
}
ArraysKt.mapNotNullTo(
LanguageVersion.values(),
permittedAPIVersions,
version -> isLessOrEqual(version, upperBound) && !version.isUnsupported() ? new VersionView.Specific(version) : null
);
apiVersionComboBox.setModel(
new DefaultComboBoxModel(permittedAPIVersions.toArray())
);
apiVersionComboBox.setSelectedItem(
VersionComparatorUtil.compare(selectedAPIVersion.getVersionString(), upperBound.getVersionString()) <= 0
? selectedAPIView
: upperBoundView
);
}
@SuppressWarnings("unchecked")
private void fillJvmVersionList() {
for (TargetPlatform jvm : JvmIdePlatformKind.INSTANCE.getPlatforms()) {
jvmVersionComboBox.addItem(PlatformUtilKt.subplatformsOfType(jvm, JdkPlatform.class).get(0).getTargetVersion().getDescription());
}
}
private void fillLanguageAndAPIVersionList() {
languageVersionComboBox.addItem(VersionView.LatestStable.INSTANCE);
apiVersionComboBox.addItem(VersionView.LatestStable.INSTANCE);
for (LanguageVersion version : LanguageVersion.values()) {
if (version.isUnsupported() || !version.isStable() && !ApplicationManager.getApplication().isInternal()) {
continue;
}
VersionView.Specific specificVersion = new VersionView.Specific(version);
languageVersionComboBox.addItem(specificVersion);
apiVersionComboBox.addItem(specificVersion);
}
languageVersionComboBox.setRenderer(new DescriptionListCellRenderer());
apiVersionComboBox.setRenderer(new DescriptionListCellRenderer());
}
@SuppressWarnings("unchecked")
private void fillCoroutineSupportList() {
for (LanguageFeature.State coroutineSupport : languageFeatureStates) {
coroutineSupportComboBox.addItem(coroutineSupport);
}
coroutineSupportComboBox.setRenderer(new DescriptionListCellRenderer());
}
public void setTargetPlatform(@Nullable IdePlatformKind<?> targetPlatform) {
k2jsPanel.setVisible(JsIdePlatformUtil.isJavaScript(targetPlatform));
scriptPanel.setVisible(JvmIdePlatformUtil.isJvm(targetPlatform));
}
@SuppressWarnings("unchecked")
private void fillModuleKindList() {
for (String moduleKind : moduleKindDescriptions.keySet()) {
moduleKindComboBox.addItem(moduleKind);
}
moduleKindComboBox.setRenderer(new ListCellRendererWrapper<String>() {
@Override
public void customize(JList list, String value, int index, boolean selected, boolean hasFocus) {
setText(getModuleKindDescription(value));
}
});
}
@SuppressWarnings("unchecked")
private void fillSourceMapSourceEmbeddingList() {
for (String moduleKind : soruceMapSourceEmbeddingDescriptions.keySet()) {
sourceMapEmbedSources.addItem(moduleKind);
}
sourceMapEmbedSources.setRenderer(new ListCellRendererWrapper<String>() {
@Override
public void customize(JList list, String value, int index, boolean selected, boolean hasFocus) {
setText(value != null ? getSourceMapSourceEmbeddingDescription(value) : "");
}
});
}
@NotNull
@Override
public String getId() {
return "project.kotlinCompiler";
}
@Nullable
@Override
public Runnable enableSearch(String option) {
return null;
}
@Nullable
@Override
public JComponent createComponent() {
return contentPane;
}
@Override
public boolean isModified() {
return isModified(reportWarningsCheckBox, !commonCompilerArguments.getSuppressWarnings()) ||
!getSelectedLanguageVersionView().equals(KotlinFacetSettingsKt.getLanguageVersionView(commonCompilerArguments)) ||
!getSelectedAPIVersionView().equals(KotlinFacetSettingsKt.getApiVersionView(commonCompilerArguments)) ||
!getSelectedCoroutineState().equals(commonCompilerArguments.getCoroutinesState()) ||
!additionalArgsOptionsField.getText().equals(compilerSettings.getAdditionalArguments()) ||
isModified(scriptTemplatesField, compilerSettings.getScriptTemplates()) ||
isModified(scriptTemplatesClasspathField, compilerSettings.getScriptTemplatesClasspath()) ||
isModified(copyRuntimeFilesCheckBox, compilerSettings.getCopyJsLibraryFiles()) ||
isModified(outputDirectory, compilerSettings.getOutputDirectoryForJsLibraryFiles()) ||
(compilerWorkspaceSettings != null &&
(isModified(enableIncrementalCompilationForJvmCheckBox, compilerWorkspaceSettings.getPreciseIncrementalEnabled()) ||
isModified(enableIncrementalCompilationForJsCheckBox, compilerWorkspaceSettings.getIncrementalCompilationForJsEnabled()) ||
isModified(keepAliveCheckBox, compilerWorkspaceSettings.getEnableDaemon()))) ||
isModified(generateSourceMapsCheckBox, k2jsCompilerArguments.getSourceMap()) ||
isModifiedWithNullize(outputPrefixFile, k2jsCompilerArguments.getOutputPrefix()) ||
isModifiedWithNullize(outputPostfixFile, k2jsCompilerArguments.getOutputPostfix()) ||
!getSelectedModuleKind().equals(getModuleKindOrDefault(k2jsCompilerArguments.getModuleKind())) ||
isModified(sourceMapPrefix, StringUtil.notNullize(k2jsCompilerArguments.getSourceMapPrefix())) ||
!getSelectedSourceMapSourceEmbedding().equals(
getSourceMapSourceEmbeddingOrDefault(k2jsCompilerArguments.getSourceMapEmbedSources())) ||
!getSelectedJvmVersion().equals(getJvmVersionOrDefault(k2jvmCompilerArguments.getJvmTarget()));
}
@NotNull
private String getSelectedModuleKind() {
return getModuleKindOrDefault((String) moduleKindComboBox.getSelectedItem());
}
private String getSelectedSourceMapSourceEmbedding() {
return getSourceMapSourceEmbeddingOrDefault((String) sourceMapEmbedSources.getSelectedItem());
}
@NotNull
private String getSelectedJvmVersion() {
return getJvmVersionOrDefault((String) jvmVersionComboBox.getSelectedItem());
}
@NotNull
public VersionView getSelectedLanguageVersionView() {
Object item = languageVersionComboBox.getSelectedItem();
return item != null ? (VersionView) item : VersionView.LatestStable.INSTANCE;
}
@NotNull
private VersionView getSelectedAPIVersionView() {
Object item = apiVersionComboBox.getSelectedItem();
return item != null ? (VersionView) item : VersionView.LatestStable.INSTANCE;
}
@NotNull
private String getSelectedCoroutineState() {
if (getSelectedLanguageVersionView().getVersion().compareTo(LanguageVersion.KOTLIN_1_3) >= 0) {
return CommonCompilerArguments.DEFAULT;
}
LanguageFeature.State state = (LanguageFeature.State) coroutineSupportComboBox.getSelectedItem();
if (state == null) return CommonCompilerArguments.DEFAULT;
switch (state) {
case ENABLED: return CommonCompilerArguments.ENABLE;
case ENABLED_WITH_WARNING: return CommonCompilerArguments.WARN;
case ENABLED_WITH_ERROR: return CommonCompilerArguments.ERROR;
default: return CommonCompilerArguments.DEFAULT;
}
}
public void applyTo(
CommonCompilerArguments commonCompilerArguments,
K2JVMCompilerArguments k2jvmCompilerArguments,
K2JSCompilerArguments k2jsCompilerArguments,
CompilerSettings compilerSettings
) throws ConfigurationException {
if (isProjectSettings) {
boolean shouldInvalidateCaches =
!getSelectedLanguageVersionView().equals(KotlinFacetSettingsKt.getLanguageVersionView(commonCompilerArguments)) ||
!getSelectedAPIVersionView().equals(KotlinFacetSettingsKt.getApiVersionView(commonCompilerArguments)) ||
!getSelectedCoroutineState().equals(commonCompilerArguments.getCoroutinesState()) ||
!additionalArgsOptionsField.getText().equals(compilerSettings.getAdditionalArguments());
if (shouldInvalidateCaches) {
ApplicationUtilsKt.runWriteAction(
new Function0<Object>() {
@Override
public Object invoke() {
RootUtilsKt.invalidateProjectRoots(project);
return null;
}
}
);
}
}
commonCompilerArguments.setSuppressWarnings(!reportWarningsCheckBox.isSelected());
KotlinFacetSettingsKt.setLanguageVersionView(commonCompilerArguments, getSelectedLanguageVersionView());
KotlinFacetSettingsKt.setApiVersionView(commonCompilerArguments, getSelectedAPIVersionView());
commonCompilerArguments.setCoroutinesState(getSelectedCoroutineState());
compilerSettings.setAdditionalArguments(additionalArgsOptionsField.getText());
compilerSettings.setScriptTemplates(scriptTemplatesField.getText());
compilerSettings.setScriptTemplatesClasspath(scriptTemplatesClasspathField.getText());
compilerSettings.setCopyJsLibraryFiles(copyRuntimeFilesCheckBox.isSelected());
compilerSettings.setOutputDirectoryForJsLibraryFiles(outputDirectory.getText());
if (compilerWorkspaceSettings != null) {
compilerWorkspaceSettings.setPreciseIncrementalEnabled(enableIncrementalCompilationForJvmCheckBox.isSelected());
compilerWorkspaceSettings.setIncrementalCompilationForJsEnabled(enableIncrementalCompilationForJsCheckBox.isSelected());
boolean oldEnableDaemon = compilerWorkspaceSettings.getEnableDaemon();
compilerWorkspaceSettings.setEnableDaemon(keepAliveCheckBox.isSelected());
if (keepAliveCheckBox.isSelected() != oldEnableDaemon) {
PluginStartupComponent.getInstance().resetAliveFlag();
}
}
k2jsCompilerArguments.setSourceMap(generateSourceMapsCheckBox.isSelected());
k2jsCompilerArguments.setOutputPrefix(StringUtil.nullize(outputPrefixFile.getText(), true));
k2jsCompilerArguments.setOutputPostfix(StringUtil.nullize(outputPostfixFile.getText(), true));
k2jsCompilerArguments.setModuleKind(getSelectedModuleKind());
k2jsCompilerArguments.setSourceMapPrefix(sourceMapPrefix.getText());
k2jsCompilerArguments.setSourceMapEmbedSources(generateSourceMapsCheckBox.isSelected() ? getSelectedSourceMapSourceEmbedding() : null);
k2jvmCompilerArguments.setJvmTarget(getSelectedJvmVersion());
if (isProjectSettings) {
KotlinCommonCompilerArgumentsHolder.Companion.getInstance(project).setSettings(commonCompilerArguments);
Kotlin2JvmCompilerArgumentsHolder.Companion.getInstance(project).setSettings(k2jvmCompilerArguments);
Kotlin2JsCompilerArgumentsHolder.Companion.getInstance(project).setSettings(k2jsCompilerArguments);
KotlinCompilerSettings.Companion.getInstance(project).setSettings(compilerSettings);
}
for (ClearBuildStateExtension extension : ClearBuildStateExtension.getExtensions()) {
extension.clearState(project);
}
}
@Override
public void apply() throws ConfigurationException {
applyTo(commonCompilerArguments, k2jvmCompilerArguments, k2jsCompilerArguments, compilerSettings);
}
@Override
public void reset() {
reportWarningsCheckBox.setSelected(!commonCompilerArguments.getSuppressWarnings());
setSelectedItem(languageVersionComboBox, KotlinFacetSettingsKt.getLanguageVersionView(commonCompilerArguments));
onLanguageLevelChanged((VersionView) languageVersionComboBox.getSelectedItem()); // getSelectedLanguageVersionView() replaces null
setSelectedItem(apiVersionComboBox, KotlinFacetSettingsKt.getApiVersionView(commonCompilerArguments));
coroutineSupportComboBox.setSelectedItem(CoroutineSupport.byCompilerArguments(commonCompilerArguments));
additionalArgsOptionsField.setText(compilerSettings.getAdditionalArguments());
scriptTemplatesField.setText(compilerSettings.getScriptTemplates());
scriptTemplatesClasspathField.setText(compilerSettings.getScriptTemplatesClasspath());
copyRuntimeFilesCheckBox.setSelected(compilerSettings.getCopyJsLibraryFiles());
outputDirectory.setText(compilerSettings.getOutputDirectoryForJsLibraryFiles());
if (compilerWorkspaceSettings != null) {
enableIncrementalCompilationForJvmCheckBox.setSelected(compilerWorkspaceSettings.getPreciseIncrementalEnabled());
enableIncrementalCompilationForJsCheckBox.setSelected(compilerWorkspaceSettings.getIncrementalCompilationForJsEnabled());
keepAliveCheckBox.setSelected(compilerWorkspaceSettings.getEnableDaemon());
}
generateSourceMapsCheckBox.setSelected(k2jsCompilerArguments.getSourceMap());
outputPrefixFile.setText(k2jsCompilerArguments.getOutputPrefix());
outputPostfixFile.setText(k2jsCompilerArguments.getOutputPostfix());
moduleKindComboBox.setSelectedItem(getModuleKindOrDefault(k2jsCompilerArguments.getModuleKind()));
sourceMapPrefix.setText(k2jsCompilerArguments.getSourceMapPrefix());
sourceMapPrefix.setEnabled(k2jsCompilerArguments.getSourceMap());
sourceMapEmbedSources.setSelectedItem(getSourceMapSourceEmbeddingOrDefault(k2jsCompilerArguments.getSourceMapEmbedSources()));
jvmVersionComboBox.setSelectedItem(getJvmVersionOrDefault(k2jvmCompilerArguments.getJvmTarget()));
}
private static void setSelectedItem(JComboBox<VersionView> comboBox, VersionView versionView) {
// Imported projects might have outdated language/api versions - we display them as well (see createVersionValidator() for details)
int index = ((DefaultComboBoxModel<VersionView>) comboBox.getModel()).getIndexOf(versionView);
if (index == -1)
comboBox.addItem(versionView);
comboBox.setSelectedItem(versionView);
}
@Override
public void disposeUIResources() {
}
@Nls
@Override
public String getDisplayName() {
return KotlinBundle.message("configuration.name.kotlin.compiler");
}
@Nullable
@Override
public String getHelpTopic() {
return "reference.compiler.kotlin";
}
public JPanel getContentPane() {
return contentPane;
}
public ThreeStateCheckBox getReportWarningsCheckBox() {
return reportWarningsCheckBox;
}
public RawCommandLineEditor getAdditionalArgsOptionsField() {
return additionalArgsOptionsField;
}
public ThreeStateCheckBox getGenerateSourceMapsCheckBox() {
return generateSourceMapsCheckBox;
}
public TextFieldWithBrowseButton getOutputPrefixFile() {
return outputPrefixFile;
}
public TextFieldWithBrowseButton getOutputPostfixFile() {
return outputPostfixFile;
}
public TextFieldWithBrowseButton getOutputDirectory() {
return outputDirectory;
}
public ThreeStateCheckBox getCopyRuntimeFilesCheckBox() {
return copyRuntimeFilesCheckBox;
}
public ThreeStateCheckBox getKeepAliveCheckBox() {
return keepAliveCheckBox;
}
public JComboBox getModuleKindComboBox() {
return moduleKindComboBox;
}
public JTextField getScriptTemplatesField() {
return scriptTemplatesField;
}
public JTextField getScriptTemplatesClasspathField() {
return scriptTemplatesClasspathField;
}
public JComboBox getLanguageVersionComboBox() {
return languageVersionComboBox;
}
public JComboBox getApiVersionComboBox() {
return apiVersionComboBox;
}
public JComboBox getCoroutineSupportComboBox() {
return coroutineSupportComboBox;
}
public void setEnabled(boolean value) {
isEnabled = value;
UIUtil.setEnabled(getContentPane(), value, true);
}
public CommonCompilerArguments getCommonCompilerArguments() {
return commonCompilerArguments;
}
public void setCommonCompilerArguments(CommonCompilerArguments commonCompilerArguments) {
this.commonCompilerArguments = commonCompilerArguments;
}
public K2JSCompilerArguments getK2jsCompilerArguments() {
return k2jsCompilerArguments;
}
public void setK2jsCompilerArguments(K2JSCompilerArguments k2jsCompilerArguments) {
this.k2jsCompilerArguments = k2jsCompilerArguments;
}
public K2JVMCompilerArguments getK2jvmCompilerArguments() {
return k2jvmCompilerArguments;
}
public void setK2jvmCompilerArguments(K2JVMCompilerArguments k2jvmCompilerArguments) {
this.k2jvmCompilerArguments = k2jvmCompilerArguments;
}
public CompilerSettings getCompilerSettings() {
return compilerSettings;
}
public void setCompilerSettings(CompilerSettings compilerSettings) {
this.compilerSettings = compilerSettings;
}
private void createUIComponents() {
// Explicit use of DefaultComboBoxModel guarantees that setSelectedItem() can make safe cast.
languageVersionComboBox = new ComboBox<>(new DefaultComboBoxModel<>());
apiVersionComboBox = new ComboBox<>(new DefaultComboBoxModel<>());
// Workaround: ThreeStateCheckBox doesn't send suitable notification on state change
// TODO: replace with PropertyChangerListener after fix is available in IDEA
copyRuntimeFilesCheckBox = new ThreeStateCheckBox() {
@Override
public void setState(State state) {
super.setState(state);
updateOutputDirEnabled();
}
};
}
}
@@ -1,319 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.configuration
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataImportListener
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.vcs.changes.ChangeListManager
import com.intellij.openapi.vcs.ex.ProjectLevelVcsManagerEx
import com.intellij.util.CommonProcessors
import com.intellij.util.text.VersionComparatorUtil
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.idea.configuration.ui.showMigrationNotification
import org.jetbrains.kotlin.idea.facet.KotlinFacet
import org.jetbrains.kotlin.idea.framework.GRADLE_SYSTEM_ID
import org.jetbrains.kotlin.idea.framework.MAVEN_SYSTEM_ID
import org.jetbrains.kotlin.idea.migration.CodeMigrationToggleAction
import org.jetbrains.kotlin.idea.migration.applicableMigrationTools
import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.idea.util.runReadActionInSmartMode
import org.jetbrains.kotlin.idea.versions.LibInfo
import java.io.File
class KotlinMigrationProjectComponent(val project: Project) {
@Volatile
private var old: MigrationState? = null
@Volatile
private var importFinishListener: ((MigrationTestState?) -> Unit)? = null
init {
val connection = project.messageBus.connect(project)
connection.subscribe(ProjectDataImportListener.TOPIC, ProjectDataImportListener {
getInstanceIfNotDisposed(project)?.onImportFinished()
})
}
class MigrationTestState(val migrationInfo: MigrationInfo?, val hasApplicableTools: Boolean)
@TestOnly
fun setImportFinishListener(newListener: ((MigrationTestState?) -> Unit)?) {
synchronized(this) {
if (newListener != null && importFinishListener != null) {
importFinishListener!!.invoke(null)
}
importFinishListener = newListener
}
}
private fun notifyFinish(migrationInfo: MigrationInfo?, hasApplicableTools: Boolean) {
importFinishListener?.invoke(MigrationTestState(migrationInfo, hasApplicableTools))
}
fun onImportAboutToStart() {
if (!CodeMigrationToggleAction.isEnabled(project) || !hasChangesInProjectFiles(project)) {
old = null
return
}
old = MigrationState.build(project)
}
fun onImportFinished() {
if (!CodeMigrationToggleAction.isEnabled(project) || old == null) {
notifyFinish(null, false)
return
}
ApplicationManager.getApplication().executeOnPooledThread {
var migrationInfo: MigrationInfo? = null
var hasApplicableTools = false
try {
val new = project.runReadActionInSmartMode {
MigrationState.build(project)
}
val localOld = old.also {
old = null
} ?: return@executeOnPooledThread
migrationInfo = prepareMigrationInfo(localOld, new) ?: return@executeOnPooledThread
if (applicableMigrationTools(migrationInfo).isEmpty()) {
hasApplicableTools = false
return@executeOnPooledThread
} else {
hasApplicableTools = true
}
if (ApplicationManager.getApplication().isUnitTestMode) {
return@executeOnPooledThread
}
ApplicationManager.getApplication().invokeLater {
showMigrationNotification(project, migrationInfo)
}
} finally {
notifyFinish(migrationInfo, hasApplicableTools)
}
}
}
companion object {
fun getInstance(project: Project): KotlinMigrationProjectComponent =
project.getComponent(KotlinMigrationProjectComponent::class.java)
?: error("Can't find ${KotlinMigrationProjectComponent::class.qualifiedName} component")
fun getInstanceIfNotDisposed(project: Project): KotlinMigrationProjectComponent? {
return runReadAction {
if (!project.isDisposed) getInstance(project) else null
}
}
private fun prepareMigrationInfo(old: MigrationState?, new: MigrationState?): MigrationInfo? {
if (old == null || new == null) {
return null
}
val oldLibraryVersion = old.stdlibInfo?.version
val newLibraryVersion = new.stdlibInfo?.version
if (oldLibraryVersion == null || newLibraryVersion == null) {
return null
}
if (VersionComparatorUtil.COMPARATOR.compare(newLibraryVersion, oldLibraryVersion) > 0 ||
old.apiVersion < new.apiVersion || old.languageVersion < new.languageVersion
) {
return MigrationInfo(
oldLibraryVersion, newLibraryVersion,
old.apiVersion, new.apiVersion,
old.languageVersion, new.languageVersion
)
}
return null
}
private fun hasChangesInProjectFiles(project: Project): Boolean {
if (ProjectLevelVcsManagerEx.getInstance(project).allVcsRoots.isEmpty()) {
return true
}
val checkedFiles = HashSet<File>()
project.basePath?.let { projectBasePath ->
checkedFiles.add(File(projectBasePath))
}
val changedFiles = ChangeListManager.getInstance(project).affectedPaths
for (changedFile in changedFiles) {
when (changedFile.extension) {
"gradle" -> return true
"properties" -> return true
"kts" -> return true
"iml" -> return true
"xml" -> {
if (changedFile.name == "pom.xml") return true
val parentDir = changedFile.parentFile
if (parentDir.isDirectory && parentDir.name == Project.DIRECTORY_STORE_FOLDER) {
return true
}
}
"kt", "java", "groovy" -> {
val dirs: Sequence<File> = generateSequence(changedFile) { it.parentFile }
.drop(1) // Drop original file
.takeWhile { it.isDirectory }
val isInBuildSrc = dirs
.takeWhile { checkedFiles.add(it) }
.any { it.name == BUILD_SRC_FOLDER_NAME }
if (isInBuildSrc) {
return true
}
}
}
}
return false
}
}
}
private class MigrationState(
var stdlibInfo: LibInfo?,
var apiVersion: ApiVersion,
var languageVersion: LanguageVersion
) {
companion object {
fun build(project: Project): MigrationState {
val libraries = maxKotlinLibVersion(project)
val languageVersionSettings = collectMaxCompilerSettings(project)
return MigrationState(libraries, languageVersionSettings.apiVersion, languageVersionSettings.languageVersion)
}
}
}
data class MigrationInfo(
val oldStdlibVersion: String,
val newStdlibVersion: String,
val oldApiVersion: ApiVersion,
val newApiVersion: ApiVersion,
val oldLanguageVersion: LanguageVersion,
val newLanguageVersion: LanguageVersion
) {
fun oldVersionsToMap(): Map<String, String> = mapOf(
"old_stdlib_version" to oldStdlibVersion,
"old_api_version" to oldApiVersion.versionString,
"old_language_version" to oldLanguageVersion.versionString
)
companion object {
fun create(
oldStdlibVersion: String,
oldApiVersion: ApiVersion,
oldLanguageVersion: LanguageVersion,
newStdlibVersion: String = oldStdlibVersion,
newApiVersion: ApiVersion = oldApiVersion,
newLanguageVersion: LanguageVersion = oldLanguageVersion
): MigrationInfo {
return MigrationInfo(
oldStdlibVersion, newStdlibVersion,
oldApiVersion, newApiVersion,
oldLanguageVersion, newLanguageVersion
)
}
}
}
fun MigrationInfo.isLanguageVersionUpdate(old: LanguageVersion, new: LanguageVersion): Boolean {
return oldLanguageVersion <= old && newLanguageVersion >= new
}
private const val BUILD_SRC_FOLDER_NAME = "buildSrc"
private const val KOTLIN_GROUP_ID = "org.jetbrains.kotlin"
private fun maxKotlinLibVersion(project: Project): LibInfo? {
return runReadAction {
var maxStdlibInfo: LibInfo? = null
val allLibProcessor = CommonProcessors.CollectUniquesProcessor<Library>()
ProjectRootManager.getInstance(project).orderEntries().forEachLibrary(allLibProcessor)
for (library in allLibProcessor.results) {
if (!ExternalSystemApiUtil.isExternalSystemLibrary(library, GRADLE_SYSTEM_ID) &&
!ExternalSystemApiUtil.isExternalSystemLibrary(library, MAVEN_SYSTEM_ID)
) {
continue
}
if (library.name?.contains(" $KOTLIN_GROUP_ID:kotlin-stdlib") != true) {
continue
}
val libraryInfo = parseExternalLibraryName(library) ?: continue
if (maxStdlibInfo == null || VersionComparatorUtil.COMPARATOR.compare(libraryInfo.version, maxStdlibInfo.version) > 0) {
maxStdlibInfo = LibInfo(KOTLIN_GROUP_ID, libraryInfo.artifactId, libraryInfo.version)
}
}
maxStdlibInfo
}
}
private fun collectMaxCompilerSettings(project: Project): LanguageVersionSettings {
return runReadAction {
var maxApiVersion: ApiVersion? = null
var maxLanguageVersion: LanguageVersion? = null
for (module in ModuleManager.getInstance(project).modules) {
if (!module.isKotlinModule()) {
// Otherwise project compiler settings will give unreliable maximum for compiler settings
continue
}
val languageVersionSettings = module.languageVersionSettings
if (maxApiVersion == null || languageVersionSettings.apiVersion > maxApiVersion) {
maxApiVersion = languageVersionSettings.apiVersion
}
if (maxLanguageVersion == null || languageVersionSettings.languageVersion > maxLanguageVersion) {
maxLanguageVersion = languageVersionSettings.languageVersion
}
}
LanguageVersionSettingsImpl(maxLanguageVersion ?: LanguageVersion.LATEST_STABLE, maxApiVersion ?: ApiVersion.LATEST_STABLE)
}
}
private fun Module.isKotlinModule(): Boolean {
if (isDisposed) return false
if (KotlinFacet.get(this) != null) {
return true
}
// This code works only for Maven and Gradle import, and it's expected that Kotlin facets are configured for
// all modules with external system.
return false
}
@@ -1,10 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.configuration
// FIX ME WHEN BUNCH 192 REMOVED
typealias KotlinMigrationProjectService = KotlinMigrationProjectComponent
typealias MigrationTestState = KotlinMigrationProjectComponent.MigrationTestState
@@ -1,16 +0,0 @@
/*
* 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.configuration
internal object MLCompletionForKotlin {
const val isAvailable: Boolean = false
var isEnabled: Boolean
get() = false
set(value) {
throw UnsupportedOperationException()
}
}
@@ -1,86 +0,0 @@
/*
* 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<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) {
}
}
@@ -1,13 +0,0 @@
/*
* 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.hierarchy.calls
import com.intellij.ide.hierarchy.call.CallHierarchyNodeDescriptor
import com.intellij.psi.PsiMethod
fun extractMemberFromDescriptor(nodeDescriptor: CallHierarchyNodeDescriptor): PsiMethod? {
return nodeDescriptor.enclosingElement as? PsiMethod
}
@@ -1,53 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.js
import com.intellij.openapi.module.Module
import com.intellij.openapi.roots.CompilerModuleExtension
import org.jetbrains.jps.util.JpsPathUtil
import org.jetbrains.kotlin.idea.facet.KotlinFacet
import org.jetbrains.kotlin.idea.framework.isGradleModule
import org.jetbrains.kotlin.idea.project.platform
import org.jetbrains.kotlin.platform.js.isJs
import org.jetbrains.plugins.gradle.settings.GradleSystemRunningSettings
val Module.jsTestOutputFilePath: String?
get() {
KotlinFacet.get(this)?.configuration?.settings?.testOutputPath?.let { return it }
if (!shouldUseJpsOutput) return null
val compilerExtension = CompilerModuleExtension.getInstance(this)
val outputDir = compilerExtension?.compilerOutputUrlForTests ?: return null
return JpsPathUtil.urlToPath("$outputDir/${name}_test.js")
}
val Module.jsProductionOutputFilePath: String?
get() {
KotlinFacet.get(this)?.configuration?.settings?.productionOutputPath?.let { return it }
if (!shouldUseJpsOutput) return null
val compilerExtension = CompilerModuleExtension.getInstance(this)
val outputDir = compilerExtension?.compilerOutputUrl ?: return null
return JpsPathUtil.urlToPath("$outputDir/$name.js")
}
fun Module.asJsModule(): Module? = takeIf { it.platform.isJs() }
val Module.shouldUseJpsOutput: Boolean
get() = !(isGradleModule() && GradleSystemRunningSettings.getInstance().isUseGradleAwareMake)
@@ -1,70 +0,0 @@
/*
* Copyright 2010-2018 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.migration
import com.intellij.codeInspection.InspectionEP
import com.intellij.codeInspection.InspectionProfileEntry
import com.intellij.codeInspection.ex.InspectionManagerEx
import com.intellij.codeInspection.ex.InspectionProfileImpl
import com.intellij.codeInspection.ex.InspectionToolWrapper
import com.intellij.codeInspection.ex.createSimple
import com.intellij.openapi.util.InvalidDataException
import com.intellij.openapi.util.WriteExternalException
import com.intellij.profile.codeInspection.InspectionProfileManager
import com.intellij.psi.PsiElement
import org.jdom.Element
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.configuration.MigrationInfo
import org.jetbrains.kotlin.idea.quickfix.migration.MigrationFix
import java.util.*
fun createMigrationProfile(
managerEx: InspectionManagerEx,
psiElement: PsiElement?,
migrationInfo: MigrationInfo? = null
): InspectionProfileImpl {
val rootProfile = InspectionProfileManager.getInstance().currentProfile
val migrationFixWrappers = applicableMigrationToolsImpl(migrationInfo)
val allWrappers = LinkedHashSet<InspectionToolWrapper<*, *>>()
for (toolWrapper in migrationFixWrappers) {
allWrappers.add(toolWrapper)
rootProfile.collectDependentInspections(toolWrapper, allWrappers, managerEx.project)
}
val model = createSimple(KotlinBundle.message("inspection.migration.profile.name"), managerEx.project, migrationFixWrappers)
try {
val element = Element("toCopy")
for (wrapper in migrationFixWrappers) {
wrapper.tool.writeSettings(element)
val tw = (if (psiElement == null)
model.getInspectionTool(wrapper.shortName, managerEx.project)
else
model.getInspectionTool(wrapper.shortName, psiElement))!!
tw.tool.readSettings(element)
}
} catch (ignored: WriteExternalException) {
} catch (ignored: InvalidDataException) {
}
return model
}
fun applicableMigrationTools(migrationInfo: MigrationInfo) = applicableMigrationToolsImpl(migrationInfo)
private fun applicableMigrationToolsImpl(migrationInfo: MigrationInfo?): List<InspectionToolWrapper<InspectionProfileEntry, InspectionEP>> {
val rootProfile = InspectionProfileManager.getInstance().currentProfile
return rootProfile.allTools.asSequence()
.map { it.tool }
.filter { toolWrapper: InspectionToolWrapper<*, *> ->
val tool = toolWrapper.tool
tool is MigrationFix && (migrationInfo == null || tool.isApplicable(migrationInfo))
}
.toList()
}
@@ -1,512 +0,0 @@
/*
* 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.refactoring.changeSignature.ui
import com.intellij.openapi.editor.colors.EditorColorsManager
import com.intellij.openapi.editor.colors.EditorFontType
import com.intellij.openapi.editor.event.DocumentEvent
import com.intellij.openapi.editor.event.DocumentListener
import com.intellij.openapi.options.ConfigurationException
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.Messages
import com.intellij.openapi.ui.VerticalFlowLayout
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.PsiCodeFragment
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
import com.intellij.refactoring.BaseRefactoringProcessor
import com.intellij.refactoring.RefactoringBundle
import com.intellij.refactoring.changeSignature.ChangeSignatureDialogBase
import com.intellij.refactoring.changeSignature.MethodDescriptor
import com.intellij.refactoring.changeSignature.ParameterTableModelItemBase
import com.intellij.refactoring.ui.ComboBoxVisibilityPanel
import com.intellij.ui.DottedBorder
import com.intellij.ui.EditorTextField
import com.intellij.ui.components.JBLabel
import com.intellij.ui.treeStructure.Tree
import com.intellij.util.Consumer
import com.intellij.util.IJSwingUtilities
import com.intellij.util.ui.UIUtil
import com.intellij.util.ui.table.JBTableRow
import com.intellij.util.ui.table.JBTableRowEditor
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.refactoring.changeSignature.*
import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinMethodDescriptor.Kind
import org.jetbrains.kotlin.idea.refactoring.validateElement
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.isIdentifier
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.isError
import java.awt.BorderLayout
import java.awt.Font
import java.awt.Toolkit
import java.awt.event.ItemEvent
import java.util.*
import javax.swing.*
class KotlinChangeSignatureDialog(
project: Project,
methodDescriptor: KotlinMethodDescriptor,
context: PsiElement,
private val commandName: String?
) : ChangeSignatureDialogBase<
KotlinParameterInfo,
PsiElement,
Visibility,
KotlinMethodDescriptor,
ParameterTableModelItemBase<KotlinParameterInfo>,
KotlinCallableParameterTableModel>(project, methodDescriptor, false, context) {
override fun getFileType(): KotlinFileType = KotlinFileType.INSTANCE
override fun createParametersInfoModel(descriptor: KotlinMethodDescriptor) =
createParametersInfoModel(descriptor, myDefaultValueContext)
override fun createReturnTypeCodeFragment() = createReturnTypeCodeFragment(myProject, myMethod)
private val parametersTableModel: KotlinCallableParameterTableModel get() = super.myParametersTableModel
override fun getRowPresentation(
item: ParameterTableModelItemBase<KotlinParameterInfo>,
selected: Boolean,
focused: Boolean
): JComponent? {
val panel = JPanel(BorderLayout())
val valOrVar = if (myMethod.kind === Kind.PRIMARY_CONSTRUCTOR) {
when (item.parameter.valOrVar) {
KotlinValVar.None -> " "
KotlinValVar.Val -> "val "
KotlinValVar.Var -> "var "
}
} else {
""
}
val parameterName = getPresentationName(item)
val typeText = item.typeCodeFragment.text
val defaultValue = item.defaultValueCodeFragment.text
val separator = StringUtil.repeatSymbol(' ', getParamNamesMaxLength() - parameterName.length + 1)
val text = "$valOrVar$parameterName:$separator$typeText" + if (StringUtil.isNotEmpty(defaultValue)) {
KotlinBundle.message("text.default.value", defaultValue)
} else {
""
}
val field = object : EditorTextField(" $text", project, fileType) {
override fun shouldHaveBorder() = false
}
val plainFont = EditorColorsManager.getInstance().globalScheme.getFont(EditorFontType.PLAIN)
field.font = Font(plainFont.fontName, plainFont.style, 12)
if (selected && focused) {
panel.background = UIUtil.getTableSelectionBackground()
field.setAsRendererWithSelection(UIUtil.getTableSelectionBackground(), UIUtil.getTableSelectionForeground())
} else {
panel.background = UIUtil.getTableBackground()
if (selected && !focused) {
panel.border = DottedBorder(UIUtil.getTableForeground())
}
}
panel.add(field, BorderLayout.WEST)
return panel
}
private fun getPresentationName(item: ParameterTableModelItemBase<KotlinParameterInfo>): String {
val parameter = item.parameter
return if (parameter == parametersTableModel.receiver) "<receiver>" else parameter.name
}
private fun getColumnTextMaxLength(nameFunction: Function1<ParameterTableModelItemBase<KotlinParameterInfo>, String?>) =
parametersTableModel.items.asSequence().map { nameFunction(it)?.length ?: 0 }.max() ?: 0
private fun getParamNamesMaxLength() = getColumnTextMaxLength { getPresentationName(it) }
private fun getTypesMaxLength() = getColumnTextMaxLength { it.typeCodeFragment?.text }
private fun getDefaultValuesMaxLength() = getColumnTextMaxLength { it.defaultValueCodeFragment?.text }
override fun isListTableViewSupported() = true
override fun isEmptyRow(row: ParameterTableModelItemBase<KotlinParameterInfo>): Boolean {
if (row.parameter.name.isNotEmpty()) return false
if (row.parameter.typeText.isNotEmpty()) return false
return true
}
override fun createCallerChooser(title: String, treeToReuse: Tree?, callback: Consumer<Set<PsiElement>>) =
KotlinCallerChooser(myMethod.method, myProject, title, treeToReuse, callback)
// Forbid receiver propagation
override fun mayPropagateParameters() =
parameters.any { it.isNewParameter && it != parametersTableModel.receiver }
override fun getTableEditor(table: JTable, item: ParameterTableModelItemBase<KotlinParameterInfo>): JBTableRowEditor? {
return object : JBTableRowEditor() {
private val components = ArrayList<JComponent>()
private val nameEditor = EditorTextField(item.parameter.name, project, fileType)
private fun updateNameEditor() {
nameEditor.isEnabled = item.parameter != parametersTableModel.receiver
}
private fun isDefaultColumnEnabled() =
item.parameter.isNewParameter && item.parameter != myMethod.receiver
override fun prepareEditor(table: JTable, row: Int) {
layout = BoxLayout(this, BoxLayout.X_AXIS)
var column = 0
for (columnInfo in parametersTableModel.columnInfos) {
val panel = JPanel(VerticalFlowLayout(VerticalFlowLayout.TOP, 4, 2, true, false))
val editor: EditorTextField?
val component: JComponent
val columnFinal = column
if (KotlinCallableParameterTableModel.isTypeColumn(columnInfo)) {
val document = PsiDocumentManager.getInstance(project).getDocument(item.typeCodeFragment)
editor = EditorTextField(document, project, fileType)
component = editor
} else if (KotlinCallableParameterTableModel.isNameColumn(columnInfo)) {
editor = nameEditor
component = editor
updateNameEditor()
} else if (KotlinCallableParameterTableModel.isDefaultValueColumn(columnInfo) && isDefaultColumnEnabled()) {
val document = PsiDocumentManager.getInstance(project).getDocument(item.defaultValueCodeFragment)
editor = EditorTextField(document, project, fileType)
component = editor
} else if (KotlinPrimaryConstructorParameterTableModel.isValVarColumn(columnInfo)) {
val comboBox = JComboBox(KotlinValVar.values())
comboBox.selectedItem = item.parameter.valOrVar
comboBox.addItemListener {
parametersTableModel.setValueAtWithoutUpdate(it.item, row, columnFinal)
updateSignature()
}
component = comboBox
editor = null
} else if (KotlinFunctionParameterTableModel.isReceiverColumn(columnInfo)) {
val checkBox = JCheckBox()
checkBox.isSelected = parametersTableModel.receiver == item.parameter
checkBox.addItemListener {
val newReceiver = if (it.stateChange == ItemEvent.SELECTED) item.parameter else null
(parametersTableModel as KotlinFunctionParameterTableModel).receiver = newReceiver
updateSignature()
updateNameEditor()
}
component = checkBox
editor = null
} else
continue
val label = JBLabel(columnInfo.name, UIUtil.ComponentStyle.SMALL)
panel.add(label)
if (editor != null) {
editor.addDocumentListener(
object : DocumentListener {
override fun documentChanged(e: DocumentEvent) {
fireDocumentChanged(e, columnFinal)
}
}
)
editor.setPreferredWidth(table.width / parametersTableModel.columnCount)
}
components.add(component)
panel.add(component)
add(panel)
IJSwingUtilities.adjustComponentsOnMac(label, component)
column++
}
}
override fun getValue(): JBTableRow {
return JBTableRow { column ->
val columnInfo = parametersTableModel.columnInfos[column]
when {
KotlinPrimaryConstructorParameterTableModel.isValVarColumn(columnInfo) ->
(components[column] as @Suppress("NO_TYPE_ARGUMENTS_ON_RHS") JComboBox).selectedItem
KotlinCallableParameterTableModel.isTypeColumn(columnInfo) ->
item.typeCodeFragment
KotlinCallableParameterTableModel.isNameColumn(columnInfo) ->
(components[column] as EditorTextField).text
KotlinCallableParameterTableModel.isDefaultValueColumn(columnInfo) ->
item.defaultValueCodeFragment
else ->
null
}
}
}
private fun getColumnWidth(letters: Int): Int {
var font = EditorColorsManager.getInstance().globalScheme.getFont(EditorFontType.PLAIN)
font = Font(font.fontName, font.style, 12)
return letters * Toolkit.getDefaultToolkit().getFontMetrics(font).stringWidth("W")
}
private fun getEditorIndex(x: Int): Int {
@Suppress("NAME_SHADOWING") var x = x
val columnLetters = if (isDefaultColumnEnabled())
intArrayOf(4, getParamNamesMaxLength(), getTypesMaxLength(), getDefaultValuesMaxLength())
else
intArrayOf(4, getParamNamesMaxLength(), getTypesMaxLength())
var columnIndex = 0
for (i in (if (myMethod.kind === Kind.PRIMARY_CONSTRUCTOR) 0 else 1) until columnLetters.size) {
val width = getColumnWidth(columnLetters[i])
if (x <= width)
return columnIndex
columnIndex++
x -= width
}
return columnIndex - 1
}
override fun getPreferredFocusedComponent(): JComponent {
val me = mouseEvent
val index = when {
me != null -> getEditorIndex(me.point.getX().toInt())
myMethod.kind === Kind.PRIMARY_CONSTRUCTOR -> 1
else -> 0
}
val component = components[index]
return if (component is EditorTextField) component.focusTarget else component
}
override fun getFocusableComponents(): Array<JComponent> {
return Array(components.size) {
val component = components[it]
(component as? EditorTextField)?.focusTarget ?: component
}
}
}
}
override fun calculateSignature(): String {
val changeInfo = evaluateChangeInfo(
parametersTableModel,
myReturnTypeCodeFragment,
getMethodDescriptor(),
visibility,
methodName,
myDefaultValueContext,
true
)
return changeInfo.getNewSignature(getMethodDescriptor().originalPrimaryCallable)
}
override fun createVisibilityControl() = ComboBoxVisibilityPanel(
arrayOf(Visibilities.INTERNAL, Visibilities.PRIVATE, Visibilities.PROTECTED, Visibilities.PUBLIC)
)
override fun updateSignatureAlarmFired() {
super.updateSignatureAlarmFired()
validateButtons()
}
override fun validateAndCommitData(): String? {
if (myMethod.canChangeReturnType() == MethodDescriptor.ReadWriteOption.ReadWrite &&
myReturnTypeCodeFragment.getTypeInfo(isCovariant = true, forPreview = false).type == null
) {
if (showOkCancelDialog(
myProject,
KotlinBundle.message("message.text.return.type.cannot.be.resolved",
myReturnTypeCodeFragment?.text.toString()
),
RefactoringBundle.message("changeSignature.refactoring.name"),
Messages.getWarningIcon()
) != Messages.OK
) {
return EXIT_SILENTLY
}
}
for (item in parametersTableModel.items) {
if (item.typeCodeFragment.getTypeInfo(isCovariant = true, forPreview = false).type == null) {
val paramText = if (item.parameter != parametersTableModel.receiver)
KotlinBundle.message("text.parameter.0", item.parameter.name)
else
KotlinBundle.message("text.receiver")
if (showOkCancelDialog(
myProject,
KotlinBundle.message("message.type.for.cannot.be.resolved",
item.typeCodeFragment.text,
paramText
),
RefactoringBundle.message("changeSignature.refactoring.name"),
Messages.getWarningIcon()
) != Messages.OK
) {
return EXIT_SILENTLY
}
}
}
return null
}
override fun canRun() {
if (myNamePanel.isVisible && myMethod.canChangeName() && !methodName.isIdentifier()) {
throw ConfigurationException(KotlinBundle.message("function.name.is.invalid"))
}
if (myMethod.canChangeReturnType() === MethodDescriptor.ReadWriteOption.ReadWrite) {
(myReturnTypeCodeFragment as? KtTypeCodeFragment)
?.validateElement(KotlinBundle.message("return.type.is.invalid"))
}
for (item in parametersTableModel.items) {
val parameterName = item.parameter.name
if (item.parameter != parametersTableModel.receiver && !parameterName.isIdentifier()) {
throw ConfigurationException(KotlinBundle.message("parameter.name.is.invalid", parameterName))
}
(item.typeCodeFragment as? KtTypeCodeFragment)
?.validateElement(KotlinBundle.message("parameter.type.is.invalid", item.typeCodeFragment.text))
}
}
override fun createRefactoringProcessor(): BaseRefactoringProcessor {
val changeInfo = evaluateChangeInfo(
parametersTableModel,
myReturnTypeCodeFragment,
getMethodDescriptor(),
visibility,
methodName,
myDefaultValueContext,
false
)
changeInfo.primaryPropagationTargets = myMethodsToPropagateParameters ?: emptyList()
return KotlinChangeSignatureProcessor(myProject, changeInfo, commandName ?: title)
}
private fun getMethodDescriptor(): KotlinMethodDescriptor = myMethod
override fun getSelectedIdx(): Int {
return myMethod.parameters.withIndex().firstOrNull { it.value.isNewParameter }?.index
?: super.getSelectedIdx()
}
companion object {
private fun createParametersInfoModel(
descriptor: KotlinMethodDescriptor,
defaultValueContext: PsiElement
): KotlinCallableParameterTableModel {
val typeContext = getTypeCodeFragmentContext(descriptor.baseDeclaration)
return when (descriptor.kind) {
Kind.FUNCTION -> KotlinFunctionParameterTableModel(descriptor, typeContext, defaultValueContext)
Kind.PRIMARY_CONSTRUCTOR -> KotlinPrimaryConstructorParameterTableModel(descriptor, typeContext, defaultValueContext)
Kind.SECONDARY_CONSTRUCTOR -> KotlinSecondaryConstructorParameterTableModel(descriptor, typeContext, defaultValueContext)
}
}
fun getTypeCodeFragmentContext(startFrom: PsiElement): KtElement {
return startFrom.parentsWithSelf.mapNotNull {
when {
it is KtNamedFunction -> it.bodyExpression ?: it.valueParameterList
it is KtPropertyAccessor -> it.bodyExpression
it is KtDeclaration && KtPsiUtil.isLocal(it) -> null
it is KtConstructor<*> -> it
it is KtClassOrObject -> it
it is KtFile -> it
else -> null
}
}.first()
}
private fun createReturnTypeCodeFragment(project: Project, method: KotlinMethodDescriptor) =
KtPsiFactory(project).createTypeCodeFragment(method.returnTypeInfo.render(), getTypeCodeFragmentContext(method.baseDeclaration))
fun createRefactoringProcessorForSilentChangeSignature(
project: Project,
commandName: String,
method: KotlinMethodDescriptor,
defaultValueContext: PsiElement
): BaseRefactoringProcessor {
val parameterTableModel = createParametersInfoModel(method, defaultValueContext)
parameterTableModel.setParameterInfos(method.parameters)
val changeInfo = evaluateChangeInfo(
parameterTableModel,
createReturnTypeCodeFragment(project, method),
method,
method.visibility,
method.name,
defaultValueContext,
false
)
return KotlinChangeSignatureProcessor(project, changeInfo, commandName)
}
fun PsiCodeFragment?.getTypeInfo(isCovariant: Boolean, forPreview: Boolean): KotlinTypeInfo {
if (this !is KtTypeCodeFragment) return KotlinTypeInfo(isCovariant)
val typeRef = getContentElement()
val type = typeRef?.analyze(BodyResolveMode.PARTIAL)?.get(BindingContext.TYPE, typeRef)
return when {
type != null && !type.isError -> KotlinTypeInfo(isCovariant, type, if (forPreview) typeRef.text else null)
typeRef != null -> KotlinTypeInfo(isCovariant, null, typeRef.text)
else -> KotlinTypeInfo(isCovariant)
}
}
private fun evaluateChangeInfo(
parametersModel: KotlinCallableParameterTableModel,
returnTypeCodeFragment: PsiCodeFragment?,
methodDescriptor: KotlinMethodDescriptor,
visibility: Visibility?,
methodName: String,
defaultValueContext: PsiElement,
forPreview: Boolean
): KotlinChangeInfo {
val parameters = parametersModel.items.map { parameter ->
val parameterInfo = parameter.parameter
parameterInfo.currentTypeInfo = parameter.typeCodeFragment.getTypeInfo(false, forPreview)
val codeFragment = parameter.defaultValueCodeFragment as KtExpressionCodeFragment
val oldDefaultValue = parameterInfo.defaultValueForCall
if (codeFragment.text != (if (oldDefaultValue != null) oldDefaultValue.text else "")) {
parameterInfo.defaultValueForCall = codeFragment.getContentElement()
}
parameterInfo
}
return KotlinChangeInfo(
methodDescriptor.original,
methodName,
returnTypeCodeFragment.getTypeInfo(true, forPreview),
visibility ?: Visibilities.DEFAULT_VISIBILITY,
parameters,
parametersModel.receiver,
defaultValueContext
)
}
}
}
@@ -1,74 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.refactoring.cutPaste
import com.intellij.codeHighlighting.Pass
import com.intellij.codeHighlighting.TextEditorHighlightingPass
import com.intellij.codeHighlighting.TextEditorHighlightingPassFactory
import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar
import com.intellij.codeInsight.daemon.impl.HighlightInfo
import com.intellij.codeInsight.daemon.impl.HighlightInfoType
import com.intellij.codeInsight.daemon.impl.UpdateHighlightersUtil
import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction
import com.intellij.openapi.components.ProjectComponent
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFile
import com.intellij.psi.util.PsiModificationTracker
import org.jetbrains.kotlin.idea.core.util.range
class MoveDeclarationsPassFactory(highlightingPassRegistrar: TextEditorHighlightingPassRegistrar) : ProjectComponent,
TextEditorHighlightingPassFactory {
init {
highlightingPassRegistrar.registerTextEditorHighlightingPass(
this,
TextEditorHighlightingPassRegistrar.Anchor.BEFORE,
Pass.POPUP_HINTS,
true,
true
)
}
override fun createHighlightingPass(file: PsiFile, editor: Editor): TextEditorHighlightingPass? {
return MyPass(file.project, file, editor)
}
private class MyPass(
private val project: Project,
private val file: PsiFile,
private val editor: Editor
) : TextEditorHighlightingPass(project, editor.document, true) {
override fun doCollectInformation(progress: ProgressIndicator) {}
override fun doApplyInformationToEditor() {
val info = buildHighlightingInfo()
UpdateHighlightersUtil.setHighlightersToEditor(project, myDocument!!, 0, file.textLength, listOfNotNull(info), colorsScheme, id)
}
private fun buildHighlightingInfo(): HighlightInfo? {
val cookie = editor.getUserData(MoveDeclarationsEditorCookie.KEY) ?: return null
if (cookie.modificationCount != PsiModificationTracker.SERVICE.getInstance(project).modificationCount) return null
val processor = MoveDeclarationsProcessor.build(editor, cookie)
if (processor == null) {
editor.putUserData(MoveDeclarationsEditorCookie.KEY, null)
return null
}
val info = HighlightInfo.newHighlightInfo(HighlightInfoType.INFORMATION)
.range(cookie.bounds.range!!)
.createUnconditionally()
QuickFixAction.registerQuickFixAction(info, MoveDeclarationsIntentionAction(processor, cookie.bounds, cookie.modificationCount))
return info
}
}
}
File diff suppressed because it is too large Load Diff
@@ -1,121 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.roots
import com.intellij.openapi.externalSystem.model.DataNode
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.rootManager
import com.intellij.openapi.roots.ModifiableRootModel
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.openapi.roots.SourceFolder
import com.intellij.openapi.vfs.NonPhysicalFileSystem
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiCodeFragment
import com.intellij.psi.PsiFile
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.jps.model.JpsElement
import org.jetbrains.jps.model.ex.JpsElementBase
import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes
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.JpsModuleSourceRoot
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.idea.framework.KotlinSdkType
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
import java.util.*
private fun JpsModuleSourceRoot.getOrCreateProperties() =
getProperties(rootType)?.also { (it as? JpsElementBase<*>)?.setParent(null) } ?: rootType.createDefaultProperties()
fun JpsModuleSourceRoot.getMigratedSourceRootTypeWithProperties(): Pair<JpsModuleSourceRootType<JpsElement>, JpsElement>? {
val currentRootType = rootType
@Suppress("UNCHECKED_CAST")
val newSourceRootType: JpsModuleSourceRootType<JpsElement> = when (currentRootType) {
JavaSourceRootType.SOURCE -> SourceKotlinRootType as JpsModuleSourceRootType<JpsElement>
JavaSourceRootType.TEST_SOURCE -> TestSourceKotlinRootType
JavaResourceRootType.RESOURCE -> ResourceKotlinRootType
JavaResourceRootType.TEST_RESOURCE -> TestResourceKotlinRootType
else -> return null
} as JpsModuleSourceRootType<JpsElement>
return newSourceRootType to getOrCreateProperties()
}
fun migrateNonJvmSourceFolders(modifiableRootModel: ModifiableRootModel) {
for (contentEntry in modifiableRootModel.contentEntries) {
for (sourceFolder in contentEntry.sourceFolders) {
val (newSourceRootType, properties) = sourceFolder.jpsElement.getMigratedSourceRootTypeWithProperties() ?: continue
val url = sourceFolder.url
contentEntry.removeSourceFolder(sourceFolder)
contentEntry.addSourceFolder(url, newSourceRootType, properties)
}
}
KotlinSdkType.setUpIfNeeded()
}
fun populateNonJvmSourceRootTypes(sourceSetNode: DataNode<GradleSourceSetData>, module: Module) = Unit
fun getKotlinAwareDestinationSourceRoots(project: Project): List<VirtualFile> {
return ModuleManager.getInstance(project).modules.flatMap { it.collectKotlinAwareDestinationSourceRoots() }
}
private val KOTLIN_AWARE_SOURCE_ROOT_TYPES: Set<JpsModuleSourceRootType<JavaSourceRootProperties>> =
JavaModuleSourceRootTypes.SOURCES + ALL_KOTLIN_SOURCE_ROOT_TYPES
private fun Module.collectKotlinAwareDestinationSourceRoots(): List<VirtualFile> {
return rootManager
.contentEntries
.asSequence()
.flatMap { it.getSourceFolders(KOTLIN_AWARE_SOURCE_ROOT_TYPES).asSequence() }
.filterNot { isForGeneratedSources(it) }
.mapNotNull { it.file }
.toList()
}
fun isOutsideSourceRootSet(psiFile: PsiFile?, sourceRootTypes: Set<JpsModuleSourceRootType<*>>): Boolean {
if (psiFile == null || psiFile is PsiCodeFragment) return false
val file = psiFile.virtualFile ?: return false
if (file.fileSystem is NonPhysicalFileSystem) return false
val projectFileIndex = ProjectRootManager.getInstance(psiFile.project).fileIndex
return !projectFileIndex.isUnderSourceRootOfType(file, sourceRootTypes) && !projectFileIndex.isInLibrary(file)
}
fun isOutsideKotlinAwareSourceRoot(psiFile: PsiFile?) = isOutsideSourceRootSet(psiFile, KOTLIN_AWARE_SOURCE_ROOT_TYPES)
/**
* @return list of all java source roots in the project which can be suggested as a target directory for a class created by user
*/
fun getSuitableDestinationSourceRoots(project: Project): List<VirtualFile> {
val roots = ArrayList<VirtualFile>()
for (module in ModuleManager.getInstance(project).modules) {
collectSuitableDestinationSourceRoots(module, roots)
}
return roots
}
fun collectSuitableDestinationSourceRoots(module: Module, result: MutableList<VirtualFile>) {
for (entry in ModuleRootManager.getInstance(module).contentEntries) {
for (sourceFolder in entry.getSourceFolders(KOTLIN_AWARE_SOURCE_ROOT_TYPES)) {
if (!isForGeneratedSources(sourceFolder)) {
ContainerUtil.addIfNotNull(result, sourceFolder.file)
}
}
}
}
fun isForGeneratedSources(sourceFolder: SourceFolder): Boolean {
val properties = sourceFolder.jpsElement.getProperties(KOTLIN_AWARE_SOURCE_ROOT_TYPES)
val javaResourceProperties = sourceFolder.jpsElement.getProperties(JavaModuleSourceRootTypes.RESOURCES)
val kotlinResourceProperties = sourceFolder.jpsElement.getProperties(ALL_KOTLIN_RESOURCE_ROOT_TYPES)
return properties != null && properties.isForGeneratedSources
|| (javaResourceProperties != null && javaResourceProperties.isForGeneratedSources)
|| (kotlinResourceProperties != null && kotlinResourceProperties.isForGeneratedSources)
}
@@ -1,62 +0,0 @@
/*
* 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.util
import com.intellij.openapi.Disposable
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.progress.util.BackgroundTaskUtil
import com.intellij.openapi.project.DumbService
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Computable
import com.intellij.openapi.util.ThrowableComputable
import org.jetbrains.annotations.Nls
import org.jetbrains.kotlin.idea.util.application.runReadAction
import java.util.concurrent.Future
import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException
object ProgressIndicatorUtils {
private val LOG = Logger.getInstance(ProgressIndicatorUtils::class.java)
@JvmStatic
fun <T> underModalProgress(
project: Project,
@Nls progressTitle: String,
computable: () -> T
): T {
val dumbService = DumbService.getInstance(project)
val useAlternativeResolve = dumbService.isAlternativeResolveEnabled
val inReadAction =
ThrowableComputable<T, RuntimeException> { runReadAction { return@runReadAction computable() } }
val prioritizedRunnable =
ThrowableComputable<T, RuntimeException> { ProgressManager.getInstance().computePrioritized(inReadAction) }
val process =
if (useAlternativeResolve) ThrowableComputable { dumbService.computeWithAlternativeResolveEnabled(prioritizedRunnable) } else prioritizedRunnable
return ProgressManager.getInstance().runProcessWithProgressSynchronously(process, progressTitle, true, project)
}
fun <T> runUnderDisposeAwareIndicator(
parent: Disposable,
computable: () -> T
): T = BackgroundTaskUtil.runUnderDisposeAwareIndicator(parent, Computable { computable() })
@JvmStatic
fun <T> awaitWithCheckCanceled(future: Future<T>): T {
while (true) {
ProgressManager.checkCanceled()
try {
return future.get(50, TimeUnit.MILLISECONDS)
} catch (e: TimeoutException) {
// ignore
} catch (e: Exception) {
LOG.warn(e)
throw ProcessCanceledException(e)
}
}
}
}
@@ -1,70 +0,0 @@
/*
* 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.versions
import com.intellij.ide.util.PropertiesComponent
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.BaseComponent
import com.intellij.openapi.vfs.JarFileSystem
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFileVisitor
import com.intellij.openapi.vfs.newvfs.NewVirtualFile
import org.jetbrains.kotlin.idea.KotlinPluginUtil
import java.io.File
private val INSTALLED_KOTLIN_VERSION = "installed.kotlin.plugin.version"
/**
* Component forces update for built-in libraries in plugin directory. They are ignored because of
* com.intellij.util.indexing.FileBasedIndex.isUnderConfigOrSystem()
*/
// FIX ME WHEN BUNCH 192 REMOVED
class KotlinUpdatePluginComponent : BaseComponent {
override fun initComponent() {
if (ApplicationManager.getApplication()?.isUnitTestMode == true) {
return
}
val installedKotlinVersion = PropertiesComponent.getInstance()?.getValue(INSTALLED_KOTLIN_VERSION)
if (installedKotlinVersion == null || KotlinPluginUtil.getPluginVersion() != installedKotlinVersion) {
// Force refresh jar handlers
for (libraryJarDescriptor in LibraryJarDescriptor.values()) {
requestFullJarUpdate(libraryJarDescriptor.getPathInPlugin())
}
PropertiesComponent.getInstance()?.setValue(INSTALLED_KOTLIN_VERSION, KotlinPluginUtil.getPluginVersion())
}
}
override fun getComponentName(): String {
return "ReindexBundledRuntimeComponent"
}
override fun disposeComponent() {
}
private fun requestFullJarUpdate(jarFilePath: File) {
val localVirtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(jarFilePath) ?: return
// Build and update JarHandler
val jarFile = JarFileSystem.getInstance().getJarRootForLocalFile(localVirtualFile) ?: return
VfsUtilCore.visitChildrenRecursively(jarFile, object : VirtualFileVisitor<Any?>() {})
((jarFile as NewVirtualFile)).markDirtyRecursively()
}
}
@@ -1,5 +0,0 @@
Actual data differs from file content: ClassAndConstuctors.source.expected expected:< [SomeClassWithConstructors.class
public final class <1><2><3><4>SomeClassWithConstructors public constructor(arg: kotlin.String)] {
> but was:< [classAndConstructors.kt
class <1><2><3><4>SomeClassWithConstructors(private val arg: String) ] {
>
@@ -1,10 +0,0 @@
Actual data differs from file content: OverloadedFun.source.expected expected:<...d from a class file
[// Implementation of methods is not available
package testData.libraries
@kotlin.jvm.JvmOverloads public fun <T> kotlin.String.<2><4><6>overloadedFun(vararg specs: kotlin.String, allowExisting: kotlin.Boolean /* = compiled code */, x: kotlin.Int, y: kotlin.Int /* = compiled code */, z: T): kotlin.String { /* compiled code */ }]
> but was:<...d from a class file
[ overloadedFun.kt
fun <T> String.<2><4><6>overloadedFun(vararg specs: String, allowExisting: Boolean = false, x: Int, y: Int = 2, z: T): String {]
>
@@ -1,12 +0,0 @@
Actual data differs from file content: RenamedElements.source.expected expected:<[RenamedElementsKt.class
<1>// IntelliJ API Decompiler stub source generated from a class file
// Implementation of methods is not available
package testData.libraries
@kotlin.jvm.JvmName public fun <2>funToRename(x: kotlin.Int): kotlin.Unit { /* compiled code */ }]
> but was:<[ RenamedElementsKt.class
<1>// IntelliJ API Decompiler stub source generated from a class file
renamedElements.kt
fun <2>funToRename(x: Int) {]
>
@@ -1,9 +0,0 @@
Actual data differs from file content: LibraryNestedClassSecondaryConstructorUsages.results.txt expected:<...3 class Y(): A.T()
[[LibraryNestedClassSecondaryConstructorUsages.1.java] New instance creation 14 A.T a = new A.T();
[LibraryNestedClassSecondaryConstructorUsages.1.java] Unclassified usage 10 super();
[LibraryNestedClassSecondaryConstructorUsages.1.java] Unclassified usage 6 public J() {
[library.kt] New instance creation 64 val tt = A.T()
[library.kt] Supertype 40 class VV(): A.T()
]> but was:<...3 class Y(): A.T()
[[library.kt] New instance creation 64 val tt = A.T()
[library.kt] Supertype 40 class VV(): A.T()]>
@@ -1,6 +0,0 @@
Actual data differs from file content: LibrarySecondaryConstructorUsages.results.txt expected:<... 13 class Y(): A()
[[LibrarySecondaryConstructorUsages.1.java] New instance creation 14 A a = new A();
[LibrarySecondaryConstructorUsages.1.java] Unclassified usage 10 super();
[LibrarySecondaryConstructorUsages.1.java] Unclassified usage 6 public J() {
[]library.kt] New inst...> but was:<... 13 class Y(): A()
[[]library.kt] New inst...>
@@ -1,24 +0,0 @@
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.2.60-dev-286'
}
group 'testgroup'
version '1.0-SNAPSHOT'
repositories {
maven {
url 'https://teamcity.jetbrains.com/guestAuth/app/rest/builds/buildType:(id:Kotlin_KotlinPublic_Compiler),number:1.2.60-dev-286,branch:(default:any)/artifacts/content/maven'
}
mavenCentral()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
}
compileKotlin {
kotlinOptions {
jvmTarget = "1.8"
}
}
compileTestKotlin {
kotlinOptions {
jvmTarget = "1.8"
}
}
@@ -1,12 +0,0 @@
<node text="KA ()" base="true">
<node text="JA ()"/>
<node text="JA.newKA() ()"/>
<node text="KClient ()"/>
<node text="KClient ()"/>
<node text="KClient.bar ()"/>
<node text="KClient.bar() ()"/>
<node text="KClient.bar.localFun() ()"/>
<node text="KClientObj ()"/>
<node text="main0.kt ()"/>
<node text="packageFun(String) ()"/>
</node>
@@ -1,12 +0,0 @@
<node text="KA.foo(String) ()" base="true">
<node text="JA(2 usages) ()"/>
<node text="JA.foo()(2 usages) ()"/>
<node text="KClient(2 usages) ()"/>
<node text="KClient(2 usages) ()"/>
<node text="KClient.bar()(2 usages) ()"/>
<node text="KClient.bar(2 usages) ()"/>
<node text="KClient.bar.localFun()(2 usages) ()"/>
<node text="KClientObj(2 usages) ()"/>
<node text="main0.kt(2 usages) ()"/>
<node text="packageFun(String)(2 usages) ()"/>
</node>
@@ -1,12 +0,0 @@
<node text="T.KA ()" base="true">
<node text="JA ()"/>
<node text="JA.newKA() ()"/>
<node text="KClient ()"/>
<node text="KClient ()"/>
<node text="KClient.bar ()"/>
<node text="KClient.bar() ()"/>
<node text="KClient.bar.localFun() ()"/>
<node text="KClientObj ()"/>
<node text="main0.kt ()"/>
<node text="packageFun(String) ()"/>
</node>
@@ -1,12 +0,0 @@
<node text="T.KA ()" base="true">
<node text="JA ()"/>
<node text="JA.newKA() ()"/>
<node text="KClient ()"/>
<node text="KClient ()"/>
<node text="KClient.bar ()"/>
<node text="KClient.bar() ()"/>
<node text="KClient.bar.localFun() ()"/>
<node text="KClientObj ()"/>
<node text="main0.kt ()"/>
<node text="packageFun(String) ()"/>
</node>
@@ -1,11 +0,0 @@
<node text="packageFun(String) ()" base="true">
<node text="JA ()"/>
<node text="JA.foo() ()"/>
<node text="KClient ()"/>
<node text="KClient ()"/>
<node text="KClient.bar ()"/>
<node text="KClient.bar() ()"/>
<node text="KClient.bar.localFun() ()"/>
<node text="KClientObj ()"/>
<node text="main0.kt ()"/>
</node>
@@ -1,11 +0,0 @@
<node text="packageVal ()" base="true">
<node text="JA ()"/>
<node text="JA.getName()(2 usages) ()"/>
<node text="KClient ()"/>
<node text="KClient ()"/>
<node text="KClient.bar() ()"/>
<node text="KClient.bar(2 usages) ()"/>
<node text="KClient.bar.localFun() ()"/>
<node text="KClientObj(2 usages) ()"/>
<node text="packageFun(String) ()"/>
</node>
@@ -1,12 +0,0 @@
<node text="KA.name ()" base="true">
<node text="JA(2 usages) ()"/>
<node text="JA.getName()(2 usages) ()"/>
<node text="KClient(2 usages) ()"/>
<node text="KClient(2 usages) ()"/>
<node text="KClient.bar()(2 usages) ()"/>
<node text="KClient.bar(4 usages) ()"/>
<node text="KClient.bar.localFun()(2 usages) ()"/>
<node text="KClientObj(4 usages) ()"/>
<node text="main0.kt(2 usages) ()"/>
<node text="packageFun(String)(2 usages) ()"/>
</node>
@@ -1,5 +0,0 @@
<node text="J.foo() ()" base="true">
<node text="A(2 usages) ()"/>
<node text="Main1Kt.test(J) ()"/>
<node text="Main1Kt ()"/>
</node>

Some files were not shown because too many files have changed in this diff Show More