mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-17 00:21:29 +00:00
Compare commits
11 Commits
push/pdn_b
...
202/prepar
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f9421f9bd | ||
|
|
e844f15ec9 | ||
|
|
266c705ad9 | ||
|
|
9169d2da05 | ||
|
|
220a5f49c7 | ||
|
|
0e58df18c1 | ||
|
|
0a31cf8e2e | ||
|
|
bde8603fe4 | ||
|
|
f2fe2940ac | ||
|
|
5eac69fdda | ||
|
|
063be2fa1c |
1
.idea/vcs.xml
generated
1
.idea/vcs.xml
generated
@@ -32,5 +32,6 @@
|
||||
</component>
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/kotlin-ultimate" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.incremental.storage
|
||||
|
||||
import com.intellij.util.io.DataExternalizer
|
||||
import com.intellij.util.io.KeyDescriptor
|
||||
import com.intellij.util.io.JpsPersistentHashMap
|
||||
import com.intellij.util.io.PersistentHashMap
|
||||
import java.io.File
|
||||
|
||||
|
||||
@@ -28,10 +28,10 @@ class NonCachingLazyStorage<K, V>(
|
||||
private val valueExternalizer: DataExternalizer<V>
|
||||
) : LazyStorage<K, V> {
|
||||
@Volatile
|
||||
private var storage: JpsPersistentHashMap<K, V>? = null
|
||||
private var storage: PersistentHashMap<K, V>? = null
|
||||
|
||||
@Synchronized
|
||||
private fun getStorageIfExists(): JpsPersistentHashMap<K, V>? {
|
||||
private fun getStorageIfExists(): PersistentHashMap<K, V>? {
|
||||
if (storage != null) return storage
|
||||
|
||||
if (storageFile.exists()) {
|
||||
@@ -43,7 +43,7 @@ class NonCachingLazyStorage<K, V>(
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun getStorageOrCreateNew(): JpsPersistentHashMap<K, V> {
|
||||
private fun getStorageOrCreateNew(): PersistentHashMap<K, V> {
|
||||
if (storage == null) {
|
||||
storage = createMap()
|
||||
}
|
||||
@@ -69,7 +69,7 @@ class NonCachingLazyStorage<K, V>(
|
||||
}
|
||||
|
||||
override fun append(key: K, value: V) {
|
||||
getStorageOrCreateNew().appendDataWithoutCache(key, value)
|
||||
getStorageOrCreateNew().appendData(key) { dataOutput -> valueExternalizer.save(dataOutput, value) }
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
@@ -79,7 +79,7 @@ class NonCachingLazyStorage<K, V>(
|
||||
} catch (ignored: Throwable) {
|
||||
}
|
||||
|
||||
JpsPersistentHashMap.deleteFilesStartingWith(storageFile)
|
||||
PersistentHashMap.deleteFilesStartingWith(storageFile)
|
||||
storage = null
|
||||
}
|
||||
|
||||
@@ -101,6 +101,6 @@ class NonCachingLazyStorage<K, V>(
|
||||
storage?.close()
|
||||
}
|
||||
|
||||
private fun createMap(): JpsPersistentHashMap<K, V> =
|
||||
JpsPersistentHashMap(storageFile, keyDescriptor, valueExternalizer)
|
||||
private fun createMap(): PersistentHashMap<K, V> =
|
||||
PersistentHashMap(storageFile, keyDescriptor, valueExternalizer)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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.incremental.storage
|
||||
|
||||
import com.intellij.util.io.DataExternalizer
|
||||
import com.intellij.util.io.KeyDescriptor
|
||||
import com.intellij.util.io.JpsPersistentHashMap
|
||||
import java.io.File
|
||||
|
||||
|
||||
class NonCachingLazyStorage<K, V>(
|
||||
private val storageFile: File,
|
||||
private val keyDescriptor: KeyDescriptor<K>,
|
||||
private val valueExternalizer: DataExternalizer<V>
|
||||
) : LazyStorage<K, V> {
|
||||
@Volatile
|
||||
private var storage: JpsPersistentHashMap<K, V>? = null
|
||||
|
||||
@Synchronized
|
||||
private fun getStorageIfExists(): JpsPersistentHashMap<K, V>? {
|
||||
if (storage != null) return storage
|
||||
|
||||
if (storageFile.exists()) {
|
||||
storage = createMap()
|
||||
return storage
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun getStorageOrCreateNew(): JpsPersistentHashMap<K, V> {
|
||||
if (storage == null) {
|
||||
storage = createMap()
|
||||
}
|
||||
|
||||
return storage!!
|
||||
}
|
||||
|
||||
override val keys: Collection<K>
|
||||
get() = getStorageIfExists()?.allKeysWithExistingMapping ?: listOf()
|
||||
|
||||
override operator fun contains(key: K): Boolean =
|
||||
getStorageIfExists()?.containsMapping(key) ?: false
|
||||
|
||||
override operator fun get(key: K): V? =
|
||||
getStorageIfExists()?.get(key)
|
||||
|
||||
override operator fun set(key: K, value: V) {
|
||||
getStorageOrCreateNew().put(key, value)
|
||||
}
|
||||
|
||||
override fun remove(key: K) {
|
||||
getStorageIfExists()?.remove(key)
|
||||
}
|
||||
|
||||
override fun append(key: K, value: V) {
|
||||
getStorageOrCreateNew().appendDataWithoutCache(key, value)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun clean() {
|
||||
try {
|
||||
storage?.close()
|
||||
} catch (ignored: Throwable) {
|
||||
}
|
||||
|
||||
JpsPersistentHashMap.deleteFilesStartingWith(storageFile)
|
||||
storage = null
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun flush(memoryCachesOnly: Boolean) {
|
||||
val existingStorage = storage ?: return
|
||||
|
||||
if (memoryCachesOnly) {
|
||||
if (existingStorage.isDirty) {
|
||||
existingStorage.dropMemoryCaches()
|
||||
}
|
||||
} else {
|
||||
existingStorage.force()
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun close() {
|
||||
storage?.close()
|
||||
}
|
||||
|
||||
private fun createMap(): JpsPersistentHashMap<K, V> =
|
||||
JpsPersistentHashMap(storageFile, keyDescriptor, valueExternalizer)
|
||||
}
|
||||
@@ -200,7 +200,11 @@ extra["intellijSeparateSdks"] = intellijSeparateSdks
|
||||
|
||||
extra["IntellijCoreDependencies"] =
|
||||
listOf(
|
||||
if (Platform[191].orHigher()) "asm-all-7.0.1" else "asm-all",
|
||||
when {
|
||||
Platform[202].orHigher() -> "asm-all-8.0.1"
|
||||
Platform[191].orHigher() -> "asm-all-7.0.1"
|
||||
else -> "asm-all"
|
||||
},
|
||||
"guava",
|
||||
"jdom",
|
||||
"jna",
|
||||
|
||||
@@ -105,7 +105,7 @@ dependencies {
|
||||
|
||||
implementation("com.github.jengelman.gradle.plugins:shadow:${rootProject.extra["versions.shadow"]}")
|
||||
implementation("net.sf.proguard:proguard-gradle:6.2.2")
|
||||
implementation("org.jetbrains.intellij.deps:asm-all:7.0.1")
|
||||
implementation("org.jetbrains.intellij.deps:asm-all:8.0.1")
|
||||
|
||||
implementation("gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext:0.5")
|
||||
}
|
||||
|
||||
@@ -107,6 +107,7 @@ fun Project.projectTest(
|
||||
systemProperty("jps.kotlin.home", rootProject.extra["distKotlinHomeDir"]!!)
|
||||
systemProperty("kotlin.ni", if (rootProject.hasProperty("newInferenceTests")) "true" else "false")
|
||||
systemProperty("org.jetbrains.kotlin.skip.muted.tests", if (rootProject.hasProperty("skipMutedTests")) "true" else "false")
|
||||
systemProperty("idea.ignore.disabled.plugins", "true")
|
||||
|
||||
var subProjectTempRoot: Path? = null
|
||||
doFirst {
|
||||
|
||||
@@ -29,7 +29,14 @@ dependencies {
|
||||
testCompile(intellijDep()) { includeJars("openapi", rootProject = rootProject) }
|
||||
}
|
||||
|
||||
testCompile(intellijDep()) { includeJars("util", "idea", "idea_rt", "groovy-all", rootProject = rootProject) }
|
||||
testCompile(intellijDep()) { includeJars("util", "idea", "idea_rt", rootProject = rootProject) }
|
||||
Platform[202].orHigher {
|
||||
testCompile(intellijDep()) { includeJars("groovy", rootProject = rootProject) }
|
||||
}
|
||||
Platform[201].orLower {
|
||||
testCompile(intellijDep()) { includeJars("groovy-all", rootProject = rootProject) }
|
||||
}
|
||||
|
||||
Platform[191].orLower {
|
||||
testCompile(intellijDep()) { includeJars("jps-builders") }
|
||||
}
|
||||
|
||||
@@ -8,4 +8,4 @@ package org.jetbrains.kotlin.codegen.coroutines
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
|
||||
|
||||
typealias SourceFrames = Array<Frame<SourceValue>?>
|
||||
typealias SourceFrames = Array<Frame<SourceValue>>
|
||||
@@ -8,4 +8,4 @@ package org.jetbrains.kotlin.codegen.coroutines
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
|
||||
|
||||
typealias SourceFrames = Array<Frame<SourceValue>>
|
||||
typealias SourceFrames = Array<Frame<SourceValue>?>
|
||||
@@ -8,4 +8,4 @@ package org.jetbrains.kotlin.codegen.optimization.common
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||
|
||||
typealias TypeAnnotatedFrames = Array<Frame<BasicValue>?>
|
||||
typealias TypeAnnotatedFrames = Array<Frame<BasicValue>>
|
||||
@@ -8,4 +8,4 @@ package org.jetbrains.kotlin.codegen.optimization.common
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||
|
||||
typealias TypeAnnotatedFrames = Array<Frame<BasicValue>>
|
||||
typealias TypeAnnotatedFrames = Array<Frame<BasicValue>?>
|
||||
@@ -5,4 +5,4 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.state
|
||||
|
||||
typealias JvmMethodExceptionTypes = Array<out String>?
|
||||
typealias JvmMethodExceptionTypes = Array<out String?>?
|
||||
@@ -5,4 +5,4 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.state
|
||||
|
||||
typealias JvmMethodExceptionTypes = Array<out String?>?
|
||||
typealias JvmMethodExceptionTypes = Array<out String>?
|
||||
@@ -17,8 +17,6 @@
|
||||
package org.jetbrains.kotlin.cli.common.messages;
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.impl.jar.CoreJarVirtualFile;
|
||||
import com.intellij.openapi.vfs.local.CoreLocalVirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -51,10 +49,6 @@ public class MessageUtil {
|
||||
|
||||
@NotNull
|
||||
public static String virtualFileToPath(@NotNull VirtualFile virtualFile) {
|
||||
// Convert path to platform-dependent format when virtualFile is local file.
|
||||
if (virtualFile instanceof CoreLocalVirtualFile || virtualFile instanceof CoreJarVirtualFile) {
|
||||
return toSystemDependentName(virtualFile.getPath());
|
||||
}
|
||||
return virtualFile.getPath();
|
||||
return toSystemDependentName(virtualFile.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,147 +4,52 @@
|
||||
*/
|
||||
package org.jetbrains.kotlin.cli.jvm.compiler;
|
||||
|
||||
import com.intellij.DynamicBundle;
|
||||
import com.intellij.codeInsight.ContainerProvider;
|
||||
import com.intellij.codeInsight.JavaContainerProvider;
|
||||
import com.intellij.codeInsight.folding.JavaCodeFoldingSettings;
|
||||
import com.intellij.codeInsight.folding.impl.JavaCodeFoldingSettingsBase;
|
||||
import com.intellij.codeInsight.folding.impl.JavaFoldingBuilderBase;
|
||||
import com.intellij.codeInsight.runner.JavaMainMethodProvider;
|
||||
import com.intellij.core.CoreApplicationEnvironment;
|
||||
import com.intellij.core.CoreJavaDirectoryService;
|
||||
import com.intellij.core.CorePsiPackageImplementationHelper;
|
||||
import com.intellij.ide.highlighter.ArchiveFileType;
|
||||
import com.intellij.ide.highlighter.JavaClassFileType;
|
||||
import com.intellij.ide.highlighter.JavaFileType;
|
||||
import com.intellij.lang.LanguageASTFactory;
|
||||
import com.intellij.core.JavaCoreApplicationEnvironment;
|
||||
import com.intellij.lang.MetaLanguage;
|
||||
import com.intellij.lang.folding.LanguageFolding;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.lang.java.JavaParserDefinition;
|
||||
import com.intellij.navigation.ItemPresentationProviders;
|
||||
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.fileTypes.PlainTextFileType;
|
||||
import com.intellij.openapi.fileTypes.PlainTextLanguage;
|
||||
import com.intellij.openapi.fileTypes.PlainTextParserDefinition;
|
||||
import com.intellij.openapi.projectRoots.JavaVersionService;
|
||||
import com.intellij.openapi.vfs.VirtualFileSystem;
|
||||
import com.intellij.psi.*;
|
||||
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.impl.LanguageConstantExpressionEvaluator;
|
||||
import com.intellij.psi.impl.PsiExpressionEvaluator;
|
||||
import com.intellij.psi.impl.PsiSubstitutorFactoryImpl;
|
||||
import com.intellij.psi.impl.compiled.ClassFileStubBuilder;
|
||||
import com.intellij.psi.impl.file.PsiPackageImplementationHelper;
|
||||
import com.intellij.psi.impl.search.MethodSuperSearcher;
|
||||
import com.intellij.psi.impl.source.tree.JavaASTFactory;
|
||||
import com.intellij.psi.impl.source.tree.PlainTextASTFactory;
|
||||
import com.intellij.psi.meta.MetaDataContributor;
|
||||
import com.intellij.psi.presentation.java.*;
|
||||
import com.intellij.psi.search.searches.SuperMethodsSearch;
|
||||
import com.intellij.psi.stubs.BinaryFileStubBuilders;
|
||||
import com.intellij.util.QueryExecutor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem;
|
||||
|
||||
/**
|
||||
* adapted from com.intellij.core.JavaCoreApplicationEnvironment
|
||||
* TODO: initiate removal original from com.intellij.core since it seems that there are no usages left
|
||||
*/
|
||||
public class KotlinCoreApplicationEnvironment extends CoreApplicationEnvironment {
|
||||
public class KotlinCoreApplicationEnvironment extends JavaCoreApplicationEnvironment {
|
||||
public static KotlinCoreApplicationEnvironment create(@NotNull Disposable parentDisposable, boolean unitTestMode) {
|
||||
KotlinCoreApplicationEnvironment environment = new KotlinCoreApplicationEnvironment(parentDisposable, unitTestMode);
|
||||
registerExtensionPoints();
|
||||
return environment;
|
||||
}
|
||||
|
||||
public static KotlinCoreApplicationEnvironment create(@NotNull Disposable parentDisposable, boolean unitTestMode) {
|
||||
return new KotlinCoreApplicationEnvironment(parentDisposable, unitTestMode);
|
||||
}
|
||||
private KotlinCoreApplicationEnvironment(@NotNull Disposable parentDisposable, boolean unitTestMode) {
|
||||
super(parentDisposable, unitTestMode);
|
||||
}
|
||||
|
||||
private KotlinCoreApplicationEnvironment(@NotNull Disposable parentDisposable, boolean unitTestMode) {
|
||||
super(parentDisposable, unitTestMode);
|
||||
private static void registerExtensionPoints() {
|
||||
registerApplicationExtensionPoint(DynamicBundle.LanguageBundleEP.EP_NAME, DynamicBundle.LanguageBundleEP.class);
|
||||
registerApplicationExtensionPoint(FileContextProvider.EP_NAME, FileContextProvider.class);
|
||||
|
||||
registerExtensionPoints();
|
||||
registerApplicationExtensionPoint(MetaDataContributor.EP_NAME, MetaDataContributor.class);
|
||||
registerApplicationExtensionPoint(PsiAugmentProvider.EP_NAME, PsiAugmentProvider.class);
|
||||
registerApplicationExtensionPoint(JavaMainMethodProvider.EP_NAME, JavaMainMethodProvider.class);
|
||||
|
||||
registerExtensions();
|
||||
}
|
||||
registerApplicationExtensionPoint(ContainerProvider.EP_NAME, ContainerProvider.class);
|
||||
registerApplicationExtensionPoint(ClassFileDecompilers.EP_NAME, ClassFileDecompilers.Decompiler.class);
|
||||
|
||||
private void registerExtensionPoints() {
|
||||
ExtensionsArea area = Extensions.getRootArea();
|
||||
registerApplicationExtensionPoint(MetaLanguage.EP_NAME, MetaLanguage.class);
|
||||
|
||||
CoreApplicationEnvironment.registerExtensionPoint(area, BinaryFileStubBuilders.EP_NAME, FileTypeExtensionPoint.class);
|
||||
CoreApplicationEnvironment.registerExtensionPoint(area, FileContextProvider.EP_NAME, FileContextProvider.class);
|
||||
IdeaExtensionPoints.INSTANCE.registerVersionSpecificAppExtensionPoints(Extensions.getRootArea());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private void registerExtensions() {
|
||||
registerFileType(JavaClassFileType.INSTANCE, "class");
|
||||
registerFileType(JavaFileType.INSTANCE, "java");
|
||||
registerFileType(ArchiveFileType.INSTANCE, "jar;zip");
|
||||
registerFileType(PlainTextFileType.INSTANCE, "txt;sh;bat;cmd;policy;log;cgi;MF;jad;jam;htaccess");
|
||||
|
||||
addExplicitExtension(LanguageASTFactory.INSTANCE, PlainTextLanguage.INSTANCE, new PlainTextASTFactory());
|
||||
registerParserDefinition(new PlainTextParserDefinition());
|
||||
|
||||
addExplicitExtension(FileTypeFileViewProviders.INSTANCE, JavaClassFileType.INSTANCE, new ClassFileViewProviderFactory());
|
||||
addExplicitExtension(BinaryFileStubBuilders.INSTANCE, JavaClassFileType.INSTANCE, new ClassFileStubBuilder());
|
||||
|
||||
addExplicitExtension(LanguageASTFactory.INSTANCE, JavaLanguage.INSTANCE, new JavaASTFactory());
|
||||
registerParserDefinition(new JavaParserDefinition());
|
||||
addExplicitExtension(LanguageConstantExpressionEvaluator.INSTANCE, JavaLanguage.INSTANCE, new PsiExpressionEvaluator());
|
||||
|
||||
addExtension(ContainerProvider.EP_NAME, new JavaContainerProvider());
|
||||
|
||||
myApplication.registerService(PsiPackageImplementationHelper.class, new CorePsiPackageImplementationHelper());
|
||||
myApplication.registerService(PsiSubstitutorFactory.class, new PsiSubstitutorFactoryImpl());
|
||||
|
||||
myApplication.registerService(JavaDirectoryService.class, createJavaDirectoryService());
|
||||
myApplication.registerService(JavaVersionService.class, new JavaVersionService());
|
||||
|
||||
addExplicitExtension(ItemPresentationProviders.INSTANCE, PsiPackage.class, new PackagePresentationProvider());
|
||||
addExplicitExtension(ItemPresentationProviders.INSTANCE, PsiClass.class, new ClassPresentationProvider());
|
||||
addExplicitExtension(ItemPresentationProviders.INSTANCE, PsiMethod.class, new MethodPresentationProvider());
|
||||
addExplicitExtension(ItemPresentationProviders.INSTANCE, PsiField.class, new FieldPresentationProvider());
|
||||
addExplicitExtension(ItemPresentationProviders.INSTANCE, PsiLocalVariable.class, new VariablePresentationProvider());
|
||||
addExplicitExtension(ItemPresentationProviders.INSTANCE, PsiParameter.class, new VariablePresentationProvider());
|
||||
|
||||
registerApplicationService(JavaCodeFoldingSettings.class, new JavaCodeFoldingSettingsBase());
|
||||
addExplicitExtension(LanguageFolding.INSTANCE, JavaLanguage.INSTANCE, new JavaFoldingBuilderBase() {
|
||||
@Override
|
||||
protected boolean shouldShowExplicitLambdaType(@NotNull PsiAnonymousClass anonymousClass, @NotNull PsiNewExpression expression) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isBelowRightMargin(@NotNull PsiFile file, int lineLength) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
registerApplicationExtensionPoint(SuperMethodsSearch.EP_NAME, QueryExecutor.class);
|
||||
addExtension(SuperMethodsSearch.EP_NAME, new MethodSuperSearcher());
|
||||
}
|
||||
|
||||
// overridden in upsource
|
||||
protected CoreJavaDirectoryService createJavaDirectoryService() {
|
||||
return new CoreJavaDirectoryService();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected VirtualFileSystem createJrtFileSystem() {
|
||||
return new CoreJrtFileSystem();
|
||||
}
|
||||
@Nullable
|
||||
@Override
|
||||
protected VirtualFileSystem createJrtFileSystem() {
|
||||
return new CoreJrtFileSystem();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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.JavaContainerProvider;
|
||||
import com.intellij.codeInsight.folding.JavaCodeFoldingSettings;
|
||||
import com.intellij.codeInsight.folding.impl.JavaCodeFoldingSettingsBase;
|
||||
import com.intellij.codeInsight.folding.impl.JavaFoldingBuilderBase;
|
||||
import com.intellij.codeInsight.runner.JavaMainMethodProvider;
|
||||
import com.intellij.core.CoreApplicationEnvironment;
|
||||
import com.intellij.core.CoreJavaDirectoryService;
|
||||
import com.intellij.core.CorePsiPackageImplementationHelper;
|
||||
import com.intellij.ide.highlighter.ArchiveFileType;
|
||||
import com.intellij.ide.highlighter.JavaClassFileType;
|
||||
import com.intellij.ide.highlighter.JavaFileType;
|
||||
import com.intellij.lang.LanguageASTFactory;
|
||||
import com.intellij.lang.MetaLanguage;
|
||||
import com.intellij.lang.folding.LanguageFolding;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.lang.java.JavaParserDefinition;
|
||||
import com.intellij.navigation.ItemPresentationProviders;
|
||||
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.fileTypes.PlainTextFileType;
|
||||
import com.intellij.openapi.fileTypes.PlainTextLanguage;
|
||||
import com.intellij.openapi.fileTypes.PlainTextParserDefinition;
|
||||
import com.intellij.openapi.projectRoots.JavaVersionService;
|
||||
import com.intellij.openapi.vfs.VirtualFileSystem;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.augment.PsiAugmentProvider;
|
||||
import com.intellij.psi.augment.TypeAnnotationModifier;
|
||||
import com.intellij.psi.compiled.ClassFileDecompilers;
|
||||
import com.intellij.psi.impl.LanguageConstantExpressionEvaluator;
|
||||
import com.intellij.psi.impl.PsiExpressionEvaluator;
|
||||
import com.intellij.psi.impl.PsiSubstitutorFactoryImpl;
|
||||
import com.intellij.psi.impl.compiled.ClassFileStubBuilder;
|
||||
import com.intellij.psi.impl.file.PsiPackageImplementationHelper;
|
||||
import com.intellij.psi.impl.search.MethodSuperSearcher;
|
||||
import com.intellij.psi.impl.source.tree.JavaASTFactory;
|
||||
import com.intellij.psi.impl.source.tree.PlainTextASTFactory;
|
||||
import com.intellij.psi.meta.MetaDataContributor;
|
||||
import com.intellij.psi.presentation.java.*;
|
||||
import com.intellij.psi.search.searches.SuperMethodsSearch;
|
||||
import com.intellij.psi.stubs.BinaryFileStubBuilders;
|
||||
import com.intellij.util.QueryExecutor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem;
|
||||
|
||||
/**
|
||||
* adapted from com.intellij.core.JavaCoreApplicationEnvironment
|
||||
* TODO: initiate removal original from com.intellij.core since it seems that there are no usages left
|
||||
*/
|
||||
public class KotlinCoreApplicationEnvironment extends CoreApplicationEnvironment {
|
||||
|
||||
public static KotlinCoreApplicationEnvironment create(@NotNull Disposable parentDisposable, boolean unitTestMode) {
|
||||
return new KotlinCoreApplicationEnvironment(parentDisposable, unitTestMode);
|
||||
}
|
||||
|
||||
private KotlinCoreApplicationEnvironment(@NotNull Disposable parentDisposable, boolean unitTestMode) {
|
||||
super(parentDisposable, unitTestMode);
|
||||
|
||||
registerExtensionPoints();
|
||||
|
||||
registerExtensions();
|
||||
}
|
||||
|
||||
private 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);
|
||||
}
|
||||
|
||||
private void registerExtensions() {
|
||||
registerFileType(JavaClassFileType.INSTANCE, "class");
|
||||
registerFileType(JavaFileType.INSTANCE, "java");
|
||||
registerFileType(ArchiveFileType.INSTANCE, "jar;zip");
|
||||
registerFileType(PlainTextFileType.INSTANCE, "txt;sh;bat;cmd;policy;log;cgi;MF;jad;jam;htaccess");
|
||||
|
||||
addExplicitExtension(LanguageASTFactory.INSTANCE, PlainTextLanguage.INSTANCE, new PlainTextASTFactory());
|
||||
registerParserDefinition(new PlainTextParserDefinition());
|
||||
|
||||
addExplicitExtension(FileTypeFileViewProviders.INSTANCE, JavaClassFileType.INSTANCE, new ClassFileViewProviderFactory());
|
||||
addExplicitExtension(BinaryFileStubBuilders.INSTANCE, JavaClassFileType.INSTANCE, new ClassFileStubBuilder());
|
||||
|
||||
addExplicitExtension(LanguageASTFactory.INSTANCE, JavaLanguage.INSTANCE, new JavaASTFactory());
|
||||
registerParserDefinition(new JavaParserDefinition());
|
||||
addExplicitExtension(LanguageConstantExpressionEvaluator.INSTANCE, JavaLanguage.INSTANCE, new PsiExpressionEvaluator());
|
||||
|
||||
addExtension(ContainerProvider.EP_NAME, new JavaContainerProvider());
|
||||
|
||||
myApplication.registerService(PsiPackageImplementationHelper.class, new CorePsiPackageImplementationHelper());
|
||||
myApplication.registerService(PsiSubstitutorFactory.class, new PsiSubstitutorFactoryImpl());
|
||||
|
||||
myApplication.registerService(JavaDirectoryService.class, createJavaDirectoryService());
|
||||
myApplication.registerService(JavaVersionService.class, new JavaVersionService());
|
||||
|
||||
addExplicitExtension(ItemPresentationProviders.INSTANCE, PsiPackage.class, new PackagePresentationProvider());
|
||||
addExplicitExtension(ItemPresentationProviders.INSTANCE, PsiClass.class, new ClassPresentationProvider());
|
||||
addExplicitExtension(ItemPresentationProviders.INSTANCE, PsiMethod.class, new MethodPresentationProvider());
|
||||
addExplicitExtension(ItemPresentationProviders.INSTANCE, PsiField.class, new FieldPresentationProvider());
|
||||
addExplicitExtension(ItemPresentationProviders.INSTANCE, PsiLocalVariable.class, new VariablePresentationProvider());
|
||||
addExplicitExtension(ItemPresentationProviders.INSTANCE, PsiParameter.class, new VariablePresentationProvider());
|
||||
|
||||
registerApplicationService(JavaCodeFoldingSettings.class, new JavaCodeFoldingSettingsBase());
|
||||
addExplicitExtension(LanguageFolding.INSTANCE, JavaLanguage.INSTANCE, new JavaFoldingBuilderBase() {
|
||||
@Override
|
||||
protected boolean shouldShowExplicitLambdaType(@NotNull PsiAnonymousClass anonymousClass, @NotNull PsiNewExpression expression) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isBelowRightMargin(@NotNull PsiFile file, int lineLength) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
registerApplicationExtensionPoint(SuperMethodsSearch.EP_NAME, QueryExecutor.class);
|
||||
addExtension(SuperMethodsSearch.EP_NAME, new MethodSuperSearcher());
|
||||
}
|
||||
|
||||
// overridden in upsource
|
||||
protected CoreJavaDirectoryService createJavaDirectoryService() {
|
||||
return new CoreJavaDirectoryService();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected VirtualFileSystem createJrtFileSystem() {
|
||||
return new CoreJrtFileSystem();
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import com.intellij.psi.*
|
||||
|
||||
class MockExternalAnnotationsManager : ExternalAnnotationsManager() {
|
||||
override fun chooseAnnotationsPlace(element: PsiElement): AnnotationPlace = AnnotationPlace.NOWHERE
|
||||
override fun chooseAnnotationsPlaceNoUi(element: PsiElement): AnnotationPlace = AnnotationPlace.NOWHERE
|
||||
|
||||
override fun isExternalAnnotationWritable(listOwner: PsiModifierListOwner, annotationFQN: String): Boolean = false
|
||||
override fun isExternalAnnotation(annotation: PsiAnnotation): Boolean = false
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.cli.jvm.compiler
|
||||
|
||||
import com.intellij.codeInsight.ExternalAnnotationsManager
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.*
|
||||
|
||||
class MockExternalAnnotationsManager : ExternalAnnotationsManager() {
|
||||
override fun chooseAnnotationsPlace(element: PsiElement): AnnotationPlace = AnnotationPlace.NOWHERE
|
||||
|
||||
override fun isExternalAnnotationWritable(listOwner: PsiModifierListOwner, annotationFQN: String): Boolean = false
|
||||
override fun isExternalAnnotation(annotation: PsiAnnotation): Boolean = false
|
||||
|
||||
override fun findExternalAnnotationsFiles(listOwner: PsiModifierListOwner): List<PsiFile>? = null
|
||||
override fun findExternalAnnotation(listOwner: PsiModifierListOwner, annotationFQN: String): PsiAnnotation? = null
|
||||
override fun findExternalAnnotations(listOwner: PsiModifierListOwner): Array<out PsiAnnotation>? = null
|
||||
|
||||
override fun annotateExternally(
|
||||
listOwner: PsiModifierListOwner,
|
||||
annotationFQName: String,
|
||||
fromFile: PsiFile,
|
||||
value: Array<out PsiNameValuePair>?
|
||||
) {
|
||||
throw UnsupportedOperationException("not implemented")
|
||||
}
|
||||
|
||||
override fun deannotate(listOwner: PsiModifierListOwner, annotationFQN: String): Boolean {
|
||||
throw UnsupportedOperationException("not implemented")
|
||||
}
|
||||
|
||||
override fun editExternalAnnotation(
|
||||
listOwner: PsiModifierListOwner,
|
||||
annotationFQN: String,
|
||||
value: Array<out PsiNameValuePair>?
|
||||
): Boolean {
|
||||
throw UnsupportedOperationException("not implemented")
|
||||
}
|
||||
|
||||
override fun hasAnnotationRootsForFile(file: VirtualFile): Boolean = false
|
||||
|
||||
override fun findDefaultConstructorExternalAnnotations(aClass: PsiClass, annotationFQN: String): List<PsiAnnotation> = emptyList()
|
||||
|
||||
override fun findDefaultConstructorExternalAnnotations(aClass: PsiClass): List<PsiAnnotation> = emptyList()
|
||||
|
||||
override fun findExternalAnnotations(listOwner: PsiModifierListOwner, annotationFQN: String): List<PsiAnnotation> = emptyList()
|
||||
}
|
||||
@@ -6,4 +6,10 @@
|
||||
package org.jetbrains.kotlin.cli.jvm.compiler
|
||||
|
||||
fun setupIdeaStandaloneExecution() {
|
||||
System.getProperties().setProperty("idea.plugins.compatible.build", "202.5103")
|
||||
System.getProperties().setProperty("project.structure.add.tools.jar.to.new.jdk", "false")
|
||||
System.getProperties().setProperty("psi.track.invalidation", "true")
|
||||
System.getProperties().setProperty("psi.incremental.reparse.depth.limit", "1000")
|
||||
System.getProperties().setProperty("ide.hide.excluded.files", "false")
|
||||
System.getProperties().setProperty("ast.loading.filter", "false")
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* 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.cli.jvm.compiler
|
||||
|
||||
fun setupIdeaStandaloneExecution() {
|
||||
}
|
||||
@@ -8,9 +8,11 @@ package org.jetbrains.kotlin.cli.jvm.compiler
|
||||
import com.intellij.core.CoreApplicationEnvironment
|
||||
import com.intellij.openapi.extensions.ExtensionsArea
|
||||
import java.io.File
|
||||
import java.nio.file.FileSystems
|
||||
|
||||
// FIX ME WHEN BUNCH 193 REMOVED
|
||||
fun registerExtensionPointAndExtensionsEx(pluginFile: File, fileName: String, area: ExtensionsArea) {
|
||||
val pluginRoot = FileSystems.getDefault().getPath(pluginFile.path)
|
||||
@Suppress("MissingRecentApi")
|
||||
CoreApplicationEnvironment.registerExtensionPointAndExtensions(pluginFile, fileName, area)
|
||||
CoreApplicationEnvironment.registerExtensionPointAndExtensions(pluginRoot, fileName, area)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.cli.jvm.compiler
|
||||
|
||||
import com.intellij.core.CoreApplicationEnvironment
|
||||
import com.intellij.openapi.extensions.ExtensionsArea
|
||||
import java.io.File
|
||||
|
||||
// FIX ME WHEN BUNCH 193 REMOVED
|
||||
fun registerExtensionPointAndExtensionsEx(pluginFile: File, fileName: String, area: ExtensionsArea) {
|
||||
@Suppress("MissingRecentApi")
|
||||
CoreApplicationEnvironment.registerExtensionPointAndExtensions(pluginFile, fileName, area)
|
||||
}
|
||||
@@ -140,7 +140,6 @@ public abstract class KtParsingTestCase extends KtPlatformLiteFixture {
|
||||
// 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) {
|
||||
|
||||
@@ -140,6 +140,7 @@ public abstract class KtParsingTestCase extends KtPlatformLiteFixture {
|
||||
// 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) {
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.test.testFramework;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.concurrency.IdeaForkJoinWorkerThreadFactory;
|
||||
import com.intellij.diagnostic.PerformanceWatcher;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.Application;
|
||||
@@ -23,20 +25,33 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.application.impl.ApplicationInfoImpl;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileVisitor;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.impl.DocumentCommitProcessor;
|
||||
import com.intellij.psi.impl.DocumentCommitThread;
|
||||
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
|
||||
import com.intellij.rt.execution.junit.FileComparisonFailure;
|
||||
import com.intellij.testFramework.*;
|
||||
import com.intellij.testFramework.exceptionCases.AbstractExceptionCase;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ReflectionUtil;
|
||||
import com.intellij.testFramework.fixtures.IdeaTestExecutionPolicy;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.hash.HashMap;
|
||||
import com.intellij.util.containers.PeekableIterator;
|
||||
import com.intellij.util.containers.PeekableIteratorWrapper;
|
||||
import com.intellij.util.indexing.FileBasedIndex;
|
||||
import com.intellij.util.indexing.FileBasedIndexImpl;
|
||||
import com.intellij.util.lang.CompoundRuntimeException;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import gnu.trove.Equality;
|
||||
@@ -47,11 +62,11 @@ import org.jdom.Element;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.test.IdeaSystemPropertiesForParallelRunConfigurator;
|
||||
import org.jetbrains.kotlin.testFramework.MockComponentManagerCreationTracer;
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker;
|
||||
import org.jetbrains.kotlin.types.FlexibleTypeImpl;
|
||||
import org.junit.Assert;
|
||||
import org.junit.ComparisonFailure;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
@@ -61,14 +76,19 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@SuppressWarnings("UseOfSystemOutOrSystemErr")
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
@SuppressWarnings("ALL")
|
||||
public abstract class KtUsefulTestCase extends TestCase {
|
||||
public static final boolean IS_UNDER_TEAMCITY = System.getenv("TEAMCITY_VERSION") != null;
|
||||
private static final String TEMP_DIR_MARKER = "unitTest_";
|
||||
public static final String TEMP_DIR_MARKER = "unitTest_";
|
||||
public static final boolean OVERWRITE_TESTDATA = Boolean.getBoolean("idea.tests.overwrite.data");
|
||||
|
||||
private static final String ORIGINAL_TEMP_DIR = FileUtil.getTempDirectory();
|
||||
@@ -79,24 +99,34 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
private Application application;
|
||||
|
||||
static {
|
||||
IdeaSystemPropertiesForParallelRunConfigurator.setProperties();
|
||||
//TODO: investigate and enable
|
||||
//IdeaForkJoinWorkerThreadFactory.setupPoisonFactory();
|
||||
IdeaForkJoinWorkerThreadFactory.setupPoisonFactory();
|
||||
Logger.setFactory(TestLoggerFactory.class);
|
||||
}
|
||||
protected static final Logger LOG = Logger.getInstance(KtUsefulTestCase.class);
|
||||
|
||||
@NotNull
|
||||
protected final Disposable myTestRootDisposable = new TestDisposable();
|
||||
private final Disposable myTestRootDisposable = new TestDisposable();
|
||||
|
||||
private static final String ourPathToKeep = null;
|
||||
static Path ourPathToKeep;
|
||||
private final List<String> myPathsToKeep = new ArrayList<>();
|
||||
|
||||
private File myTempDir;
|
||||
private String myTempDir;
|
||||
|
||||
private static final String DEFAULT_SETTINGS_EXTERNALIZED;
|
||||
private static final CodeInsightSettings defaultSettings = new CodeInsightSettings();
|
||||
static {
|
||||
// Radar #5755208: Command line Java applications need a way to launch without a Dock icon.
|
||||
System.setProperty("apple.awt.UIElement", "true");
|
||||
|
||||
try {
|
||||
Element oldS = new Element("temp");
|
||||
defaultSettings.writeExternal(oldS);
|
||||
DEFAULT_SETTINGS_EXTERNALIZED = JDOMUtil.writeElement(oldS);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
// -- KOTLIN ADDITIONAL START --
|
||||
|
||||
FlexibleTypeImpl.RUN_SLOW_ASSERTIONS = true;
|
||||
@@ -105,6 +135,42 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
// -- KOTLIN ADDITIONAL END --
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass here the exception you want to be thrown first
|
||||
* E.g.<pre>
|
||||
* {@code
|
||||
* void tearDown() {
|
||||
* try {
|
||||
* doTearDowns();
|
||||
* }
|
||||
* catch(Exception e) {
|
||||
* addSuppressedException(e);
|
||||
* }
|
||||
* finally {
|
||||
* super.tearDown();
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
*/
|
||||
protected void addSuppressedException(@NotNull Throwable e) {
|
||||
List<Throwable> list = mySuppressedExceptions;
|
||||
if (list == null) {
|
||||
mySuppressedExceptions = list = new SmartList<>();
|
||||
}
|
||||
list.add(e);
|
||||
}
|
||||
private List<Throwable> mySuppressedExceptions;
|
||||
|
||||
|
||||
public KtUsefulTestCase() {
|
||||
}
|
||||
|
||||
public KtUsefulTestCase(@NotNull String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
protected boolean shouldContainTempFiles() {
|
||||
return true;
|
||||
}
|
||||
@@ -122,11 +188,17 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
super.setUp();
|
||||
|
||||
if (shouldContainTempFiles()) {
|
||||
String testName = FileUtil.sanitizeFileName(getTestName(true));
|
||||
if (StringUtil.isEmptyOrSpaces(testName)) testName = "";
|
||||
IdeaTestExecutionPolicy policy = IdeaTestExecutionPolicy.current();
|
||||
String testName = null;
|
||||
if (policy != null) {
|
||||
testName = policy.getPerTestTempDirName();
|
||||
}
|
||||
if (testName == null) {
|
||||
testName = FileUtil.sanitizeFileName(getTestName(true));
|
||||
}
|
||||
testName = new File(testName).getName(); // in case the test name contains file separators
|
||||
myTempDir = FileUtil.createTempDirectory(TEMP_DIR_MARKER, testName, false);
|
||||
FileUtil.resetCanonicalTempPathCache(myTempDir.getPath());
|
||||
myTempDir = FileUtil.createTempDirectory(TEMP_DIR_MARKER + testName, "", false).getPath();
|
||||
FileUtil.resetCanonicalTempPathCache(myTempDir);
|
||||
}
|
||||
|
||||
boolean isStressTest = isStressTest();
|
||||
@@ -137,6 +209,16 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
|
||||
// turn off Disposer debugging for performance tests
|
||||
Disposer.setDebugMode(!isStressTest);
|
||||
|
||||
if (isIconRequired()) {
|
||||
// ensure that IconLoader will use dummy empty icon
|
||||
IconLoader.deactivate();
|
||||
//IconManager.activate();
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isIconRequired() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -145,6 +227,11 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
// don't use method references here to make stack trace reading easier
|
||||
//noinspection Convert2MethodRef
|
||||
new RunAll(
|
||||
() -> {
|
||||
if (isIconRequired()) {
|
||||
//IconManager.deactivate();
|
||||
}
|
||||
},
|
||||
() -> disposeRootDisposable(),
|
||||
() -> cleanupSwingDataStructures(),
|
||||
() -> cleanupDeleteOnExitHookList(),
|
||||
@@ -153,7 +240,7 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
if (shouldContainTempFiles()) {
|
||||
FileUtil.resetCanonicalTempPathCache(ORIGINAL_TEMP_DIR);
|
||||
if (hasTmpFilesToKeep()) {
|
||||
File[] files = myTempDir.listFiles();
|
||||
File[] files = new File(myTempDir).listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
if (!shouldKeepTmpFile(file)) {
|
||||
@@ -163,15 +250,14 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
}
|
||||
}
|
||||
else {
|
||||
FileUtil.delete(myTempDir);
|
||||
FileUtil.delete(new File(myTempDir));
|
||||
}
|
||||
}
|
||||
},
|
||||
() -> UIUtil.removeLeakingAppleListeners()
|
||||
).run();
|
||||
() -> waitForAppLeakingThreads(10, TimeUnit.SECONDS)
|
||||
).run(ObjectUtils.notNull(mySuppressedExceptions, Collections.emptyList()));
|
||||
}
|
||||
finally {
|
||||
super.tearDown();
|
||||
// -- KOTLIN ADDITIONAL START --
|
||||
TestApplicationUtilKt.resetApplicationToNull(application);
|
||||
application = null;
|
||||
@@ -188,12 +274,12 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
}
|
||||
|
||||
private boolean hasTmpFilesToKeep() {
|
||||
return ourPathToKeep != null && FileUtil.isAncestor(myTempDir.getPath(), ourPathToKeep, false) || !myPathsToKeep.isEmpty();
|
||||
return ourPathToKeep != null && FileUtil.isAncestor(myTempDir, ourPathToKeep.toString(), false) || !myPathsToKeep.isEmpty();
|
||||
}
|
||||
|
||||
private boolean shouldKeepTmpFile(@NotNull File file) {
|
||||
String path = file.getPath();
|
||||
if (FileUtil.pathsEqual(path, ourPathToKeep)) return true;
|
||||
if (FileUtil.pathsEqual(path, ourPathToKeep.toString())) return true;
|
||||
for (String pathToKeep : myPathsToKeep) {
|
||||
if (FileUtil.pathsEqual(path, pathToKeep)) return true;
|
||||
}
|
||||
@@ -201,7 +287,7 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
}
|
||||
|
||||
private static final Set<String> DELETE_ON_EXIT_HOOK_DOT_FILES;
|
||||
private static final Class DELETE_ON_EXIT_HOOK_CLASS;
|
||||
private static final Class<?> DELETE_ON_EXIT_HOOK_CLASS;
|
||||
static {
|
||||
Class<?> aClass;
|
||||
try {
|
||||
@@ -237,12 +323,45 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private static void cleanupSwingDataStructures() throws Exception {
|
||||
Object manager = ReflectionUtil.getDeclaredMethod(Class.forName("javax.swing.KeyboardManager"), "getCurrentManager").invoke(null);
|
||||
Map componentKeyStrokeMap = ReflectionUtil.getField(manager.getClass(), manager, Hashtable.class, "componentKeyStrokeMap");
|
||||
Map<?, ?> componentKeyStrokeMap = ReflectionUtil.getField(manager.getClass(), manager, Hashtable.class, "componentKeyStrokeMap");
|
||||
componentKeyStrokeMap.clear();
|
||||
Map containerMap = ReflectionUtil.getField(manager.getClass(), manager, Hashtable.class, "containerMap");
|
||||
Map<?, ?> containerMap = ReflectionUtil.getField(manager.getClass(), manager, Hashtable.class, "containerMap");
|
||||
containerMap.clear();
|
||||
}
|
||||
|
||||
static void doCheckForSettingsDamage(@NotNull CodeStyleSettings oldCodeStyleSettings, @NotNull CodeStyleSettings currentCodeStyleSettings) {
|
||||
final CodeInsightSettings settings = CodeInsightSettings.getInstance();
|
||||
// don't use method references here to make stack trace reading easier
|
||||
//noinspection Convert2MethodRef
|
||||
new RunAll()
|
||||
.append(() -> {
|
||||
try {
|
||||
checkCodeInsightSettingsEqual(defaultSettings, settings);
|
||||
}
|
||||
catch (AssertionError error) {
|
||||
CodeInsightSettings clean = new CodeInsightSettings();
|
||||
for (Field field : clean.getClass().getFields()) {
|
||||
try {
|
||||
ReflectionUtil.copyFieldValue(clean, settings, field);
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
})
|
||||
.append(() -> {
|
||||
currentCodeStyleSettings.getIndentOptions(StdFileTypes.JAVA);
|
||||
try {
|
||||
checkCodeStyleSettingsEqual(oldCodeStyleSettings, currentCodeStyleSettings);
|
||||
}
|
||||
finally {
|
||||
currentCodeStyleSettings.clearCodeStyleSettings();
|
||||
}
|
||||
})
|
||||
.run();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Disposable getTestRootDisposable() {
|
||||
return myTestRootDisposable;
|
||||
@@ -252,13 +371,11 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
protected void runTest() throws Throwable {
|
||||
final Throwable[] throwables = new Throwable[1];
|
||||
|
||||
AtomicBoolean completed = new AtomicBoolean(false);
|
||||
Runnable runnable = () -> {
|
||||
try {
|
||||
//TestLoggerFactory.onTestStarted();
|
||||
TestLoggerFactory.onTestStarted();
|
||||
super.runTest();
|
||||
TestLoggerFactory.onTestFinished(true);
|
||||
completed.set(true);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
TestLoggerFactory.onTestFinished(false);
|
||||
@@ -281,9 +398,6 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
if (throwables[0] != null) {
|
||||
throw throwables[0];
|
||||
}
|
||||
if (!completed.get()) {
|
||||
throw new IllegalStateException("test didn't start");
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean shouldRunTest() {
|
||||
@@ -291,19 +405,18 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
}
|
||||
|
||||
protected void invokeTestRunnable(@NotNull Runnable runnable) throws Exception {
|
||||
//IdeaTestExecutionPolicy policy = IdeaTestExecutionPolicy.current();
|
||||
//if (policy != null && !policy.runInDispatchThread()) {
|
||||
// runnable.run();
|
||||
//}
|
||||
//else {
|
||||
if (runInDispatchThread()) {
|
||||
EdtTestUtilKt.runInEdtAndWait(() -> {
|
||||
runnable.run();
|
||||
return null;
|
||||
});
|
||||
//}
|
||||
}
|
||||
else {
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
|
||||
private void defaultRunBare() throws Throwable {
|
||||
protected void defaultRunBare() throws Throwable {
|
||||
Throwable exception = null;
|
||||
try {
|
||||
long setupStart = System.nanoTime();
|
||||
@@ -324,11 +437,17 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
logPerClassCost(teardownCost, TOTAL_TEARDOWN_COST_MILLIS);
|
||||
}
|
||||
catch (Throwable tearingDown) {
|
||||
if (exception == null) exception = tearingDown;
|
||||
else exception = new CompoundRuntimeException(Arrays.asList(exception, tearingDown));
|
||||
if (exception == null) {
|
||||
exception = tearingDown;
|
||||
}
|
||||
else {
|
||||
exception = new CompoundRuntimeException(Arrays.asList(exception, tearingDown));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (exception != null) throw exception;
|
||||
if (exception != null) {
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -368,7 +487,7 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
|
||||
if (runInDispatchThread()) {
|
||||
TestRunnerUtil.replaceIdeEventQueueSafely();
|
||||
com.intellij.testFramework.EdtTestUtil.runInEdtAndWait(this::defaultRunBare);
|
||||
EdtTestUtil.runInEdtAndWait(this::defaultRunBare);
|
||||
}
|
||||
else {
|
||||
defaultRunBare();
|
||||
@@ -376,13 +495,20 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
}
|
||||
|
||||
protected boolean runInDispatchThread() {
|
||||
//IdeaTestExecutionPolicy policy = IdeaTestExecutionPolicy.current();
|
||||
//if (policy != null) {
|
||||
// return policy.runInDispatchThread();
|
||||
//}
|
||||
IdeaTestExecutionPolicy policy = IdeaTestExecutionPolicy.current();
|
||||
if (policy != null) {
|
||||
return policy.runInDispatchThread();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* If you want a more shorter name than runInEdtAndWait.
|
||||
*/
|
||||
protected void edt(@NotNull ThrowableRunnable<Throwable> runnable) {
|
||||
EdtTestUtil.runInEdtAndWait(runnable);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String toString(@NotNull Iterable<?> collection) {
|
||||
if (!collection.iterator().hasNext()) {
|
||||
@@ -515,9 +641,20 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
}
|
||||
|
||||
public static <T> void assertContainsOrdered(@NotNull Collection<? extends T> collection, @NotNull Collection<? extends T> expected) {
|
||||
ArrayList<T> copy = new ArrayList<>(collection);
|
||||
copy.retainAll(expected);
|
||||
assertOrderedEquals(toString(collection), copy, expected);
|
||||
PeekableIterator<T> expectedIt = new PeekableIteratorWrapper<>(expected.iterator());
|
||||
PeekableIterator<T> actualIt = new PeekableIteratorWrapper<>(collection.iterator());
|
||||
|
||||
while (actualIt.hasNext() && expectedIt.hasNext()) {
|
||||
T expectedElem = expectedIt.peek();
|
||||
T actualElem = actualIt.peek();
|
||||
if (expectedElem.equals(actualElem)) {
|
||||
expectedIt.next();
|
||||
}
|
||||
actualIt.next();
|
||||
}
|
||||
if (expectedIt.hasNext()) {
|
||||
throw new ComparisonFailure("", toString(expected), toString(collection));
|
||||
}
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
@@ -592,7 +729,7 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
if (collection.size() != checkers.length) {
|
||||
Assert.fail(toString(collection));
|
||||
}
|
||||
Set<Consumer<T>> checkerSet = new HashSet<>(Arrays.asList(checkers));
|
||||
Set<Consumer<T>> checkerSet = ContainerUtil.set(checkers);
|
||||
int i = 0;
|
||||
Throwable lastError = null;
|
||||
for (final T actual : collection) {
|
||||
@@ -767,7 +904,7 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
//noinspection UseOfSystemOutOrSystemErr
|
||||
System.out.println("File " + filePath + " created.");
|
||||
}
|
||||
fileText = FileUtil.loadFile(new File(filePath), CharsetToolkit.UTF8_CHARSET);
|
||||
fileText = FileUtil.loadFile(new File(filePath), StandardCharsets.UTF_8);
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
VfsTestUtil.overwriteTestData(filePath, actualText);
|
||||
@@ -784,14 +921,14 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
}
|
||||
|
||||
protected static void clearFields(@NotNull Object test) throws IllegalAccessException {
|
||||
Class aClass = test.getClass();
|
||||
Class<?> aClass = test.getClass();
|
||||
while (aClass != null) {
|
||||
clearDeclaredFields(test, aClass);
|
||||
aClass = aClass.getSuperclass();
|
||||
}
|
||||
}
|
||||
|
||||
public static void clearDeclaredFields(@NotNull Object test, @NotNull Class aClass) throws IllegalAccessException {
|
||||
public static void clearDeclaredFields(@NotNull Object test, @NotNull Class<?> aClass) throws IllegalAccessException {
|
||||
for (final Field field : aClass.getDeclaredFields()) {
|
||||
final String name = field.getDeclaringClass().getName();
|
||||
if (!name.startsWith("junit.framework.") && !name.startsWith("com.intellij.testFramework.")) {
|
||||
@@ -817,6 +954,14 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkCodeInsightSettingsEqual(@NotNull CodeInsightSettings oldSettings, @NotNull CodeInsightSettings settings) {
|
||||
if (!oldSettings.equals(settings)) {
|
||||
Element newS = new Element("temp");
|
||||
settings.writeExternal(newS);
|
||||
Assert.assertEquals("Code insight settings damaged", DEFAULT_SETTINGS_EXTERNALIZED, JDOMUtil.writeElement(newS));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPerformanceTest() {
|
||||
String testName = getName();
|
||||
String className = getClass().getSimpleName();
|
||||
@@ -843,6 +988,21 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
return name != null && (name.contains("Stress") || name.contains("Slow"));
|
||||
}
|
||||
|
||||
public static void doPostponedFormatting(@NotNull Project project) {
|
||||
DocumentUtil.writeInRunUndoTransparentAction(() -> {
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
||||
PostprocessReformattingAspect.getInstance(project).doPostponedFormatting();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that code block throw corresponding exception.
|
||||
*
|
||||
* @param exceptionCase Block annotated with some exception type
|
||||
*/
|
||||
protected void assertException(@NotNull AbstractExceptionCase<?> exceptionCase) {
|
||||
assertException(exceptionCase, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that code block throw corresponding exception with expected error msg.
|
||||
@@ -856,6 +1016,42 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
assertExceptionOccurred(true, exceptionCase, expectedErrorMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the code block throws an exception of the specified class.
|
||||
*
|
||||
* @param exceptionClass Expected exception type
|
||||
* @param runnable Block annotated with some exception type
|
||||
*/
|
||||
public static <T extends Throwable> void assertThrows(@NotNull Class<? extends Throwable> exceptionClass,
|
||||
@NotNull ThrowableRunnable<T> runnable) {
|
||||
assertThrows(exceptionClass, null, runnable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the code block throws an exception of the specified class with expected error msg.
|
||||
* If expected error message is null it will not be checked.
|
||||
*
|
||||
* @param exceptionClass Expected exception type
|
||||
* @param expectedErrorMsgPart expected error message, of any
|
||||
* @param runnable Block annotated with some exception type
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "SameParameterValue"})
|
||||
public static <T extends Throwable> void assertThrows(@NotNull Class<? extends Throwable> exceptionClass,
|
||||
@Nullable String expectedErrorMsgPart,
|
||||
@NotNull ThrowableRunnable<T> runnable) {
|
||||
assertExceptionOccurred(true, new AbstractExceptionCase() {
|
||||
@Override
|
||||
public Class<Throwable> getExpectedExceptionClass() {
|
||||
return (Class<Throwable>)exceptionClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tryClosure() throws Throwable {
|
||||
runnable.run();
|
||||
}
|
||||
}, expectedErrorMsgPart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that code block doesn't throw corresponding exception.
|
||||
*
|
||||
@@ -878,21 +1074,22 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
|
||||
private static <T extends Throwable> void assertExceptionOccurred(boolean shouldOccur,
|
||||
@NotNull AbstractExceptionCase<T> exceptionCase,
|
||||
String expectedErrorMsg) throws T {
|
||||
String expectedErrorMsgPart) throws T {
|
||||
boolean wasThrown = false;
|
||||
try {
|
||||
exceptionCase.tryClosure();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
Throwable cause = e;
|
||||
|
||||
if (shouldOccur) {
|
||||
wasThrown = true;
|
||||
final String errorMessage = exceptionCase.getAssertionErrorMessage();
|
||||
assertEquals(errorMessage, exceptionCase.getExpectedExceptionClass(), e.getClass());
|
||||
if (expectedErrorMsg != null) {
|
||||
assertEquals("Compare error messages", expectedErrorMsg, e.getMessage());
|
||||
assertInstanceOf(cause, exceptionCase.getExpectedExceptionClass());
|
||||
if (expectedErrorMsgPart != null) {
|
||||
assertTrue(cause.getMessage(), cause.getMessage().contains(expectedErrorMsgPart));
|
||||
}
|
||||
}
|
||||
else if (exceptionCase.getExpectedExceptionClass().equals(e.getClass())) {
|
||||
else if (exceptionCase.getExpectedExceptionClass().equals(cause.getClass())) {
|
||||
wasThrown = true;
|
||||
|
||||
//noinspection UseOfSystemOutOrSystemErr
|
||||
@@ -900,7 +1097,7 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
//noinspection UseOfSystemOutOrSystemErr
|
||||
e.printStackTrace(System.out);
|
||||
|
||||
fail("Exception isn't expected here. Exception message: " + e.getMessage());
|
||||
fail("Exception isn't expected here. Exception message: " + cause.getMessage());
|
||||
}
|
||||
else {
|
||||
throw e;
|
||||
@@ -908,7 +1105,7 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
}
|
||||
finally {
|
||||
if (shouldOccur && !wasThrown) {
|
||||
fail(exceptionCase.getAssertionErrorMessage());
|
||||
fail(exceptionCase.getExpectedExceptionClass().getName() + " must be thrown.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -937,7 +1134,7 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
}
|
||||
|
||||
public static void refreshRecursively(@NotNull VirtualFile file) {
|
||||
VfsUtilCore.visitChildrenRecursively(file, new VirtualFileVisitor() {
|
||||
VfsUtilCore.visitChildrenRecursively(file, new VirtualFileVisitor<Void>() {
|
||||
@Override
|
||||
public boolean visitFile(@NotNull VirtualFile file) {
|
||||
file.getChildren();
|
||||
@@ -947,11 +1144,27 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
file.refresh(false, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static VirtualFile refreshAndFindFile(@NotNull final File file) {
|
||||
return UIUtil.invokeAndWaitIfNeeded(() -> LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file));
|
||||
}
|
||||
|
||||
public static void waitForAppLeakingThreads(long timeout, @NotNull TimeUnit timeUnit) {
|
||||
EdtTestUtil.runInEdtAndWait(() -> {
|
||||
Application app = ApplicationManager.getApplication();
|
||||
if (app != null && !app.isDisposed()) {
|
||||
FileBasedIndexImpl index = (FileBasedIndexImpl)app.getServiceIfCreated(FileBasedIndex.class);
|
||||
if (index != null) {
|
||||
index.getChangedFilesCollector().waitForVfsEventsExecuted(timeout, timeUnit);
|
||||
}
|
||||
|
||||
DocumentCommitThread commitThread = (DocumentCommitThread)app.getServiceIfCreated(DocumentCommitProcessor.class);
|
||||
if (commitThread != null) {
|
||||
commitThread.waitForAllCommits(timeout, timeUnit);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected class TestDisposable implements Disposable {
|
||||
private volatile boolean myDisposed;
|
||||
|
||||
@@ -972,5 +1185,5 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
String testName = getTestName(false);
|
||||
return KtUsefulTestCase.this.getClass() + (StringUtil.isEmpty(testName) ? "" : ".test" + testName);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.test.testFramework;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.concurrency.IdeaForkJoinWorkerThreadFactory;
|
||||
import com.intellij.diagnostic.PerformanceWatcher;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.Application;
|
||||
@@ -25,33 +23,20 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.application.impl.ApplicationInfoImpl;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileVisitor;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.impl.DocumentCommitProcessor;
|
||||
import com.intellij.psi.impl.DocumentCommitThread;
|
||||
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
|
||||
import com.intellij.rt.execution.junit.FileComparisonFailure;
|
||||
import com.intellij.testFramework.*;
|
||||
import com.intellij.testFramework.exceptionCases.AbstractExceptionCase;
|
||||
import com.intellij.testFramework.fixtures.IdeaTestExecutionPolicy;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ReflectionUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.PeekableIterator;
|
||||
import com.intellij.util.containers.PeekableIteratorWrapper;
|
||||
import com.intellij.util.indexing.FileBasedIndex;
|
||||
import com.intellij.util.indexing.FileBasedIndexImpl;
|
||||
import com.intellij.util.containers.hash.HashMap;
|
||||
import com.intellij.util.lang.CompoundRuntimeException;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import gnu.trove.Equality;
|
||||
@@ -62,11 +47,11 @@ import org.jdom.Element;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.test.IdeaSystemPropertiesForParallelRunConfigurator;
|
||||
import org.jetbrains.kotlin.testFramework.MockComponentManagerCreationTracer;
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker;
|
||||
import org.jetbrains.kotlin.types.FlexibleTypeImpl;
|
||||
import org.junit.Assert;
|
||||
import org.junit.ComparisonFailure;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
@@ -76,19 +61,14 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
@SuppressWarnings("ALL")
|
||||
@SuppressWarnings("UseOfSystemOutOrSystemErr")
|
||||
public abstract class KtUsefulTestCase extends TestCase {
|
||||
public static final boolean IS_UNDER_TEAMCITY = System.getenv("TEAMCITY_VERSION") != null;
|
||||
public static final String TEMP_DIR_MARKER = "unitTest_";
|
||||
private static final String TEMP_DIR_MARKER = "unitTest_";
|
||||
public static final boolean OVERWRITE_TESTDATA = Boolean.getBoolean("idea.tests.overwrite.data");
|
||||
|
||||
private static final String ORIGINAL_TEMP_DIR = FileUtil.getTempDirectory();
|
||||
@@ -99,34 +79,24 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
private Application application;
|
||||
|
||||
static {
|
||||
IdeaForkJoinWorkerThreadFactory.setupPoisonFactory();
|
||||
IdeaSystemPropertiesForParallelRunConfigurator.setProperties();
|
||||
//TODO: investigate and enable
|
||||
//IdeaForkJoinWorkerThreadFactory.setupPoisonFactory();
|
||||
Logger.setFactory(TestLoggerFactory.class);
|
||||
}
|
||||
protected static final Logger LOG = Logger.getInstance(KtUsefulTestCase.class);
|
||||
|
||||
@NotNull
|
||||
private final Disposable myTestRootDisposable = new TestDisposable();
|
||||
protected final Disposable myTestRootDisposable = new TestDisposable();
|
||||
|
||||
static Path ourPathToKeep;
|
||||
private static final String ourPathToKeep = null;
|
||||
private final List<String> myPathsToKeep = new ArrayList<>();
|
||||
|
||||
private String myTempDir;
|
||||
private File myTempDir;
|
||||
|
||||
private static final String DEFAULT_SETTINGS_EXTERNALIZED;
|
||||
private static final CodeInsightSettings defaultSettings = new CodeInsightSettings();
|
||||
static {
|
||||
// Radar #5755208: Command line Java applications need a way to launch without a Dock icon.
|
||||
System.setProperty("apple.awt.UIElement", "true");
|
||||
|
||||
try {
|
||||
Element oldS = new Element("temp");
|
||||
defaultSettings.writeExternal(oldS);
|
||||
DEFAULT_SETTINGS_EXTERNALIZED = JDOMUtil.writeElement(oldS);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
// -- KOTLIN ADDITIONAL START --
|
||||
|
||||
FlexibleTypeImpl.RUN_SLOW_ASSERTIONS = true;
|
||||
@@ -135,42 +105,6 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
// -- KOTLIN ADDITIONAL END --
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass here the exception you want to be thrown first
|
||||
* E.g.<pre>
|
||||
* {@code
|
||||
* void tearDown() {
|
||||
* try {
|
||||
* doTearDowns();
|
||||
* }
|
||||
* catch(Exception e) {
|
||||
* addSuppressedException(e);
|
||||
* }
|
||||
* finally {
|
||||
* super.tearDown();
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
*/
|
||||
protected void addSuppressedException(@NotNull Throwable e) {
|
||||
List<Throwable> list = mySuppressedExceptions;
|
||||
if (list == null) {
|
||||
mySuppressedExceptions = list = new SmartList<>();
|
||||
}
|
||||
list.add(e);
|
||||
}
|
||||
private List<Throwable> mySuppressedExceptions;
|
||||
|
||||
|
||||
public KtUsefulTestCase() {
|
||||
}
|
||||
|
||||
public KtUsefulTestCase(@NotNull String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
protected boolean shouldContainTempFiles() {
|
||||
return true;
|
||||
}
|
||||
@@ -188,17 +122,11 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
super.setUp();
|
||||
|
||||
if (shouldContainTempFiles()) {
|
||||
IdeaTestExecutionPolicy policy = IdeaTestExecutionPolicy.current();
|
||||
String testName = null;
|
||||
if (policy != null) {
|
||||
testName = policy.getPerTestTempDirName();
|
||||
}
|
||||
if (testName == null) {
|
||||
testName = FileUtil.sanitizeFileName(getTestName(true));
|
||||
}
|
||||
String testName = FileUtil.sanitizeFileName(getTestName(true));
|
||||
if (StringUtil.isEmptyOrSpaces(testName)) testName = "";
|
||||
testName = new File(testName).getName(); // in case the test name contains file separators
|
||||
myTempDir = FileUtil.createTempDirectory(TEMP_DIR_MARKER + testName, "", false).getPath();
|
||||
FileUtil.resetCanonicalTempPathCache(myTempDir);
|
||||
myTempDir = FileUtil.createTempDirectory(TEMP_DIR_MARKER, testName, false);
|
||||
FileUtil.resetCanonicalTempPathCache(myTempDir.getPath());
|
||||
}
|
||||
|
||||
boolean isStressTest = isStressTest();
|
||||
@@ -209,16 +137,6 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
|
||||
// turn off Disposer debugging for performance tests
|
||||
Disposer.setDebugMode(!isStressTest);
|
||||
|
||||
if (isIconRequired()) {
|
||||
// ensure that IconLoader will use dummy empty icon
|
||||
IconLoader.deactivate();
|
||||
//IconManager.activate();
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isIconRequired() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -227,11 +145,6 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
// don't use method references here to make stack trace reading easier
|
||||
//noinspection Convert2MethodRef
|
||||
new RunAll(
|
||||
() -> {
|
||||
if (isIconRequired()) {
|
||||
//IconManager.deactivate();
|
||||
}
|
||||
},
|
||||
() -> disposeRootDisposable(),
|
||||
() -> cleanupSwingDataStructures(),
|
||||
() -> cleanupDeleteOnExitHookList(),
|
||||
@@ -240,7 +153,7 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
if (shouldContainTempFiles()) {
|
||||
FileUtil.resetCanonicalTempPathCache(ORIGINAL_TEMP_DIR);
|
||||
if (hasTmpFilesToKeep()) {
|
||||
File[] files = new File(myTempDir).listFiles();
|
||||
File[] files = myTempDir.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
if (!shouldKeepTmpFile(file)) {
|
||||
@@ -250,14 +163,15 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
}
|
||||
}
|
||||
else {
|
||||
FileUtil.delete(new File(myTempDir));
|
||||
FileUtil.delete(myTempDir);
|
||||
}
|
||||
}
|
||||
},
|
||||
() -> waitForAppLeakingThreads(10, TimeUnit.SECONDS)
|
||||
).run(ObjectUtils.notNull(mySuppressedExceptions, Collections.emptyList()));
|
||||
() -> UIUtil.removeLeakingAppleListeners()
|
||||
).run();
|
||||
}
|
||||
finally {
|
||||
super.tearDown();
|
||||
// -- KOTLIN ADDITIONAL START --
|
||||
TestApplicationUtilKt.resetApplicationToNull(application);
|
||||
application = null;
|
||||
@@ -274,12 +188,12 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
}
|
||||
|
||||
private boolean hasTmpFilesToKeep() {
|
||||
return ourPathToKeep != null && FileUtil.isAncestor(myTempDir, ourPathToKeep.toString(), false) || !myPathsToKeep.isEmpty();
|
||||
return ourPathToKeep != null && FileUtil.isAncestor(myTempDir.getPath(), ourPathToKeep, false) || !myPathsToKeep.isEmpty();
|
||||
}
|
||||
|
||||
private boolean shouldKeepTmpFile(@NotNull File file) {
|
||||
String path = file.getPath();
|
||||
if (FileUtil.pathsEqual(path, ourPathToKeep.toString())) return true;
|
||||
if (FileUtil.pathsEqual(path, ourPathToKeep)) return true;
|
||||
for (String pathToKeep : myPathsToKeep) {
|
||||
if (FileUtil.pathsEqual(path, pathToKeep)) return true;
|
||||
}
|
||||
@@ -287,7 +201,7 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
}
|
||||
|
||||
private static final Set<String> DELETE_ON_EXIT_HOOK_DOT_FILES;
|
||||
private static final Class<?> DELETE_ON_EXIT_HOOK_CLASS;
|
||||
private static final Class DELETE_ON_EXIT_HOOK_CLASS;
|
||||
static {
|
||||
Class<?> aClass;
|
||||
try {
|
||||
@@ -323,45 +237,12 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private static void cleanupSwingDataStructures() throws Exception {
|
||||
Object manager = ReflectionUtil.getDeclaredMethod(Class.forName("javax.swing.KeyboardManager"), "getCurrentManager").invoke(null);
|
||||
Map<?, ?> componentKeyStrokeMap = ReflectionUtil.getField(manager.getClass(), manager, Hashtable.class, "componentKeyStrokeMap");
|
||||
Map componentKeyStrokeMap = ReflectionUtil.getField(manager.getClass(), manager, Hashtable.class, "componentKeyStrokeMap");
|
||||
componentKeyStrokeMap.clear();
|
||||
Map<?, ?> containerMap = ReflectionUtil.getField(manager.getClass(), manager, Hashtable.class, "containerMap");
|
||||
Map containerMap = ReflectionUtil.getField(manager.getClass(), manager, Hashtable.class, "containerMap");
|
||||
containerMap.clear();
|
||||
}
|
||||
|
||||
static void doCheckForSettingsDamage(@NotNull CodeStyleSettings oldCodeStyleSettings, @NotNull CodeStyleSettings currentCodeStyleSettings) {
|
||||
final CodeInsightSettings settings = CodeInsightSettings.getInstance();
|
||||
// don't use method references here to make stack trace reading easier
|
||||
//noinspection Convert2MethodRef
|
||||
new RunAll()
|
||||
.append(() -> {
|
||||
try {
|
||||
checkCodeInsightSettingsEqual(defaultSettings, settings);
|
||||
}
|
||||
catch (AssertionError error) {
|
||||
CodeInsightSettings clean = new CodeInsightSettings();
|
||||
for (Field field : clean.getClass().getFields()) {
|
||||
try {
|
||||
ReflectionUtil.copyFieldValue(clean, settings, field);
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
})
|
||||
.append(() -> {
|
||||
currentCodeStyleSettings.getIndentOptions(StdFileTypes.JAVA);
|
||||
try {
|
||||
checkCodeStyleSettingsEqual(oldCodeStyleSettings, currentCodeStyleSettings);
|
||||
}
|
||||
finally {
|
||||
currentCodeStyleSettings.clearCodeStyleSettings();
|
||||
}
|
||||
})
|
||||
.run();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Disposable getTestRootDisposable() {
|
||||
return myTestRootDisposable;
|
||||
@@ -371,11 +252,13 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
protected void runTest() throws Throwable {
|
||||
final Throwable[] throwables = new Throwable[1];
|
||||
|
||||
AtomicBoolean completed = new AtomicBoolean(false);
|
||||
Runnable runnable = () -> {
|
||||
try {
|
||||
TestLoggerFactory.onTestStarted();
|
||||
//TestLoggerFactory.onTestStarted();
|
||||
super.runTest();
|
||||
TestLoggerFactory.onTestFinished(true);
|
||||
completed.set(true);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
TestLoggerFactory.onTestFinished(false);
|
||||
@@ -398,6 +281,9 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
if (throwables[0] != null) {
|
||||
throw throwables[0];
|
||||
}
|
||||
if (!completed.get()) {
|
||||
throw new IllegalStateException("test didn't start");
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean shouldRunTest() {
|
||||
@@ -405,18 +291,19 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
}
|
||||
|
||||
protected void invokeTestRunnable(@NotNull Runnable runnable) throws Exception {
|
||||
if (runInDispatchThread()) {
|
||||
//IdeaTestExecutionPolicy policy = IdeaTestExecutionPolicy.current();
|
||||
//if (policy != null && !policy.runInDispatchThread()) {
|
||||
// runnable.run();
|
||||
//}
|
||||
//else {
|
||||
EdtTestUtilKt.runInEdtAndWait(() -> {
|
||||
runnable.run();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
else {
|
||||
runnable.run();
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
protected void defaultRunBare() throws Throwable {
|
||||
private void defaultRunBare() throws Throwable {
|
||||
Throwable exception = null;
|
||||
try {
|
||||
long setupStart = System.nanoTime();
|
||||
@@ -437,17 +324,11 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
logPerClassCost(teardownCost, TOTAL_TEARDOWN_COST_MILLIS);
|
||||
}
|
||||
catch (Throwable tearingDown) {
|
||||
if (exception == null) {
|
||||
exception = tearingDown;
|
||||
}
|
||||
else {
|
||||
exception = new CompoundRuntimeException(Arrays.asList(exception, tearingDown));
|
||||
}
|
||||
if (exception == null) exception = tearingDown;
|
||||
else exception = new CompoundRuntimeException(Arrays.asList(exception, tearingDown));
|
||||
}
|
||||
}
|
||||
if (exception != null) {
|
||||
throw exception;
|
||||
}
|
||||
if (exception != null) throw exception;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -487,7 +368,7 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
|
||||
if (runInDispatchThread()) {
|
||||
TestRunnerUtil.replaceIdeEventQueueSafely();
|
||||
EdtTestUtil.runInEdtAndWait(this::defaultRunBare);
|
||||
com.intellij.testFramework.EdtTestUtil.runInEdtAndWait(this::defaultRunBare);
|
||||
}
|
||||
else {
|
||||
defaultRunBare();
|
||||
@@ -495,20 +376,13 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
}
|
||||
|
||||
protected boolean runInDispatchThread() {
|
||||
IdeaTestExecutionPolicy policy = IdeaTestExecutionPolicy.current();
|
||||
if (policy != null) {
|
||||
return policy.runInDispatchThread();
|
||||
}
|
||||
//IdeaTestExecutionPolicy policy = IdeaTestExecutionPolicy.current();
|
||||
//if (policy != null) {
|
||||
// return policy.runInDispatchThread();
|
||||
//}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* If you want a more shorter name than runInEdtAndWait.
|
||||
*/
|
||||
protected void edt(@NotNull ThrowableRunnable<Throwable> runnable) {
|
||||
EdtTestUtil.runInEdtAndWait(runnable);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String toString(@NotNull Iterable<?> collection) {
|
||||
if (!collection.iterator().hasNext()) {
|
||||
@@ -641,20 +515,9 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
}
|
||||
|
||||
public static <T> void assertContainsOrdered(@NotNull Collection<? extends T> collection, @NotNull Collection<? extends T> expected) {
|
||||
PeekableIterator<T> expectedIt = new PeekableIteratorWrapper<>(expected.iterator());
|
||||
PeekableIterator<T> actualIt = new PeekableIteratorWrapper<>(collection.iterator());
|
||||
|
||||
while (actualIt.hasNext() && expectedIt.hasNext()) {
|
||||
T expectedElem = expectedIt.peek();
|
||||
T actualElem = actualIt.peek();
|
||||
if (expectedElem.equals(actualElem)) {
|
||||
expectedIt.next();
|
||||
}
|
||||
actualIt.next();
|
||||
}
|
||||
if (expectedIt.hasNext()) {
|
||||
throw new ComparisonFailure("", toString(expected), toString(collection));
|
||||
}
|
||||
ArrayList<T> copy = new ArrayList<>(collection);
|
||||
copy.retainAll(expected);
|
||||
assertOrderedEquals(toString(collection), copy, expected);
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
@@ -729,7 +592,7 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
if (collection.size() != checkers.length) {
|
||||
Assert.fail(toString(collection));
|
||||
}
|
||||
Set<Consumer<T>> checkerSet = ContainerUtil.set(checkers);
|
||||
Set<Consumer<T>> checkerSet = new HashSet<>(Arrays.asList(checkers));
|
||||
int i = 0;
|
||||
Throwable lastError = null;
|
||||
for (final T actual : collection) {
|
||||
@@ -904,7 +767,7 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
//noinspection UseOfSystemOutOrSystemErr
|
||||
System.out.println("File " + filePath + " created.");
|
||||
}
|
||||
fileText = FileUtil.loadFile(new File(filePath), StandardCharsets.UTF_8);
|
||||
fileText = FileUtil.loadFile(new File(filePath), CharsetToolkit.UTF8_CHARSET);
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
VfsTestUtil.overwriteTestData(filePath, actualText);
|
||||
@@ -921,14 +784,14 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
}
|
||||
|
||||
protected static void clearFields(@NotNull Object test) throws IllegalAccessException {
|
||||
Class<?> aClass = test.getClass();
|
||||
Class aClass = test.getClass();
|
||||
while (aClass != null) {
|
||||
clearDeclaredFields(test, aClass);
|
||||
aClass = aClass.getSuperclass();
|
||||
}
|
||||
}
|
||||
|
||||
public static void clearDeclaredFields(@NotNull Object test, @NotNull Class<?> aClass) throws IllegalAccessException {
|
||||
public static void clearDeclaredFields(@NotNull Object test, @NotNull Class aClass) throws IllegalAccessException {
|
||||
for (final Field field : aClass.getDeclaredFields()) {
|
||||
final String name = field.getDeclaringClass().getName();
|
||||
if (!name.startsWith("junit.framework.") && !name.startsWith("com.intellij.testFramework.")) {
|
||||
@@ -954,14 +817,6 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkCodeInsightSettingsEqual(@NotNull CodeInsightSettings oldSettings, @NotNull CodeInsightSettings settings) {
|
||||
if (!oldSettings.equals(settings)) {
|
||||
Element newS = new Element("temp");
|
||||
settings.writeExternal(newS);
|
||||
Assert.assertEquals("Code insight settings damaged", DEFAULT_SETTINGS_EXTERNALIZED, JDOMUtil.writeElement(newS));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPerformanceTest() {
|
||||
String testName = getName();
|
||||
String className = getClass().getSimpleName();
|
||||
@@ -988,21 +843,6 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
return name != null && (name.contains("Stress") || name.contains("Slow"));
|
||||
}
|
||||
|
||||
public static void doPostponedFormatting(@NotNull Project project) {
|
||||
DocumentUtil.writeInRunUndoTransparentAction(() -> {
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
||||
PostprocessReformattingAspect.getInstance(project).doPostponedFormatting();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that code block throw corresponding exception.
|
||||
*
|
||||
* @param exceptionCase Block annotated with some exception type
|
||||
*/
|
||||
protected void assertException(@NotNull AbstractExceptionCase<?> exceptionCase) {
|
||||
assertException(exceptionCase, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that code block throw corresponding exception with expected error msg.
|
||||
@@ -1016,42 +856,6 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
assertExceptionOccurred(true, exceptionCase, expectedErrorMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the code block throws an exception of the specified class.
|
||||
*
|
||||
* @param exceptionClass Expected exception type
|
||||
* @param runnable Block annotated with some exception type
|
||||
*/
|
||||
public static <T extends Throwable> void assertThrows(@NotNull Class<? extends Throwable> exceptionClass,
|
||||
@NotNull ThrowableRunnable<T> runnable) {
|
||||
assertThrows(exceptionClass, null, runnable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the code block throws an exception of the specified class with expected error msg.
|
||||
* If expected error message is null it will not be checked.
|
||||
*
|
||||
* @param exceptionClass Expected exception type
|
||||
* @param expectedErrorMsgPart expected error message, of any
|
||||
* @param runnable Block annotated with some exception type
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "SameParameterValue"})
|
||||
public static <T extends Throwable> void assertThrows(@NotNull Class<? extends Throwable> exceptionClass,
|
||||
@Nullable String expectedErrorMsgPart,
|
||||
@NotNull ThrowableRunnable<T> runnable) {
|
||||
assertExceptionOccurred(true, new AbstractExceptionCase() {
|
||||
@Override
|
||||
public Class<Throwable> getExpectedExceptionClass() {
|
||||
return (Class<Throwable>)exceptionClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tryClosure() throws Throwable {
|
||||
runnable.run();
|
||||
}
|
||||
}, expectedErrorMsgPart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that code block doesn't throw corresponding exception.
|
||||
*
|
||||
@@ -1074,22 +878,21 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
|
||||
private static <T extends Throwable> void assertExceptionOccurred(boolean shouldOccur,
|
||||
@NotNull AbstractExceptionCase<T> exceptionCase,
|
||||
String expectedErrorMsgPart) throws T {
|
||||
String expectedErrorMsg) throws T {
|
||||
boolean wasThrown = false;
|
||||
try {
|
||||
exceptionCase.tryClosure();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
Throwable cause = e;
|
||||
|
||||
if (shouldOccur) {
|
||||
wasThrown = true;
|
||||
assertInstanceOf(cause, exceptionCase.getExpectedExceptionClass());
|
||||
if (expectedErrorMsgPart != null) {
|
||||
assertTrue(cause.getMessage(), cause.getMessage().contains(expectedErrorMsgPart));
|
||||
final String errorMessage = exceptionCase.getAssertionErrorMessage();
|
||||
assertEquals(errorMessage, exceptionCase.getExpectedExceptionClass(), e.getClass());
|
||||
if (expectedErrorMsg != null) {
|
||||
assertEquals("Compare error messages", expectedErrorMsg, e.getMessage());
|
||||
}
|
||||
}
|
||||
else if (exceptionCase.getExpectedExceptionClass().equals(cause.getClass())) {
|
||||
else if (exceptionCase.getExpectedExceptionClass().equals(e.getClass())) {
|
||||
wasThrown = true;
|
||||
|
||||
//noinspection UseOfSystemOutOrSystemErr
|
||||
@@ -1097,7 +900,7 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
//noinspection UseOfSystemOutOrSystemErr
|
||||
e.printStackTrace(System.out);
|
||||
|
||||
fail("Exception isn't expected here. Exception message: " + cause.getMessage());
|
||||
fail("Exception isn't expected here. Exception message: " + e.getMessage());
|
||||
}
|
||||
else {
|
||||
throw e;
|
||||
@@ -1105,7 +908,7 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
}
|
||||
finally {
|
||||
if (shouldOccur && !wasThrown) {
|
||||
fail(exceptionCase.getExpectedExceptionClass().getName() + " must be thrown.");
|
||||
fail(exceptionCase.getAssertionErrorMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1134,7 +937,7 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
}
|
||||
|
||||
public static void refreshRecursively(@NotNull VirtualFile file) {
|
||||
VfsUtilCore.visitChildrenRecursively(file, new VirtualFileVisitor<Void>() {
|
||||
VfsUtilCore.visitChildrenRecursively(file, new VirtualFileVisitor() {
|
||||
@Override
|
||||
public boolean visitFile(@NotNull VirtualFile file) {
|
||||
file.getChildren();
|
||||
@@ -1144,27 +947,11 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
file.refresh(false, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static VirtualFile refreshAndFindFile(@NotNull final File file) {
|
||||
return UIUtil.invokeAndWaitIfNeeded(() -> LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file));
|
||||
}
|
||||
|
||||
public static void waitForAppLeakingThreads(long timeout, @NotNull TimeUnit timeUnit) {
|
||||
EdtTestUtil.runInEdtAndWait(() -> {
|
||||
Application app = ApplicationManager.getApplication();
|
||||
if (app != null && !app.isDisposed()) {
|
||||
FileBasedIndexImpl index = (FileBasedIndexImpl)app.getServiceIfCreated(FileBasedIndex.class);
|
||||
if (index != null) {
|
||||
index.getChangedFilesCollector().waitForVfsEventsExecuted(timeout, timeUnit);
|
||||
}
|
||||
|
||||
DocumentCommitThread commitThread = (DocumentCommitThread)app.getServiceIfCreated(DocumentCommitProcessor.class);
|
||||
if (commitThread != null) {
|
||||
commitThread.waitForAllCommits(timeout, timeUnit);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected class TestDisposable implements Disposable {
|
||||
private volatile boolean myDisposed;
|
||||
|
||||
@@ -1185,5 +972,5 @@ public abstract class KtUsefulTestCase extends TestCase {
|
||||
String testName = getTestName(false);
|
||||
return KtUsefulTestCase.this.getClass() + (StringUtil.isEmpty(testName) ? "" : ".test" + testName);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
versions.intellijSdk=193.6494.35
|
||||
versions.intellijSdk=202.5103-EAP-CANDIDATE-SNAPSHOT
|
||||
versions.androidBuildTools=r23.0.1
|
||||
versions.idea.NodeJS=181.3494.12
|
||||
versions.jar.asm-all=7.0.1
|
||||
versions.jar.guava=27.1-jre
|
||||
versions.jar.groovy-all=2.4.17
|
||||
versions.idea.NodeJS=193.6494.7
|
||||
versions.jar.asm-all=8.0.1
|
||||
versions.jar.guava=29.0-jre
|
||||
versions.jar.groovy=2.5.11
|
||||
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.streamex=0.7.2
|
||||
versions.jar.gson=2.8.6
|
||||
versions.jar.oro=2.0.8
|
||||
versions.jar.picocontainer=1.2
|
||||
versions.jar.serviceMessages=2019.1.4
|
||||
versions.jar.lz4-java=1.6.0
|
||||
versions.jar.lz4-java=1.7.1
|
||||
ignore.jar.snappy-in-java=true
|
||||
versions.gradle-api=4.5.1
|
||||
versions.shadow=5.2.0
|
||||
@@ -1,18 +1,18 @@
|
||||
versions.intellijSdk=202.3567-SNAPSHOT
|
||||
versions.intellijSdk=193.6494.35
|
||||
versions.androidBuildTools=r23.0.1
|
||||
versions.idea.NodeJS=193.6494.7
|
||||
versions.idea.NodeJS=181.3494.12
|
||||
versions.jar.asm-all=7.0.1
|
||||
versions.jar.guava=29.0-jre
|
||||
versions.jar.guava=27.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.7.2
|
||||
versions.jar.gson=2.8.6
|
||||
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.serviceMessages=2019.1.4
|
||||
versions.jar.lz4-java=1.7.1
|
||||
versions.jar.lz4-java=1.6.0
|
||||
ignore.jar.snappy-in-java=true
|
||||
versions.gradle-api=4.5.1
|
||||
versions.shadow=5.2.0
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.util
|
||||
|
||||
import com.intellij.AbstractBundle
|
||||
import com.intellij.DynamicBundle
|
||||
|
||||
abstract class AbstractKotlinBundle protected constructor(pathToBundle: String) : AbstractBundle(pathToBundle) {
|
||||
abstract class AbstractKotlinBundle protected constructor(pathToBundle: String) : DynamicBundle(pathToBundle) {
|
||||
protected fun String.withHtml(): String = "<html>$this</html>"
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* 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.util
|
||||
|
||||
import com.intellij.AbstractBundle
|
||||
|
||||
abstract class AbstractKotlinBundle protected constructor(pathToBundle: String) : AbstractBundle(pathToBundle) {
|
||||
protected fun String.withHtml(): String = "<html>$this</html>"
|
||||
}
|
||||
@@ -9,6 +9,6 @@ import com.intellij.psi.PsiMethod
|
||||
import com.intellij.util.Processor
|
||||
|
||||
// FIX ME WHEN BUNCH 193 REMOVED
|
||||
typealias StringProcessor = Processor<String>
|
||||
typealias PsiMethodProcessor = Processor<PsiMethod>
|
||||
typealias StringProcessor = Processor<in String>
|
||||
typealias PsiMethodProcessor = Processor<in PsiMethod>
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* 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.caches
|
||||
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.util.Processor
|
||||
|
||||
// FIX ME WHEN BUNCH 193 REMOVED
|
||||
typealias StringProcessor = Processor<String>
|
||||
typealias PsiMethodProcessor = Processor<PsiMethod>
|
||||
|
||||
@@ -1,83 +1,50 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
|
||||
package org.jetbrains.kotlin.idea.caches.trackers
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.SimpleModificationTracker
|
||||
import com.intellij.pom.tree.TreeAspect
|
||||
import com.intellij.psi.impl.PsiTreeChangeEventImpl
|
||||
import com.intellij.psi.util.PsiModificationTracker
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.idea.util.application.getServiceSafe
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
/**
|
||||
* Tested in OutOfBlockModificationTestGenerated
|
||||
*/
|
||||
// FIX ME WHEN BUNCH 193 REMOVED
|
||||
class KotlinCodeBlockModificationListener(
|
||||
project: Project,
|
||||
treeAspect: TreeAspect
|
||||
) : KotlinCodeBlockModificationListenerCompat(project) {
|
||||
|
||||
@Suppress("UnstableApiUsage")
|
||||
private val isLanguageTrackerEnabled = modificationTrackerImpl.isEnableLanguageTrackerCompat
|
||||
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
// When there're we no per-language trackers we had to increment global tracker first and process result afterward
|
||||
private val customIncrement = if (isLanguageTrackerEnabled) 0 else 1
|
||||
class KotlinCodeBlockModificationListener(project: Project) : KotlinCodeBlockModificationListenerCompat(project) {
|
||||
|
||||
init {
|
||||
init(
|
||||
treeAspect,
|
||||
TreeAspect.getInstance(project),
|
||||
incOCBCounter = { ktFile ->
|
||||
if (isLanguageTrackerEnabled) {
|
||||
kotlinOutOfCodeBlockTrackerImpl.incModificationCount()
|
||||
perModuleOutOfCodeBlockTrackerUpdater.onKotlinPhysicalFileOutOfBlockChange(ktFile, true)
|
||||
} else {
|
||||
perModuleOutOfCodeBlockTrackerUpdater.onKotlinPhysicalFileOutOfBlockChange(ktFile, false)
|
||||
// Increment counter and process changes in PsiModificationTracker.Listener
|
||||
modificationTrackerImpl.incCounter()
|
||||
}
|
||||
kotlinOutOfCodeBlockTrackerImpl.incModificationCount()
|
||||
perModuleOutOfCodeBlockTrackerUpdater.onKotlinPhysicalFileOutOfBlockChange(ktFile, true)
|
||||
},
|
||||
kotlinOutOfCodeBlockTrackerProducer = {
|
||||
if (isLanguageTrackerEnabled) {
|
||||
SimpleModificationTracker()
|
||||
} else {
|
||||
object : SimpleModificationTracker() {
|
||||
override fun getModificationCount(): Long {
|
||||
@Suppress("DEPRECATION")
|
||||
return modificationTrackerImpl.outOfCodeBlockModificationCount
|
||||
}
|
||||
}
|
||||
}
|
||||
SimpleModificationTracker()
|
||||
},
|
||||
psiModificationTrackerListener = {
|
||||
@Suppress("UnstableApiUsage")
|
||||
if (isLanguageTrackerEnabled) {
|
||||
val kotlinTrackerInternalIDECount =
|
||||
modificationTrackerImpl.forLanguage(KotlinLanguage.INSTANCE).modificationCount
|
||||
if (kotlinModificationTracker == kotlinTrackerInternalIDECount) {
|
||||
// Some update that we are not sure is from Kotlin language, as Kotlin language tracker wasn't changed
|
||||
kotlinOutOfCodeBlockTrackerImpl.incModificationCount()
|
||||
} else {
|
||||
kotlinModificationTracker = kotlinTrackerInternalIDECount
|
||||
}
|
||||
val kotlinTrackerInternalIDECount =
|
||||
modificationTrackerImpl.forLanguage(KotlinLanguage.INSTANCE).modificationCount
|
||||
if (kotlinModificationTracker == kotlinTrackerInternalIDECount) {
|
||||
// Some update that we are not sure is from Kotlin language, as Kotlin language tracker wasn't changed
|
||||
kotlinOutOfCodeBlockTrackerImpl.incModificationCount()
|
||||
} else {
|
||||
kotlinModificationTracker = kotlinTrackerInternalIDECount
|
||||
}
|
||||
|
||||
perModuleOutOfCodeBlockTrackerUpdater.onPsiModificationTrackerUpdate(customIncrement)
|
||||
perModuleOutOfCodeBlockTrackerUpdater.onPsiModificationTrackerUpdate()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun treeChanged(event: PsiTreeChangeEventImpl) {
|
||||
assert(isLanguageTrackerEnabled)
|
||||
super.treeChanged(event)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getInstance(project: Project): KotlinCodeBlockModificationListener =
|
||||
project.getComponent(KotlinCodeBlockModificationListener::class.java)
|
||||
fun getInstance(project: Project): KotlinCodeBlockModificationListener = project.getServiceSafe()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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.caches.trackers
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.SimpleModificationTracker
|
||||
import com.intellij.pom.tree.TreeAspect
|
||||
import com.intellij.psi.impl.PsiTreeChangeEventImpl
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
|
||||
/**
|
||||
* Tested in OutOfBlockModificationTestGenerated
|
||||
*/
|
||||
// FIX ME WHEN BUNCH 193 REMOVED
|
||||
class KotlinCodeBlockModificationListener(
|
||||
project: Project,
|
||||
treeAspect: TreeAspect
|
||||
) : KotlinCodeBlockModificationListenerCompat(project) {
|
||||
|
||||
@Suppress("UnstableApiUsage")
|
||||
private val isLanguageTrackerEnabled = modificationTrackerImpl.isEnableLanguageTrackerCompat
|
||||
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
// When there're we no per-language trackers we had to increment global tracker first and process result afterward
|
||||
private val customIncrement = if (isLanguageTrackerEnabled) 0 else 1
|
||||
|
||||
init {
|
||||
init(
|
||||
treeAspect,
|
||||
incOCBCounter = { ktFile ->
|
||||
if (isLanguageTrackerEnabled) {
|
||||
kotlinOutOfCodeBlockTrackerImpl.incModificationCount()
|
||||
perModuleOutOfCodeBlockTrackerUpdater.onKotlinPhysicalFileOutOfBlockChange(ktFile, true)
|
||||
} else {
|
||||
perModuleOutOfCodeBlockTrackerUpdater.onKotlinPhysicalFileOutOfBlockChange(ktFile, false)
|
||||
// Increment counter and process changes in PsiModificationTracker.Listener
|
||||
modificationTrackerImpl.incCounter()
|
||||
}
|
||||
},
|
||||
kotlinOutOfCodeBlockTrackerProducer = {
|
||||
if (isLanguageTrackerEnabled) {
|
||||
SimpleModificationTracker()
|
||||
} else {
|
||||
object : SimpleModificationTracker() {
|
||||
override fun getModificationCount(): Long {
|
||||
@Suppress("DEPRECATION")
|
||||
return modificationTrackerImpl.outOfCodeBlockModificationCount
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
psiModificationTrackerListener = {
|
||||
@Suppress("UnstableApiUsage")
|
||||
if (isLanguageTrackerEnabled) {
|
||||
val kotlinTrackerInternalIDECount =
|
||||
modificationTrackerImpl.forLanguage(KotlinLanguage.INSTANCE).modificationCount
|
||||
if (kotlinModificationTracker == kotlinTrackerInternalIDECount) {
|
||||
// Some update that we are not sure is from Kotlin language, as Kotlin language tracker wasn't changed
|
||||
kotlinOutOfCodeBlockTrackerImpl.incModificationCount()
|
||||
} else {
|
||||
kotlinModificationTracker = kotlinTrackerInternalIDECount
|
||||
}
|
||||
}
|
||||
|
||||
perModuleOutOfCodeBlockTrackerUpdater.onPsiModificationTrackerUpdate(customIncrement)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun treeChanged(event: PsiTreeChangeEventImpl) {
|
||||
assert(isLanguageTrackerEnabled)
|
||||
super.treeChanged(event)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getInstance(project: Project): KotlinCodeBlockModificationListener =
|
||||
project.getComponent(KotlinCodeBlockModificationListener::class.java)
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,9 @@ package org.jetbrains.kotlin.idea.highlighter
|
||||
import com.intellij.codeInsight.intention.EmptyIntentionAction
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.lang.annotation.Annotation
|
||||
import com.intellij.lang.annotation.AnnotationBuilder
|
||||
import com.intellij.lang.annotation.AnnotationHolder
|
||||
import com.intellij.lang.annotation.HighlightSeverity
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey
|
||||
import com.intellij.openapi.util.TextRange
|
||||
@@ -31,53 +32,43 @@ class AnnotationPresentationInfo(
|
||||
for (range in ranges) {
|
||||
for (diagnostic in diagnostics) {
|
||||
val fixes = fixesMap[diagnostic]
|
||||
val annotation = create(diagnostic, range, holder)
|
||||
|
||||
fixes.forEach {
|
||||
when (it) {
|
||||
is KotlinUniversalQuickFix -> annotation.registerUniversalFix(it, null, null)
|
||||
is IntentionAction -> annotation.registerFix(it)
|
||||
create(diagnostic, range, holder) { annotation ->
|
||||
fixes.forEach {
|
||||
when (it) {
|
||||
is KotlinUniversalQuickFix -> annotation.newFix(it).universal().registerFix()
|
||||
is IntentionAction -> annotation.newFix(it).registerFix()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (diagnostic.severity == Severity.WARNING) {
|
||||
annotation.problemGroup = KotlinSuppressableWarningProblemGroup(diagnostic.factory)
|
||||
if (diagnostic.severity == Severity.WARNING) {
|
||||
annotation.problemGroup(KotlinSuppressableWarningProblemGroup(diagnostic.factory))
|
||||
|
||||
if (fixes.isEmpty()) {
|
||||
// if there are no quick fixes we need to register an EmptyIntentionAction to enable 'suppress' actions
|
||||
annotation.registerFix(EmptyIntentionAction(diagnostic.factory.name))
|
||||
if (fixes.isEmpty()) {
|
||||
// if there are no quick fixes we need to register an EmptyIntentionAction to enable 'suppress' actions
|
||||
annotation.newFix(EmptyIntentionAction(diagnostic.factory.name)).registerFix()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun create(diagnostic: Diagnostic, range: TextRange, holder: AnnotationHolder): Annotation {
|
||||
val defaultMessage = nonDefaultMessage ?: getDefaultMessage(diagnostic)
|
||||
|
||||
val annotation = when (diagnostic.severity) {
|
||||
Severity.ERROR -> holder.createErrorAnnotation(range, defaultMessage)
|
||||
Severity.WARNING -> {
|
||||
if (highlightType == ProblemHighlightType.WEAK_WARNING) {
|
||||
holder.createWeakWarningAnnotation(range, defaultMessage)
|
||||
} else {
|
||||
holder.createWarningAnnotation(range, defaultMessage)
|
||||
}
|
||||
}
|
||||
Severity.INFO -> holder.createInfoAnnotation(range, defaultMessage)
|
||||
private fun create(diagnostic: Diagnostic, range: TextRange, holder: AnnotationHolder, consumer: (AnnotationBuilder) -> Unit) {
|
||||
val severity = when (diagnostic.severity) {
|
||||
Severity.ERROR -> HighlightSeverity.ERROR
|
||||
Severity.WARNING -> if (highlightType == ProblemHighlightType.WEAK_WARNING) {
|
||||
HighlightSeverity.WEAK_WARNING
|
||||
} else HighlightSeverity.WARNING
|
||||
Severity.INFO -> HighlightSeverity.WEAK_WARNING
|
||||
}
|
||||
|
||||
annotation.tooltip = getMessage(diagnostic)
|
||||
|
||||
if (highlightType != null) {
|
||||
annotation.highlightType = highlightType
|
||||
}
|
||||
|
||||
if (textAttributes != null) {
|
||||
annotation.textAttributes = textAttributes
|
||||
}
|
||||
|
||||
return annotation
|
||||
holder.newAnnotation(severity, nonDefaultMessage ?: getDefaultMessage(diagnostic))
|
||||
.range(range)
|
||||
.tooltip(getMessage(diagnostic))
|
||||
.also { builder -> highlightType?.let { builder.highlightType(it) } }
|
||||
.also { builder -> textAttributes?.let { builder.textAttributes(it) } }
|
||||
.also { consumer(it) }
|
||||
.create()
|
||||
}
|
||||
|
||||
private fun getMessage(diagnostic: Diagnostic): String {
|
||||
@@ -103,4 +94,5 @@ class AnnotationPresentationInfo(
|
||||
}
|
||||
return message
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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.highlighter
|
||||
|
||||
import com.intellij.codeInsight.intention.EmptyIntentionAction
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.lang.annotation.Annotation
|
||||
import com.intellij.lang.annotation.AnnotationHolder
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.util.containers.MultiMap
|
||||
import com.intellij.xml.util.XmlStringUtil
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
|
||||
import org.jetbrains.kotlin.idea.inspections.KotlinUniversalQuickFix
|
||||
|
||||
class AnnotationPresentationInfo(
|
||||
val ranges: List<TextRange>,
|
||||
val nonDefaultMessage: String? = null,
|
||||
val highlightType: ProblemHighlightType? = null,
|
||||
val textAttributes: TextAttributesKey? = null
|
||||
) {
|
||||
|
||||
fun processDiagnostics(holder: AnnotationHolder, diagnostics: List<Diagnostic>, fixesMap: MultiMap<Diagnostic, IntentionAction>) {
|
||||
for (range in ranges) {
|
||||
for (diagnostic in diagnostics) {
|
||||
val fixes = fixesMap[diagnostic]
|
||||
val annotation = create(diagnostic, range, holder)
|
||||
|
||||
fixes.forEach {
|
||||
when (it) {
|
||||
is KotlinUniversalQuickFix -> annotation.registerUniversalFix(it, null, null)
|
||||
is IntentionAction -> annotation.registerFix(it)
|
||||
}
|
||||
}
|
||||
|
||||
if (diagnostic.severity == Severity.WARNING) {
|
||||
annotation.problemGroup = KotlinSuppressableWarningProblemGroup(diagnostic.factory)
|
||||
|
||||
if (fixes.isEmpty()) {
|
||||
// if there are no quick fixes we need to register an EmptyIntentionAction to enable 'suppress' actions
|
||||
annotation.registerFix(EmptyIntentionAction(diagnostic.factory.name))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun create(diagnostic: Diagnostic, range: TextRange, holder: AnnotationHolder): Annotation {
|
||||
val defaultMessage = nonDefaultMessage ?: getDefaultMessage(diagnostic)
|
||||
|
||||
val annotation = when (diagnostic.severity) {
|
||||
Severity.ERROR -> holder.createErrorAnnotation(range, defaultMessage)
|
||||
Severity.WARNING -> {
|
||||
if (highlightType == ProblemHighlightType.WEAK_WARNING) {
|
||||
holder.createWeakWarningAnnotation(range, defaultMessage)
|
||||
} else {
|
||||
holder.createWarningAnnotation(range, defaultMessage)
|
||||
}
|
||||
}
|
||||
Severity.INFO -> holder.createInfoAnnotation(range, defaultMessage)
|
||||
}
|
||||
|
||||
annotation.tooltip = getMessage(diagnostic)
|
||||
|
||||
if (highlightType != null) {
|
||||
annotation.highlightType = highlightType
|
||||
}
|
||||
|
||||
if (textAttributes != null) {
|
||||
annotation.textAttributes = textAttributes
|
||||
}
|
||||
|
||||
return annotation
|
||||
}
|
||||
|
||||
private fun getMessage(diagnostic: Diagnostic): String {
|
||||
var message = IdeErrorMessages.render(diagnostic)
|
||||
if (ApplicationManager.getApplication().isInternal || ApplicationManager.getApplication().isUnitTestMode) {
|
||||
val factoryName = diagnostic.factory.name
|
||||
message = if (message.startsWith("<html>")) {
|
||||
"<html>[$factoryName] ${message.substring("<html>".length)}"
|
||||
} else {
|
||||
"[$factoryName] $message"
|
||||
}
|
||||
}
|
||||
if (!message.startsWith("<html>")) {
|
||||
message = "<html><body>${XmlStringUtil.escapeString(message)}</body></html>"
|
||||
}
|
||||
return message
|
||||
}
|
||||
|
||||
private fun getDefaultMessage(diagnostic: Diagnostic): String {
|
||||
val message = DefaultErrorMessages.render(diagnostic)
|
||||
if (ApplicationManager.getApplication().isInternal || ApplicationManager.getApplication().isUnitTestMode) {
|
||||
return "[${diagnostic.factory.name}] $message"
|
||||
}
|
||||
return message
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ public class ModuleHighlightUtil2 {
|
||||
}
|
||||
}
|
||||
else if (root.getFileSystem() instanceof JarFileSystem && "jar".equalsIgnoreCase(root.getExtension())) {
|
||||
return LightJavaModule.getModule(PsiManager.getInstance(project), root);
|
||||
return LightJavaModule.findModule(PsiManager.getInstance(project), root);
|
||||
}
|
||||
}
|
||||
else if ((root = index.getSourceRootForFile(file)) != null) {
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
@@ -6,12 +6,9 @@
|
||||
package org.jetbrains.kotlin.idea.search.ideaExtensions
|
||||
|
||||
import com.intellij.ide.highlighter.JavaFileType
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.impl.cache.CacheManager
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.search.ScopeOptimizer
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.psi.search.UsageSearchContext
|
||||
import com.intellij.psi.search.*
|
||||
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.search.excludeFileTypes
|
||||
@@ -31,19 +28,22 @@ class KotlinReferenceScopeOptimizer : ScopeOptimizer {
|
||||
val file = callable.parent as KtFile
|
||||
val packageName = file.packageFqName.takeUnless { it.isRoot } ?: return null
|
||||
val project = file.project
|
||||
val cacheManager = CacheManager.SERVICE.getInstance(project)
|
||||
val searchHelper = PsiSearchHelper.getInstance(project)
|
||||
|
||||
val kotlinScope = GlobalSearchScope.getScopeRestrictedByFileTypes(useScope, KotlinFileType.INSTANCE)
|
||||
val javaScope = GlobalSearchScope.getScopeRestrictedByFileTypes(useScope, JavaFileType.INSTANCE)
|
||||
val restScope = useScope.excludeFileTypes(KotlinFileType.INSTANCE, JavaFileType.INSTANCE) as GlobalSearchScope
|
||||
|
||||
//TODO: use all components of package name?
|
||||
val shortPackageName = packageName.shortName().identifier
|
||||
val kotlinFiles = cacheManager.getVirtualFilesWithWord(shortPackageName, UsageSearchContext.IN_CODE, kotlinScope, true)
|
||||
val kotlinFiles = mutableListOf<VirtualFile>()
|
||||
searchHelper.processCandidateFilesForText(kotlinScope, UsageSearchContext.IN_CODE, true, packageName.asString()) {
|
||||
kotlinFiles.add(it)
|
||||
}
|
||||
|
||||
val javaFacadeName = file.javaFileFacadeFqName.shortName().identifier
|
||||
val javaFiles = cacheManager.getVirtualFilesWithWord(javaFacadeName, UsageSearchContext.IN_CODE, javaScope, true)
|
||||
val javaFiles = mutableListOf<VirtualFile>()
|
||||
searchHelper.processCandidateFilesForText(javaScope, UsageSearchContext.IN_CODE, true, file.javaFileFacadeFqName.asString()) {
|
||||
javaFiles.add(it)
|
||||
}
|
||||
|
||||
return GlobalSearchScope.filesScope(project, (kotlinFiles + javaFiles).asList()).uniteWith(restScope)
|
||||
return GlobalSearchScope.filesScope(project, kotlinFiles + javaFiles).uniteWith(restScope)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.search.ideaExtensions
|
||||
|
||||
import com.intellij.ide.highlighter.JavaFileType
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.impl.cache.CacheManager
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.search.ScopeOptimizer
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.psi.search.UsageSearchContext
|
||||
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.search.excludeFileTypes
|
||||
import org.jetbrains.kotlin.psi.KtCallableDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
class KotlinReferenceScopeOptimizer : ScopeOptimizer {
|
||||
override fun getRestrictedUseScope(element: PsiElement): SearchScope? {
|
||||
if (element is KtCallableDeclaration && element.parent is KtFile) {
|
||||
return getRestrictedScopeForTopLevelCallable(element)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun getRestrictedScopeForTopLevelCallable(callable: KtCallableDeclaration): GlobalSearchScope? {
|
||||
val useScope = callable.useScope as? GlobalSearchScope ?: return null
|
||||
val file = callable.parent as KtFile
|
||||
val packageName = file.packageFqName.takeUnless { it.isRoot } ?: return null
|
||||
val project = file.project
|
||||
val cacheManager = CacheManager.SERVICE.getInstance(project)
|
||||
|
||||
val kotlinScope = GlobalSearchScope.getScopeRestrictedByFileTypes(useScope, KotlinFileType.INSTANCE)
|
||||
val javaScope = GlobalSearchScope.getScopeRestrictedByFileTypes(useScope, JavaFileType.INSTANCE)
|
||||
val restScope = useScope.excludeFileTypes(KotlinFileType.INSTANCE, JavaFileType.INSTANCE) as GlobalSearchScope
|
||||
|
||||
//TODO: use all components of package name?
|
||||
val shortPackageName = packageName.shortName().identifier
|
||||
val kotlinFiles = cacheManager.getVirtualFilesWithWord(shortPackageName, UsageSearchContext.IN_CODE, kotlinScope, true)
|
||||
|
||||
val javaFacadeName = file.javaFileFacadeFqName.shortName().identifier
|
||||
val javaFiles = cacheManager.getVirtualFilesWithWord(javaFacadeName, UsageSearchContext.IN_CODE, javaScope, true)
|
||||
|
||||
return GlobalSearchScope.filesScope(project, (kotlinFiles + javaFiles).asList()).uniteWith(restScope)
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,8 @@ package org.jetbrains.kotlin.idea.util.application
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
import com.intellij.openapi.components.ComponentManager
|
||||
import com.intellij.openapi.progress.impl.CancellationCheck
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.annotations.Nls
|
||||
|
||||
fun <T> runReadAction(action: () -> T): T {
|
||||
return ApplicationManager.getApplication().runReadAction<T>(action)
|
||||
@@ -30,22 +30,22 @@ fun <T> runWriteAction(action: () -> T): T {
|
||||
return ApplicationManager.getApplication().runWriteAction<T>(action)
|
||||
}
|
||||
|
||||
fun Project.executeWriteCommand(@Nls name: String, command: () -> Unit) {
|
||||
fun Project.executeWriteCommand(name: String, command: () -> Unit) {
|
||||
CommandProcessor.getInstance().executeCommand(this, { runWriteAction(command) }, name, null)
|
||||
}
|
||||
|
||||
fun <T> Project.executeWriteCommand(@Nls name: String, groupId: Any? = null, command: () -> T): T {
|
||||
fun <T> Project.executeWriteCommand(name: String, groupId: Any? = null, command: () -> T): T {
|
||||
return executeCommand<T>(name, groupId) { runWriteAction(command) }
|
||||
}
|
||||
|
||||
fun <T> Project.executeCommand(@Nls name: String, groupId: Any? = null, command: () -> T): T {
|
||||
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()
|
||||
fun <T> runWithCancellationCheck(block: () -> T): T = CancellationCheck.runWithCancellationCheck(block)
|
||||
|
||||
inline fun executeOnPooledThread(crossinline action: () -> Unit) =
|
||||
ApplicationManager.getApplication().executeOnPooledThread { action() }
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.ComponentManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.annotations.Nls
|
||||
|
||||
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(@Nls name: String, command: () -> Unit) {
|
||||
CommandProcessor.getInstance().executeCommand(this, { runWriteAction(command) }, name, null)
|
||||
}
|
||||
|
||||
fun <T> Project.executeWriteCommand(@Nls name: String, groupId: Any? = null, command: () -> T): T {
|
||||
return executeCommand<T>(name, groupId) { runWriteAction(command) }
|
||||
}
|
||||
|
||||
fun <T> Project.executeCommand(@Nls 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> ComponentManager.getServiceSafe(): T =
|
||||
this.getService(T::class.java) ?: error("Unable to locate service ${T::class.java.name}")
|
||||
@@ -5,9 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.completion.test.handlers
|
||||
|
||||
import com.intellij.codeInsight.lookup.LookupFocusDegree
|
||||
import com.intellij.codeInsight.lookup.impl.LookupImpl
|
||||
|
||||
// FIX ME WHEN BUNCH 193 REMOVED
|
||||
fun LookupImpl.setFocusedFocusDegree() {
|
||||
focusDegree = LookupImpl.FocusDegree.FOCUSED
|
||||
this.lookupFocusDegree = LookupFocusDegree.FOCUSED
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* 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.completion.test.handlers
|
||||
|
||||
import com.intellij.codeInsight.lookup.impl.LookupImpl
|
||||
|
||||
// FIX ME WHEN BUNCH 193 REMOVED
|
||||
fun LookupImpl.setFocusedFocusDegree() {
|
||||
focusDegree = LookupImpl.FocusDegree.FOCUSED
|
||||
}
|
||||
@@ -45,7 +45,7 @@ class ShowKotlinGradleDslLogs : IntentionAction, AnAction(), DumbAware {
|
||||
RevealFileAction.openDirectory(logsDir)
|
||||
} else {
|
||||
val parent = WindowManager.getInstance().getStatusBar(project)?.component
|
||||
?: WindowManager.getInstance().findVisibleFrame().rootPane
|
||||
?: WindowManager.getInstance().findVisibleFrame()?.rootPane
|
||||
JBPopupFactory.getInstance()
|
||||
.createHtmlTextBalloonBuilder(
|
||||
KotlinIdeaGradleBundle.message(
|
||||
|
||||
@@ -13,8 +13,8 @@ import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExten
|
||||
|
||||
// FIX ME WHEN BUNCH 193 REMOVED
|
||||
abstract class AbstractProjectResolverExtensionCompat : AbstractProjectResolverExtension() {
|
||||
override fun createModule(gradleModule: IdeaModule, projectDataNode: DataNode<ProjectData>): DataNode<ModuleData> {
|
||||
return super.createModule(gradleModule, projectDataNode).also {
|
||||
override fun createModule(gradleModule: IdeaModule, projectDataNode: DataNode<ProjectData>): DataNode<ModuleData>? {
|
||||
return super.createModule(gradleModule, projectDataNode)?.also {
|
||||
initializeModuleNode(gradleModule, it, projectDataNode)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.configuration
|
||||
|
||||
import com.intellij.openapi.externalSystem.model.DataNode
|
||||
import com.intellij.openapi.externalSystem.model.project.ModuleData
|
||||
import com.intellij.openapi.externalSystem.model.project.ProjectData
|
||||
import org.gradle.tooling.model.idea.IdeaModule
|
||||
import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension
|
||||
|
||||
// FIX ME WHEN BUNCH 193 REMOVED
|
||||
abstract class AbstractProjectResolverExtensionCompat : AbstractProjectResolverExtension() {
|
||||
override fun createModule(gradleModule: IdeaModule, projectDataNode: DataNode<ProjectData>): DataNode<ModuleData> {
|
||||
return super.createModule(gradleModule, projectDataNode).also {
|
||||
initializeModuleNode(gradleModule, it, projectDataNode)
|
||||
}
|
||||
}
|
||||
|
||||
// Inline after class remove
|
||||
abstract fun initializeModuleNode(
|
||||
gradleModule: IdeaModule,
|
||||
moduleDataNode: DataNode<ModuleData>,
|
||||
projectDataNode: DataNode<ProjectData>,
|
||||
)
|
||||
}
|
||||
@@ -5,7 +5,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.scripting.gradle
|
||||
|
||||
import com.intellij.openapi.externalSystem.service.project.autoimport.AsyncFileChangeListenerBase
|
||||
import com.intellij.openapi.externalSystem.autoimport.AsyncFileChangeListenerBase
|
||||
import com.intellij.openapi.vfs.LocalFileSystem
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent
|
||||
@@ -17,19 +18,27 @@ fun addVfsListener(
|
||||
) {
|
||||
VirtualFileManager.getInstance().addAsyncFileListener(
|
||||
object : AsyncFileChangeListenerBase() {
|
||||
val changedFiles = mutableListOf<String>()
|
||||
|
||||
override fun init() {
|
||||
changedFiles.clear()
|
||||
}
|
||||
|
||||
override fun isRelevant(path: String): Boolean {
|
||||
return buildRootsManager.maybeAffectedGradleProjectFile(path)
|
||||
}
|
||||
|
||||
override fun updateFile(file: VirtualFile, event: VFileEvent) {
|
||||
watcher.fileChanged(event.path, file.timeStamp)
|
||||
changedFiles.add(event.path)
|
||||
}
|
||||
|
||||
// do nothing
|
||||
override fun prepareFileDeletion(file: VirtualFile) {}
|
||||
override fun apply() {}
|
||||
override fun reset() {}
|
||||
|
||||
override fun apply() {
|
||||
changedFiles.forEach {
|
||||
LocalFileSystem.getInstance().findFileByPath(it)?.let { f ->
|
||||
watcher.fileChanged(f.path, f.timeStamp)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
watcher.project
|
||||
)
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import com.intellij.openapi.externalSystem.service.project.autoimport.AsyncFileChangeListenerBase
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent
|
||||
import org.jetbrains.kotlin.idea.scripting.gradle.roots.GradleBuildRootsManager
|
||||
|
||||
fun addVfsListener(
|
||||
watcher: GradleScriptListener,
|
||||
buildRootsManager: GradleBuildRootsManager
|
||||
) {
|
||||
VirtualFileManager.getInstance().addAsyncFileListener(
|
||||
object : AsyncFileChangeListenerBase() {
|
||||
override fun isRelevant(path: String): Boolean {
|
||||
return buildRootsManager.maybeAffectedGradleProjectFile(path)
|
||||
}
|
||||
|
||||
override fun updateFile(file: VirtualFile, event: VFileEvent) {
|
||||
watcher.fileChanged(event.path, file.timeStamp)
|
||||
}
|
||||
|
||||
// do nothing
|
||||
override fun prepareFileDeletion(file: VirtualFile) {}
|
||||
override fun apply() {}
|
||||
override fun reset() {}
|
||||
|
||||
},
|
||||
watcher.project
|
||||
)
|
||||
}
|
||||
@@ -7,113 +7,100 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.scripting.gradle
|
||||
|
||||
import com.intellij.notification.*
|
||||
import com.intellij.diff.util.DiffUtil
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.testFramework.LightVirtualFileBase
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.KotlinIcons
|
||||
import org.jetbrains.kotlin.idea.KotlinIdeaGradleBundle
|
||||
import org.jetbrains.kotlin.psi.UserDataProperty
|
||||
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings
|
||||
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
|
||||
import org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModelResolver
|
||||
import org.jetbrains.kotlin.idea.scripting.gradle.roots.GradleBuildRootsManager
|
||||
import org.jetbrains.plugins.gradle.service.project.GradlePartialResolverPolicy
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants
|
||||
|
||||
fun runPartialGradleImport(project: Project) {
|
||||
getGradleProjectSettings(project).forEach {
|
||||
getGradleProjectSettings(project).forEach { gradleProjectSettings ->
|
||||
ExternalSystemUtil.refreshProject(
|
||||
it.externalProjectPath,
|
||||
gradleProjectSettings.externalProjectPath,
|
||||
ImportSpecBuilder(project, GradleConstants.SYSTEM_ID)
|
||||
.build()
|
||||
.projectResolverPolicy(
|
||||
GradlePartialResolverPolicy { it is KotlinDslScriptModelResolver }
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun getMissingConfigurationNotificationText() = KotlinIdeaGradleBundle.message("script.configurations.will.be.available.after.import")
|
||||
fun getMissingConfigurationActionText() = KotlinIdeaGradleBundle.message("action.label.import.project")
|
||||
fun getMissingConfigurationNotificationText() = KotlinIdeaGradleBundle.message("script.configurations.will.be.available.after.load.changes")
|
||||
fun getMissingConfigurationActionText() = KotlinIdeaGradleBundle.message("action.text.load.script.configurations")
|
||||
|
||||
fun autoReloadScriptConfigurations(project: Project): Boolean {
|
||||
val gradleSettings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID)
|
||||
val projectSettings = gradleSettings.getLinkedProjectsSettings()
|
||||
.filterIsInstance<GradleProjectSettings>()
|
||||
.firstOrNull()
|
||||
if (projectSettings != null) {
|
||||
return projectSettings.isUseAutoImport
|
||||
return GradleScriptDefinitionsContributor.getDefinitions(project).any {
|
||||
KotlinScriptingSettings.getInstance(project).autoReloadConfigurations(it)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private const val kotlinDslNotificationGroupId = "Gradle Kotlin DSL Scripts"
|
||||
private var Project.notificationPanel: ScriptConfigurationChangedNotification?
|
||||
by UserDataProperty<Project, ScriptConfigurationChangedNotification>(Key.create("load.script.configuration.panel"))
|
||||
|
||||
fun scriptConfigurationsNeedToBeUpdated(project: Project) {
|
||||
if (autoReloadScriptConfigurations(project)) {
|
||||
// import should be run automatically by Gradle plugin
|
||||
return
|
||||
runPartialGradleImport(project)
|
||||
} else {
|
||||
// notification is shown in LoadConfigurationAction
|
||||
}
|
||||
|
||||
val existingPanel = project.notificationPanel
|
||||
if (existingPanel != null) {
|
||||
return
|
||||
}
|
||||
|
||||
val notificationGroup = NotificationGroup.findRegisteredGroup(kotlinDslNotificationGroupId)
|
||||
if (notificationGroup == null) {
|
||||
NotificationsConfiguration.getNotificationsConfiguration().register(
|
||||
kotlinDslNotificationGroupId, NotificationDisplayType.STICKY_BALLOON, false
|
||||
)
|
||||
}
|
||||
|
||||
val notification = ScriptConfigurationChangedNotification(project)
|
||||
project.notificationPanel = notification
|
||||
notification.notify(project)
|
||||
}
|
||||
|
||||
fun scriptConfigurationsAreUpToDate(project: Project): Boolean {
|
||||
if (project.notificationPanel == null) return false
|
||||
project.notificationPanel?.expire()
|
||||
return true
|
||||
}
|
||||
fun scriptConfigurationsAreUpToDate(project: Project): Boolean = true
|
||||
|
||||
private class ScriptConfigurationChangedNotification(val project: Project) :
|
||||
Notification(
|
||||
kotlinDslNotificationGroupId,
|
||||
KotlinIcons.LOAD_SCRIPT_CONFIGURATION,
|
||||
KotlinIdeaGradleBundle.message("notification.title.script.configuration.has.been.changed"),
|
||||
null,
|
||||
KotlinIdeaGradleBundle.message("notification.text.script.configuration.has.been.changed"),
|
||||
NotificationType.INFORMATION,
|
||||
null
|
||||
) {
|
||||
|
||||
init {
|
||||
addAction(LoadConfigurationAction())
|
||||
addAction(NotificationAction.createSimple(KotlinIdeaGradleBundle.message("action.label.enable.auto.import")) {
|
||||
val gradleSettings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID)
|
||||
val projectSettings = gradleSettings.getLinkedProjectsSettings()
|
||||
.filterIsInstance<GradleProjectSettings>()
|
||||
.firstOrNull()
|
||||
if (projectSettings != null) {
|
||||
projectSettings.isUseAutoImport = true
|
||||
}
|
||||
runPartialGradleImport(project)
|
||||
})
|
||||
class LoadConfigurationAction : AnAction(
|
||||
KotlinIdeaGradleBundle.message("action.text.load.script.configurations"),
|
||||
KotlinIdeaGradleBundle.message("action.description.load.script.configurations"),
|
||||
KotlinIcons.LOAD_SCRIPT_CONFIGURATION
|
||||
) {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.project ?: return
|
||||
runPartialGradleImport(project)
|
||||
}
|
||||
|
||||
override fun expire() {
|
||||
super.expire()
|
||||
|
||||
project.notificationPanel = null
|
||||
override fun update(e: AnActionEvent) {
|
||||
ensureValidActionVisibility(e)
|
||||
}
|
||||
|
||||
private class LoadConfigurationAction : AnAction(KotlinIdeaGradleBundle.message("action.label.import.project")) {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.project ?: return
|
||||
runPartialGradleImport(project)
|
||||
private fun ensureValidActionVisibility(e: AnActionEvent) {
|
||||
val editor = e.getData(CommonDataKeys.EDITOR) ?: return
|
||||
|
||||
e.presentation.isVisible = getNotificationVisibility(editor)
|
||||
}
|
||||
|
||||
private fun getNotificationVisibility(editor: Editor): Boolean {
|
||||
if (DiffUtil.isDiffEditor(editor)) {
|
||||
return false
|
||||
}
|
||||
|
||||
val project = editor.project ?: return false
|
||||
val file = getKotlinScriptFile(editor) ?: return false
|
||||
|
||||
if (autoReloadScriptConfigurations(project)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return GradleBuildRootsManager.getInstance(project).isConfigurationOutOfDate(file)
|
||||
}
|
||||
|
||||
private fun getKotlinScriptFile(editor: Editor): VirtualFile? {
|
||||
return FileDocumentManager.getInstance()
|
||||
.getFile(editor.document)
|
||||
?.takeIf {
|
||||
it !is LightVirtualFileBase
|
||||
&& it.isValid
|
||||
&& it.fileType != KotlinFileType.INSTANCE
|
||||
&& isGradleKotlinScript(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:Suppress("UnstableApiUsage")
|
||||
|
||||
package org.jetbrains.kotlin.idea.scripting.gradle
|
||||
|
||||
import com.intellij.notification.*
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Key
|
||||
import org.jetbrains.kotlin.idea.KotlinIcons
|
||||
import org.jetbrains.kotlin.idea.KotlinIdeaGradleBundle
|
||||
import org.jetbrains.kotlin.psi.UserDataProperty
|
||||
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants
|
||||
|
||||
fun runPartialGradleImport(project: Project) {
|
||||
getGradleProjectSettings(project).forEach {
|
||||
ExternalSystemUtil.refreshProject(
|
||||
it.externalProjectPath,
|
||||
ImportSpecBuilder(project, GradleConstants.SYSTEM_ID)
|
||||
.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun getMissingConfigurationNotificationText() = KotlinIdeaGradleBundle.message("script.configurations.will.be.available.after.import")
|
||||
fun getMissingConfigurationActionText() = KotlinIdeaGradleBundle.message("action.label.import.project")
|
||||
|
||||
fun autoReloadScriptConfigurations(project: Project): Boolean {
|
||||
val gradleSettings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID)
|
||||
val projectSettings = gradleSettings.getLinkedProjectsSettings()
|
||||
.filterIsInstance<GradleProjectSettings>()
|
||||
.firstOrNull()
|
||||
if (projectSettings != null) {
|
||||
return projectSettings.isUseAutoImport
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private const val kotlinDslNotificationGroupId = "Gradle Kotlin DSL Scripts"
|
||||
private var Project.notificationPanel: ScriptConfigurationChangedNotification?
|
||||
by UserDataProperty<Project, ScriptConfigurationChangedNotification>(Key.create("load.script.configuration.panel"))
|
||||
|
||||
fun scriptConfigurationsNeedToBeUpdated(project: Project) {
|
||||
if (autoReloadScriptConfigurations(project)) {
|
||||
// import should be run automatically by Gradle plugin
|
||||
return
|
||||
}
|
||||
|
||||
val existingPanel = project.notificationPanel
|
||||
if (existingPanel != null) {
|
||||
return
|
||||
}
|
||||
|
||||
val notificationGroup = NotificationGroup.findRegisteredGroup(kotlinDslNotificationGroupId)
|
||||
if (notificationGroup == null) {
|
||||
NotificationsConfiguration.getNotificationsConfiguration().register(
|
||||
kotlinDslNotificationGroupId, NotificationDisplayType.STICKY_BALLOON, false
|
||||
)
|
||||
}
|
||||
|
||||
val notification = ScriptConfigurationChangedNotification(project)
|
||||
project.notificationPanel = notification
|
||||
notification.notify(project)
|
||||
}
|
||||
|
||||
fun scriptConfigurationsAreUpToDate(project: Project): Boolean {
|
||||
if (project.notificationPanel == null) return false
|
||||
project.notificationPanel?.expire()
|
||||
return true
|
||||
}
|
||||
|
||||
private class ScriptConfigurationChangedNotification(val project: Project) :
|
||||
Notification(
|
||||
kotlinDslNotificationGroupId,
|
||||
KotlinIcons.LOAD_SCRIPT_CONFIGURATION,
|
||||
KotlinIdeaGradleBundle.message("notification.title.script.configuration.has.been.changed"),
|
||||
null,
|
||||
KotlinIdeaGradleBundle.message("notification.text.script.configuration.has.been.changed"),
|
||||
NotificationType.INFORMATION,
|
||||
null
|
||||
) {
|
||||
|
||||
init {
|
||||
addAction(LoadConfigurationAction())
|
||||
addAction(NotificationAction.createSimple(KotlinIdeaGradleBundle.message("action.label.enable.auto.import")) {
|
||||
val gradleSettings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID)
|
||||
val projectSettings = gradleSettings.getLinkedProjectsSettings()
|
||||
.filterIsInstance<GradleProjectSettings>()
|
||||
.firstOrNull()
|
||||
if (projectSettings != null) {
|
||||
projectSettings.isUseAutoImport = true
|
||||
}
|
||||
runPartialGradleImport(project)
|
||||
})
|
||||
}
|
||||
|
||||
override fun expire() {
|
||||
super.expire()
|
||||
|
||||
project.notificationPanel = null
|
||||
}
|
||||
|
||||
private class LoadConfigurationAction : AnAction(KotlinIdeaGradleBundle.message("action.label.import.project")) {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.project ?: return
|
||||
runPartialGradleImport(project)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||
import kotlin.script.experimental.api.*
|
||||
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||
import kotlin.script.experimental.location.ScriptExpectedLocation
|
||||
|
||||
class GradleKotlinScriptDefinitionWrapper(
|
||||
hostConfiguration: ScriptingHostConfiguration,
|
||||
@@ -25,6 +26,5 @@ class GradleKotlinScriptDefinitionWrapper(
|
||||
}
|
||||
}
|
||||
|
||||
override val canAutoReloadScriptConfigurationsBeSwitchedOff = !kotlinDslScriptsModelImportSupported(gradleVersion)
|
||||
override val canDefinitionBeSwitchedOff: Boolean = false
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import org.jetbrains.kotlin.scripting.definitions.ScriptCompilationConfigurationFromDefinition
|
||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||
import kotlin.script.experimental.api.*
|
||||
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||
|
||||
class GradleKotlinScriptDefinitionWrapper(
|
||||
hostConfiguration: ScriptingHostConfiguration,
|
||||
legacyDefinition: KotlinScriptDefinitionFromAnnotatedTemplate,
|
||||
gradleVersion: String,
|
||||
) : ScriptDefinition.FromLegacy(hostConfiguration, legacyDefinition) {
|
||||
override val compilationConfiguration by lazy {
|
||||
ScriptCompilationConfigurationFromDefinition(
|
||||
hostConfiguration,
|
||||
legacyDefinition
|
||||
).with {
|
||||
ScriptCompilationConfiguration.ide.acceptedLocations.put(listOf(ScriptAcceptedLocation.Project))
|
||||
}
|
||||
}
|
||||
|
||||
override val canAutoReloadScriptConfigurationsBeSwitchedOff = !kotlinDslScriptsModelImportSupported(gradleVersion)
|
||||
override val canDefinitionBeSwitchedOff: Boolean = false
|
||||
}
|
||||
@@ -5,16 +5,16 @@
|
||||
|
||||
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.Build
|
||||
import org.jetbrains.plugins.gradle.model.ClassSetImportModelProvider
|
||||
import org.jetbrains.plugins.gradle.model.ProjectImportModelProvider
|
||||
import org.jetbrains.kotlin.gradle.KotlinDslScriptAdditionalTask
|
||||
import org.jetbrains.kotlin.gradle.KotlinDslScriptModelProvider
|
||||
import org.gradle.tooling.model.kotlin.dsl.KotlinDslScriptsModel
|
||||
import org.jetbrains.kotlin.idea.scripting.gradle.kotlinDslScriptsModelImportSupported
|
||||
import org.jetbrains.plugins.gradle.service.project.ModifiableGradleProjectModel
|
||||
import org.jetbrains.plugins.gradle.service.project.ProjectModelContributor
|
||||
import org.jetbrains.plugins.gradle.service.project.ProjectResolverContext
|
||||
import org.jetbrains.plugins.gradle.service.project.ToolingModelsProvider
|
||||
|
||||
class KotlinDslScriptModelResolver : KotlinDslScriptModelResolverCommon() {
|
||||
override fun requiresTaskRunning() = true
|
||||
@@ -27,27 +27,23 @@ class KotlinDslScriptModelResolver : KotlinDslScriptModelResolverCommon() {
|
||||
setOf(KotlinDslScriptAdditionalTask::class.java)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun populateProjectExtraModels(gradleProject: IdeaProject, ideProject: DataNode<ProjectData>) {
|
||||
super.populateProjectExtraModels(gradleProject, ideProject)
|
||||
|
||||
if (kotlinDslScriptsModelImportSupported(resolverCtx.projectGradleVersion)) {
|
||||
populateBuildModels(resolverCtx.models.mainBuild, ideProject)
|
||||
|
||||
resolverCtx.models.includedBuilds.forEach { includedRoot ->
|
||||
populateBuildModels(includedRoot, ideProject)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun populateBuildModels(
|
||||
root: Build,
|
||||
ideProject: DataNode<ProjectData>
|
||||
@Suppress("UnstableApiUsage")
|
||||
class KotlinDslScriptModelContributor : ProjectModelContributor {
|
||||
override fun accept(
|
||||
projectModelBuilder: ModifiableGradleProjectModel,
|
||||
toolingModelsProvider: ToolingModelsProvider,
|
||||
resolverContext: ProjectResolverContext
|
||||
) {
|
||||
root.projects.forEach {
|
||||
if (it.projectIdentifier.projectPath == ":") {
|
||||
resolverCtx.models.getModel(it, KotlinDslScriptsModel::class.java)?.let { model ->
|
||||
processScriptModel(resolverCtx, model, it.projectIdentifier.projectPath)
|
||||
if (!kotlinDslScriptsModelImportSupported(resolverContext.projectGradleVersion)) return
|
||||
|
||||
toolingModelsProvider.projects().forEach {
|
||||
val projectIdentifier = it.projectIdentifier.projectPath
|
||||
if (projectIdentifier == ":") {
|
||||
val model = toolingModelsProvider.getProjectModel(it, KotlinDslScriptsModel::class.java)
|
||||
if (model != null) {
|
||||
processScriptModel(resolverContext, model, projectIdentifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.Build
|
||||
import org.jetbrains.plugins.gradle.model.ClassSetImportModelProvider
|
||||
import org.jetbrains.plugins.gradle.model.ProjectImportModelProvider
|
||||
|
||||
class KotlinDslScriptModelResolver : KotlinDslScriptModelResolverCommon() {
|
||||
override fun requiresTaskRunning() = true
|
||||
|
||||
override fun getModelProvider() = KotlinDslScriptModelProvider()
|
||||
|
||||
override fun getProjectsLoadedModelProvider(): ProjectImportModelProvider? {
|
||||
return ClassSetImportModelProvider(
|
||||
emptySet(),
|
||||
setOf(KotlinDslScriptAdditionalTask::class.java)
|
||||
)
|
||||
}
|
||||
|
||||
override fun populateProjectExtraModels(gradleProject: IdeaProject, ideProject: DataNode<ProjectData>) {
|
||||
super.populateProjectExtraModels(gradleProject, ideProject)
|
||||
|
||||
if (kotlinDslScriptsModelImportSupported(resolverCtx.projectGradleVersion)) {
|
||||
populateBuildModels(resolverCtx.models.mainBuild, ideProject)
|
||||
|
||||
resolverCtx.models.includedBuilds.forEach { includedRoot ->
|
||||
populateBuildModels(includedRoot, ideProject)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun populateBuildModels(
|
||||
root: Build,
|
||||
ideProject: DataNode<ProjectData>
|
||||
) {
|
||||
root.projects.forEach {
|
||||
if (it.projectIdentifier.projectPath == ":") {
|
||||
resolverCtx.models.getModel(it, KotlinDslScriptsModel::class.java)?.let { model ->
|
||||
processScriptModel(resolverCtx, model, it.projectIdentifier.projectPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,8 +147,8 @@ public abstract class AbstractModelBuilderTest {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Set<Class> getToolingExtensionClasses() {
|
||||
Set<Class> classes = ContainerUtil.<Class>set(
|
||||
private static Set<Class<?>> getToolingExtensionClasses() {
|
||||
Set<Class<?>> classes = ContainerUtil.set(
|
||||
ExternalProject.class,
|
||||
// gradle-tooling-extension-api jar
|
||||
ProjectImportAction.class,
|
||||
@@ -163,7 +163,7 @@ public abstract class AbstractModelBuilderTest {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Set<Class> doGetToolingExtensionClasses() {
|
||||
private static Set<Class<?>> doGetToolingExtensionClasses() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ public abstract class AbstractModelBuilderTest {
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Set<Class> getModels();
|
||||
protected abstract Set<Class<?>> getModels();
|
||||
|
||||
|
||||
private static void ensureTempDirCreated() throws IOException {
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* 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.codeInsight.gradle;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.io.StreamUtil;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.codehaus.groovy.runtime.typehandling.ShortTypeHandling;
|
||||
import org.gradle.tooling.BuildActionExecuter;
|
||||
import org.gradle.tooling.GradleConnector;
|
||||
import org.gradle.tooling.ProjectConnection;
|
||||
import org.gradle.tooling.internal.consumer.DefaultGradleConnector;
|
||||
import org.gradle.util.GradleVersion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.model.ClassSetProjectImportModelProvider;
|
||||
import org.jetbrains.plugins.gradle.model.ExternalProject;
|
||||
import org.jetbrains.plugins.gradle.model.ProjectImportAction;
|
||||
import org.jetbrains.plugins.gradle.service.execution.GradleExecutionHelper;
|
||||
import org.jetbrains.plugins.gradle.tooling.builder.ModelBuildScriptClasspathBuilderImpl;
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.rules.TestName;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assume.assumeThat;
|
||||
|
||||
// part of org.jetbrains.plugins.gradle.tooling.builder.AbstractModelBuilderTest
|
||||
@RunWith(value = Parameterized.class)
|
||||
public abstract class AbstractModelBuilderTest {
|
||||
|
||||
public static final Object[][] SUPPORTED_GRADLE_VERSIONS = {{"4.9"}, {"5.6.4"}};
|
||||
|
||||
private static final Pattern TEST_METHOD_NAME_PATTERN = Pattern.compile("(.*)\\[(\\d*: with Gradle-.*)\\]");
|
||||
|
||||
private static File ourTempDir;
|
||||
|
||||
@NotNull
|
||||
private final String gradleVersion;
|
||||
private File testDir;
|
||||
private ProjectImportAction.AllModels allModels;
|
||||
|
||||
@Rule public TestName name = new TestName();
|
||||
@Rule public VersionMatcherRule versionMatcherRule = new VersionMatcherRule();
|
||||
|
||||
public AbstractModelBuilderTest(@NotNull String gradleVersion) {
|
||||
this.gradleVersion = gradleVersion;
|
||||
}
|
||||
|
||||
@Parameterized.Parameters(name = "{index}: with Gradle-{0}")
|
||||
public static Collection<Object[]> data() {
|
||||
return Arrays.asList(SUPPORTED_GRADLE_VERSIONS);
|
||||
}
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
assumeThat(gradleVersion, versionMatcherRule.getMatcher());
|
||||
|
||||
ensureTempDirCreated();
|
||||
|
||||
String methodName = name.getMethodName();
|
||||
Matcher m = TEST_METHOD_NAME_PATTERN.matcher(methodName);
|
||||
if (m.matches()) {
|
||||
methodName = m.group(1);
|
||||
}
|
||||
|
||||
testDir = new File(ourTempDir, methodName);
|
||||
FileUtil.ensureExists(testDir);
|
||||
|
||||
InputStream buildScriptStream = getClass().getResourceAsStream("/" + methodName + "/" + GradleConstants.DEFAULT_SCRIPT_NAME);
|
||||
try {
|
||||
FileUtil.writeToFile(
|
||||
new File(testDir, GradleConstants.DEFAULT_SCRIPT_NAME),
|
||||
FileUtil.loadTextAndClose(buildScriptStream)
|
||||
);
|
||||
}
|
||||
finally {
|
||||
StreamUtil.closeStream(buildScriptStream);
|
||||
}
|
||||
|
||||
InputStream settingsStream = getClass().getResourceAsStream("/" + methodName + "/" + GradleConstants.SETTINGS_FILE_NAME);
|
||||
try {
|
||||
if (settingsStream != null) {
|
||||
FileUtil.writeToFile(
|
||||
new File(testDir, GradleConstants.SETTINGS_FILE_NAME),
|
||||
FileUtil.loadTextAndClose(settingsStream)
|
||||
);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
StreamUtil.closeStream(settingsStream);
|
||||
}
|
||||
|
||||
GradleConnector connector = GradleConnector.newConnector();
|
||||
|
||||
URI distributionUri = new DistributionLocator().getDistributionFor(GradleVersion.version(gradleVersion));
|
||||
connector.useDistribution(distributionUri);
|
||||
connector.forProjectDirectory(testDir);
|
||||
int daemonMaxIdleTime = 10;
|
||||
try {
|
||||
daemonMaxIdleTime = Integer.parseInt(System.getProperty("gradleDaemonMaxIdleTime", "10"));
|
||||
}
|
||||
catch (NumberFormatException ignore) {
|
||||
}
|
||||
|
||||
((DefaultGradleConnector) connector).daemonMaxIdleTime(daemonMaxIdleTime, TimeUnit.SECONDS);
|
||||
ProjectConnection connection = connector.connect();
|
||||
|
||||
try {
|
||||
ProjectImportAction projectImportAction = new ProjectImportAction(false);
|
||||
projectImportAction.addProjectImportModelProvider(new ClassSetProjectImportModelProvider(getModels()));
|
||||
BuildActionExecuter<ProjectImportAction.AllModels> buildActionExecutor = connection.action(projectImportAction);
|
||||
File initScript = GradleExecutionHelper.generateInitScript(false, getToolingExtensionClasses());
|
||||
assertNotNull(initScript);
|
||||
String jdkHome = IdeaTestUtil.requireRealJdkHome();
|
||||
buildActionExecutor.setJavaHome(new File(jdkHome));
|
||||
buildActionExecutor.setJvmArguments("-Xmx128m", "-XX:MaxPermSize=64m");
|
||||
buildActionExecutor
|
||||
.withArguments("--info", "--recompile-scripts", GradleConstants.INIT_SCRIPT_CMD_OPTION, initScript.getAbsolutePath());
|
||||
allModels = buildActionExecutor.run();
|
||||
assertNotNull(allModels);
|
||||
}
|
||||
finally {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Set<Class> getToolingExtensionClasses() {
|
||||
Set<Class> classes = ContainerUtil.<Class>set(
|
||||
ExternalProject.class,
|
||||
// gradle-tooling-extension-api jar
|
||||
ProjectImportAction.class,
|
||||
// gradle-tooling-extension-impl jar
|
||||
ModelBuildScriptClasspathBuilderImpl.class,
|
||||
Multimap.class,
|
||||
ShortTypeHandling.class
|
||||
);
|
||||
|
||||
ContainerUtil.addAllNotNull(classes, doGetToolingExtensionClasses());
|
||||
return classes;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Set<Class> doGetToolingExtensionClasses() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (testDir != null) {
|
||||
FileUtil.delete(testDir);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Set<Class> getModels();
|
||||
|
||||
|
||||
private static void ensureTempDirCreated() throws IOException {
|
||||
if (ourTempDir != null) return;
|
||||
|
||||
ourTempDir = new File(FileUtil.getTempDirectory(), "gradleTests");
|
||||
FileUtil.delete(ourTempDir);
|
||||
FileUtil.ensureExists(ourTempDir);
|
||||
}
|
||||
|
||||
public static class DistributionLocator {
|
||||
private static final String RELEASE_REPOSITORY_ENV = "GRADLE_RELEASE_REPOSITORY";
|
||||
private static final String SNAPSHOT_REPOSITORY_ENV = "GRADLE_SNAPSHOT_REPOSITORY";
|
||||
private static final String GRADLE_RELEASE_REPO = "https://services.gradle.org/distributions";
|
||||
private static final String GRADLE_SNAPSHOT_REPO = "https://services.gradle.org/distributions-snapshots";
|
||||
|
||||
@NotNull private final String myReleaseRepoUrl;
|
||||
@NotNull private final String mySnapshotRepoUrl;
|
||||
|
||||
public DistributionLocator() {
|
||||
this(DistributionLocator.getRepoUrl(false), DistributionLocator.getRepoUrl(true));
|
||||
}
|
||||
|
||||
public DistributionLocator(@NotNull String releaseRepoUrl, @NotNull String snapshotRepoUrl) {
|
||||
myReleaseRepoUrl = releaseRepoUrl;
|
||||
mySnapshotRepoUrl = snapshotRepoUrl;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public URI getDistributionFor(@NotNull GradleVersion version) throws URISyntaxException {
|
||||
return getDistribution(getDistributionRepository(version), version, "gradle", "bin");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String getDistributionRepository(@NotNull GradleVersion version) {
|
||||
return version.isSnapshot() ? mySnapshotRepoUrl : myReleaseRepoUrl;
|
||||
}
|
||||
|
||||
private static URI getDistribution(
|
||||
@NotNull String repositoryUrl,
|
||||
@NotNull GradleVersion version,
|
||||
@NotNull String archiveName,
|
||||
@NotNull String archiveClassifier
|
||||
) throws URISyntaxException {
|
||||
return new URI(String.format("%s/%s-%s-%s.zip", repositoryUrl, archiveName, version.getVersion(), archiveClassifier));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getRepoUrl(boolean isSnapshotUrl) {
|
||||
String envRepoUrl = System.getenv(isSnapshotUrl ? SNAPSHOT_REPOSITORY_ENV : RELEASE_REPOSITORY_ENV);
|
||||
if (envRepoUrl != null) return envRepoUrl;
|
||||
|
||||
return isSnapshotUrl ? GRADLE_SNAPSHOT_REPO : GRADLE_RELEASE_REPO;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,15 +30,18 @@ class ShowKotlinBytecodeAction : AnAction() {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.project ?: return
|
||||
val toolWindowManager = ToolWindowManager.getInstance(project)
|
||||
var toolWindow = toolWindowManager.getToolWindow(TOOLWINDOW_ID)
|
||||
if (toolWindow == null) {
|
||||
toolWindow = toolWindowManager.registerToolWindow(TOOLWINDOW_ID, false, ToolWindowAnchor.RIGHT)
|
||||
toolWindow.icon = KotlinIcons.SMALL_LOGO_13
|
||||
|
||||
val contentManager = toolWindow.contentManager
|
||||
val contentFactory = ContentFactory.SERVICE.getInstance()
|
||||
contentManager.addContent(contentFactory.createContent(KotlinBytecodeToolWindow(project, toolWindow), "", false))
|
||||
}
|
||||
val toolWindow = toolWindowManager.getToolWindow(TOOLWINDOW_ID) ?: toolWindowManager.registerToolWindow(
|
||||
TOOLWINDOW_ID,
|
||||
false,
|
||||
ToolWindowAnchor.RIGHT,
|
||||
)
|
||||
.apply {
|
||||
setIcon(KotlinIcons.SMALL_LOGO_13)
|
||||
val contentFactory = ContentFactory.SERVICE.getInstance()
|
||||
contentManager.addContent(contentFactory.createContent(KotlinBytecodeToolWindow(project, this), "", false))
|
||||
}
|
||||
|
||||
toolWindow.activate(null)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.actions
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||
import com.intellij.openapi.wm.ToolWindowAnchor
|
||||
import com.intellij.openapi.wm.ToolWindowManager
|
||||
import com.intellij.ui.content.ContentFactory
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.KotlinIcons
|
||||
import org.jetbrains.kotlin.idea.internal.KotlinBytecodeToolWindow
|
||||
|
||||
class ShowKotlinBytecodeAction : AnAction() {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.project ?: return
|
||||
val toolWindowManager = ToolWindowManager.getInstance(project)
|
||||
var toolWindow = toolWindowManager.getToolWindow(TOOLWINDOW_ID)
|
||||
if (toolWindow == null) {
|
||||
toolWindow = toolWindowManager.registerToolWindow(TOOLWINDOW_ID, false, ToolWindowAnchor.RIGHT)
|
||||
toolWindow.icon = KotlinIcons.SMALL_LOGO_13
|
||||
|
||||
val contentManager = toolWindow.contentManager
|
||||
val contentFactory = ContentFactory.SERVICE.getInstance()
|
||||
contentManager.addContent(contentFactory.createContent(KotlinBytecodeToolWindow(project, toolWindow), "", false))
|
||||
}
|
||||
toolWindow.activate(null)
|
||||
}
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
val file = e.getData(CommonDataKeys.PSI_FILE)
|
||||
e.presentation.isEnabled = e.project != null && file?.fileType == KotlinFileType.INSTANCE
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TOOLWINDOW_ID = "Kotlin Bytecode"
|
||||
}
|
||||
}
|
||||
@@ -20,12 +20,12 @@ import com.intellij.execution.filters.OpenFileHyperlinkInfo
|
||||
import com.intellij.execution.impl.ConsoleViewImpl
|
||||
import com.intellij.execution.runners.ExecutionUtil
|
||||
import com.intellij.execution.ui.ConsoleViewContentType
|
||||
import com.intellij.ide.scratch.ScratchFileType
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.TransactionGuard
|
||||
import com.intellij.openapi.command.WriteCommandAction
|
||||
import com.intellij.openapi.editor.ex.EditorEx
|
||||
import com.intellij.openapi.fileTypes.PlainTextFileType
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.wm.ToolWindow
|
||||
@@ -113,8 +113,8 @@ private class ToolWindowScratchOutputHandler(private val parentDisposable: Dispo
|
||||
OpenFileHyperlinkInfo(
|
||||
project,
|
||||
psiFile.virtualFile,
|
||||
expression.lineStart,
|
||||
),
|
||||
expression.lineStart
|
||||
)
|
||||
)
|
||||
print(" ", ConsoleViewContentType.NORMAL_OUTPUT)
|
||||
}
|
||||
@@ -149,7 +149,7 @@ private class ToolWindowScratchOutputHandler(private val parentDisposable: Dispo
|
||||
toolWindow.show(null)
|
||||
}
|
||||
|
||||
toolWindow.icon = ExecutionUtil.getLiveIndicator(scratchIcon())
|
||||
toolWindow.setIcon(ExecutionUtil.getLiveIndicator(ScratchFileType.INSTANCE.icon))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ private class ToolWindowScratchOutputHandler(private val parentDisposable: Dispo
|
||||
toolWindow.hide(null)
|
||||
}
|
||||
|
||||
toolWindow.icon = scratchIcon()
|
||||
toolWindow.setIcon(ScratchFileType.INSTANCE.icon ?: error("Text icon is expected to be present"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,22 +187,18 @@ private class ToolWindowScratchOutputHandler(private val parentDisposable: Dispo
|
||||
val project = file.project
|
||||
val toolWindowManager = ToolWindowManager.getInstance(project)
|
||||
toolWindowManager.registerToolWindow(ScratchToolWindowFactory.ID, true, ToolWindowAnchor.BOTTOM)
|
||||
val window = toolWindowManager.getToolWindow(ScratchToolWindowFactory.ID)
|
||||
val window =
|
||||
toolWindowManager.getToolWindow(ScratchToolWindowFactory.ID) ?: error("ScratchToolWindowFactory.ID should be registered")
|
||||
ScratchToolWindowFactory().createToolWindowContent(project, window)
|
||||
|
||||
Disposer.register(
|
||||
parentDisposable,
|
||||
Disposable {
|
||||
toolWindowManager.unregisterToolWindow(ScratchToolWindowFactory.ID)
|
||||
},
|
||||
)
|
||||
Disposer.register(parentDisposable, Disposable {
|
||||
toolWindowManager.unregisterToolWindow(ScratchToolWindowFactory.ID)
|
||||
})
|
||||
|
||||
return window
|
||||
}
|
||||
}
|
||||
|
||||
private fun scratchIcon() = PlainTextFileType.INSTANCE.icon
|
||||
|
||||
private fun getLineInfo(psiFile: PsiFile, expression: ScratchExpression) =
|
||||
"${psiFile.name}:${expression.lineStart + 1}"
|
||||
|
||||
@@ -213,8 +209,8 @@ private class ScratchToolWindowFactory : ToolWindowFactory {
|
||||
|
||||
override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) {
|
||||
val consoleView = ConsoleViewImpl(project, true)
|
||||
toolWindow.isToHideOnEmptyContent = true
|
||||
toolWindow.icon = scratchIcon()
|
||||
toolWindow.setToHideOnEmptyContent(true)
|
||||
toolWindow.setIcon(ScratchFileType.INSTANCE.icon ?: error("Text icon should be present"))
|
||||
toolWindow.hide(null)
|
||||
|
||||
val contentManager = toolWindow.contentManager
|
||||
@@ -242,33 +238,27 @@ private object TestOutputHandler : ScratchOutputHandlerAdapter() {
|
||||
}
|
||||
|
||||
override fun onFinish(file: ScratchFile) {
|
||||
TransactionGuard.submitTransaction(
|
||||
file.project,
|
||||
Runnable {
|
||||
val psiFile = file.getPsiFile()
|
||||
?: error(
|
||||
"PsiFile cannot be found for scratch to render inlays in tests:\n" +
|
||||
"project.isDisposed = ${file.project.isDisposed}\n" +
|
||||
"inlays = ${inlays.joinToString { it.second }}\n" +
|
||||
"errors = ${errors.joinToString()}",
|
||||
)
|
||||
TransactionGuard.submitTransaction(file.project, Runnable {
|
||||
val psiFile = file.getPsiFile()
|
||||
?: error(
|
||||
"PsiFile cannot be found for scratch to render inlays in tests:\n" +
|
||||
"project.isDisposed = ${file.project.isDisposed}\n" +
|
||||
"inlays = ${inlays.joinToString { it.second }}\n" +
|
||||
"errors = ${errors.joinToString()}"
|
||||
)
|
||||
|
||||
if (inlays.isNotEmpty()) {
|
||||
testPrint(
|
||||
psiFile,
|
||||
inlays.map { (expression, text) ->
|
||||
"/** ${getLineInfo(psiFile, expression)} $text */"
|
||||
},
|
||||
)
|
||||
inlays.clear()
|
||||
}
|
||||
if (inlays.isNotEmpty()) {
|
||||
testPrint(psiFile, inlays.map { (expression, text) ->
|
||||
"/** ${getLineInfo(psiFile, expression)} $text */"
|
||||
})
|
||||
inlays.clear()
|
||||
}
|
||||
|
||||
if (errors.isNotEmpty()) {
|
||||
testPrint(psiFile, listOf(errors.joinToString(prefix = "/** ", postfix = " */")))
|
||||
errors.clear()
|
||||
}
|
||||
},
|
||||
)
|
||||
if (errors.isNotEmpty()) {
|
||||
testPrint(psiFile, listOf(errors.joinToString(prefix = "/** ", postfix = " */")))
|
||||
errors.clear()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun testPrint(file: PsiFile, comments: List<String>) {
|
||||
@@ -276,7 +266,7 @@ private object TestOutputHandler : ScratchOutputHandlerAdapter() {
|
||||
for (comment in comments) {
|
||||
file.addAfter(
|
||||
KtPsiFactory(file.project).createComment(comment),
|
||||
file.lastChild,
|
||||
file.lastChild
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* 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.output
|
||||
|
||||
import com.intellij.execution.filters.OpenFileHyperlinkInfo
|
||||
import com.intellij.execution.impl.ConsoleViewImpl
|
||||
import com.intellij.execution.runners.ExecutionUtil
|
||||
import com.intellij.execution.ui.ConsoleViewContentType
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.TransactionGuard
|
||||
import com.intellij.openapi.command.WriteCommandAction
|
||||
import com.intellij.openapi.editor.ex.EditorEx
|
||||
import com.intellij.openapi.fileTypes.PlainTextFileType
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.wm.ToolWindow
|
||||
import com.intellij.openapi.wm.ToolWindowAnchor
|
||||
import com.intellij.openapi.wm.ToolWindowFactory
|
||||
import com.intellij.openapi.wm.ToolWindowManager
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.idea.scratch.ScratchExpression
|
||||
import org.jetbrains.kotlin.idea.scratch.ScratchFile
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
|
||||
/**
|
||||
* Method to retrieve shared instance of scratches ToolWindow output handler.
|
||||
*
|
||||
* [releaseToolWindowHandler] must be called for every output handler received from this method.
|
||||
*
|
||||
* Can be called from EDT only.
|
||||
*
|
||||
* @return new toolWindow output handler if one does not exist, otherwise returns the existing one. When application in test mode,
|
||||
* returns [TestOutputHandler].
|
||||
*/
|
||||
fun requestToolWindowHandler(): ScratchOutputHandler {
|
||||
return if (ApplicationManager.getApplication().isUnitTestMode) {
|
||||
TestOutputHandler
|
||||
} else {
|
||||
ScratchToolWindowHandlerKeeper.requestOutputHandler()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called once with the output handler received from the [requestToolWindowHandler] call.
|
||||
*
|
||||
* When release is called for every request, the output handler is actually disposed.
|
||||
*
|
||||
* When application in test mode, does nothing.
|
||||
*
|
||||
* Can be called from EDT only.
|
||||
*/
|
||||
fun releaseToolWindowHandler(scratchOutputHandler: ScratchOutputHandler) {
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode) {
|
||||
ScratchToolWindowHandlerKeeper.releaseOutputHandler(scratchOutputHandler)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements logic of shared pointer for the toolWindow output handler.
|
||||
*
|
||||
* Not thread safe! Can be used only from the EDT.
|
||||
*/
|
||||
private object ScratchToolWindowHandlerKeeper {
|
||||
private var toolWindowHandler: ScratchOutputHandler? = null
|
||||
private var toolWindowDisposable = Disposer.newDisposable()
|
||||
private var counter = 0
|
||||
|
||||
fun requestOutputHandler(): ScratchOutputHandler {
|
||||
if (counter == 0) {
|
||||
toolWindowHandler = ToolWindowScratchOutputHandler(toolWindowDisposable)
|
||||
}
|
||||
|
||||
counter += 1
|
||||
return toolWindowHandler!!
|
||||
}
|
||||
|
||||
fun releaseOutputHandler(scratchOutputHandler: ScratchOutputHandler) {
|
||||
require(counter > 0) { "Counter is $counter, nothing to release!" }
|
||||
require(toolWindowHandler === scratchOutputHandler) { "$scratchOutputHandler differs from stored $toolWindowHandler" }
|
||||
|
||||
counter -= 1
|
||||
if (counter == 0) {
|
||||
Disposer.dispose(toolWindowDisposable)
|
||||
toolWindowDisposable = Disposer.newDisposable()
|
||||
toolWindowHandler = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ToolWindowScratchOutputHandler(private val parentDisposable: Disposable) : ScratchOutputHandlerAdapter() {
|
||||
|
||||
override fun handle(file: ScratchFile, expression: ScratchExpression, output: ScratchOutput) {
|
||||
printToConsole(file) {
|
||||
val psiFile = file.getPsiFile()
|
||||
if (psiFile != null) {
|
||||
printHyperlink(
|
||||
getLineInfo(psiFile, expression),
|
||||
OpenFileHyperlinkInfo(
|
||||
project,
|
||||
psiFile.virtualFile,
|
||||
expression.lineStart,
|
||||
),
|
||||
)
|
||||
print(" ", ConsoleViewContentType.NORMAL_OUTPUT)
|
||||
}
|
||||
print(output.text, output.type.convert())
|
||||
}
|
||||
}
|
||||
|
||||
override fun error(file: ScratchFile, message: String) {
|
||||
printToConsole(file) {
|
||||
print(message, ConsoleViewContentType.ERROR_OUTPUT)
|
||||
}
|
||||
}
|
||||
|
||||
private fun printToConsole(file: ScratchFile, print: ConsoleViewImpl.() -> Unit) {
|
||||
ApplicationManager.getApplication().invokeLater {
|
||||
val project = file.project.takeIf { !it.isDisposed } ?: return@invokeLater
|
||||
|
||||
val toolWindow = getToolWindow(project) ?: createToolWindow(file)
|
||||
|
||||
val contents = toolWindow.contentManager.contents
|
||||
for (content in contents) {
|
||||
val component = content.component
|
||||
if (component is ConsoleViewImpl) {
|
||||
component.print()
|
||||
component.print("\n", ConsoleViewContentType.NORMAL_OUTPUT)
|
||||
}
|
||||
}
|
||||
|
||||
toolWindow.setAvailable(true, null)
|
||||
|
||||
if (!file.options.isInteractiveMode) {
|
||||
toolWindow.show(null)
|
||||
}
|
||||
|
||||
toolWindow.icon = ExecutionUtil.getLiveIndicator(scratchIcon())
|
||||
}
|
||||
}
|
||||
|
||||
override fun clear(file: ScratchFile) {
|
||||
ApplicationManager.getApplication().invokeLater {
|
||||
val toolWindow = getToolWindow(file.project) ?: return@invokeLater
|
||||
val contents = toolWindow.contentManager.contents
|
||||
for (content in contents) {
|
||||
val component = content.component
|
||||
if (component is ConsoleViewImpl) {
|
||||
component.clear()
|
||||
}
|
||||
}
|
||||
|
||||
if (!file.options.isInteractiveMode) {
|
||||
toolWindow.hide(null)
|
||||
}
|
||||
|
||||
toolWindow.icon = scratchIcon()
|
||||
}
|
||||
}
|
||||
|
||||
private fun ScratchOutputType.convert() = when (this) {
|
||||
ScratchOutputType.OUTPUT -> ConsoleViewContentType.SYSTEM_OUTPUT
|
||||
ScratchOutputType.RESULT -> ConsoleViewContentType.NORMAL_OUTPUT
|
||||
ScratchOutputType.ERROR -> ConsoleViewContentType.ERROR_OUTPUT
|
||||
}
|
||||
|
||||
private fun getToolWindow(project: Project): ToolWindow? {
|
||||
val toolWindowManager = ToolWindowManager.getInstance(project)
|
||||
return toolWindowManager.getToolWindow(ScratchToolWindowFactory.ID)
|
||||
}
|
||||
|
||||
private fun createToolWindow(file: ScratchFile): ToolWindow {
|
||||
val project = file.project
|
||||
val toolWindowManager = ToolWindowManager.getInstance(project)
|
||||
toolWindowManager.registerToolWindow(ScratchToolWindowFactory.ID, true, ToolWindowAnchor.BOTTOM)
|
||||
val window = toolWindowManager.getToolWindow(ScratchToolWindowFactory.ID)
|
||||
ScratchToolWindowFactory().createToolWindowContent(project, window)
|
||||
|
||||
Disposer.register(
|
||||
parentDisposable,
|
||||
Disposable {
|
||||
toolWindowManager.unregisterToolWindow(ScratchToolWindowFactory.ID)
|
||||
},
|
||||
)
|
||||
|
||||
return window
|
||||
}
|
||||
}
|
||||
|
||||
private fun scratchIcon() = PlainTextFileType.INSTANCE.icon
|
||||
|
||||
private fun getLineInfo(psiFile: PsiFile, expression: ScratchExpression) =
|
||||
"${psiFile.name}:${expression.lineStart + 1}"
|
||||
|
||||
private class ScratchToolWindowFactory : ToolWindowFactory {
|
||||
companion object {
|
||||
const val ID = "Scratch Output"
|
||||
}
|
||||
|
||||
override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) {
|
||||
val consoleView = ConsoleViewImpl(project, true)
|
||||
toolWindow.isToHideOnEmptyContent = true
|
||||
toolWindow.icon = scratchIcon()
|
||||
toolWindow.hide(null)
|
||||
|
||||
val contentManager = toolWindow.contentManager
|
||||
val content = contentManager.factory.createContent(consoleView.component, null, false)
|
||||
contentManager.addContent(content)
|
||||
val editor = consoleView.editor
|
||||
if (editor is EditorEx) {
|
||||
editor.isRendererMode = true
|
||||
}
|
||||
|
||||
Disposer.register(project, consoleView)
|
||||
}
|
||||
}
|
||||
|
||||
private object TestOutputHandler : ScratchOutputHandlerAdapter() {
|
||||
private val errors = arrayListOf<String>()
|
||||
private val inlays = arrayListOf<Pair<ScratchExpression, String>>()
|
||||
|
||||
override fun handle(file: ScratchFile, expression: ScratchExpression, output: ScratchOutput) {
|
||||
inlays.add(expression to output.text)
|
||||
}
|
||||
|
||||
override fun error(file: ScratchFile, message: String) {
|
||||
errors.add(message)
|
||||
}
|
||||
|
||||
override fun onFinish(file: ScratchFile) {
|
||||
TransactionGuard.submitTransaction(
|
||||
file.project,
|
||||
Runnable {
|
||||
val psiFile = file.getPsiFile()
|
||||
?: error(
|
||||
"PsiFile cannot be found for scratch to render inlays in tests:\n" +
|
||||
"project.isDisposed = ${file.project.isDisposed}\n" +
|
||||
"inlays = ${inlays.joinToString { it.second }}\n" +
|
||||
"errors = ${errors.joinToString()}",
|
||||
)
|
||||
|
||||
if (inlays.isNotEmpty()) {
|
||||
testPrint(
|
||||
psiFile,
|
||||
inlays.map { (expression, text) ->
|
||||
"/** ${getLineInfo(psiFile, expression)} $text */"
|
||||
},
|
||||
)
|
||||
inlays.clear()
|
||||
}
|
||||
|
||||
if (errors.isNotEmpty()) {
|
||||
testPrint(psiFile, listOf(errors.joinToString(prefix = "/** ", postfix = " */")))
|
||||
errors.clear()
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private fun testPrint(file: PsiFile, comments: List<String>) {
|
||||
WriteCommandAction.runWriteCommandAction(file.project) {
|
||||
for (comment in comments) {
|
||||
file.addAfter(
|
||||
KtPsiFactory(file.project).createComment(comment),
|
||||
file.lastChild,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,6 @@ import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.ui.JBSplitter;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.idea.KotlinJvmBundle;
|
||||
@@ -473,7 +472,6 @@ class SplitEditorToolbar extends JPanel implements Disposable {
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@ApiStatus.ScheduledForRemoval
|
||||
public void addGutterToTrack(@NotNull EditorGutterComponentEx gutterComponentEx) {}
|
||||
|
||||
public void refresh() {
|
||||
@@ -481,7 +479,6 @@ class SplitEditorToolbar extends JPanel implements Disposable {
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@ApiStatus.ScheduledForRemoval
|
||||
@Override
|
||||
public void dispose() {}
|
||||
}
|
||||
@@ -0,0 +1,487 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.scratch.ui;
|
||||
|
||||
|
||||
import com.intellij.codeHighlighting.BackgroundEditorHighlighter;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.structureView.StructureViewBuilder;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.editor.ex.EditorGutterComponentEx;
|
||||
import com.intellij.openapi.fileEditor.*;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.UserDataHolderBase;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.ui.JBSplitter;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.idea.KotlinJvmBundle;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Two panel editor with three states: Editor, Preview and Editor with Preview.
|
||||
* Based on SplitFileEditor by Valentin Fondaratov
|
||||
* <p/>
|
||||
* <b>NOTE:</b> This class is a copy of {@link com.intellij.openapi.fileEditor.TextEditorWithPreview} from the most recent intellij-community
|
||||
* repository. We cannot use bundled version of this class because it doesn't yet have customization methods
|
||||
* (namely {@link TextEditorWithPreview#createLeftToolbarActionGroup()}).
|
||||
* <p/>
|
||||
* {@link SplitEditorToolbar} is also copied from the platform.
|
||||
* <p/>
|
||||
* This class also may have some minimal customizations to allow tracking when its layout have been changed. In the future we hope to
|
||||
* remove this copied class entirely and to use the bundled version.
|
||||
*/
|
||||
public class TextEditorWithPreview extends UserDataHolderBase implements FileEditor {
|
||||
protected final TextEditor myEditor;
|
||||
protected final FileEditor myPreview;
|
||||
@NotNull
|
||||
private final MyListenersMultimap myListenersGenerator = new MyListenersMultimap();
|
||||
private Layout myLayout;
|
||||
private JComponent myComponent;
|
||||
private SplitEditorToolbar myToolbarWrapper;
|
||||
private final String myName;
|
||||
|
||||
public TextEditorWithPreview(@NotNull TextEditor editor, @NotNull FileEditor preview, @NotNull String editorName) {
|
||||
myEditor = editor;
|
||||
myPreview = preview;
|
||||
myName = editorName;
|
||||
}
|
||||
|
||||
public TextEditorWithPreview(@NotNull TextEditor editor, @NotNull FileEditor preview) {
|
||||
this(editor, preview, "TextEditorWithPreview");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BackgroundEditorHighlighter getBackgroundHighlighter() {
|
||||
return myEditor.getBackgroundHighlighter();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public FileEditorLocation getCurrentLocation() {
|
||||
return myEditor.getCurrentLocation();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public StructureViewBuilder getStructureViewBuilder() {
|
||||
return myEditor.getStructureViewBuilder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
Disposer.dispose(myEditor);
|
||||
Disposer.dispose(myPreview);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectNotify() {
|
||||
myEditor.selectNotify();
|
||||
myPreview.selectNotify();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deselectNotify() {
|
||||
myEditor.deselectNotify();
|
||||
myPreview.deselectNotify();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JComponent getComponent() {
|
||||
if (myComponent == null) {
|
||||
final JBSplitter splitter = new JBSplitter(false, 0.5f, 0.15f, 0.85f);
|
||||
splitter.setSplitterProportionKey(getSplitterProportionKey());
|
||||
splitter.setFirstComponent(myEditor.getComponent());
|
||||
splitter.setSecondComponent(myPreview.getComponent());
|
||||
splitter.setDividerWidth(3);
|
||||
|
||||
myToolbarWrapper = createMarkdownToolbarWrapper(splitter);
|
||||
Disposer.register(this, myToolbarWrapper);
|
||||
|
||||
if (myLayout == null) {
|
||||
String lastUsed = PropertiesComponent.getInstance().getValue(getLayoutPropertyName());
|
||||
setLayout(Layout.fromName(lastUsed, Layout.SHOW_EDITOR_AND_PREVIEW));
|
||||
}
|
||||
adjustEditorsVisibility();
|
||||
|
||||
myComponent = JBUI.Panels.simplePanel(splitter).addToTop(myToolbarWrapper);
|
||||
}
|
||||
return myComponent;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private SplitEditorToolbar createMarkdownToolbarWrapper (@NotNull JComponent targetComponentForActions) {
|
||||
final ActionToolbar leftToolbar = createToolbar();
|
||||
if (leftToolbar != null) {
|
||||
leftToolbar.setTargetComponent(targetComponentForActions);
|
||||
leftToolbar.setReservePlaceAutoPopupIcon(false);
|
||||
}
|
||||
|
||||
final ActionToolbar rightToolbar = createRightToolbar();
|
||||
rightToolbar.setTargetComponent(targetComponentForActions);
|
||||
rightToolbar.setReservePlaceAutoPopupIcon(false);
|
||||
|
||||
return new SplitEditorToolbar(leftToolbar, rightToolbar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setState(@NotNull FileEditorState state) {
|
||||
if (state instanceof MyFileEditorState) {
|
||||
final MyFileEditorState compositeState = (MyFileEditorState)state;
|
||||
if (compositeState.getFirstState() != null) {
|
||||
myEditor.setState(compositeState.getFirstState());
|
||||
}
|
||||
if (compositeState.getSecondState() != null) {
|
||||
myPreview.setState(compositeState.getSecondState());
|
||||
}
|
||||
if (compositeState.getSplitLayout() != null) {
|
||||
setLayout(compositeState.getSplitLayout());
|
||||
invalidateLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void adjustEditorsVisibility() {
|
||||
myEditor.getComponent().setVisible(myLayout == Layout.SHOW_EDITOR || myLayout == Layout.SHOW_EDITOR_AND_PREVIEW);
|
||||
myPreview.getComponent().setVisible(myLayout == Layout.SHOW_PREVIEW || myLayout == Layout.SHOW_EDITOR_AND_PREVIEW);
|
||||
}
|
||||
|
||||
private void invalidateLayout() {
|
||||
adjustEditorsVisibility();
|
||||
myToolbarWrapper.refresh();
|
||||
myComponent.repaint();
|
||||
|
||||
final JComponent focusComponent = getPreferredFocusedComponent();
|
||||
if (focusComponent != null) {
|
||||
IdeFocusManager.findInstanceByComponent(focusComponent).requestFocus(focusComponent, true);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected String getSplitterProportionKey() {
|
||||
return "TextEditorWithPreview.SplitterProportionKey";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
switch (myLayout) {
|
||||
case SHOW_EDITOR_AND_PREVIEW:
|
||||
case SHOW_EDITOR:
|
||||
return myEditor.getPreferredFocusedComponent();
|
||||
case SHOW_PREVIEW:
|
||||
return myPreview.getPreferredFocusedComponent();
|
||||
default:
|
||||
throw new IllegalStateException(myLayout.myName);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FileEditorState getState(@NotNull FileEditorStateLevel level) {
|
||||
return new MyFileEditorState(myLayout, myEditor.getState(level), myPreview.getState(level));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPropertyChangeListener(@NotNull PropertyChangeListener listener) {
|
||||
myEditor.addPropertyChangeListener(listener);
|
||||
myPreview.addPropertyChangeListener(listener);
|
||||
|
||||
final DoublingEventListenerDelegate delegate = myListenersGenerator.addListenerAndGetDelegate(listener);
|
||||
myEditor.addPropertyChangeListener(delegate);
|
||||
myPreview.addPropertyChangeListener(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePropertyChangeListener(@NotNull PropertyChangeListener listener) {
|
||||
myEditor.removePropertyChangeListener(listener);
|
||||
myPreview.removePropertyChangeListener(listener);
|
||||
|
||||
final DoublingEventListenerDelegate delegate = myListenersGenerator.removeListenerAndGetDelegate(listener);
|
||||
if (delegate != null) {
|
||||
myEditor.removePropertyChangeListener(delegate);
|
||||
myPreview.removePropertyChangeListener(delegate);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TextEditor getTextEditor() {
|
||||
return myEditor;
|
||||
}
|
||||
|
||||
public Layout getLayout() {
|
||||
return myLayout;
|
||||
}
|
||||
|
||||
protected void setLayout(@NotNull Layout layout) {
|
||||
myLayout = layout;
|
||||
}
|
||||
|
||||
static class MyFileEditorState implements FileEditorState {
|
||||
private final Layout mySplitLayout;
|
||||
private final FileEditorState myFirstState;
|
||||
private final FileEditorState mySecondState;
|
||||
|
||||
MyFileEditorState(Layout layout, FileEditorState firstState, FileEditorState secondState) {
|
||||
mySplitLayout = layout;
|
||||
myFirstState = firstState;
|
||||
mySecondState = secondState;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Layout getSplitLayout() {
|
||||
return mySplitLayout;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FileEditorState getFirstState() {
|
||||
return myFirstState;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FileEditorState getSecondState() {
|
||||
return mySecondState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeMergedWith(FileEditorState otherState, FileEditorStateLevel level) {
|
||||
return otherState instanceof MyFileEditorState
|
||||
&& (myFirstState == null || myFirstState.canBeMergedWith(((MyFileEditorState)otherState).myFirstState, level))
|
||||
&& (mySecondState == null || mySecondState.canBeMergedWith(((MyFileEditorState)otherState).mySecondState, level));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
return myEditor.isModified() || myPreview.isModified();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return myEditor.isValid() && myPreview.isValid();
|
||||
}
|
||||
|
||||
private class DoublingEventListenerDelegate implements PropertyChangeListener {
|
||||
@NotNull
|
||||
private final PropertyChangeListener myDelegate;
|
||||
|
||||
private DoublingEventListenerDelegate(@NotNull PropertyChangeListener delegate) {
|
||||
myDelegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
myDelegate.propertyChange(
|
||||
new PropertyChangeEvent(TextEditorWithPreview.this, evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()));
|
||||
}
|
||||
}
|
||||
|
||||
private class MyListenersMultimap {
|
||||
private final Map<PropertyChangeListener, Pair<Integer, DoublingEventListenerDelegate>> myMap = new HashMap<>();
|
||||
|
||||
@NotNull
|
||||
public DoublingEventListenerDelegate addListenerAndGetDelegate(@NotNull PropertyChangeListener listener) {
|
||||
if (!myMap.containsKey(listener)) {
|
||||
myMap.put(listener, Pair.create(1, new DoublingEventListenerDelegate(listener)));
|
||||
}
|
||||
else {
|
||||
final Pair<Integer, DoublingEventListenerDelegate> oldPair = myMap.get(listener);
|
||||
myMap.put(listener, Pair.create(oldPair.getFirst() + 1, oldPair.getSecond()));
|
||||
}
|
||||
|
||||
return myMap.get(listener).getSecond();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public DoublingEventListenerDelegate removeListenerAndGetDelegate(@NotNull PropertyChangeListener listener) {
|
||||
final Pair<Integer, DoublingEventListenerDelegate> oldPair = myMap.get(listener);
|
||||
if (oldPair == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (oldPair.getFirst() == 1) {
|
||||
myMap.remove(listener);
|
||||
}
|
||||
else {
|
||||
myMap.put(listener, Pair.create(oldPair.getFirst() - 1, oldPair.getSecond()));
|
||||
}
|
||||
return oldPair.getSecond();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected ActionToolbar createToolbar() {
|
||||
ActionGroup actionGroup = createLeftToolbarActionGroup();
|
||||
if (actionGroup != null) {
|
||||
return ActionManager.getInstance().createActionToolbar("TextEditorWithPreview", actionGroup, true);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected ActionGroup createLeftToolbarActionGroup() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ActionToolbar createRightToolbar() {
|
||||
final ActionGroup viewActions = createViewActionGroup();
|
||||
final ActionGroup group = createRightToolbarActionGroup();
|
||||
final ActionGroup rightToolbarActions = group == null
|
||||
? viewActions
|
||||
: new DefaultActionGroup(group, Separator.create(), viewActions);
|
||||
return ActionManager.getInstance().createActionToolbar("TextEditorWithPreview", rightToolbarActions, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected ActionGroup createViewActionGroup() {
|
||||
return new DefaultActionGroup(
|
||||
getShowEditorAction(),
|
||||
getShowEditorAndPreviewAction(),
|
||||
getShowPreviewAction()
|
||||
);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected ActionGroup createRightToolbarActionGroup() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected ToggleAction getShowEditorAction() {
|
||||
return new ChangeViewModeAction(Layout.SHOW_EDITOR);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected ToggleAction getShowPreviewAction() {
|
||||
return new ChangeViewModeAction(Layout.SHOW_PREVIEW);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected ToggleAction getShowEditorAndPreviewAction() {
|
||||
return new ChangeViewModeAction(Layout.SHOW_EDITOR_AND_PREVIEW);
|
||||
}
|
||||
|
||||
public enum Layout {
|
||||
SHOW_EDITOR(KotlinJvmBundle.message("editor.editor.only"), AllIcons.General.LayoutEditorOnly),
|
||||
SHOW_PREVIEW(KotlinJvmBundle.message("editor.preview.only"), AllIcons.General.LayoutPreviewOnly),
|
||||
SHOW_EDITOR_AND_PREVIEW(KotlinJvmBundle.message("editor.editor.and.preview"), AllIcons.General.LayoutEditorPreview);
|
||||
|
||||
private final String myName;
|
||||
private final Icon myIcon;
|
||||
|
||||
Layout(String name, Icon icon) {
|
||||
myName = name;
|
||||
myIcon = icon;
|
||||
}
|
||||
|
||||
public static Layout fromName(String name, Layout defaultValue) {
|
||||
for (Layout layout : Layout.values()) {
|
||||
if (layout.myName.equals(name)) {
|
||||
return layout;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
public Icon getIcon() {
|
||||
return myIcon;
|
||||
}
|
||||
}
|
||||
|
||||
private class ChangeViewModeAction extends ToggleAction implements DumbAware {
|
||||
private final Layout myActionLayout;
|
||||
|
||||
ChangeViewModeAction(Layout layout) {
|
||||
super(layout.getName(), layout.getName(), layout.getIcon());
|
||||
myActionLayout = layout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelected(@NotNull AnActionEvent e) {
|
||||
return myLayout == myActionLayout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(@NotNull AnActionEvent e, boolean state) {
|
||||
if (state) {
|
||||
setLayout(myActionLayout);
|
||||
PropertiesComponent.getInstance().setValue(getLayoutPropertyName(), myLayout.myName, Layout.SHOW_EDITOR_AND_PREVIEW.myName);
|
||||
adjustEditorsVisibility();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String getLayoutPropertyName() {
|
||||
return myName + "Layout";
|
||||
}
|
||||
}
|
||||
|
||||
class SplitEditorToolbar extends JPanel implements Disposable {
|
||||
|
||||
private final ActionToolbar myRightToolbar;
|
||||
|
||||
public SplitEditorToolbar(@Nullable ActionToolbar leftToolbar, @NotNull ActionToolbar rightToolbar) {
|
||||
super(new GridBagLayout());
|
||||
myRightToolbar = rightToolbar;
|
||||
|
||||
if (leftToolbar != null) {
|
||||
add(leftToolbar.getComponent());
|
||||
}
|
||||
|
||||
final JPanel centerPanel = new JPanel(new BorderLayout());
|
||||
add(centerPanel, new GridBagConstraints(2, 0, 1, 1, 1.0, 1.0,
|
||||
GridBagConstraints.CENTER, GridBagConstraints.BOTH, JBUI.emptyInsets(), 0, 0));
|
||||
|
||||
add(myRightToolbar.getComponent());
|
||||
|
||||
setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, UIUtil.CONTRAST_BORDER_COLOR));
|
||||
|
||||
if (leftToolbar != null) leftToolbar.updateActionsImmediately();
|
||||
rightToolbar.updateActionsImmediately();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@ApiStatus.ScheduledForRemoval
|
||||
public void addGutterToTrack(@NotNull EditorGutterComponentEx gutterComponentEx) {}
|
||||
|
||||
public void refresh() {
|
||||
myRightToolbar.updateActionsImmediately();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@ApiStatus.ScheduledForRemoval
|
||||
@Override
|
||||
public void dispose() {}
|
||||
}
|
||||
@@ -11,5 +11,5 @@ import com.intellij.openapi.project.Project
|
||||
|
||||
// FIX ME WHEN BUNCH 193 REMOVED
|
||||
fun setTemplateTestingCompat(project: Project, disposable: Disposable) {
|
||||
TemplateManagerImpl.setTemplateTesting(project, disposable)
|
||||
TemplateManagerImpl.setTemplateTesting(disposable)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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.liveTemplates
|
||||
|
||||
import com.intellij.codeInsight.template.impl.TemplateManagerImpl
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.project.Project
|
||||
|
||||
// FIX ME WHEN BUNCH 193 REMOVED
|
||||
fun setTemplateTestingCompat(project: Project, disposable: Disposable) {
|
||||
TemplateManagerImpl.setTemplateTesting(project, disposable)
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.isGradle
|
||||
import org.jetbrains.plugins.gradle.service.project.open.linkAndRefreshGradleProject
|
||||
import java.nio.file.Path
|
||||
|
||||
// FIX ME WHEN BUNCH 201 REMOVED
|
||||
class IdeaGradleWizardService(private val project: Project) : ProjectImportingWizardService,
|
||||
IdeaWizardService {
|
||||
override fun isSuitableFor(buildSystemType: BuildSystemType): Boolean =
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.openapi.project.Project
|
||||
import org.jetbrains.kotlin.tools.projectWizard.core.Reader
|
||||
import org.jetbrains.kotlin.tools.projectWizard.core.TaskResult
|
||||
import org.jetbrains.kotlin.tools.projectWizard.core.UNIT_SUCCESS
|
||||
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.service.project.open.linkAndRefreshGradleProject
|
||||
import java.nio.file.Path
|
||||
|
||||
class IdeaGradleWizardService(private val project: Project) : ProjectImportingWizardService,
|
||||
IdeaWizardService {
|
||||
override fun isSuitableFor(buildSystemType: BuildSystemType): Boolean =
|
||||
buildSystemType.isGradle
|
||||
|
||||
override fun importProject(
|
||||
reader: Reader,
|
||||
path: Path,
|
||||
modulesIrs: List<ModuleIR>,
|
||||
buildSystem: BuildSystemType
|
||||
): TaskResult<Unit> {
|
||||
withGradleWrapperEnabled {
|
||||
linkAndRefreshGradleProject(path.toString(), project)
|
||||
}
|
||||
return UNIT_SUCCESS
|
||||
}
|
||||
|
||||
private fun withGradleWrapperEnabled(action: () -> Unit) {
|
||||
val oldGradleDistributionType = System.getProperty("idea.gradle.distributionType")
|
||||
System.setProperty("idea.gradle.distributionType", "WRAPPED")
|
||||
try {
|
||||
action()
|
||||
} finally {
|
||||
if (oldGradleDistributionType != null) {
|
||||
System.setProperty("idea.gradle.distributionType", oldGradleDistributionType)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,12 +41,14 @@ class ConsoleCompilerHelper(
|
||||
}
|
||||
|
||||
fun compileModule() {
|
||||
if (ExecutionManager.getInstance(project).contentManager.removeRunContent(executor, contentDescriptor)) {
|
||||
ProjectTaskManager.getInstance(project).build(module).onSuccess { executionResult ->
|
||||
if (!module.isDisposed) {
|
||||
KotlinConsoleKeeper.getInstance(project).run(module, previousCompilationFailed = executionResult.hasErrors())
|
||||
if (ExecutionManager.getInstance(project).getContentManager().removeRunContent(executor, contentDescriptor)) {
|
||||
ProjectTaskManager.getInstance(project).build(arrayOf(module), object : ProjectTaskNotification {
|
||||
override fun finished(context: ProjectTaskContext, executionResult: ProjectTaskResult) {
|
||||
if (!module.isDisposed) {
|
||||
KotlinConsoleKeeper.getInstance(project).run(module, previousCompilationFailed = executionResult.errors > 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.ProjectTaskContext
|
||||
import com.intellij.task.ProjectTaskManager
|
||||
import com.intellij.task.ProjectTaskNotification
|
||||
import com.intellij.task.ProjectTaskResult
|
||||
|
||||
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(module).onSuccess { executionResult ->
|
||||
if (!module.isDisposed) {
|
||||
KotlinConsoleKeeper.getInstance(project).run(module, previousCompilationFailed = executionResult.hasErrors())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
@@ -49,7 +50,7 @@ public class PluginTestCaseBase {
|
||||
@NotNull
|
||||
@TestOnly
|
||||
private static Sdk createMockJdk(@NotNull String name, String path) {
|
||||
return ((JavaSdkImpl)JavaSdk.getInstance()).createMockJdk(name, path, false);
|
||||
return IdeaTestUtil.createMockJdk(name, path, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -17,5 +17,4 @@ fun editorTrackerProjectOpened(project: Project) {
|
||||
|
||||
// FIX ME WHEN BUNCH 193 REMOVED
|
||||
fun runPostStartupActivitiesOnce(project: Project) {
|
||||
(StartupManager.getInstance(project) as StartupManagerImpl).runPostStartupActivities()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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) {
|
||||
EditorTracker.getInstance(project)
|
||||
}
|
||||
|
||||
// FIX ME WHEN BUNCH 193 REMOVED
|
||||
fun runPostStartupActivitiesOnce(project: Project) {
|
||||
(StartupManager.getInstance(project) as StartupManagerImpl).runPostStartupActivities()
|
||||
}
|
||||
@@ -6,20 +6,22 @@
|
||||
package org.jetbrains.kotlin.idea.debugger.coroutine.data
|
||||
|
||||
import com.intellij.debugger.engine.DebugProcessImpl
|
||||
import com.intellij.debugger.engine.JVMStackFrameInfoProvider
|
||||
import com.intellij.debugger.engine.JavaStackFrame
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
|
||||
import com.intellij.debugger.jdi.StackFrameProxyImpl
|
||||
import com.intellij.debugger.memory.utils.StackFrameItem
|
||||
import com.intellij.debugger.ui.tree.render.DescriptorLabelListener
|
||||
import com.intellij.xdebugger.XSourcePosition
|
||||
import com.intellij.xdebugger.frame.XCompositeNode
|
||||
import com.intellij.xdebugger.frame.XNamedValue
|
||||
import com.intellij.xdebugger.frame.XStackFrame
|
||||
import com.intellij.xdebugger.frame.XValueChildrenList
|
||||
import com.intellij.xdebugger.impl.frame.XDebuggerFramesList
|
||||
import com.sun.jdi.Location
|
||||
import org.jetbrains.kotlin.idea.debugger.*
|
||||
import org.jetbrains.kotlin.idea.debugger.coroutine.KotlinDebuggerCoroutinesBundle
|
||||
import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.LocationStackFrameProxyImpl
|
||||
import org.jetbrains.kotlin.idea.debugger.coroutine.util.findPosition
|
||||
import org.jetbrains.kotlin.idea.debugger.coroutine.util.isFilteredInvokeSuspend
|
||||
import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger
|
||||
import org.jetbrains.kotlin.idea.debugger.stackFrame.KotlinStackFrame
|
||||
|
||||
@@ -32,12 +34,12 @@ class CreationCoroutineStackFrameItem(
|
||||
val first: Boolean
|
||||
) : CoroutineStackFrameItem(location, emptyList()) {
|
||||
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): CoroutineGeneratedFrame? {
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): XStackFrame? {
|
||||
return debugProcess.invokeInManagerThread {
|
||||
val frame = debugProcess.findFirstFrame() ?: return@invokeInManagerThread null
|
||||
val locationFrame = LocationStackFrameProxyImpl(location, frame)
|
||||
val position = location.findPosition(debugProcess.project)
|
||||
CreationCoroutineStackFrame(debugProcess, this, first)
|
||||
CreationCoroutineStackFrame(locationFrame, position, first)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,18 +53,19 @@ class SuspendCoroutineStackFrameItem(
|
||||
spilledVariables: List<XNamedValue> = emptyList()
|
||||
) : CoroutineStackFrameItem(location, spilledVariables)
|
||||
|
||||
|
||||
/**
|
||||
* Restored from memory dump
|
||||
*/
|
||||
class DefaultCoroutineStackFrameItem(location: Location, spilledVariables: List<XNamedValue>) :
|
||||
CoroutineStackFrameItem(location, spilledVariables) {
|
||||
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): CoroutineGeneratedFrame? {
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): XStackFrame? {
|
||||
return debugProcess.invokeInManagerThread {
|
||||
val frame = debugProcess.findFirstFrame() ?: return@invokeInManagerThread null
|
||||
val locationStackFrameProxyImpl = LocationStackFrameProxyImpl(location, frame)
|
||||
val position = location.findPosition(debugProcess.project) ?: return@invokeInManagerThread null
|
||||
CoroutineStackFrame(debugProcess, this)
|
||||
CoroutineStackFrame(locationStackFrameProxyImpl, position, spilledVariables, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,24 +85,25 @@ class DefaultCoroutineStackFrameItem(location: Location, spilledVariables: List<
|
||||
open class RunningCoroutineStackFrameItem(
|
||||
val frame: StackFrameProxyImpl,
|
||||
spilledVariables: List<XNamedValue> = emptyList()
|
||||
) : CoroutineStackFrameItem(frame.location(), spilledVariables), FrameProvider {
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): CoroutineGeneratedFrame? {
|
||||
) : CoroutineStackFrameItem(frame.location(), spilledVariables) {
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): XStackFrame? {
|
||||
return debugProcess.invokeInManagerThread {
|
||||
CoroutineStackFrame(debugProcess, this)
|
||||
val position = frame.location().findPosition(debugProcess.project)
|
||||
CoroutineStackFrame(frame, position)
|
||||
}
|
||||
}
|
||||
|
||||
override fun provideFrame(debugProcess: DebugProcessImpl): XStackFrame? =
|
||||
debugProcess.invokeInManagerThread { KotlinStackFrame(frame) }
|
||||
}
|
||||
|
||||
sealed class CoroutineStackFrameItem(val location: Location, val spilledVariables: List<XNamedValue>) :
|
||||
StackFrameItem(location, spilledVariables) {
|
||||
val log by logger
|
||||
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): CoroutineGeneratedFrame? {
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): XStackFrame? {
|
||||
return debugProcess.invokeInManagerThread {
|
||||
CoroutineStackFrame(debugProcess, this)
|
||||
val frame = debugProcess.findFirstFrame() ?: return@invokeInManagerThread null
|
||||
val locationFrame = LocationStackFrameProxyImpl(location, frame)
|
||||
val position = location.findPosition(debugProcess.project)
|
||||
CoroutineStackFrame(locationFrame, position)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,10 +112,6 @@ sealed class CoroutineStackFrameItem(val location: Location, val spilledVariable
|
||||
location.safeLineNumber() + ":" + location.safeKotlinPreferredLineNumber()
|
||||
}
|
||||
|
||||
interface FrameProvider {
|
||||
fun provideFrame(debugProcess: DebugProcessImpl): XStackFrame?
|
||||
}
|
||||
|
||||
fun DebugProcessImpl.findFirstFrame(): StackFrameProxyImpl? =
|
||||
suspendManager.pausedContext.thread?.forceFrames()?.firstOrNull()
|
||||
|
||||
@@ -123,19 +123,71 @@ fun DebugProcessImpl.findFirstFrame(): StackFrameProxyImpl? =
|
||||
*/
|
||||
class CoroutinePreflightFrame(
|
||||
val coroutineInfoData: CoroutineInfoData,
|
||||
private val frame: StackFrameProxyImpl,
|
||||
val frame: StackFrameProxyImpl,
|
||||
val threadPreCoroutineFrames: List<StackFrameProxyImpl>,
|
||||
val mode: SuspendExitMode
|
||||
) : KotlinStackFrame(frame), JVMStackFrameInfoProvider {
|
||||
val mode: SuspendExitMode,
|
||||
private val firstFrameVariables: List<XNamedValue> = coroutineInfoData.topFrameVariables()
|
||||
) : CoroutineStackFrame(frame, null, firstFrameVariables) {
|
||||
|
||||
override fun isInLibraryContent() = false
|
||||
|
||||
override fun isSynthetic() = false
|
||||
|
||||
}
|
||||
|
||||
class CreationCoroutineStackFrame(
|
||||
frame: StackFrameProxyImpl,
|
||||
sourcePosition: XSourcePosition?,
|
||||
val first: Boolean
|
||||
) : CoroutineStackFrame(frame, sourcePosition, emptyList(), false), XDebuggerFramesList.ItemWithSeparatorAbove {
|
||||
|
||||
override fun getCaptionAboveOf() =
|
||||
KotlinDebuggerCoroutinesBundle.message("coroutine.dump.creation.trace")
|
||||
|
||||
override fun hasSeparatorAbove() =
|
||||
first
|
||||
}
|
||||
|
||||
open class CoroutineStackFrame(
|
||||
frame: StackFrameProxyImpl,
|
||||
val position: XSourcePosition?,
|
||||
private val spilledVariables: List<XNamedValue>? = null,
|
||||
private val includeFrameVariables: Boolean = true,
|
||||
) : KotlinStackFrame(frame) {
|
||||
|
||||
init {
|
||||
descriptor.updateRepresentation(null, DescriptorLabelListener.DUMMY_LISTENER)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
|
||||
val frame = other as? JavaStackFrame ?: return false
|
||||
|
||||
return descriptor.frameProxy == frame.descriptor.frameProxy
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return descriptor.frameProxy.hashCode()
|
||||
}
|
||||
|
||||
override fun computeChildren(node: XCompositeNode) {
|
||||
if (includeFrameVariables || spilledVariables == null) {
|
||||
super.computeChildren(node)
|
||||
} else {
|
||||
// ignore original frame variables
|
||||
val list = XValueChildrenList()
|
||||
spilledVariables.forEach { list.add(it) }
|
||||
node.addChildren(list, true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun superBuildVariables(evaluationContext: EvaluationContextImpl, children: XValueChildrenList) {
|
||||
super.superBuildVariables(evaluationContext, children)
|
||||
val topRestoredFrame = coroutineInfoData.stackTrace.firstOrNull()
|
||||
if (topRestoredFrame != null && topRestoredFrame.location.isFilteredInvokeSuspend()) {
|
||||
val firstFrameVariables: List<XNamedValue> = topRestoredFrame.spilledVariables
|
||||
if (spilledVariables != null) {
|
||||
children.let {
|
||||
val varNames = (0 until children.size()).map { children.getName(it) }.toSet()
|
||||
firstFrameVariables.forEach {
|
||||
spilledVariables.forEach {
|
||||
if (!varNames.contains(it.name))
|
||||
children.add(it)
|
||||
}
|
||||
@@ -143,32 +195,6 @@ class CoroutinePreflightFrame(
|
||||
}
|
||||
}
|
||||
|
||||
override fun isInLibraryContent() = false
|
||||
|
||||
override fun isSynthetic() = false
|
||||
}
|
||||
|
||||
class CreationCoroutineStackFrame(debugProcess: DebugProcessImpl, item: CoroutineStackFrameItem, val first: Boolean) : CoroutineStackFrame(debugProcess, item) {
|
||||
override fun getCaptionAboveOf() = KotlinDebuggerCoroutinesBundle.message("coroutine.dump.creation.trace")
|
||||
|
||||
override fun hasSeparatorAbove(): Boolean =
|
||||
first
|
||||
}
|
||||
|
||||
open class CoroutineStackFrame(val debugProcess: DebugProcessImpl, val item: CoroutineStackFrameItem) :
|
||||
StackFrameItem.CapturedStackFrame(debugProcess, item) {
|
||||
|
||||
override fun computeChildren(node: XCompositeNode) {
|
||||
if (item is FrameProvider)
|
||||
item.provideFrame(debugProcess)?.computeChildren(node)
|
||||
else
|
||||
super.computeChildren(node)
|
||||
}
|
||||
|
||||
override fun getCaptionAboveOf() = "CoroutineExit"
|
||||
|
||||
override fun hasSeparatorAbove(): Boolean =
|
||||
false
|
||||
}
|
||||
|
||||
typealias CoroutineGeneratedFrame = StackFrameItem.CapturedStackFrame
|
||||
override fun getSourcePosition() =
|
||||
position ?: super.getSourcePosition()
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 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.coroutine.data
|
||||
|
||||
import com.intellij.debugger.engine.DebugProcessImpl
|
||||
import com.intellij.debugger.engine.JVMStackFrameInfoProvider
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
|
||||
import com.intellij.debugger.jdi.StackFrameProxyImpl
|
||||
import com.intellij.debugger.memory.utils.StackFrameItem
|
||||
import com.intellij.xdebugger.frame.XCompositeNode
|
||||
import com.intellij.xdebugger.frame.XNamedValue
|
||||
import com.intellij.xdebugger.frame.XStackFrame
|
||||
import com.intellij.xdebugger.frame.XValueChildrenList
|
||||
import com.sun.jdi.Location
|
||||
import org.jetbrains.kotlin.idea.debugger.*
|
||||
import org.jetbrains.kotlin.idea.debugger.coroutine.KotlinDebuggerCoroutinesBundle
|
||||
import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.LocationStackFrameProxyImpl
|
||||
import org.jetbrains.kotlin.idea.debugger.coroutine.util.findPosition
|
||||
import org.jetbrains.kotlin.idea.debugger.coroutine.util.isFilteredInvokeSuspend
|
||||
import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger
|
||||
import org.jetbrains.kotlin.idea.debugger.stackFrame.KotlinStackFrame
|
||||
|
||||
/**
|
||||
* Creation frame of coroutine either in RUNNING or SUSPENDED state.
|
||||
*/
|
||||
class CreationCoroutineStackFrameItem(
|
||||
val stackTraceElement: StackTraceElement,
|
||||
location: Location,
|
||||
val first: Boolean
|
||||
) : CoroutineStackFrameItem(location, emptyList()) {
|
||||
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): CoroutineGeneratedFrame? {
|
||||
return debugProcess.invokeInManagerThread {
|
||||
val frame = debugProcess.findFirstFrame() ?: return@invokeInManagerThread null
|
||||
val locationFrame = LocationStackFrameProxyImpl(location, frame)
|
||||
val position = location.findPosition(debugProcess.project)
|
||||
CreationCoroutineStackFrame(debugProcess, this, first)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restored frame in SUSPENDED coroutine, not attached to any thread.
|
||||
*/
|
||||
class SuspendCoroutineStackFrameItem(
|
||||
val stackTraceElement: StackTraceElement,
|
||||
location: Location,
|
||||
spilledVariables: List<XNamedValue> = emptyList()
|
||||
) : CoroutineStackFrameItem(location, spilledVariables)
|
||||
|
||||
/**
|
||||
* Restored from memory dump
|
||||
*/
|
||||
class DefaultCoroutineStackFrameItem(location: Location, spilledVariables: List<XNamedValue>) :
|
||||
CoroutineStackFrameItem(location, spilledVariables) {
|
||||
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): CoroutineGeneratedFrame? {
|
||||
return debugProcess.invokeInManagerThread {
|
||||
val frame = debugProcess.findFirstFrame() ?: return@invokeInManagerThread null
|
||||
val locationStackFrameProxyImpl = LocationStackFrameProxyImpl(location, frame)
|
||||
val position = location.findPosition(debugProcess.project) ?: return@invokeInManagerThread null
|
||||
CoroutineStackFrame(debugProcess, this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Original frame appeared before resumeWith call.
|
||||
*
|
||||
* Sequence is the following
|
||||
*
|
||||
* - KotlinStackFrame
|
||||
* - invokeSuspend(KotlinStackFrame) -|
|
||||
* | replaced with CoroutinePreflightStackFrame
|
||||
* - resumeWith(KotlinStackFrame) ----|
|
||||
* - Kotlin/JavaStackFrame -> PreCoroutineStackFrameItem : CoroutinePreflightStackFrame.threadPreCoroutineFrames
|
||||
*
|
||||
*/
|
||||
open class RunningCoroutineStackFrameItem(
|
||||
val frame: StackFrameProxyImpl,
|
||||
spilledVariables: List<XNamedValue> = emptyList()
|
||||
) : CoroutineStackFrameItem(frame.location(), spilledVariables), FrameProvider {
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): CoroutineGeneratedFrame? {
|
||||
return debugProcess.invokeInManagerThread {
|
||||
CoroutineStackFrame(debugProcess, this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun provideFrame(debugProcess: DebugProcessImpl): XStackFrame? =
|
||||
debugProcess.invokeInManagerThread { KotlinStackFrame(frame) }
|
||||
}
|
||||
|
||||
sealed class CoroutineStackFrameItem(val location: Location, val spilledVariables: List<XNamedValue>) :
|
||||
StackFrameItem(location, spilledVariables) {
|
||||
val log by logger
|
||||
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): CoroutineGeneratedFrame? {
|
||||
return debugProcess.invokeInManagerThread {
|
||||
CoroutineStackFrame(debugProcess, this)
|
||||
}
|
||||
}
|
||||
|
||||
fun uniqueId() =
|
||||
location.safeSourceName() + ":" + location.safeMethod().toString() + ":" +
|
||||
location.safeLineNumber() + ":" + location.safeKotlinPreferredLineNumber()
|
||||
}
|
||||
|
||||
interface FrameProvider {
|
||||
fun provideFrame(debugProcess: DebugProcessImpl): XStackFrame?
|
||||
}
|
||||
|
||||
fun DebugProcessImpl.findFirstFrame(): StackFrameProxyImpl? =
|
||||
suspendManager.pausedContext.thread?.forceFrames()?.firstOrNull()
|
||||
|
||||
/**
|
||||
* Coroutine exit frame represented by a stack frames
|
||||
* invokeSuspend():-1
|
||||
* resumeWith()
|
||||
*
|
||||
*/
|
||||
class CoroutinePreflightFrame(
|
||||
val coroutineInfoData: CoroutineInfoData,
|
||||
private val frame: StackFrameProxyImpl,
|
||||
val threadPreCoroutineFrames: List<StackFrameProxyImpl>,
|
||||
val mode: SuspendExitMode
|
||||
) : KotlinStackFrame(frame), JVMStackFrameInfoProvider {
|
||||
|
||||
override fun superBuildVariables(evaluationContext: EvaluationContextImpl, children: XValueChildrenList) {
|
||||
super.superBuildVariables(evaluationContext, children)
|
||||
val topRestoredFrame = coroutineInfoData.stackTrace.firstOrNull()
|
||||
if (topRestoredFrame != null && topRestoredFrame.location.isFilteredInvokeSuspend()) {
|
||||
val firstFrameVariables: List<XNamedValue> = topRestoredFrame.spilledVariables
|
||||
children.let {
|
||||
val varNames = (0 until children.size()).map { children.getName(it) }.toSet()
|
||||
firstFrameVariables.forEach {
|
||||
if (!varNames.contains(it.name))
|
||||
children.add(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun isInLibraryContent() = false
|
||||
|
||||
override fun isSynthetic() = false
|
||||
}
|
||||
|
||||
class CreationCoroutineStackFrame(debugProcess: DebugProcessImpl, item: CoroutineStackFrameItem, val first: Boolean) : CoroutineStackFrame(debugProcess, item) {
|
||||
override fun getCaptionAboveOf() = KotlinDebuggerCoroutinesBundle.message("coroutine.dump.creation.trace")
|
||||
|
||||
override fun hasSeparatorAbove(): Boolean =
|
||||
first
|
||||
}
|
||||
|
||||
open class CoroutineStackFrame(val debugProcess: DebugProcessImpl, val item: CoroutineStackFrameItem) :
|
||||
StackFrameItem.CapturedStackFrame(debugProcess, item) {
|
||||
|
||||
override fun computeChildren(node: XCompositeNode) {
|
||||
if (item is FrameProvider)
|
||||
item.provideFrame(debugProcess)?.computeChildren(node)
|
||||
else
|
||||
super.computeChildren(node)
|
||||
}
|
||||
|
||||
override fun getCaptionAboveOf() = "CoroutineExit"
|
||||
|
||||
override fun hasSeparatorAbove(): Boolean =
|
||||
false
|
||||
}
|
||||
|
||||
typealias CoroutineGeneratedFrame = StackFrameItem.CapturedStackFrame
|
||||
@@ -11,8 +11,8 @@ import com.intellij.openapi.project.ex.ProjectManagerEx
|
||||
// FIX ME WHEN BUNCH 193 REMOVED
|
||||
fun ProjectManagerEx.forceCloseProjectEx(project: Project, dispose: Boolean): Boolean {
|
||||
if (!dispose) error("dispose should be true")
|
||||
return this.forceCloseProject(project, true)
|
||||
return this.forceCloseProject(project)
|
||||
}
|
||||
|
||||
// FIX ME WHEN BUNCH 193 REMOVED
|
||||
typealias TestApplicationManager = com.intellij.idea.IdeaTestApplication
|
||||
typealias TestApplicationManager = com.intellij.testFramework.TestApplicationManager
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* 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.project.Project
|
||||
import com.intellij.openapi.project.ex.ProjectManagerEx
|
||||
|
||||
// FIX ME WHEN BUNCH 193 REMOVED
|
||||
fun ProjectManagerEx.forceCloseProjectEx(project: Project, dispose: Boolean): Boolean {
|
||||
if (!dispose) error("dispose should be true")
|
||||
return this.forceCloseProject(project, true)
|
||||
}
|
||||
|
||||
// FIX ME WHEN BUNCH 193 REMOVED
|
||||
typealias TestApplicationManager = com.intellij.idea.IdeaTestApplication
|
||||
@@ -13,11 +13,13 @@ import com.intellij.openapi.externalSystem.util.ExternalSystemUtil
|
||||
import com.intellij.openapi.project.DumbService
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.ProjectRootManager
|
||||
import org.gradle.util.GradleVersion
|
||||
import org.jetbrains.plugins.gradle.service.project.open.setupGradleSettings
|
||||
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings
|
||||
import org.jetbrains.plugins.gradle.settings.GradleSettings
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants
|
||||
import org.jetbrains.plugins.gradle.util.GradleLog
|
||||
import org.jetbrains.plugins.gradle.util.suggestGradleVersion
|
||||
import java.io.File
|
||||
import kotlin.test.assertNotNull
|
||||
|
||||
@@ -34,14 +36,13 @@ const val GRADLE_JDK_NAME = "Gradle JDK"
|
||||
*/
|
||||
private fun _importProject(projectPath: String, project: Project) {
|
||||
GradleLog.LOG.info("Import project at $projectPath")
|
||||
val projectSdk = ProjectRootManager.getInstance(project).projectSdk
|
||||
assertNotNull(projectSdk, "project SDK not found for ${project.name} at $projectPath")
|
||||
val gradleProjectSettings = GradleProjectSettings()
|
||||
val gradleVersion = suggestGradleVersion(project) ?: GradleVersion.current()
|
||||
|
||||
GradleSettings.getInstance(project).gradleVmOptions =
|
||||
"-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${System.getProperty("user.dir")}"
|
||||
|
||||
setupGradleSettings(gradleProjectSettings, projectPath, project, projectSdk)
|
||||
setupGradleSettings(project, gradleProjectSettings, projectPath, gradleVersion)
|
||||
gradleProjectSettings.gradleJvm = GRADLE_JDK_NAME
|
||||
|
||||
GradleSettings.getInstance(project).getLinkedProjectSettings(projectPath)?.let { linkedProjectSettings ->
|
||||
@@ -65,8 +66,6 @@ private fun _attachGradleProjectAndRefresh(
|
||||
ExternalSystemUtil.ensureToolWindowInitialized(project, GradleConstants.SYSTEM_ID)
|
||||
}
|
||||
}
|
||||
|
||||
ExternalProjectsManagerImpl.disableProjectWatcherAutoUpdate(project)
|
||||
val settings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID)
|
||||
if (settings.getLinkedProjectSettings(externalProjectPath) == null) {
|
||||
settings.linkProject(gradleProjectSettings)
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.openapi.externalSystem.importing.ImportSpecBuilder
|
||||
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil
|
||||
import com.intellij.openapi.project.DumbService
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.ProjectRootManager
|
||||
import org.jetbrains.plugins.gradle.service.project.open.setupGradleSettings
|
||||
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings
|
||||
import org.jetbrains.plugins.gradle.settings.GradleSettings
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants
|
||||
import org.jetbrains.plugins.gradle.util.GradleLog
|
||||
import java.io.File
|
||||
import kotlin.test.assertNotNull
|
||||
|
||||
fun refreshGradleProject(projectPath: String, project: Project) {
|
||||
_importProject(File(projectPath).absolutePath, project)
|
||||
|
||||
dispatchAllInvocationEvents()
|
||||
}
|
||||
|
||||
const val GRADLE_JDK_NAME = "Gradle JDK"
|
||||
|
||||
/**
|
||||
* inspired by org.jetbrains.plugins.gradle.service.project.open.importProject(projectDirectory, project)
|
||||
*/
|
||||
private fun _importProject(projectPath: String, project: Project) {
|
||||
GradleLog.LOG.info("Import project at $projectPath")
|
||||
val projectSdk = ProjectRootManager.getInstance(project).projectSdk
|
||||
assertNotNull(projectSdk, "project SDK not found for ${project.name} at $projectPath")
|
||||
val gradleProjectSettings = GradleProjectSettings()
|
||||
|
||||
GradleSettings.getInstance(project).gradleVmOptions =
|
||||
"-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${System.getProperty("user.dir")}"
|
||||
|
||||
setupGradleSettings(gradleProjectSettings, projectPath, project, projectSdk)
|
||||
gradleProjectSettings.gradleJvm = GRADLE_JDK_NAME
|
||||
|
||||
GradleSettings.getInstance(project).getLinkedProjectSettings(projectPath)?.let { linkedProjectSettings ->
|
||||
linkedProjectSettings.gradleJvm = GRADLE_JDK_NAME
|
||||
}
|
||||
|
||||
_attachGradleProjectAndRefresh(gradleProjectSettings, project)
|
||||
}
|
||||
|
||||
/**
|
||||
* inspired by org.jetbrains.plugins.gradle.service.project.open.attachGradleProjectAndRefresh(gradleProjectSettings, project)
|
||||
* except everything is MODAL_SYNC
|
||||
*/
|
||||
private fun _attachGradleProjectAndRefresh(
|
||||
gradleProjectSettings: GradleProjectSettings,
|
||||
project: Project
|
||||
) {
|
||||
val externalProjectPath = gradleProjectSettings.externalProjectPath
|
||||
ExternalProjectsManagerImpl.getInstance(project).runWhenInitialized {
|
||||
DumbService.getInstance(project).runWhenSmart {
|
||||
ExternalSystemUtil.ensureToolWindowInitialized(project, GradleConstants.SYSTEM_ID)
|
||||
}
|
||||
}
|
||||
|
||||
ExternalProjectsManagerImpl.disableProjectWatcherAutoUpdate(project)
|
||||
val settings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID)
|
||||
if (settings.getLinkedProjectSettings(externalProjectPath) == null) {
|
||||
settings.linkProject(gradleProjectSettings)
|
||||
}
|
||||
|
||||
StatefulTestGradleProjectRefreshCallback(externalProjectPath, project).use { callback ->
|
||||
ExternalSystemUtil.refreshProject(
|
||||
externalProjectPath,
|
||||
ImportSpecBuilder(project, GradleConstants.SYSTEM_ID)
|
||||
.use(ProgressExecutionMode.MODAL_SYNC)
|
||||
.callback(callback)
|
||||
.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.testFramework
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings
|
||||
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl
|
||||
import com.intellij.ide.impl.OpenProjectTask
|
||||
import com.intellij.ide.startup.impl.StartupManagerImpl
|
||||
import com.intellij.lang.LanguageAnnotators
|
||||
import com.intellij.lang.LanguageExtensionPoint
|
||||
@@ -19,6 +20,7 @@ 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.platform.PlatformProjectOpenProcessor
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.impl.PsiDocumentManagerBase
|
||||
import com.intellij.testFramework.ExtensionTestUtil
|
||||
@@ -70,7 +72,7 @@ fun dispatchAllInvocationEvents() {
|
||||
}
|
||||
|
||||
fun loadProjectWithName(path: String, name: String): Project? =
|
||||
ProjectManagerEx.getInstanceEx().loadProject(Paths.get(path), name)
|
||||
PlatformProjectOpenProcessor.openExistingProject(Paths.get(path), Paths.get(path), OpenProjectTask(projectName = name))
|
||||
|
||||
fun TestApplicationManager.closeProject(project: Project) {
|
||||
val name = project.name
|
||||
@@ -92,11 +94,7 @@ fun TestApplicationManager.closeProject(project: Project) {
|
||||
}
|
||||
|
||||
fun runStartupActivities(project: Project) {
|
||||
with(StartupManager.getInstance(project) as StartupManagerImpl) {
|
||||
//scheduleInitialVfsRefresh()
|
||||
runStartupActivities()
|
||||
}
|
||||
runPostStartupActivitiesOnce(project)
|
||||
// obsolete
|
||||
}
|
||||
|
||||
fun waitForAllEditorsFinallyLoaded(project: Project) {
|
||||
|
||||
@@ -1,63 +1,57 @@
|
||||
<idea-plugin>
|
||||
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
|
||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinMPPSourceSetsFrameworkSupportProvider"/>
|
||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJavaFrameworkSupportProvider"/>
|
||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSBrowserFrameworkSupportProvider"/>
|
||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSNodeFrameworkSupportProvider"/>
|
||||
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinMPPFrameworkSupportProvider"/>
|
||||
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJavaFrameworkSupportProvider"/>
|
||||
<kotlinDslFrameworkSupport
|
||||
implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSBrowserFrameworkSupportProvider"/>
|
||||
<kotlinDslFrameworkSupport
|
||||
implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSNodeFrameworkSupportProvider"/>
|
||||
<pluginDescriptions implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradlePluginDescription"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinNonJvmGutterConfigurator"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModelResolver" order="first"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.cocoapods.KotlinCocoaPodsModelResolver" order="first"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.commonizer.KotlinCommonizerModelResolver" order="first"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectResolverExtension" order="first"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleCoroutineDebugProjectResolver" order="last"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.kapt.idea.KaptProjectResolverExtension" order="last"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.allopen.ide.AllOpenProjectResolverExtension" order="last"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.noarg.ide.NoArgProjectResolverExtension" order="last"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.samWithReceiver.ide.SamWithReceiverProjectResolverExtension" order="last"/>
|
||||
</extensions>
|
||||
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
|
||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinMPPSourceSetsFrameworkSupportProvider"/>
|
||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJavaFrameworkSupportProvider"/>
|
||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSBrowserFrameworkSupportProvider"/>
|
||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSNodeFrameworkSupportProvider"/>
|
||||
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinMPPFrameworkSupportProvider"/>
|
||||
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJavaFrameworkSupportProvider"/>
|
||||
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSBrowserFrameworkSupportProvider"/>
|
||||
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSNodeFrameworkSupportProvider"/>
|
||||
<pluginDescriptions implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradlePluginDescription"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModelResolver" order="first"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.commonizer.KotlinCommonizerModelResolver" order="first"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectResolverExtension" order="first"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleCoroutineDebugProjectResolver" order="last"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.kapt.idea.KaptProjectResolverExtension" order="last"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.allopen.ide.AllOpenProjectResolverExtension" order="last"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.noarg.ide.NoArgProjectResolverExtension" order="last"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.samWithReceiver.ide.SamWithReceiverProjectResolverExtension" order="last"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleSourceSetDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleLibraryDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinTargetDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.KotlinJavaMPPSourceSetDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.klib.KotlinNativeLibraryDataService"/>
|
||||
<externalSystemTaskNotificationListener
|
||||
implementation="org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslSyncListener"
|
||||
/>
|
||||
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.scripting.gradle.MissingGradleScriptConfigurationNotificationProvider"/>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleSourceSetDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleLibraryDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinTargetDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.KotlinJavaMPPSourceSetDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.klib.KotlinNativeLibraryDataService"/>
|
||||
<externalSystemTaskNotificationListener
|
||||
implementation="org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslSyncListener"
|
||||
/>
|
||||
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.scripting.gradle.MissingGradleScriptConfigurationNotificationProvider"/>
|
||||
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinJvmTestClassGradleConfigurationProducer"/>
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinMultiplatformJvmTestClassGradleConfigurationProducer"/>
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinJvmTestMethodGradleConfigurationProducer"/>
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinMultiplatformJvmTestMethodGradleConfigurationProducer"/>
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinJvmTestClassGradleConfigurationProducer"/>
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinMultiplatformJvmTestClassGradleConfigurationProducer"/>
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinJvmTestMethodGradleConfigurationProducer"/>
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinMultiplatformJvmTestMethodGradleConfigurationProducer"/>
|
||||
|
||||
</extensions>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="org.jetbrains.kotlin">
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.allopen.ide.AllOpenGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.scripting.idea.plugin.ScriptingGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.kapt.idea.KaptGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.noarg.ide.NoArgGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.samWithReceiver.ide.SamWithReceiverGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlinx.serialization.idea.KotlinSerializationGradleImportHandler"/>
|
||||
<extensions defaultExtensionNs="org.jetbrains.kotlin">
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.allopen.ide.AllOpenGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.scripting.idea.plugin.ScriptingGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.kapt.idea.KaptGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.noarg.ide.NoArgGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.samWithReceiver.ide.SamWithReceiverGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlinx.serialization.idea.KotlinSerializationGradleImportHandler"/>
|
||||
|
||||
<projectConfigurator implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleModuleConfigurator"/>
|
||||
<projectConfigurator implementation="org.jetbrains.kotlin.idea.configuration.KotlinJsGradleModuleConfigurator"/>
|
||||
<gradleModelFacade implementation="org.jetbrains.kotlin.idea.inspections.gradle.DefaultGradleModelFacade"/>
|
||||
<projectConfigurator implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleModuleConfigurator"/>
|
||||
<projectConfigurator implementation="org.jetbrains.kotlin.idea.configuration.KotlinJsGradleModuleConfigurator"/>
|
||||
<gradleModelFacade implementation="org.jetbrains.kotlin.idea.inspections.gradle.DefaultGradleModelFacade"/>
|
||||
|
||||
<scriptDefinitionContributor implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptDefinitionsContributor"
|
||||
order="first"/>
|
||||
<scriptAdditionalIdeaDependenciesProvider
|
||||
implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptAdditionalIdeaDependenciesProvider"/>
|
||||
<scriptDefinitionContributor implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptDefinitionsContributor" order="first"/>
|
||||
<scriptAdditionalIdeaDependenciesProvider implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptAdditionalIdeaDependenciesProvider"/>
|
||||
|
||||
</extensions>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
|
||||
63
idea/resources/META-INF/gradle-java.xml.193
Normal file
63
idea/resources/META-INF/gradle-java.xml.193
Normal file
@@ -0,0 +1,63 @@
|
||||
<idea-plugin>
|
||||
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
|
||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinMPPSourceSetsFrameworkSupportProvider"/>
|
||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJavaFrameworkSupportProvider"/>
|
||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSBrowserFrameworkSupportProvider"/>
|
||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSNodeFrameworkSupportProvider"/>
|
||||
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinMPPFrameworkSupportProvider"/>
|
||||
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJavaFrameworkSupportProvider"/>
|
||||
<kotlinDslFrameworkSupport
|
||||
implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSBrowserFrameworkSupportProvider"/>
|
||||
<kotlinDslFrameworkSupport
|
||||
implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSNodeFrameworkSupportProvider"/>
|
||||
<pluginDescriptions implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradlePluginDescription"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinNonJvmGutterConfigurator"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModelResolver" order="first"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.cocoapods.KotlinCocoaPodsModelResolver" order="first"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.commonizer.KotlinCommonizerModelResolver" order="first"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectResolverExtension" order="first"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleCoroutineDebugProjectResolver" order="last"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.kapt.idea.KaptProjectResolverExtension" order="last"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.allopen.ide.AllOpenProjectResolverExtension" order="last"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.noarg.ide.NoArgProjectResolverExtension" order="last"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.samWithReceiver.ide.SamWithReceiverProjectResolverExtension" order="last"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleSourceSetDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleLibraryDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinTargetDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.KotlinJavaMPPSourceSetDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.klib.KotlinNativeLibraryDataService"/>
|
||||
<externalSystemTaskNotificationListener
|
||||
implementation="org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslSyncListener"
|
||||
/>
|
||||
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.scripting.gradle.MissingGradleScriptConfigurationNotificationProvider"/>
|
||||
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinJvmTestClassGradleConfigurationProducer"/>
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinMultiplatformJvmTestClassGradleConfigurationProducer"/>
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinJvmTestMethodGradleConfigurationProducer"/>
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinMultiplatformJvmTestMethodGradleConfigurationProducer"/>
|
||||
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="org.jetbrains.kotlin">
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.allopen.ide.AllOpenGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.scripting.idea.plugin.ScriptingGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.kapt.idea.KaptGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.noarg.ide.NoArgGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.samWithReceiver.ide.SamWithReceiverGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlinx.serialization.idea.KotlinSerializationGradleImportHandler"/>
|
||||
|
||||
<projectConfigurator implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleModuleConfigurator"/>
|
||||
<projectConfigurator implementation="org.jetbrains.kotlin.idea.configuration.KotlinJsGradleModuleConfigurator"/>
|
||||
<gradleModelFacade implementation="org.jetbrains.kotlin.idea.inspections.gradle.DefaultGradleModelFacade"/>
|
||||
|
||||
<scriptDefinitionContributor implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptDefinitionsContributor"
|
||||
order="first"/>
|
||||
<scriptAdditionalIdeaDependenciesProvider
|
||||
implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptAdditionalIdeaDependenciesProvider"/>
|
||||
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -24,6 +24,8 @@
|
||||
<orderEnumerationHandlerFactory implementation="org.jetbrains.kotlin.idea.gradle.execution.KotlinGradleOrderEnumerationHandler$Factory" order="first"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinMPPGradleProjectResolver"/>
|
||||
<testTasksProvider implementation="org.jetbrains.kotlin.idea.run.KotlinMPPGradleTestTasksProvider"/>
|
||||
|
||||
<projectModelContributor implementation="org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModelContributor"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
@@ -42,5 +44,9 @@
|
||||
<action id="Kotlin.Gradle.ShowDslLogs" class="org.jetbrains.kotlin.idea.actions.ShowKotlinGradleDslLogs"
|
||||
text="Show Kotlin Gradle DSL Logs" description="Show Kotlin Gradle DSL logs">
|
||||
</action>
|
||||
|
||||
<action id="LoadConfigurationAction" class="org.jetbrains.kotlin.idea.scripting.gradle.LoadConfigurationAction">
|
||||
<add-to-group group-id="ExternalSystem.ProjectRefreshActionGroup" anchor="first"/>
|
||||
</action>
|
||||
</actions>
|
||||
</idea-plugin>
|
||||
|
||||
46
idea/resources/META-INF/gradle.xml.193
Normal file
46
idea/resources/META-INF/gradle.xml.193
Normal file
@@ -0,0 +1,46 @@
|
||||
<idea-plugin>
|
||||
<extensionPoints>
|
||||
<extensionPoint qualifiedName="org.jetbrains.kotlin.gradleProjectImportHandler" area="IDEA_PROJECT"
|
||||
interface="org.jetbrains.kotlin.idea.configuration.GradleProjectImportHandler"/>
|
||||
|
||||
<extensionPoint qualifiedName="org.jetbrains.kotlin.gradleModelFacade"
|
||||
interface="org.jetbrains.kotlin.idea.inspections.gradle.KotlinGradleModelFacade"/>
|
||||
</extensionPoints>
|
||||
|
||||
<extensions defaultExtensionNs="org.jetbrains.kotlin">
|
||||
<buildSystemTypeDetector implementation="org.jetbrains.kotlin.idea.configuration.GradleDetector"/>
|
||||
<scriptDiagnosticFixProvider implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptDiagnosticFixProvider"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="org.jetbrains.kotlin.scripting.idea">
|
||||
<listener order="first" implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptListener"/>
|
||||
|
||||
<loader order="first" implementation="org.jetbrains.kotlin.idea.scripting.gradle.legacy.GradleLegacyScriptConfigurationLoader"/>
|
||||
|
||||
<scriptingSupport implementation="org.jetbrains.kotlin.idea.scripting.gradle.roots.GradleBuildRootsManager"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
|
||||
<orderEnumerationHandlerFactory implementation="org.jetbrains.kotlin.idea.gradle.execution.KotlinGradleOrderEnumerationHandler$Factory" order="first"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinMPPGradleProjectResolver"/>
|
||||
<testTasksProvider implementation="org.jetbrains.kotlin.idea.run.KotlinMPPGradleTestTasksProvider"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<projectTaskRunner implementation="org.jetbrains.kotlin.idea.gradle.execution.KotlinMPPGradleProjectTaskRunner" order="first, before gradle"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinSourceSetDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectSettingsDataService"/>
|
||||
|
||||
<registryKey key="kotlin.mpp.tests.force.gradle"
|
||||
description="Run multi-platform tests with Gradle runner even if the platform runner is used by default.
|
||||
This setting currently affects only HMPP projects. You may need to delete existing test configurations for the change to take place."
|
||||
defaultValue="true"
|
||||
restartRequired="false"/>
|
||||
</extensions>
|
||||
|
||||
<actions>
|
||||
<action id="Kotlin.Gradle.ShowDslLogs" class="org.jetbrains.kotlin.idea.actions.ShowKotlinGradleDslLogs"
|
||||
text="Show Kotlin Gradle DSL Logs" description="Show Kotlin Gradle DSL logs">
|
||||
</action>
|
||||
</actions>
|
||||
</idea-plugin>
|
||||
@@ -1,5 +1,9 @@
|
||||
<idea-plugin>
|
||||
|
||||
<extensions defaultExtensionNs="org.jetbrains.uast">
|
||||
<generate.uastCodeGenerationPlugin implementation="org.jetbrains.uast.kotlin.generate.KotlinUastCodeGenerationPlugin"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<postStartupActivity implementation="org.jetbrains.kotlin.idea.configuration.ui.KotlinConfigurationCheckerStartupActivity"/>
|
||||
<postStartupActivity implementation="org.jetbrains.kotlin.idea.JvmPluginStartupActivity"/>
|
||||
|
||||
12
idea/resources/META-INF/jvm.xml.193
Normal file
12
idea/resources/META-INF/jvm.xml.193
Normal file
@@ -0,0 +1,12 @@
|
||||
<idea-plugin>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<postStartupActivity implementation="org.jetbrains.kotlin.idea.configuration.ui.KotlinConfigurationCheckerStartupActivity"/>
|
||||
<postStartupActivity implementation="org.jetbrains.kotlin.idea.JvmPluginStartupActivity"/>
|
||||
<postStartupActivity implementation="org.jetbrains.kotlin.idea.compiler.KotlinCompilerStartupActivity"/>
|
||||
<postStartupActivity implementation="org.jetbrains.kotlin.idea.scratch.ScratchFileModuleInfoProvider"/>
|
||||
|
||||
<projectService serviceImplementation="org.jetbrains.kotlin.idea.configuration.ui.KotlinConfigurationCheckerService"/>
|
||||
</extensions>
|
||||
|
||||
</idea-plugin>
|
||||
@@ -13,7 +13,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
|
||||
<version>@snapshot@</version>
|
||||
<vendor url="http://www.jetbrains.com">JetBrains</vendor>
|
||||
|
||||
<idea-version since-build="193.4099.13" until-build="193.*"/>
|
||||
<idea-version since-build="202.1" until-build="203.*"/>
|
||||
|
||||
<depends>com.intellij.modules.platform</depends>
|
||||
|
||||
@@ -35,7 +35,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
|
||||
<!-- ULTIMATE-PLUGIN-PLACEHOLDER -->
|
||||
|
||||
<!-- CIDR-PLUGIN-PLACEHOLDER-START -->
|
||||
<depends>com.intellij.modules.idea</depends>
|
||||
<incompatible-with>com.intellij.modules.androidstudio</incompatible-with>
|
||||
<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>
|
||||
@@ -60,12 +60,6 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
|
||||
|
||||
<xi:include href="scripting-support.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<project-components>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.kotlin.idea.caches.trackers.KotlinCodeBlockModificationListener</implementation-class>
|
||||
</component>
|
||||
</project-components>
|
||||
|
||||
<extensionPoints>
|
||||
<xi:include href="extensions/compiler.xml" xpointer="xpointer(/idea-plugin/extensionPoints/*)"/>
|
||||
|
||||
@@ -97,6 +91,8 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
|
||||
<highlightingPassFactory implementation="org.jetbrains.kotlin.idea.parameterInfo.custom.KotlinCodeHintsPass$Registrar"/>
|
||||
<highlightingPassFactory implementation="org.jetbrains.kotlin.idea.refactoring.cutPaste.MoveDeclarationsPassFactory$Registrar"/>
|
||||
|
||||
<projectService serviceImplementation="org.jetbrains.kotlin.idea.caches.trackers.KotlinCodeBlockModificationListener"/>
|
||||
|
||||
<statistics.counterUsagesCollector groupId="kotlin.gradle.target" version="2"/>
|
||||
<statistics.counterUsagesCollector groupId="kotlin.maven.target" version="3"/>
|
||||
<statistics.counterUsagesCollector groupId="kotlin.jps.target" version="3"/>
|
||||
@@ -118,8 +114,12 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
|
||||
|
||||
<completion.ml.model implementation="org.jetbrains.kotlin.idea.completion.ml.KotlinMLRankingProvider"/>
|
||||
<completion.ml.contextFeatures language="kotlin" implementationClass="org.jetbrains.kotlin.idea.completion.ml.KotlinContextFeatureProvider"/>
|
||||
<suggestedRefactoringSupport language="kotlin" implementationClass="org.jetbrains.kotlin.idea.refactoring.suggested.KotlinSuggestedRefactoringSupport"/>
|
||||
|
||||
<defaultLiveTemplatesProvider implementation="org.jetbrains.kotlin.idea.liveTemplates.KotlinLiveTemplatesProvider"/>
|
||||
<refactoring.moveInnerHandler language="kotlin"
|
||||
implementationClass="org.jetbrains.kotlin.idea.refactoring.move.MoveKotlinInnerHandler"/>
|
||||
|
||||
<defaultLiveTemplates file="liveTemplates/Kotlin.xml"/>
|
||||
|
||||
<fileType name="Kotlin"
|
||||
implementationClass="org.jetbrains.kotlin.idea.KotlinFileType"
|
||||
|
||||
@@ -13,7 +13,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
|
||||
<version>@snapshot@</version>
|
||||
<vendor url="http://www.jetbrains.com">JetBrains</vendor>
|
||||
|
||||
<idea-version since-build="202.1" until-build="203.*"/>
|
||||
<idea-version since-build="193.4099.13" until-build="193.*"/>
|
||||
|
||||
<depends>com.intellij.modules.platform</depends>
|
||||
|
||||
@@ -35,7 +35,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
|
||||
<!-- ULTIMATE-PLUGIN-PLACEHOLDER -->
|
||||
|
||||
<!-- CIDR-PLUGIN-PLACEHOLDER-START -->
|
||||
<incompatible-with>com.intellij.modules.androidstudio</incompatible-with>
|
||||
<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>
|
||||
@@ -60,6 +60,12 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
|
||||
|
||||
<xi:include href="scripting-support.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<project-components>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.kotlin.idea.caches.trackers.KotlinCodeBlockModificationListener</implementation-class>
|
||||
</component>
|
||||
</project-components>
|
||||
|
||||
<extensionPoints>
|
||||
<xi:include href="extensions/compiler.xml" xpointer="xpointer(/idea-plugin/extensionPoints/*)"/>
|
||||
|
||||
@@ -91,8 +97,6 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
|
||||
<highlightingPassFactory implementation="org.jetbrains.kotlin.idea.parameterInfo.custom.KotlinCodeHintsPass$Registrar"/>
|
||||
<highlightingPassFactory implementation="org.jetbrains.kotlin.idea.refactoring.cutPaste.MoveDeclarationsPassFactory$Registrar"/>
|
||||
|
||||
<projectService serviceImplementation="org.jetbrains.kotlin.idea.caches.trackers.KotlinCodeBlockModificationListener"/>
|
||||
|
||||
<statistics.counterUsagesCollector groupId="kotlin.gradle.target" version="2"/>
|
||||
<statistics.counterUsagesCollector groupId="kotlin.maven.target" version="3"/>
|
||||
<statistics.counterUsagesCollector groupId="kotlin.jps.target" version="3"/>
|
||||
@@ -114,12 +118,8 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
|
||||
|
||||
<completion.ml.model implementation="org.jetbrains.kotlin.idea.completion.ml.KotlinMLRankingProvider"/>
|
||||
<completion.ml.contextFeatures language="kotlin" implementationClass="org.jetbrains.kotlin.idea.completion.ml.KotlinContextFeatureProvider"/>
|
||||
<suggestedRefactoringSupport language="kotlin" implementationClass="org.jetbrains.kotlin.idea.refactoring.suggested.KotlinSuggestedRefactoringSupport"/>
|
||||
|
||||
<refactoring.moveInnerHandler language="kotlin"
|
||||
implementationClass="org.jetbrains.kotlin.idea.refactoring.move.MoveKotlinInnerHandler"/>
|
||||
|
||||
<defaultLiveTemplates file="liveTemplates/Kotlin.xml"/>
|
||||
<defaultLiveTemplatesProvider implementation="org.jetbrains.kotlin.idea.liveTemplates.KotlinLiveTemplatesProvider"/>
|
||||
|
||||
<fileType name="Kotlin"
|
||||
implementationClass="org.jetbrains.kotlin.idea.KotlinFileType"
|
||||
@@ -46,7 +46,7 @@ abstract class AbstractScratchLineMarkersTest : FileEditorManagerTestCase() {
|
||||
val project = myFixture.project
|
||||
val document = myFixture.editor.document
|
||||
|
||||
val data = ExpectedHighlightingData(document, false, false, false, myFixture.file)
|
||||
val data = ExpectedHighlightingData(document, false, false, false)
|
||||
data.init()
|
||||
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
||||
@@ -69,7 +69,7 @@ abstract class AbstractScratchLineMarkersTest : FileEditorManagerTestCase() {
|
||||
): List<LineMarkerInfo<*>> {
|
||||
myFixture.doHighlighting()
|
||||
|
||||
return AbstractLineMarkersTest.checkHighlighting(myFixture.project, documentToAnalyze, expectedHighlighting, expectedFile)
|
||||
return AbstractLineMarkersTest.checkHighlighting(myFixture.file, documentToAnalyze, expectedHighlighting, expectedFile)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,5 +5,35 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea
|
||||
|
||||
import com.intellij.codeInsight.javadoc.JavaDocExternalFilter
|
||||
import com.intellij.psi.PsiDocCommentBase
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import java.util.function.Consumer
|
||||
|
||||
// FIX ME WHEN BUNCH 201 REMOVED
|
||||
class KotlinDocumentationProvider : KotlinDocumentationProviderCompatBase()
|
||||
class KotlinDocumentationProvider : KotlinDocumentationProviderCompatBase() {
|
||||
|
||||
override fun collectDocComments(file: PsiFile, sink: Consumer<PsiDocCommentBase>) {
|
||||
if (file !is KtFile) return
|
||||
|
||||
PsiTreeUtil.processElements(file) {
|
||||
val comment = (it as? KtDeclaration)?.docComment
|
||||
if (comment != null) sink.accept(comment)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override fun generateRenderedDoc(element: PsiElement): String? {
|
||||
val docComment = (element as? KtDeclaration)?.docComment ?: return null
|
||||
|
||||
val result = StringBuilder().also {
|
||||
it.renderKDoc(docComment.getDefaultSection(), docComment.getAllSections())
|
||||
}
|
||||
|
||||
return JavaDocExternalFilter.filterInternalDocInfo(result.toString())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
// FIX ME WHEN BUNCH 201 REMOVED
|
||||
class KotlinDocumentationProvider : KotlinDocumentationProviderCompatBase()
|
||||
@@ -5,7 +5,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.codeInsight
|
||||
|
||||
import com.intellij.xml.breadcrumbs.BreadcrumbsInfoProvider
|
||||
import com.intellij.ide.ui.UISettings
|
||||
import com.intellij.ui.breadcrumbs.BreadcrumbsProvider
|
||||
|
||||
// FIX ME WHEN BUNCH 201 REMOVED
|
||||
typealias BreadcrumbsProviderCompatBase = BreadcrumbsInfoProvider
|
||||
abstract class BreadcrumbsProviderCompatBase : BreadcrumbsProvider {
|
||||
override fun isShownByDefault(): Boolean =
|
||||
!UISettings.instance.showMembersInNavigationBar
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user