~~~~ switch 191 ~~~~
diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/MockExternalAnnotationsManager.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/MockExternalAnnotationsManager.kt
index a6d2a75..ebb3b44 100644
--- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/MockExternalAnnotationsManager.kt
+++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/MockExternalAnnotationsManager.kt
@@ -51,7 +51,11 @@
throw UnsupportedOperationException("not implemented")
}
- override fun hasAnnotationRootsForFile(file: VirtualFile): 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()
}
diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/MockExternalAnnotationsManager.kt.183 b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/MockExternalAnnotationsManager.kt.183
new file mode 100644
index 0000000..a6d2a75
--- /dev/null
+++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/MockExternalAnnotationsManager.kt.183
@@ -0,0 +1,57 @@
+/*
+ * 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? = null
+
+ 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 {
+ throw UnsupportedOperationException("not implemented")
+ }
+}
diff --git a/compiler/compiler.pro b/compiler/compiler.pro
index 10a361d..01c7dce 100644
--- a/compiler/compiler.pro
+++ b/compiler/compiler.pro
@@ -16,6 +16,7 @@
-dontnote **
-dontwarn com.intellij.util.ui.IsRetina*
+-dontwarn com.intellij.util.ui.UIUtilities
-dontwarn com.intellij.util.RetinaImage*
-dontwarn apple.awt.*
-dontwarn dk.brics.automaton.*
@@ -196,7 +197,6 @@
-keep class org.jetbrains.org.objectweb.asm.tree.FieldNode { *; }
-keep class org.jetbrains.org.objectweb.asm.tree.ParameterNode { *; }
-keep class org.jetbrains.org.objectweb.asm.tree.TypeAnnotationNode { *; }
--keep class org.jetbrains.org.objectweb.asm.tree.InsnList { *; }
-keep class org.jetbrains.org.objectweb.asm.signature.SignatureReader { *; }
-keep class org.jetbrains.org.objectweb.asm.signature.SignatureVisitor { *; }
diff --git a/compiler/compiler.pro.183 b/compiler/compiler.pro.183
new file mode 100644
index 0000000..10a361d
--- /dev/null
+++ b/compiler/compiler.pro.183
@@ -0,0 +1,250 @@
+-injars '<kotlin-compiler-jar-before-shrink>'(
+!org/apache/log4j/jmx/Agent*,
+!org/apache/log4j/net/JMS*,
+!org/apache/log4j/net/SMTP*,
+!org/apache/log4j/or/jms/MessageRenderer*,
+!org/jdom/xpath/Jaxen*,
+!org/jline/builtins/ssh/**,
+!org/mozilla/javascript/xml/impl/xmlbeans/**,
+!net/sf/cglib/**,
+!META-INF/maven**,
+**.class,**.properties,**.kt,**.kotlin_*,**.jnilib,**.so,**.dll,**.txt,**.caps,
+META-INF/services/**,META-INF/native/**,META-INF/extensions/**,META-INF/MANIFEST.MF,
+messages/**)
+
+-outjars '<kotlin-compiler-jar>'
+
+-dontnote **
+-dontwarn com.intellij.util.ui.IsRetina*
+-dontwarn com.intellij.util.RetinaImage*
+-dontwarn apple.awt.*
+-dontwarn dk.brics.automaton.*
+-dontwarn org.fusesource.**
+-dontwarn org.imgscalr.Scalr**
+-dontwarn org.xerial.snappy.SnappyBundleActivator
+-dontwarn com.intellij.util.CompressionUtil
+-dontwarn com.intellij.util.SnappyInitializer
+-dontwarn com.intellij.util.SVGLoader
+-dontwarn com.intellij.util.SVGLoader$MyTranscoder
+-dontwarn net.sf.cglib.**
+-dontwarn org.objectweb.asm.** # this is ASM3, the old version that we do not use
+-dontwarn com.sun.jna.NativeString
+-dontwarn com.sun.jna.WString
+-dontwarn com.intellij.psi.util.PsiClassUtil
+-dontwarn org.apache.hadoop.io.compress.*
+-dontwarn com.google.j2objc.annotations.Weak
+-dontwarn org.iq80.snappy.HadoopSnappyCodec$SnappyCompressionInputStream
+-dontwarn org.iq80.snappy.HadoopSnappyCodec$SnappyCompressionOutputStream
+-dontwarn com.google.common.util.concurrent.*
+-dontwarn org.apache.xerces.dom.**
+-dontwarn org.apache.xerces.util.**
+-dontwarn org.w3c.dom.ElementTraversal
+-dontwarn javaslang.match.annotation.Unapply
+-dontwarn javaslang.match.annotation.Patterns
+-dontwarn javaslang.*
+-dontwarn com.google.errorprone.**
+-dontwarn com.google.j2objc.**
+-dontwarn javax.crypto.**
+-dontwarn java.lang.invoke.MethodHandle
+-dontwarn org.jline.builtins.Nano$Buffer
+-dontwarn org.jetbrains.annotations.ReadOnly
+-dontwarn org.jetbrains.annotations.Mutable
+-dontwarn com.intellij.util.io.TarUtil
+-dontwarn com.intellij.util.io.Compressor$Tar
+
+# Nullability annotations used in Guava
+-dontwarn org.checkerframework.checker.nullness.compatqual.NullableDecl
+-dontwarn org.checkerframework.checker.nullness.compatqual.MonotonicNonNullDecl
+-dontwarn org.checkerframework.checker.nullness.qual.Nullable
+-dontwarn org.checkerframework.checker.nullness.qual.MonotonicNonNull
+
+# Depends on apache batick which has lots of dependencies
+-dontwarn com.intellij.util.SVGLoader*
+-dontwarn org.apache.batik.script.rhino.RhinoInterpreter
+-dontwarn org.apache.batik.script.rhino.RhinoInterpreterFactory
+
+-dontwarn org.jdom.xpath.jaxen.*
+-dontwarn com.intellij.util.io.Decompressor*
+-dontwarn org.w3c.dom.Location
+-dontwarn org.w3c.dom.Window
+
+
+#-libraryjars '<rtjar>'
+#-libraryjars '<jssejar>'
+#-libraryjars '<bootstrap.runtime>'
+#-libraryjars '<bootstrap.reflect>'
+#-libraryjars '<bootstrap.script.runtime>'
+#-libraryjars '<tools.jar>'
+
+-dontoptimize
+-dontobfuscate
+
+-keep class org.fusesource.** { *; }
+-keep class com.sun.jna.** { *; }
+
+-keep class org.jetbrains.annotations.** {
+ public protected *;
+}
+
+-keep class javax.inject.** {
+ public protected *;
+}
+
+-keep class org.jetbrains.kotlin.** {
+ public protected *;
+}
+
+-keep class org.jetbrains.kotlin.compiler.plugin.** {
+ public protected *;
+}
+
+-keep class org.jetbrains.kotlin.extensions.** {
+ public protected *;
+}
+
+-keep class org.jetbrains.kotlin.protobuf.** {
+ public protected *;
+}
+
+-keep class org.jetbrains.kotlin.container.** { *; }
+
+-keep class org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructorsKt { *; }
+
+-keep class org.jetbrains.org.objectweb.asm.Opcodes { *; }
+
+-keep class org.jetbrains.kotlin.codegen.extensions.** {
+ public protected *;
+}
+
+-keepclassmembers class com.intellij.openapi.vfs.VirtualFile {
+ public protected *;
+}
+
+-keep class com.intellij.openapi.vfs.StandardFileSystems {
+ public static *;
+}
+
+# needed for jar cache cleanup in the gradle plugin and compile daemon
+-keepclassmembers class com.intellij.openapi.vfs.impl.ZipHandler {
+ public static void clearFileAccessorCache();
+}
+
+-keep class jet.** {
+ public protected *;
+}
+
+-keep class com.intellij.psi.** {
+ public protected *;
+}
+
+# This is needed so that the platform code which parses XML wouldn't fail, see KT-16968
+# This API is used from org.jdom.input.SAXBuilder via reflection.
+-keep class org.jdom.input.JAXPParserFactory { public ** createParser(...); }
+# Without this class PluginManagerCore.loadDescriptorFromJar fails
+-keep class org.jdom.output.XMLOutputter { *; }
+
+# for kdoc & dokka
+-keep class com.intellij.openapi.util.TextRange { *; }
+-keep class com.intellij.lang.impl.PsiBuilderImpl* {
+ public protected *;
+}
+-keep class com.intellij.openapi.util.text.StringHash { *; }
+
+# for j2k
+-keep class com.intellij.codeInsight.NullableNotNullManager { public protected *; }
+
+# for gradle (see KT-12549)
+-keep class com.intellij.lang.properties.charset.Native2AsciiCharsetProvider { *; }
+
+# for kotlin-build-common (consider repacking compiler together with kotlin-build-common and remove this part afterwards)
+-keep class com.intellij.util.io.IOUtil { public *; }
+-keep class com.intellij.openapi.util.io.FileUtil { public *; }
+-keep class com.intellij.util.SystemProperties { public *; }
+-keep class com.intellij.util.containers.hash.LinkedHashMap { *; }
+-keep class com.intellij.util.containers.ConcurrentIntObjectMap { *; }
+-keep class com.intellij.util.containers.ComparatorUtil { *; }
+-keep class com.intellij.util.io.PersistentHashMapValueStorage { *; }
+-keep class com.intellij.util.io.PersistentHashMap { *; }
+-keep class com.intellij.util.io.BooleanDataDescriptor { *; }
+-keep class com.intellij.util.io.EnumeratorStringDescriptor { *; }
+-keep class com.intellij.util.io.ExternalIntegerKeyDescriptor { *; }
+-keep class com.intellij.util.containers.hash.EqualityPolicy { *; }
+-keep class com.intellij.util.containers.hash.EqualityPolicy.* { *; }
+-keep class com.intellij.util.containers.Interner { *; }
+-keep class gnu.trove.TIntHashSet { *; }
+-keep class gnu.trove.TIntIterator { *; }
+-keep class org.iq80.snappy.SlowMemory { *; }
+-keep class javaslang.match.PatternsProcessor { *; }
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keepclassmembers class * {
+ ** toString();
+ ** hashCode();
+ void start();
+ void stop();
+ void dispose();
+}
+
+-keep class org.jetbrains.org.objectweb.asm.tree.AnnotationNode { *; }
+-keep class org.jetbrains.org.objectweb.asm.tree.ClassNode { *; }
+-keep class org.jetbrains.org.objectweb.asm.tree.LocalVariableNode { *; }
+-keep class org.jetbrains.org.objectweb.asm.tree.MethodNode { *; }
+-keep class org.jetbrains.org.objectweb.asm.tree.FieldNode { *; }
+-keep class org.jetbrains.org.objectweb.asm.tree.ParameterNode { *; }
+-keep class org.jetbrains.org.objectweb.asm.tree.TypeAnnotationNode { *; }
+-keep class org.jetbrains.org.objectweb.asm.tree.InsnList { *; }
+
+-keep class org.jetbrains.org.objectweb.asm.signature.SignatureReader { *; }
+-keep class org.jetbrains.org.objectweb.asm.signature.SignatureVisitor { *; }
+
+-keep class org.jetbrains.org.objectweb.asm.Type {
+ public protected *;
+}
+
+-keepclassmembers class org.jetbrains.org.objectweb.asm.ClassReader {
+ *** SKIP_CODE;
+ *** SKIP_DEBUG;
+ *** SKIP_FRAMES;
+}
+
+-keepclassmembers class com.intellij.openapi.project.Project {
+ ** getBasePath();
+}
+
+# for kotlin-android-extensions in maven
+-keep class com.intellij.openapi.module.ModuleServiceManager { public *; }
+
+# for building kotlin-build-common-test
+-keep class org.jetbrains.kotlin.build.SerializationUtilsKt { *; }
+
+# for tools.jar
+-keep class com.sun.tools.javac.** { *; }
+-keep class com.sun.source.** { *; }
+
+# for coroutines
+-keep class kotlinx.coroutines.** { *; }
+
+# for webdemo
+-keep class com.intellij.openapi.progress.ProgressManager { *; }
+
+# for kapt
+-keep class com.intellij.openapi.project.Project { *; }
+-keepclassmembers class com.intellij.util.PathUtil {
+ public static java.lang.String getJarPathForClass(java.lang.Class);
+}
+
+-keepclassmembers class com.intellij.util.PathUtil {
+ public static java.lang.String getJarPathForClass(java.lang.Class);
+}
+
+# remove when KT-18563 would be fixed
+-keep class org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt { *; }
+
+-keep class net.jpountz.lz4.* { *; }
+
+# used in LazyScriptDescriptor
+-keep class org.jetbrains.kotlin.utils.addToStdlib.AddToStdlibKt { *; }
diff --git a/gradle/versions.properties b/gradle/versions.properties
index fd0f144..12bd112 100644
--- a/gradle/versions.properties
+++ b/gradle/versions.properties
@@ -1,6 +1,7 @@
-versions.intellijSdk=183.5153.4
+versions.intellijSdk=191-SNAPSHOT
versions.androidBuildTools=r23.0.1
versions.idea.NodeJS=181.3494.12
+versions.jar.asm-all=7.0
versions.jar.guava=25.1-jre
versions.jar.groovy-all=2.4.15
versions.jar.lombok-ast=0.2.3
@@ -10,6 +11,5 @@
versions.jar.gson=2.8.5
versions.jar.oro=2.0.8
versions.jar.picocontainer=1.2
-versions.jar.asm-all=7.0
ignore.jar.snappy-in-java=true
versions.gradle-api=4.5.1
diff --git a/gradle/versions.properties.183 b/gradle/versions.properties.183
new file mode 100644
index 0000000..fd0f144
--- /dev/null
+++ b/gradle/versions.properties.183
@@ -0,0 +1,15 @@
+versions.intellijSdk=183.5153.4
+versions.androidBuildTools=r23.0.1
+versions.idea.NodeJS=181.3494.12
+versions.jar.guava=25.1-jre
+versions.jar.groovy-all=2.4.15
+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.7
+versions.jar.gson=2.8.5
+versions.jar.oro=2.0.8
+versions.jar.picocontainer=1.2
+versions.jar.asm-all=7.0
+ignore.jar.snappy-in-java=true
+versions.gradle-api=4.5.1
diff --git a/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinResourceRootType.kt b/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinResourceRootType.kt
index b9172990..09884bf 100644
--- a/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinResourceRootType.kt
+++ b/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinResourceRootType.kt
@@ -11,17 +11,14 @@
import org.jetbrains.jps.model.java.JpsJavaExtensionService
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
-sealed class KotlinResourceRootType(val isTest: Boolean) : JpsElementTypeBase<JavaResourceRootProperties>(),
- JpsModuleSourceRootType<JavaResourceRootProperties>, KotlinRootType {
- object Resource : KotlinResourceRootType(false)
- object TestResource : KotlinResourceRootType(true)
+sealed class KotlinResourceRootType() : JpsElementTypeBase<JavaResourceRootProperties>(),
+ JpsModuleSourceRootType<JavaResourceRootProperties> {
+ object Resource : KotlinResourceRootType()
+
+ object TestResource : KotlinResourceRootType() {
+ override fun isForTests() = true
+ }
override fun createDefaultProperties() =
JpsJavaExtensionService.getInstance().createResourceRootProperties("", false)
-
- override fun isTestRoot() = isTest
-
- override fun isForTests() = isTest
-
- override fun equals(other: Any?) = if (super.equals(other)) true else isSameRootType(this, other)
}
\ No newline at end of file
diff --git a/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinResourceRootType.kt.183 b/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinResourceRootType.kt.183
new file mode 100644
index 0000000..b9172990
--- /dev/null
+++ b/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinResourceRootType.kt.183
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2010-2018 JetBrains s.r.o. 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.config
+
+import org.jetbrains.jps.model.ex.JpsElementTypeBase
+import org.jetbrains.jps.model.java.JavaResourceRootProperties
+import org.jetbrains.jps.model.java.JavaResourceRootType
+import org.jetbrains.jps.model.java.JpsJavaExtensionService
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType
+
+sealed class KotlinResourceRootType(val isTest: Boolean) : JpsElementTypeBase<JavaResourceRootProperties>(),
+ JpsModuleSourceRootType<JavaResourceRootProperties>, KotlinRootType {
+ object Resource : KotlinResourceRootType(false)
+ object TestResource : KotlinResourceRootType(true)
+
+ override fun createDefaultProperties() =
+ JpsJavaExtensionService.getInstance().createResourceRootProperties("", false)
+
+ override fun isTestRoot() = isTest
+
+ override fun isForTests() = isTest
+
+ override fun equals(other: Any?) = if (super.equals(other)) true else isSameRootType(this, other)
+}
\ No newline at end of file
diff --git a/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinRootType.kt b/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinRootType.kt.183
similarity index 100%
rename from idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinRootType.kt
rename to idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinRootType.kt.183
diff --git a/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinSourceRootType.kt b/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinSourceRootType.kt
index 8b5b3d9..551c8d2 100644
--- a/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinSourceRootType.kt
+++ b/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinSourceRootType.kt
@@ -11,20 +11,17 @@
import org.jetbrains.jps.model.java.JpsJavaExtensionService
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
-sealed class KotlinSourceRootType(val isTest: Boolean) : JpsElementTypeBase<JavaSourceRootProperties>(), JpsModuleSourceRootType<JavaSourceRootProperties>, KotlinRootType {
- object Source : KotlinSourceRootType(false)
- object TestSource : KotlinSourceRootType(true)
+sealed class KotlinSourceRootType() : JpsElementTypeBase<JavaSourceRootProperties>(), JpsModuleSourceRootType<JavaSourceRootProperties> {
+ object Source : KotlinSourceRootType()
+
+ object TestSource : KotlinSourceRootType() {
+ override fun isForTests() = true
+ }
override fun createDefaultProperties() = JpsJavaExtensionService.getInstance().createSourceRootProperties("")
companion object {
val ALL_SOURCES = setOf(Source, TestSource)
}
-
- override fun isTestRoot() = isTest
-
- override fun isForTests() = isTest
-
- override fun equals(other: Any?) = if (super.equals(other)) true else isSameRootType(this, other)
}
diff --git a/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinSourceRootType.kt.183 b/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinSourceRootType.kt.183
new file mode 100644
index 0000000..8b5b3d9
--- /dev/null
+++ b/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinSourceRootType.kt.183
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2010-2018 JetBrains s.r.o. 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.config
+
+import org.jetbrains.jps.model.ex.JpsElementTypeBase
+import org.jetbrains.jps.model.java.JavaSourceRootProperties
+import org.jetbrains.jps.model.java.JavaSourceRootType
+import org.jetbrains.jps.model.java.JpsJavaExtensionService
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType
+
+sealed class KotlinSourceRootType(val isTest: Boolean) : JpsElementTypeBase<JavaSourceRootProperties>(), JpsModuleSourceRootType<JavaSourceRootProperties>, KotlinRootType {
+ object Source : KotlinSourceRootType(false)
+ object TestSource : KotlinSourceRootType(true)
+
+ override fun createDefaultProperties() = JpsJavaExtensionService.getInstance().createSourceRootProperties("")
+
+ companion object {
+ val ALL_SOURCES = setOf(Source, TestSource)
+ }
+
+ override fun isTestRoot() = isTest
+
+ override fun isForTests() = isTest
+
+ override fun equals(other: Any?) = if (super.equals(other)) true else isSameRootType(this, other)
+}
+
diff --git a/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/KotlinMavenImporter.kt b/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/KotlinMavenImporter.kt
index e60bc8b..c4f6f68 100644
--- a/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/KotlinMavenImporter.kt
+++ b/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/KotlinMavenImporter.kt
@@ -25,10 +25,10 @@
import com.intellij.openapi.roots.*
import com.intellij.openapi.roots.impl.libraries.LibraryEx
import com.intellij.openapi.roots.libraries.Library
-import com.intellij.openapi.util.AsyncResult
import com.intellij.util.PathUtil
import org.jdom.Element
import org.jdom.Text
+import org.jetbrains.concurrency.AsyncPromise
import org.jetbrains.idea.maven.importing.MavenImporter
import org.jetbrains.idea.maven.importing.MavenRootModelAdapter
import org.jetbrains.idea.maven.model.MavenPlugin
@@ -140,7 +140,7 @@
if (toBeDownloaded.isNotEmpty()) {
MavenProjectsManager.getInstance(module.project)
- .scheduleArtifactsDownloading(listOf(mavenProject), toBeDownloaded, true, false, AsyncResult())
+ .scheduleArtifactsDownloading(listOf(mavenProject), toBeDownloaded, true, false, AsyncPromise())
}
}
diff --git a/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/KotlinMavenImporter.kt.183 b/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/KotlinMavenImporter.kt.183
new file mode 100644
index 0000000..e60bc8b
--- /dev/null
+++ b/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/KotlinMavenImporter.kt.183
@@ -0,0 +1,422 @@
+/*
+ * 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.maven
+
+import com.intellij.openapi.components.PersistentStateComponent
+import com.intellij.openapi.components.State
+import com.intellij.openapi.components.Storage
+import com.intellij.openapi.components.StoragePathMacros
+import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider
+import com.intellij.openapi.module.Module
+import com.intellij.openapi.roots.*
+import com.intellij.openapi.roots.impl.libraries.LibraryEx
+import com.intellij.openapi.roots.libraries.Library
+import com.intellij.openapi.util.AsyncResult
+import com.intellij.util.PathUtil
+import org.jdom.Element
+import org.jdom.Text
+import org.jetbrains.idea.maven.importing.MavenImporter
+import org.jetbrains.idea.maven.importing.MavenRootModelAdapter
+import org.jetbrains.idea.maven.model.MavenPlugin
+import org.jetbrains.idea.maven.project.*
+import org.jetbrains.jps.model.java.JavaSourceRootType
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType
+import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
+import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
+import org.jetbrains.kotlin.cli.common.arguments.parseCommandLineArguments
+import org.jetbrains.kotlin.compilerRunner.ArgumentUtils
+import org.jetbrains.kotlin.config.*
+import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
+import org.jetbrains.kotlin.idea.facet.*
+import org.jetbrains.kotlin.idea.framework.detectLibraryKind
+import org.jetbrains.kotlin.idea.maven.configuration.KotlinMavenConfigurator
+import org.jetbrains.kotlin.idea.platform.tooling
+import org.jetbrains.kotlin.platform.IdePlatform
+import org.jetbrains.kotlin.platform.IdePlatformKind
+import org.jetbrains.kotlin.platform.impl.CommonIdePlatformKind
+import org.jetbrains.kotlin.platform.impl.JsIdePlatformKind
+import org.jetbrains.kotlin.platform.impl.JvmIdePlatformKind
+import org.jetbrains.kotlin.platform.impl.isCommon
+import org.jetbrains.kotlin.utils.SmartList
+import org.jetbrains.kotlin.utils.addIfNotNull
+import java.io.File
+import java.util.*
+
+interface MavenProjectImportHandler {
+ companion object : ProjectExtensionDescriptor<MavenProjectImportHandler>(
+ "org.jetbrains.kotlin.mavenProjectImportHandler",
+ MavenProjectImportHandler::class.java
+ )
+
+ operator fun invoke(facet: KotlinFacet, mavenProject: MavenProject)
+}
+
+class KotlinMavenImporter : MavenImporter(KOTLIN_PLUGIN_GROUP_ID, KOTLIN_PLUGIN_ARTIFACT_ID) {
+ companion object {
+ const val KOTLIN_PLUGIN_GROUP_ID = "org.jetbrains.kotlin"
+ const val KOTLIN_PLUGIN_ARTIFACT_ID = "kotlin-maven-plugin"
+
+ const val KOTLIN_PLUGIN_SOURCE_DIRS_CONFIG = "sourceDirs"
+ }
+
+ override fun preProcess(
+ module: Module,
+ mavenProject: MavenProject,
+ changes: MavenProjectChanges,
+ modifiableModelsProvider: IdeModifiableModelsProvider
+ ) {
+ }
+
+ override fun process(
+ modifiableModelsProvider: IdeModifiableModelsProvider,
+ module: Module,
+ rootModel: MavenRootModelAdapter,
+ mavenModel: MavenProjectsTree,
+ mavenProject: MavenProject,
+ changes: MavenProjectChanges,
+ mavenProjectToModuleName: MutableMap<MavenProject, String>,
+ postTasks: MutableList<MavenProjectsProcessorTask>
+ ) {
+
+ if (changes.plugins) {
+ contributeSourceDirectories(mavenProject, module, rootModel)
+ }
+ }
+
+ override fun postProcess(
+ module: Module,
+ mavenProject: MavenProject,
+ changes: MavenProjectChanges,
+ modifiableModelsProvider: IdeModifiableModelsProvider
+ ) {
+ super.postProcess(module, mavenProject, changes, modifiableModelsProvider)
+
+ if (changes.dependencies) {
+ scheduleDownloadStdlibSources(mavenProject, module)
+
+ val targetLibraryKind = detectPlatformByExecutions(mavenProject)?.tooling?.libraryKind
+ if (targetLibraryKind != null) {
+ modifiableModelsProvider.getModifiableRootModel(module).orderEntries().forEachLibrary { library ->
+ if ((library as LibraryEx).kind == null) {
+ val model = modifiableModelsProvider.getModifiableLibraryModel(library) as LibraryEx.ModifiableModelEx
+ detectLibraryKind(model.getFiles(OrderRootType.CLASSES))?.let { model.kind = it }
+ }
+ true
+ }
+ }
+ }
+
+ configureFacet(mavenProject, modifiableModelsProvider, module)
+ }
+
+ private fun scheduleDownloadStdlibSources(mavenProject: MavenProject, module: Module) {
+ // TODO: here we have to process all kotlin libraries but for now we only handle standard libraries
+ val artifacts = mavenProject.dependencyArtifactIndex.data[KOTLIN_PLUGIN_GROUP_ID]?.values?.flatMap { it.filter { it.isResolved } }
+ ?: emptyList()
+
+ val librariesWithNoSources = ArrayList<Library>()
+ OrderEnumerator.orderEntries(module).forEachLibrary { library ->
+ if (library.modifiableModel.getFiles(OrderRootType.SOURCES).isEmpty()) {
+ librariesWithNoSources.add(library)
+ }
+ true
+ }
+ val libraryNames = librariesWithNoSources.mapTo(HashSet()) { it.name }
+ val toBeDownloaded = artifacts.filter { it.libraryName in libraryNames }
+
+ if (toBeDownloaded.isNotEmpty()) {
+ MavenProjectsManager.getInstance(module.project)
+ .scheduleArtifactsDownloading(listOf(mavenProject), toBeDownloaded, true, false, AsyncResult())
+ }
+ }
+
+ private fun configureJSOutputPaths(
+ mavenProject: MavenProject,
+ modifiableRootModel: ModifiableRootModel,
+ facetSettings: KotlinFacetSettings,
+ mavenPlugin: MavenPlugin
+ ) {
+ fun parentPath(path: String): String =
+ File(path).absoluteFile.parentFile.absolutePath
+
+ val sharedOutputFile = mavenPlugin.configurationElement?.getChild("outputFile")?.text
+
+ val compilerModuleExtension = modifiableRootModel.getModuleExtension(CompilerModuleExtension::class.java) ?: return
+ val buildDirectory = mavenProject.buildDirectory
+
+ val executions = mavenPlugin.executions
+
+ executions.forEach {
+ val explicitOutputFile = it.configurationElement?.getChild("outputFile")?.text ?: sharedOutputFile
+ if (PomFile.KotlinGoals.Js in it.goals) {
+ // see org.jetbrains.kotlin.maven.K2JSCompilerMojo
+ val outputFilePath = PathUtil.toSystemDependentName(explicitOutputFile ?: "$buildDirectory/js/${mavenProject.mavenId.artifactId}.js")
+ compilerModuleExtension.setCompilerOutputPath(parentPath(outputFilePath))
+ facetSettings.productionOutputPath = outputFilePath
+ }
+ if (PomFile.KotlinGoals.TestJs in it.goals) {
+ // see org.jetbrains.kotlin.maven.KotlinTestJSCompilerMojo
+ val outputFilePath = PathUtil.toSystemDependentName(explicitOutputFile ?: "$buildDirectory/test-js/${mavenProject.mavenId.artifactId}-tests.js")
+ compilerModuleExtension.setCompilerOutputPathForTests(parentPath(outputFilePath))
+ facetSettings.testOutputPath = outputFilePath
+ }
+ }
+ }
+
+ private fun getCompilerArgumentsByConfigurationElement(
+ mavenProject: MavenProject,
+ configuration: Element?,
+ platform: IdePlatform<*, *>
+ ): List<String> {
+ val arguments = platform.createArguments()
+
+ arguments.apiVersion = configuration?.getChild("apiVersion")?.text ?:
+ mavenProject.properties["kotlin.compiler.apiVersion"]?.toString()
+ arguments.languageVersion = configuration?.getChild("languageVersion")?.text ?:
+ mavenProject.properties["kotlin.compiler.languageVersion"]?.toString()
+ arguments.multiPlatform = configuration?.getChild("multiPlatform")?.text?.trim()?.toBoolean() ?: false
+ arguments.suppressWarnings = configuration?.getChild("nowarn")?.text?.trim()?.toBoolean() ?: false
+
+ configuration?.getChild("experimentalCoroutines")?.text?.trim()?.let {
+ arguments.coroutinesState = it
+ }
+
+ when (arguments) {
+ is K2JVMCompilerArguments -> {
+ arguments.classpath = configuration?.getChild("classpath")?.text
+ arguments.jdkHome = configuration?.getChild("jdkHome")?.text
+ arguments.jvmTarget = configuration?.getChild("jvmTarget")?.text ?:
+ mavenProject.properties["kotlin.compiler.jvmTarget"]?.toString()
+ arguments.javaParameters = configuration?.getChild("javaParameters")?.text?.toBoolean() ?: false
+ }
+ is K2JSCompilerArguments -> {
+ arguments.sourceMap = configuration?.getChild("sourceMap")?.text?.trim()?.toBoolean() ?: false
+ arguments.sourceMapPrefix = configuration?.getChild("sourceMapPrefix")?.text?.trim() ?: ""
+ arguments.sourceMapEmbedSources = configuration?.getChild("sourceMapEmbedSources")?.text?.trim() ?: "inlining"
+ arguments.outputFile = configuration?.getChild("outputFile")?.text
+ arguments.metaInfo = configuration?.getChild("metaInfo")?.text?.trim()?.toBoolean() ?: false
+ arguments.moduleKind = configuration?.getChild("moduleKind")?.text
+ arguments.main = configuration?.getChild("main")?.text
+ }
+ }
+
+ val additionalArgs = SmartList<String>().apply {
+ val argsElement = configuration?.getChild("args")
+
+ argsElement?.content?.forEach { argElement ->
+ when (argElement) {
+ is Text -> {
+ argElement.text?.let { addAll(splitArgumentString(it)) }
+ }
+ is Element -> {
+ if (argElement.name == "arg") {
+ addIfNotNull(argElement.text)
+ }
+ }
+ }
+ }
+ }
+ parseCommandLineArguments(additionalArgs, arguments)
+
+ return ArgumentUtils.convertArgumentsToStringList(arguments)
+ }
+
+ private val compilationGoals = listOf(
+ PomFile.KotlinGoals.Compile,
+ PomFile.KotlinGoals.TestCompile,
+ PomFile.KotlinGoals.Js,
+ PomFile.KotlinGoals.TestJs,
+ PomFile.KotlinGoals.MetaData
+ )
+
+ private fun configureFacet(mavenProject: MavenProject, modifiableModelsProvider: IdeModifiableModelsProvider, module: Module) {
+ val mavenPlugin = mavenProject.findPlugin(KotlinMavenConfigurator.GROUP_ID, KotlinMavenConfigurator.MAVEN_PLUGIN_ID) ?: return
+ val compilerVersion = mavenPlugin.version ?: LanguageVersion.LATEST_STABLE.versionString
+ val kotlinFacet = module.getOrCreateFacet(
+ modifiableModelsProvider,
+ false,
+ ExternalProjectSystemRegistry.MAVEN_EXTERNAL_SOURCE_ID
+ )
+
+ // TODO There should be a way to figure out the correct platform version
+ val platform = detectPlatform(mavenProject)?.defaultPlatform
+
+ kotlinFacet.configureFacet(compilerVersion, LanguageFeature.Coroutines.defaultState, platform, modifiableModelsProvider)
+ val facetSettings = kotlinFacet.configuration.settings
+ val configuredPlatform = kotlinFacet.configuration.settings.platform!!
+ val configuration = mavenPlugin.configurationElement
+ val sharedArguments = getCompilerArgumentsByConfigurationElement(mavenProject, configuration, configuredPlatform)
+ val executionArguments = mavenPlugin.executions
+ ?.firstOrNull { it.goals.any { it in compilationGoals } }
+ ?.configurationElement?.let { getCompilerArgumentsByConfigurationElement(mavenProject, it, configuredPlatform) }
+ parseCompilerArgumentsToFacet(sharedArguments, emptyList(), kotlinFacet, modifiableModelsProvider)
+ if (executionArguments != null) {
+ parseCompilerArgumentsToFacet(executionArguments, emptyList(), kotlinFacet, modifiableModelsProvider)
+ }
+ if (facetSettings.compilerArguments is K2JSCompilerArguments) {
+ configureJSOutputPaths(mavenProject, modifiableModelsProvider.getModifiableRootModel(module), facetSettings, mavenPlugin)
+ }
+ MavenProjectImportHandler.getInstances(module.project).forEach { it(kotlinFacet, mavenProject) }
+ setImplementedModuleName(kotlinFacet, mavenProject, module)
+ kotlinFacet.noVersionAutoAdvance()
+ }
+
+ private fun detectPlatform(mavenProject: MavenProject) =
+ detectPlatformByExecutions(mavenProject) ?: detectPlatformByLibraries(mavenProject)
+
+ private fun detectPlatformByExecutions(mavenProject: MavenProject): IdePlatformKind<*>? {
+ return mavenProject.findPlugin(KOTLIN_PLUGIN_GROUP_ID, KOTLIN_PLUGIN_ARTIFACT_ID)?.executions?.flatMap { it.goals }
+ ?.mapNotNull { goal ->
+ when (goal) {
+ PomFile.KotlinGoals.Compile, PomFile.KotlinGoals.TestCompile -> JvmIdePlatformKind
+ PomFile.KotlinGoals.Js, PomFile.KotlinGoals.TestJs -> JsIdePlatformKind
+ PomFile.KotlinGoals.MetaData -> CommonIdePlatformKind
+ else -> null
+ }
+ }?.distinct()?.singleOrNull()
+ }
+
+ private fun detectPlatformByLibraries(mavenProject: MavenProject): IdePlatformKind<*>? {
+ for (kind in IdePlatformKind.ALL_KINDS) {
+ val mavenLibraryIds = kind.tooling.mavenLibraryIds
+ if (mavenLibraryIds.any { mavenProject.findDependencies(KOTLIN_PLUGIN_GROUP_ID, it).isNotEmpty() }) {
+ // TODO we could return here the correct version
+ return kind
+ }
+ }
+
+ return null
+ }
+
+ // TODO in theory it should work like this but it doesn't as it couldn't unmark source roots that are not roots anymore.
+ // I believe this is something should be done by the underlying maven importer implementation or somewhere else in the IDEA
+ // For now there is a contributeSourceDirectories implementation that deals with the issue
+ // see https://youtrack.jetbrains.com/issue/IDEA-148280
+
+ // override fun collectSourceRoots(mavenProject: MavenProject, result: PairConsumer<String, JpsModuleSourceRootType<*>>) {
+ // for ((type, dir) in collectSourceDirectories(mavenProject)) {
+ // val jpsType: JpsModuleSourceRootType<*> = when (type) {
+ // SourceType.PROD -> JavaSourceRootType.SOURCE
+ // SourceType.TEST -> JavaSourceRootType.TEST_SOURCE
+ // }
+ //
+ // result.consume(dir, jpsType)
+ // }
+ // }
+
+ private fun contributeSourceDirectories(mavenProject: MavenProject, module: Module, rootModel: MavenRootModelAdapter) {
+ val directories = collectSourceDirectories(mavenProject)
+
+ val toBeAdded = directories.map { it.second }.toSet()
+ val state = module.kotlinImporterComponent
+
+ val isNonJvmModule = mavenProject
+ .plugins
+ .asSequence()
+ .filter { it.isKotlinPlugin() }
+ .flatMap { it.executions.asSequence() }
+ .flatMap { it.goals.asSequence() }
+ .any { it in PomFile.KotlinGoals.CompileGoals && it !in PomFile.KotlinGoals.JvmGoals }
+
+ val prodSourceRootType: JpsModuleSourceRootType<*> = if (isNonJvmModule) KotlinSourceRootType.Source else JavaSourceRootType.SOURCE
+ val testSourceRootType: JpsModuleSourceRootType<*> = if (isNonJvmModule) KotlinSourceRootType.TestSource else JavaSourceRootType.TEST_SOURCE
+
+ for ((type, dir) in directories) {
+ if (rootModel.getSourceFolder(File(dir)) == null) {
+ val jpsType: JpsModuleSourceRootType<*> = when (type) {
+ SourceType.TEST -> testSourceRootType
+ SourceType.PROD -> prodSourceRootType
+ }
+
+ rootModel.addSourceFolder(dir, jpsType)
+ }
+ }
+
+ if (isNonJvmModule) {
+ mavenProject.sources.forEach { rootModel.addSourceFolder(it, KotlinSourceRootType.Source) }
+ mavenProject.testSources.forEach { rootModel.addSourceFolder(it, KotlinSourceRootType.TestSource) }
+ mavenProject.resources.forEach { rootModel.addSourceFolder(it.directory, KotlinResourceRootType.Resource) }
+ mavenProject.testResources.forEach { rootModel.addSourceFolder(it.directory, KotlinResourceRootType.TestResource) }
+ }
+
+ state.addedSources.filter { it !in toBeAdded }.forEach {
+ rootModel.unregisterAll(it, true, true)
+ state.addedSources.remove(it)
+ }
+ state.addedSources.addAll(toBeAdded)
+ }
+
+ private fun collectSourceDirectories(mavenProject: MavenProject): List<Pair<SourceType, String>> =
+ mavenProject.plugins.filter { it.isKotlinPlugin() }.flatMap { plugin ->
+ plugin.configurationElement.sourceDirectories().map { SourceType.PROD to it } +
+ plugin.executions.flatMap { execution ->
+ execution.configurationElement.sourceDirectories().map { execution.sourceType() to it }
+ }
+ }.distinct()
+
+ private fun setImplementedModuleName(kotlinFacet: KotlinFacet, mavenProject: MavenProject, module: Module) {
+ if (kotlinFacet.configuration.settings.platform.isCommon) {
+ kotlinFacet.configuration.settings.implementedModuleNames = emptyList()
+ } else {
+ val manager = MavenProjectsManager.getInstance(module.project)
+ val mavenDependencies = mavenProject.dependencies.mapNotNull { manager?.findProject(it) }
+ val implemented = mavenDependencies.filter { detectPlatformByExecutions(it).isCommon }
+
+ kotlinFacet.configuration.settings.implementedModuleNames = implemented.map { manager.findModule(it)?.name ?: it.displayName }
+ }
+ }
+}
+
+private fun MavenPlugin.isKotlinPlugin() =
+ groupId == KotlinMavenImporter.KOTLIN_PLUGIN_GROUP_ID && artifactId == KotlinMavenImporter.KOTLIN_PLUGIN_ARTIFACT_ID
+
+private fun Element?.sourceDirectories(): List<String> =
+ this?.getChildren(KotlinMavenImporter.KOTLIN_PLUGIN_SOURCE_DIRS_CONFIG)?.flatMap { it.children ?: emptyList() }?.map { it.textTrim }
+ ?: emptyList()
+
+private fun MavenPlugin.Execution.sourceType() =
+ goals.map { if (isTestGoalName(it)) SourceType.TEST else SourceType.PROD }
+ .distinct()
+ .singleOrNull() ?: SourceType.PROD
+
+private fun isTestGoalName(goalName: String) = goalName.startsWith("test-")
+
+private enum class SourceType {
+ PROD, TEST
+}
+
+@State(
+ name = "AutoImportedSourceRoots",
+ storages = [(Storage(file = StoragePathMacros.MODULE_FILE))]
+)
+class KotlinImporterComponent : PersistentStateComponent<KotlinImporterComponent.State> {
+ class State(var directories: List<String> = ArrayList())
+
+ val addedSources: MutableSet<String> = Collections.synchronizedSet(HashSet<String>())
+
+ override fun loadState(state: State) {
+ addedSources.clear()
+ addedSources.addAll(state.directories)
+ }
+
+ override fun getState(): State {
+ return State(addedSources.sorted())
+ }
+}
+
+private val Module.kotlinImporterComponent: KotlinImporterComponent
+ get() = getComponent(KotlinImporterComponent::class.java) ?: throw IllegalStateException("No maven importer state configured")
diff --git a/idea/resources/META-INF/plugin.xml b/idea/resources/META-INF/plugin.xml
index 905aec9..79d4368 100644
--- a/idea/resources/META-INF/plugin.xml
+++ b/idea/resources/META-INF/plugin.xml
@@ -13,7 +13,7 @@
<version>@snapshot@</version>
<vendor url="http://www.jetbrains.com">JetBrains</vendor>
- <idea-version since-build="183.1" until-build="183.*"/>
+ <idea-version since-build="191.2767" until-build="191.*"/>
<depends>com.intellij.modules.platform</depends>
diff --git a/idea/resources/META-INF/plugin.xml.183 b/idea/resources/META-INF/plugin.xml.183
new file mode 100644
index 0000000..905aec9
--- /dev/null
+++ b/idea/resources/META-INF/plugin.xml.183
@@ -0,0 +1,74 @@
+<idea-plugin xmlns:xi="http://www.w3.org/2001/XInclude" version="2" url="http://kotlinlang.org" allow-bundled-update="true">
+ <id>org.jetbrains.kotlin</id>
+
+ <name>Kotlin</name>
+ <description><![CDATA[
+The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
+<br>
+<a href="http://kotlinlang.org/docs/tutorials/getting-started.html">Getting Started in IntelliJ IDEA</a><br>
+<a href="http://kotlinlang.org/docs/tutorials/kotlin-android.html">Getting Started in Android Studio</a><br>
+<a href="http://slack.kotlinlang.org/">Public Slack</a><br>
+<a href="https://youtrack.jetbrains.com/issues/KT">Issue tracker</a><br>
+]]></description>
+ <version>@snapshot@</version>
+ <vendor url="http://www.jetbrains.com">JetBrains</vendor>
+
+ <idea-version since-build="183.1" until-build="183.*"/>
+
+ <depends>com.intellij.modules.platform</depends>
+
+ <!-- required for Kotlin/Native plugin -->
+ <depends optional="true">org.jetbrains.kotlin.native.platform.deps</depends>
+
+ <depends optional="true" config-file="junit.xml">JUnit</depends>
+ <depends optional="true" config-file="gradle.xml">org.jetbrains.plugins.gradle</depends>
+ <depends optional="true" config-file="gradle-java.xml">org.jetbrains.plugins.gradle.java</depends>
+ <depends optional="true" config-file="maven.xml">org.jetbrains.idea.maven</depends>
+ <depends optional="true" config-file="testng-j.xml">TestNG-J</depends>
+ <depends optional="true" config-file="android.xml">org.jetbrains.android</depends>
+ <depends optional="true" config-file="coverage.xml">Coverage</depends>
+ <depends optional="true" config-file="i18n.xml">com.intellij.java-i18n</depends>
+ <depends optional="true" config-file="decompiler.xml">org.jetbrains.java.decompiler</depends>
+ <depends optional="true" config-file="git4idea.xml">Git4Idea</depends>
+ <depends optional="true" config-file="stream-debugger.xml">org.jetbrains.debugger.streams</depends>
+
+ <!-- ULTIMATE-PLUGIN-PLACEHOLDER -->
+
+ <!-- CIDR-PLUGIN-PLACEHOLDER-START -->
+ <depends>com.intellij.modules.idea</depends>
+ <depends>com.intellij.modules.java</depends>
+ <depends optional="true" config-file="javaScriptDebug.xml">JavaScriptDebugger</depends>
+ <depends optional="true" config-file="kotlin-copyright.xml">com.intellij.copyright</depends>
+ <depends optional="true" config-file="injection.xml">org.intellij.intelliLang</depends>
+ <!-- CIDR-PLUGIN-PLACEHOLDER-END -->
+
+ <xi:include href="plugin-common.xml" xpointer="xpointer(/idea-plugin/*)"/>
+
+ <!-- CIDR-PLUGIN-EXCLUDE-START -->
+ <xi:include href="jvm.xml" xpointer="xpointer(/idea-plugin/*)"/>
+ <!-- CIDR-PLUGIN-EXCLUDE-END -->
+
+ <xi:include href="native.xml" xpointer="xpointer(/idea-plugin/*)"/>
+ <xi:include href="tipsAndTricks.xml" xpointer="xpointer(/idea-plugin/*)"/>
+
+ <xi:include href="extensions/ide.xml" xpointer="xpointer(/idea-plugin/*)"/>
+
+ <xi:include href="kotlinx-serialization.xml" xpointer="xpointer(/idea-plugin/*)"/>
+
+ <extensionPoints>
+ <xi:include href="extensions/compiler.xml" xpointer="xpointer(/idea-plugin/extensionPoints/*)"/>
+
+ <extensionPoint qualifiedName="org.jetbrains.kotlin.pluginUpdateVerifier"
+ interface="org.jetbrains.kotlin.idea.update.PluginUpdateVerifier"/>
+ </extensionPoints>
+
+ <xi:include href="plugin-kotlin-extensions.xml" xpointer="xpointer(/idea-plugin/*)"/>
+
+ <extensions defaultExtensionNs="com.intellij.jvm">
+ <declarationSearcher language="kotlin" implementationClass="org.jetbrains.kotlin.idea.jvm.KotlinDeclarationSearcher"/>
+ </extensions>
+
+ <extensions defaultExtensionNs="com.intellij.codeInsight">
+ <nonBlockingContextChecker implementation="org.jetbrains.kotlin.idea.inspections.blockingCallsDetection.CoroutineNonBlockingContextChecker"/>
+ </extensions>
+</idea-plugin>
diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt
index 8786660..00ea1bd 100644
--- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt
@@ -203,8 +203,8 @@
fun collectUsages(kotlinToLightElements: Map<KtNamedDeclaration, List<PsiNamedElement>>, result: MutableCollection<UsageInfo>) {
kotlinToLightElements.values.flatten().flatMapTo(result) { lightElement ->
val searchScope = getSearchScope(lightElement) ?: return@flatMapTo emptyList()
-
- val newFqName = StringUtil.getQualifiedName(newContainerName, lightElement.name)
+ val elementName = lightElement.name ?: return@flatMapTo emptyList()
+ val newFqName = StringUtil.getQualifiedName(newContainerName, elementName)
val foundReferences = HashSet<PsiReference>()
val results = ReferencesSearch
diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt.183 b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt.183
new file mode 100644
index 0000000..8786660
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt.183
@@ -0,0 +1,373 @@
+/*
+ * Copyright 2010-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations
+
+import com.intellij.ide.highlighter.JavaFileType
+import com.intellij.ide.util.EditorHelper
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.util.Ref
+import com.intellij.openapi.util.text.StringUtil
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiNamedElement
+import com.intellij.psi.PsiReference
+import com.intellij.psi.search.GlobalSearchScope
+import com.intellij.psi.search.searches.ReferencesSearch
+import com.intellij.refactoring.BaseRefactoringProcessor
+import com.intellij.refactoring.move.MoveCallback
+import com.intellij.refactoring.move.MoveMultipleElementsViewDescriptor
+import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassHandler
+import com.intellij.refactoring.rename.RenameUtil
+import com.intellij.refactoring.util.NonCodeUsageInfo
+import com.intellij.refactoring.util.RefactoringUIUtil
+import com.intellij.refactoring.util.TextOccurrencesUtil
+import com.intellij.usageView.UsageInfo
+import com.intellij.usageView.UsageViewBundle
+import com.intellij.usageView.UsageViewDescriptor
+import com.intellij.usageView.UsageViewUtil
+import com.intellij.util.IncorrectOperationException
+import com.intellij.util.containers.MultiMap
+import gnu.trove.THashMap
+import gnu.trove.TObjectHashingStrategy
+import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration
+import org.jetbrains.kotlin.asJava.findFacadeClass
+import org.jetbrains.kotlin.asJava.namedUnwrappedElement
+import org.jetbrains.kotlin.asJava.toLightElements
+import org.jetbrains.kotlin.idea.codeInsight.shorten.addToBeShortenedDescendantsToWaitingSet
+import org.jetbrains.kotlin.idea.core.deleteSingle
+import org.jetbrains.kotlin.idea.core.quoteIfNeeded
+import org.jetbrains.kotlin.idea.refactoring.broadcastRefactoringExit
+import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
+import org.jetbrains.kotlin.idea.refactoring.move.*
+import org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories.MoveKotlinClassHandler
+import org.jetbrains.kotlin.idea.search.projectScope
+import org.jetbrains.kotlin.idea.search.restrictByFileType
+import org.jetbrains.kotlin.idea.util.projectStructure.module
+import org.jetbrains.kotlin.lexer.KtTokens
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
+import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
+import org.jetbrains.kotlin.psi.psiUtil.isAncestor
+import org.jetbrains.kotlin.utils.ifEmpty
+import org.jetbrains.kotlin.utils.keysToMap
+import java.lang.AssertionError
+import java.util.*
+
+interface Mover : (KtNamedDeclaration, KtElement) -> KtNamedDeclaration {
+ object Default : Mover {
+ override fun invoke(originalElement: KtNamedDeclaration, targetContainer: KtElement): KtNamedDeclaration {
+ return when (targetContainer) {
+ is KtFile -> {
+ val declarationContainer: KtElement =
+ if (targetContainer.isScript()) targetContainer.script!!.blockExpression else targetContainer
+ declarationContainer.add(originalElement) as KtNamedDeclaration
+ }
+ is KtClassOrObject -> targetContainer.addDeclaration(originalElement)
+ else -> error("Unexpected element: ${targetContainer.getElementTextWithContext()}")
+ }.apply {
+ val container = originalElement.containingClassOrObject
+ if (container is KtObjectDeclaration && container.isCompanion() && container.declarations.singleOrNull() == originalElement) {
+ container.deleteSingle()
+ }
+ else {
+ originalElement.deleteSingle()
+ }
+ }
+ }
+ }
+}
+
+sealed class MoveSource {
+ abstract val elementsToMove: Collection<KtNamedDeclaration>
+
+ class Elements(override val elementsToMove: Collection<KtNamedDeclaration>) : MoveSource()
+
+ class File(val file: KtFile) : MoveSource() {
+ override val elementsToMove: Collection<KtNamedDeclaration>
+ get() = file.declarations.filterIsInstance<KtNamedDeclaration>()
+ }
+}
+
+fun MoveSource(declaration: KtNamedDeclaration) = MoveSource.Elements(listOf(declaration))
+fun MoveSource(declarations: Collection<KtNamedDeclaration>) = MoveSource.Elements(declarations)
+fun MoveSource(file: KtFile) = MoveSource.File(file)
+
+class MoveDeclarationsDescriptor @JvmOverloads constructor(
+ val project: Project,
+ val moveSource: MoveSource,
+ val moveTarget: KotlinMoveTarget,
+ val delegate: MoveDeclarationsDelegate,
+ val searchInCommentsAndStrings: Boolean = true,
+ val searchInNonCode: Boolean = true,
+ val deleteSourceFiles: Boolean = false,
+ val moveCallback: MoveCallback? = null,
+ val openInEditor: Boolean = false,
+ val allElementsToMove: List<PsiElement>? = null,
+ val analyzeConflicts: Boolean = true,
+ val searchReferences: Boolean = true
+)
+
+class ConflictUsageInfo(element: PsiElement, val messages: Collection<String>) : UsageInfo(element)
+
+private object ElementHashingStrategy : TObjectHashingStrategy<PsiElement> {
+ override fun equals(e1: PsiElement?, e2: PsiElement?): Boolean {
+ if (e1 === e2) return true
+ // Name should be enough to distinguish different light elements based on the same original declaration
+ if (e1 is KtLightDeclaration<*, *> && e2 is KtLightDeclaration<*, *>) {
+ return e1.kotlinOrigin == e2.kotlinOrigin && e1.name == e2.name
+ }
+ return e1 == e2
+ }
+
+ override fun computeHashCode(e: PsiElement?): Int {
+ return when (e) {
+ null -> 0
+ is KtLightDeclaration<*, *> -> (e.kotlinOrigin?.hashCode() ?: 0) * 31 + (e.name?.hashCode() ?: 0)
+ else -> e.hashCode()
+ }
+ }
+}
+
+class MoveKotlinDeclarationsProcessor(
+ val descriptor: MoveDeclarationsDescriptor,
+ val mover: Mover = Mover.Default) : BaseRefactoringProcessor(descriptor.project) {
+ companion object {
+ private val REFACTORING_NAME = "Move declarations"
+ val REFACTORING_ID = "move.kotlin.declarations"
+ }
+
+ val project get() = descriptor.project
+
+ private var nonCodeUsages: Array<NonCodeUsageInfo>? = null
+ private val moveEntireFile = descriptor.moveSource is MoveSource.File
+ private val elementsToMove = descriptor.moveSource.elementsToMove.filter { e -> e.parent != descriptor.moveTarget.getTargetPsiIfExists(e) }
+ private val kotlinToLightElementsBySourceFile = elementsToMove
+ .groupBy { it.containingKtFile }
+ .mapValues { it.value.keysToMap { it.toLightElements().ifEmpty { listOf(it) } } }
+ private val conflicts = MultiMap<PsiElement, String>()
+
+ override fun getRefactoringId() = REFACTORING_ID
+
+ override fun createUsageViewDescriptor(usages: Array<out UsageInfo>): UsageViewDescriptor {
+ val targetContainerFqName = descriptor.moveTarget.targetContainerFqName?.let {
+ if (it.isRoot) UsageViewBundle.message("default.package.presentable.name") else it.asString()
+ }
+ return MoveMultipleElementsViewDescriptor(elementsToMove.toTypedArray(), targetContainerFqName)
+ }
+
+ fun getConflictsAsUsages(): List<UsageInfo> = conflicts.entrySet().map { ConflictUsageInfo(it.key, it.value) }
+
+ public override fun findUsages(): Array<UsageInfo> {
+ if (!descriptor.searchReferences || elementsToMove.isEmpty()) return UsageInfo.EMPTY_ARRAY
+
+ val newContainerName = descriptor.moveTarget.targetContainerFqName?.asString() ?: ""
+
+ fun getSearchScope(element: PsiElement): GlobalSearchScope? {
+ val projectScope = project.projectScope()
+ val ktDeclaration = element.namedUnwrappedElement as? KtNamedDeclaration ?: return projectScope
+ if (ktDeclaration.hasModifier(KtTokens.PRIVATE_KEYWORD)) return projectScope
+ val moveTarget = descriptor.moveTarget
+ val (oldContainer, newContainer) = descriptor.delegate.getContainerChangeInfo(ktDeclaration, moveTarget)
+ val targetModule = moveTarget.getTargetModule(project) ?: return projectScope
+ if (oldContainer != newContainer || ktDeclaration.module != targetModule) return projectScope
+ // Check if facade class may change
+ if (newContainer is ContainerInfo.Package) {
+ val javaScope = projectScope.restrictByFileType(JavaFileType.INSTANCE)
+ val currentFile = ktDeclaration.containingKtFile
+ val newFile = when (moveTarget) {
+ is KotlinMoveTargetForExistingElement -> moveTarget.targetElement as? KtFile ?: return null
+ is KotlinMoveTargetForDeferredFile -> return javaScope
+ else -> return null
+ }
+ val currentFacade = currentFile.findFacadeClass()
+ val newFacade = newFile.findFacadeClass()
+ return if (currentFacade?.qualifiedName != newFacade?.qualifiedName) javaScope else null
+ }
+ return null
+ }
+
+ fun collectUsages(kotlinToLightElements: Map<KtNamedDeclaration, List<PsiNamedElement>>, result: MutableCollection<UsageInfo>) {
+ kotlinToLightElements.values.flatten().flatMapTo(result) { lightElement ->
+ val searchScope = getSearchScope(lightElement) ?: return@flatMapTo emptyList()
+
+ val newFqName = StringUtil.getQualifiedName(newContainerName, lightElement.name)
+
+ val foundReferences = HashSet<PsiReference>()
+ val results = ReferencesSearch
+ .search(lightElement, searchScope)
+ .mapNotNullTo(ArrayList()) { ref ->
+ if (foundReferences.add(ref) && elementsToMove.none { it.isAncestor(ref.element)}) {
+ createMoveUsageInfoIfPossible(ref, lightElement, true, false)
+ }
+ else null
+ }
+
+ val name = lightElement.getKotlinFqName()?.quoteIfNeeded()?.asString()
+ if (name != null) {
+ TextOccurrencesUtil.findNonCodeUsages(
+ lightElement,
+ name,
+ descriptor.searchInCommentsAndStrings,
+ descriptor.searchInNonCode,
+ FqName(newFqName).quoteIfNeeded().asString(),
+ results
+ )
+ }
+
+ MoveClassHandler.EP_NAME.extensions.forEach { handler ->
+ if (handler !is MoveKotlinClassHandler) handler.preprocessUsages(results)
+ }
+
+ results
+ }
+ }
+
+ val usages = ArrayList<UsageInfo>()
+ val conflictChecker = MoveConflictChecker(
+ project,
+ elementsToMove,
+ descriptor.moveTarget,
+ elementsToMove.first(),
+ allElementsToMove = descriptor.allElementsToMove
+ )
+ for ((sourceFile, kotlinToLightElements) in kotlinToLightElementsBySourceFile) {
+ val internalUsages = LinkedHashSet<UsageInfo>()
+ val externalUsages = LinkedHashSet<UsageInfo>()
+
+ if (moveEntireFile) {
+ val changeInfo = ContainerChangeInfo(
+ ContainerInfo.Package(sourceFile.packageFqName),
+ descriptor.moveTarget.targetContainerFqName?.let { ContainerInfo.Package(it) } ?: ContainerInfo.UnknownPackage
+ )
+ internalUsages += sourceFile.getInternalReferencesToUpdateOnPackageNameChange(changeInfo)
+ }
+ else {
+ kotlinToLightElements.keys.forEach {
+ val packageNameInfo = descriptor.delegate.getContainerChangeInfo(it, descriptor.moveTarget)
+ internalUsages += it.getInternalReferencesToUpdateOnPackageNameChange(packageNameInfo)
+ }
+ }
+
+ internalUsages += descriptor.delegate.findInternalUsages(descriptor)
+ collectUsages(kotlinToLightElements, externalUsages)
+ if (descriptor.analyzeConflicts) {
+ conflictChecker.checkAllConflicts(externalUsages, internalUsages, conflicts)
+ descriptor.delegate.collectConflicts(descriptor, internalUsages, conflicts)
+ }
+
+ usages += internalUsages
+ usages += externalUsages
+ }
+
+ return UsageViewUtil.removeDuplicatedUsages(usages.toTypedArray())
+ }
+
+ override fun preprocessUsages(refUsages: Ref<Array<UsageInfo>>): Boolean {
+ return showConflicts(conflicts, refUsages.get())
+ }
+
+ override fun performRefactoring(usages: Array<out UsageInfo>) = doPerformRefactoring(usages.toList())
+
+ internal fun doPerformRefactoring(usages: List<UsageInfo>) {
+ fun moveDeclaration(declaration: KtNamedDeclaration, moveTarget: KotlinMoveTarget): KtNamedDeclaration {
+ val targetContainer = moveTarget.getOrCreateTargetPsi(declaration)
+ ?: throw AssertionError("Couldn't create Kotlin file for: ${declaration::class.java}: ${declaration.text}")
+ descriptor.delegate.preprocessDeclaration(descriptor, declaration)
+ if (moveEntireFile) return declaration
+ return mover(declaration, targetContainer).apply {
+ addToBeShortenedDescendantsToWaitingSet()
+ }
+ }
+
+ val (oldInternalUsages, externalUsages) = usages.partition { it is KotlinMoveUsage && it.isInternal }
+ val newInternalUsages = ArrayList<UsageInfo>()
+
+ markInternalUsages(oldInternalUsages)
+
+ val usagesToProcess = ArrayList(externalUsages)
+
+ try {
+ descriptor.delegate.preprocessUsages(descriptor, usages)
+
+ val oldToNewElementsMapping = THashMap<PsiElement, PsiElement>(ElementHashingStrategy)
+
+ val newDeclarations = ArrayList<KtNamedDeclaration>()
+
+ for ((sourceFile, kotlinToLightElements) in kotlinToLightElementsBySourceFile) {
+ for ((oldDeclaration, oldLightElements) in kotlinToLightElements) {
+ val elementListener = transaction?.getElementListener(oldDeclaration)
+
+ val newDeclaration = moveDeclaration(oldDeclaration, descriptor.moveTarget)
+ newDeclarations += newDeclaration
+
+ oldToNewElementsMapping[oldDeclaration] = newDeclaration
+ oldToNewElementsMapping[sourceFile] = newDeclaration.containingKtFile
+
+ elementListener?.elementMoved(newDeclaration)
+ for ((oldElement, newElement) in oldLightElements.asSequence().zip(newDeclaration.toLightElements().asSequence())) {
+ oldToNewElementsMapping[oldElement] = newElement
+ }
+
+ if (descriptor.openInEditor) {
+ EditorHelper.openInEditor(newDeclaration)
+ }
+ }
+
+ if (descriptor.deleteSourceFiles) {
+ sourceFile.delete()
+ }
+ }
+
+ val internalUsageScopes: List<KtElement> = if (moveEntireFile) {
+ newDeclarations.asSequence().map { it.containingKtFile }.distinct().toList()
+ } else {
+ newDeclarations
+ }
+ internalUsageScopes.forEach { newInternalUsages += restoreInternalUsages(it, oldToNewElementsMapping) }
+
+ usagesToProcess += newInternalUsages
+
+ nonCodeUsages = postProcessMoveUsages(usagesToProcess, oldToNewElementsMapping).toTypedArray()
+ }
+ catch (e: IncorrectOperationException) {
+ nonCodeUsages = null
+ RefactoringUIUtil.processIncorrectOperation(myProject, e)
+ }
+ finally {
+ cleanUpInternalUsages(newInternalUsages + oldInternalUsages)
+ }
+ }
+
+ override fun performPsiSpoilingRefactoring() {
+ nonCodeUsages?.let { nonCodeUsages -> RenameUtil.renameNonCodeUsages(myProject, nonCodeUsages) }
+ descriptor.moveCallback?.refactoringCompleted()
+ }
+
+ fun execute(usages: List<UsageInfo>) {
+ execute(usages.toTypedArray())
+ }
+
+ override fun doRun() {
+ try {
+ super.doRun()
+ } finally {
+ broadcastRefactoringExit(myProject, refactoringId)
+ }
+ }
+
+ override fun getCommandName(): String = REFACTORING_NAME
+}
\ No newline at end of file
diff --git a/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinTargetElementEvaluator.kt b/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinTargetElementEvaluator.kt
index 2139192..00e2f45 100644
--- a/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinTargetElementEvaluator.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinTargetElementEvaluator.kt
@@ -100,7 +100,7 @@
val calleeExpression = refExpression?.getParentOfTypeAndBranch<KtCallElement> { calleeExpression }
if (calleeExpression != null) {
(ref.resolve() as? KtConstructor<*>)?.let {
- return if (flags and JavaTargetElementEvaluator.NEW_AS_CONSTRUCTOR != 0) it else it.containingClassOrObject
+ return if (flags and JavaTargetElementEvaluator().additionalReferenceSearchFlags != 0) it else it.containingClassOrObject
}
}
diff --git a/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinTargetElementEvaluator.kt.183 b/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinTargetElementEvaluator.kt.183
new file mode 100644
index 0000000..2139192
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinTargetElementEvaluator.kt.183
@@ -0,0 +1,122 @@
+/*
+ * 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.search.ideaExtensions
+
+import com.intellij.codeInsight.JavaTargetElementEvaluator
+import com.intellij.codeInsight.TargetElementEvaluatorEx
+import com.intellij.codeInsight.TargetElementUtil
+import com.intellij.codeInsight.TargetElementUtilExtender
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiFile
+import com.intellij.psi.PsiReference
+import com.intellij.util.BitUtil
+import org.jetbrains.kotlin.descriptors.CallableDescriptor
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
+import org.jetbrains.kotlin.idea.intentions.isAutoCreatedItUsage
+import org.jetbrains.kotlin.idea.references.KtDestructuringDeclarationReference
+import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
+import org.jetbrains.kotlin.idea.references.mainReference
+import org.jetbrains.kotlin.idea.references.resolveMainReferenceToDescriptors
+import org.jetbrains.kotlin.lexer.KtTokens
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.*
+import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
+import org.jetbrains.kotlin.resolve.source.getPsi
+
+class KotlinTargetElementEvaluator : TargetElementEvaluatorEx, TargetElementUtilExtender {
+ companion object {
+ const val DO_NOT_UNWRAP_LABELED_EXPRESSION = 0x100
+ const val BYPASS_IMPORT_ALIAS = 0x200
+
+ // Place caret after the open curly brace in lambda for generated 'it'
+ fun findLambdaOpenLBraceForGeneratedIt(ref: PsiReference): PsiElement? {
+ val element: PsiElement = ref.element
+ if (element.text != "it") return null
+
+ if (element !is KtNameReferenceExpression || !isAutoCreatedItUsage(element)) return null
+
+ val itDescriptor = element.resolveMainReferenceToDescriptors().singleOrNull() ?: return null
+ val descriptorWithSource = itDescriptor.containingDeclaration as? DeclarationDescriptorWithSource ?: return null
+ val lambdaExpression = descriptorWithSource.source.getPsi()?.parent as? KtLambdaExpression ?: return null
+ return lambdaExpression.leftCurlyBrace.treeNext?.psi
+ }
+
+ // Navigate to receiver element for this in extension declaration
+ fun findReceiverForThisInExtensionFunction(ref: PsiReference): PsiElement? {
+ val element: PsiElement = ref.element
+ if (element.text != "this") return null
+
+ if (element !is KtNameReferenceExpression) return null
+ val callableDescriptor = element.resolveMainReferenceToDescriptors().singleOrNull() as? CallableDescriptor ?: return null
+
+ if (!callableDescriptor.isExtension) return null
+ val callableDeclaration = callableDescriptor.source.getPsi() as? KtCallableDeclaration ?: return null
+
+ return callableDeclaration.receiverTypeReference
+ }
+ }
+
+ override fun getAdditionalDefinitionSearchFlags() = 0
+
+ override fun getAdditionalReferenceSearchFlags() = DO_NOT_UNWRAP_LABELED_EXPRESSION or BYPASS_IMPORT_ALIAS
+
+ override fun getAllAdditionalFlags() = additionalDefinitionSearchFlags + additionalReferenceSearchFlags
+
+ override fun includeSelfInGotoImplementation(element: PsiElement): Boolean = !(element is KtClass && element.isAbstract())
+
+ override fun getElementByReference(ref: PsiReference, flags: Int): PsiElement? {
+ if (ref is KtSimpleNameReference && ref.expression is KtLabelReferenceExpression) {
+ val refTarget = ref.resolve() as? KtExpression ?: return null
+ if (!BitUtil.isSet(flags, DO_NOT_UNWRAP_LABELED_EXPRESSION)) {
+ return refTarget.getLabeledParent(ref.expression.getReferencedName()) ?: refTarget
+ }
+ return refTarget
+ }
+
+ if (!BitUtil.isSet(flags, BYPASS_IMPORT_ALIAS)) {
+ (ref.element as? KtSimpleNameExpression)?.mainReference?.getImportAlias()?.let { return it }
+ }
+
+ // prefer destructing declaration entry to its target if element name is accepted
+ if (ref is KtDestructuringDeclarationReference && BitUtil.isSet(flags, TargetElementUtil.ELEMENT_NAME_ACCEPTED)) {
+ return ref.element
+ }
+
+ val refExpression = ref.element as? KtSimpleNameExpression
+ val calleeExpression = refExpression?.getParentOfTypeAndBranch<KtCallElement> { calleeExpression }
+ if (calleeExpression != null) {
+ (ref.resolve() as? KtConstructor<*>)?.let {
+ return if (flags and JavaTargetElementEvaluator.NEW_AS_CONSTRUCTOR != 0) it else it.containingClassOrObject
+ }
+ }
+
+ if (BitUtil.isSet(flags, TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED)) {
+ return findLambdaOpenLBraceForGeneratedIt(ref)
+ ?: findReceiverForThisInExtensionFunction(ref)
+ }
+
+ return null
+ }
+
+ override fun isIdentifierPart(file: PsiFile, text: CharSequence?, offset: Int): Boolean {
+ val elementAtCaret = file.findElementAt(offset)
+
+ if (elementAtCaret?.node?.elementType == KtTokens.IDENTIFIER) return true
+ // '(' is considered identifier part if it belongs to primary constructor without 'constructor' keyword
+ return elementAtCaret?.getNonStrictParentOfType<KtPrimaryConstructor>()?.textOffset == offset
+ }
+}
diff --git a/idea/src/org/jetbrains/kotlin/idea/slicer/KotlinSliceProvider.kt b/idea/src/org/jetbrains/kotlin/idea/slicer/KotlinSliceProvider.kt
index 3e72d6c..c1e6d7e 100644
--- a/idea/src/org/jetbrains/kotlin/idea/slicer/KotlinSliceProvider.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/slicer/KotlinSliceProvider.kt
@@ -75,9 +75,9 @@
return listOf(KotlinSliceUsage(usage.element, usage.parent, 0, false))
}
- override fun getExpressionAtCaret(atCaret: PsiElement?, dataFlowToThis: Boolean): KtExpression? {
+ override fun getExpressionAtCaret(atCaret: PsiElement, dataFlowToThis: Boolean): KtExpression? {
val element =
- atCaret?.parentsWithSelf
+ atCaret.parentsWithSelf
?.firstOrNull {
it is KtProperty ||
it is KtParameter ||
diff --git a/idea/src/org/jetbrains/kotlin/idea/slicer/KotlinSliceProvider.kt.183 b/idea/src/org/jetbrains/kotlin/idea/slicer/KotlinSliceProvider.kt.183
new file mode 100644
index 0000000..3e72d6c
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/slicer/KotlinSliceProvider.kt.183
@@ -0,0 +1,118 @@
+/*
+ * 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.slicer
+
+import com.intellij.codeInspection.dataFlow.Nullness
+import com.intellij.ide.util.treeView.AbstractTreeStructure
+import com.intellij.openapi.actionSystem.DefaultActionGroup
+import com.intellij.psi.PsiElement
+import com.intellij.slicer.*
+import org.jetbrains.kotlin.builtins.KotlinBuiltIns
+import org.jetbrains.kotlin.descriptors.CallableDescriptor
+import org.jetbrains.kotlin.idea.caches.resolve.analyze
+import org.jetbrains.kotlin.idea.caches.resolve.analyzeAndGetResult
+import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
+import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.guessTypes
+import org.jetbrains.kotlin.idea.references.KtReference
+import org.jetbrains.kotlin.idea.references.mainReference
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.isPlainWithEscapes
+import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
+import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
+import org.jetbrains.kotlin.types.TypeUtils
+import org.jetbrains.kotlin.types.isError
+import org.jetbrains.kotlin.types.isNullabilityFlexible
+
+class KotlinSliceProvider : SliceLanguageSupportProvider, SliceUsageTransformer {
+ companion object {
+ val LEAF_ELEMENT_EQUALITY = object : SliceLeafEquality() {
+ override fun substituteElement(element: PsiElement) = (element as? KtReference)?.resolve() ?: element
+ }
+ }
+
+ class KotlinGroupByNullnessAction(treeBuilder: SliceTreeBuilder) : GroupByNullnessActionBase(treeBuilder) {
+ override fun isAvailable() = true
+ }
+
+ val leafAnalyzer by lazy { SliceLeafAnalyzer(LEAF_ELEMENT_EQUALITY, this) }
+ val nullnessAnalyzer: SliceNullnessAnalyzerBase by lazy {
+ object : SliceNullnessAnalyzerBase(LEAF_ELEMENT_EQUALITY, this) {
+ override fun checkNullness(element: PsiElement?): Nullness {
+ val types = when (element) {
+ is KtCallableDeclaration -> listOfNotNull((element.resolveToDescriptorIfAny() as? CallableDescriptor)?.returnType)
+ is KtDeclaration -> emptyList()
+ is KtExpression -> listOfNotNull(element.analyze(BodyResolveMode.PARTIAL).getType(element))
+ else -> emptyList()
+ }
+ return when {
+ types.isEmpty() -> return Nullness.UNKNOWN
+ types.all { KotlinBuiltIns.isNullableNothing(it) } -> Nullness.NULLABLE
+ types.any { it.isError || TypeUtils.isNullableType(it) || it.isNullabilityFlexible() } -> Nullness.UNKNOWN
+ else -> Nullness.NOT_NULL
+ }
+ }
+ }
+ }
+
+ override fun createRootUsage(element: PsiElement, params: SliceAnalysisParams) = KotlinSliceUsage(element, params)
+
+ override fun transform(usage: SliceUsage): Collection<SliceUsage>? {
+ if (usage is KotlinSliceUsage) return null
+ return listOf(KotlinSliceUsage(usage.element, usage.parent, 0, false))
+ }
+
+ override fun getExpressionAtCaret(atCaret: PsiElement?, dataFlowToThis: Boolean): KtExpression? {
+ val element =
+ atCaret?.parentsWithSelf
+ ?.firstOrNull {
+ it is KtProperty ||
+ it is KtParameter ||
+ it is KtDeclarationWithBody ||
+ (it is KtClass && !it.hasExplicitPrimaryConstructor()) ||
+ (it is KtExpression && it !is KtDeclaration)
+ }
+ ?.let { KtPsiUtil.safeDeparenthesize(it as KtExpression) } ?: return null
+ if (dataFlowToThis) {
+ if (element is KtConstantExpression) return null
+ if (element is KtStringTemplateExpression && element.isPlainWithEscapes()) return null
+ if (element is KtClassLiteralExpression) return null
+ if (element is KtCallableReferenceExpression) return null
+ }
+ return element
+ }
+
+ override fun getElementForDescription(element: PsiElement): PsiElement {
+ return (element as? KtSimpleNameExpression)?.mainReference?.resolve() ?: element
+ }
+
+ override fun getRenderer() = KotlinSliceUsageCellRenderer
+
+ override fun startAnalyzeLeafValues(structure: AbstractTreeStructure, finalRunnable: Runnable) {
+ leafAnalyzer.startAnalyzeValues(structure, finalRunnable)
+ }
+
+ override fun startAnalyzeNullness(structure: AbstractTreeStructure, finalRunnable: Runnable) {
+ nullnessAnalyzer.startAnalyzeNullness(structure, finalRunnable)
+ }
+
+ override fun registerExtraPanelActions(group: DefaultActionGroup, builder: SliceTreeBuilder) {
+ if (builder.dataFlowToThis) {
+ group.add(GroupByLeavesAction(builder))
+ group.add(KotlinGroupByNullnessAction(builder))
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt
index 908675a..825b11e 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt
@@ -122,6 +122,12 @@
override fun getOriginalElement(): PsiElement? = super<UAnnotationMethod>.getOriginalElement()
+ override val returnTypeReference: UTypeReferenceExpression? by lz {
+ (sourcePsi as? KtCallableDeclaration)?.typeReference?.let {
+ LazyKotlinUTypeReferenceExpression(it, this) { javaPsi.returnType ?: UastErrorType }
+ }
+ }
+
override fun equals(other: Any?) = other is KotlinUMethod && psi == other.psi
companion object {
diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt.183 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt.183
new file mode 100644
index 0000000..908675a
--- /dev/null
+++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt.183
@@ -0,0 +1,138 @@
+/*
+ * 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.uast.kotlin.declarations
+
+import com.intellij.psi.*
+import org.jetbrains.kotlin.asJava.elements.KtLightElement
+import org.jetbrains.kotlin.asJava.elements.KtLightMethod
+import org.jetbrains.kotlin.asJava.elements.isGetter
+import org.jetbrains.kotlin.asJava.elements.isSetter
+import org.jetbrains.kotlin.lexer.KtTokens
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
+import org.jetbrains.kotlin.utils.SmartList
+import org.jetbrains.uast.*
+import org.jetbrains.uast.java.internal.JavaUElementWithComments
+import org.jetbrains.uast.kotlin.*
+
+open class KotlinUMethod(
+ psi: KtLightMethod,
+ givenParent: UElement?
+) : KotlinAbstractUElement(givenParent), UAnnotationMethod, UMethodTypeSpecific, UAnchorOwner, JavaUElementWithComments, PsiMethod by psi {
+ override val comments: List<UComment>
+ get() = super<KotlinAbstractUElement>.comments
+
+ override val psi: KtLightMethod = unwrap<UMethod, KtLightMethod>(psi)
+
+ override val javaPsi = psi
+
+ override val sourcePsi = psi.kotlinOrigin
+
+ override fun getSourceElement() = sourcePsi ?: this
+
+ override val uastDefaultValue by lz {
+ val annotationParameter = psi.kotlinOrigin as? KtParameter ?: return@lz null
+ val defaultValue = annotationParameter.defaultValue ?: return@lz null
+ getLanguagePlugin().convertElement(defaultValue, this) as? UExpression
+ }
+
+ private val kotlinOrigin = (psi.originalElement as KtLightElement<*, *>).kotlinOrigin
+
+ override fun getContainingFile(): PsiFile? = unwrapFakeFileForLightClass(psi.containingFile)
+
+ override fun getNameIdentifier() = UastLightIdentifier(psi, kotlinOrigin as KtNamedDeclaration?)
+
+ override val annotations by lz {
+ psi.annotations
+ .mapNotNull { (it as? KtLightElement<*, *>)?.kotlinOrigin as? KtAnnotationEntry }
+ .map { KotlinUAnnotation(it, this) }
+ }
+
+ private val receiver by lz { (sourcePsi as? KtCallableDeclaration)?.receiverTypeReference }
+
+ override val uastParameters by lz {
+ val lightParams = psi.parameterList.parameters
+ val receiver = receiver ?: return@lz lightParams.map {
+ KotlinUParameter(it, (it as? KtLightElement<*, *>)?.kotlinOrigin, this)
+ }
+ val receiverLight = lightParams.firstOrNull() ?: return@lz emptyList<UParameter>()
+ val uParameters = SmartList<UParameter>(KotlinReceiverUParameter(receiverLight, receiver, this))
+ lightParams.drop(1).mapTo(uParameters) { KotlinUParameter(it, (it as? KtLightElement<*, *>)?.kotlinOrigin, this) }
+ uParameters
+ }
+
+ override val uastAnchor by lazy {
+ KotlinUIdentifier(
+ nameIdentifier,
+ sourcePsi.let { sourcePsi ->
+ when (sourcePsi) {
+ is PsiNameIdentifierOwner -> sourcePsi.nameIdentifier
+ is KtObjectDeclaration -> sourcePsi.getObjectKeyword()
+ else -> sourcePsi?.navigationElement
+ }
+ },
+ this
+ )
+ }
+
+
+ override val uastBody by lz {
+ val bodyExpression = when (kotlinOrigin) {
+ is KtFunction -> kotlinOrigin.bodyExpression
+ is KtProperty -> when {
+ psi.isGetter -> kotlinOrigin.getter?.bodyExpression
+ psi.isSetter -> kotlinOrigin.setter?.bodyExpression
+ else -> null
+ }
+ else -> null
+ } ?: return@lz null
+
+ when (bodyExpression) {
+ !is KtBlockExpression -> {
+ KotlinUBlockExpression.KotlinLazyUBlockExpression(this, { block ->
+ val implicitReturn = KotlinUImplicitReturnExpression(block)
+ val uBody = getLanguagePlugin().convertElement(bodyExpression, implicitReturn) as? UExpression
+ ?: return@KotlinLazyUBlockExpression emptyList()
+ listOf(implicitReturn.apply { returnExpression = uBody })
+ })
+
+ }
+ else -> getLanguagePlugin().convertElement(bodyExpression, this) as? UExpression
+ }
+ }
+
+ override val isOverride: Boolean
+ get() = (kotlinOrigin as? KtCallableDeclaration)?.hasModifier(KtTokens.OVERRIDE_KEYWORD) ?: false
+
+ override fun getBody(): PsiCodeBlock? = super<UAnnotationMethod>.getBody()
+
+ override fun getOriginalElement(): PsiElement? = super<UAnnotationMethod>.getOriginalElement()
+
+ override fun equals(other: Any?) = other is KotlinUMethod && psi == other.psi
+
+ companion object {
+ fun create(psi: KtLightMethod, containingElement: UElement?) =
+ if (psi.kotlinOrigin is KtConstructor<*>) {
+ KotlinConstructorUMethod(
+ psi.kotlinOrigin?.containingClassOrObject,
+ psi, containingElement
+ )
+ }
+ else
+ KotlinUMethod(psi, containingElement)
+ }
+}
\ No newline at end of file
diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/evaluation/KotlinEvaluatorExtension.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/evaluation/KotlinEvaluatorExtension.kt
index e2642d6..36ad440 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/evaluation/KotlinEvaluatorExtension.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/evaluation/KotlinEvaluatorExtension.kt
@@ -9,6 +9,7 @@
import org.jetbrains.uast.kotlin.KotlinBinaryOperators
import org.jetbrains.uast.kotlin.KotlinPostfixOperators
import org.jetbrains.uast.values.*
+import org.jetbrains.uast.evaluation.to
class KotlinEvaluatorExtension : AbstractEvaluatorExtension(KotlinLanguage.INSTANCE) {
diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/evaluation/KotlinEvaluatorExtension.kt.183 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/evaluation/KotlinEvaluatorExtension.kt.183
new file mode 100644
index 0000000..e2642d6
--- /dev/null
+++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/evaluation/KotlinEvaluatorExtension.kt.183
@@ -0,0 +1,56 @@
+package org.jetbrains.uast.kotlin.evaluation
+
+import org.jetbrains.kotlin.idea.KotlinLanguage
+import org.jetbrains.uast.UBinaryExpression
+import org.jetbrains.uast.UastPostfixOperator
+import org.jetbrains.uast.evaluation.AbstractEvaluatorExtension
+import org.jetbrains.uast.evaluation.UEvaluationInfo
+import org.jetbrains.uast.evaluation.UEvaluationState
+import org.jetbrains.uast.kotlin.KotlinBinaryOperators
+import org.jetbrains.uast.kotlin.KotlinPostfixOperators
+import org.jetbrains.uast.values.*
+
+class KotlinEvaluatorExtension : AbstractEvaluatorExtension(KotlinLanguage.INSTANCE) {
+
+ private data class Range(val from: UValue, val to: UValue) {
+ override fun toString() = "$from..$to"
+ }
+
+ private class UClosedRangeConstant(override val value: Range, override val source: UBinaryExpression?) : UAbstractConstant() {
+ constructor(from: UValue, to: UValue, source: UBinaryExpression): this(Range(from, to), source)
+ }
+
+ override fun evaluatePostfix(
+ operator: UastPostfixOperator,
+ operandValue: UValue,
+ state: UEvaluationState
+ ): UEvaluationInfo {
+ return when (operator) {
+ KotlinPostfixOperators.EXCLEXCL -> when (operandValue.toConstant()) {
+ UNullConstant -> UValue.UNREACHABLE
+ is UConstant -> operandValue
+ else -> UUndeterminedValue
+ } to state
+ else -> return super.evaluatePostfix(operator, operandValue, state)
+ }
+ }
+
+ private fun UValue.contains(value: UValue): UValue {
+ val range = (this as? UClosedRangeConstant)?.value ?: return UUndeterminedValue
+ return (value greaterOrEquals range.from) and (value lessOrEquals range.to)
+ }
+
+ override fun evaluateBinary(
+ binaryExpression: UBinaryExpression,
+ leftValue: UValue,
+ rightValue: UValue,
+ state: UEvaluationState
+ ): UEvaluationInfo {
+ return when (binaryExpression.operator) {
+ KotlinBinaryOperators.IN -> rightValue.contains(leftValue)
+ KotlinBinaryOperators.NOT_IN -> !rightValue.contains(leftValue)
+ KotlinBinaryOperators.RANGE_TO -> UClosedRangeConstant(leftValue, rightValue, binaryExpression)
+ else -> UUndeterminedValue
+ } to state
+ }
+}
\ No newline at end of file
diff --git a/plugins/uast-kotlin/tests/KotlinUastApiTest.kt b/plugins/uast-kotlin/tests/KotlinUastApiTest.kt
index 42c2928..798d453 100644
--- a/plugins/uast-kotlin/tests/KotlinUastApiTest.kt
+++ b/plugins/uast-kotlin/tests/KotlinUastApiTest.kt
@@ -456,6 +456,22 @@
}
}
+ @Test
+ fun testMethodReturnTypeReference() {
+ doTest("Elvis") { _, file ->
+ assertEquals(
+ "UTypeReferenceExpression (name = java.lang.String)",
+ file.findElementByTextFromPsi<UMethod>("fun foo(bar: String): String? = null").returnTypeReference?.asLogString()
+ )
+ assertEquals(
+ null,
+ file.findElementByTextFromPsi<UMethod>("fun bar() = 42").returnTypeReference?.asLogString()
+ )
+
+ }
+ }
+
+
}
fun <T, R> Iterable<T>.assertedFind(value: R, transform: (T) -> R): T =
diff --git a/plugins/uast-kotlin/tests/KotlinUastApiTest.kt.183 b/plugins/uast-kotlin/tests/KotlinUastApiTest.kt.183
new file mode 100644
index 0000000..42c2928
--- /dev/null
+++ b/plugins/uast-kotlin/tests/KotlinUastApiTest.kt.183
@@ -0,0 +1,462 @@
+package org.jetbrains.uast.test.kotlin
+
+import com.intellij.psi.PsiAnnotation
+import com.intellij.psi.PsiModifier
+import com.intellij.testFramework.UsefulTestCase
+import org.jetbrains.kotlin.asJava.toLightAnnotation
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
+import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
+import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
+import org.jetbrains.kotlin.utils.addToStdlib.cast
+import org.jetbrains.kotlin.utils.sure
+import org.jetbrains.uast.*
+import org.jetbrains.uast.kotlin.KotlinUastLanguagePlugin
+import org.jetbrains.uast.test.env.kotlin.findElementByText
+import org.jetbrains.uast.test.env.kotlin.findElementByTextFromPsi
+import org.jetbrains.uast.visitor.AbstractUastVisitor
+import org.junit.Assert
+import org.junit.Test
+
+
+class KotlinUastApiTest : AbstractKotlinUastTest() {
+ override fun check(testName: String, file: UFile) {
+ }
+
+ @Test fun testAnnotationParameters() {
+ doTest("AnnotationParameters") { _, file ->
+ val annotation = file.findElementByText<UAnnotation>("@IntRange(from = 10, to = 0)")
+ assertEquals(annotation.findAttributeValue("from")?.evaluate(), 10)
+ val toAttribute = annotation.findAttributeValue("to")!!
+ assertEquals(toAttribute.evaluate(), 0)
+ KtUsefulTestCase.assertInstanceOf(annotation.psi.toUElement(), UAnnotation::class.java)
+ KtUsefulTestCase.assertInstanceOf(
+ annotation.psi.cast<KtAnnotationEntry>().toLightAnnotation().toUElement(),
+ UAnnotation::class.java
+ )
+ KtUsefulTestCase.assertInstanceOf(toAttribute.uastParent, UNamedExpression::class.java)
+ KtUsefulTestCase.assertInstanceOf(toAttribute.psi.toUElement()?.uastParent, UNamedExpression::class.java)
+ }
+ }
+
+ @Test fun testConvertStringTemplate() {
+ doTest("StringTemplateInClass") { _, file ->
+ val literalExpression = file.findElementByText<ULiteralExpression>("lorem")
+ val psi = literalExpression.psi!!
+ Assert.assertTrue(psi is KtLiteralStringTemplateEntry)
+ val literalExpressionAgain = psi.toUElement()
+ Assert.assertTrue(literalExpressionAgain is ULiteralExpression)
+
+ }
+ }
+
+ @Test fun testConvertStringTemplateWithExpectedType() {
+ doTest("StringTemplateWithVar") { _, file ->
+ val index = file.psi.text.indexOf("foo")
+ val stringTemplate = file.psi.findElementAt(index)!!.getParentOfType<KtStringTemplateExpression>(false)
+ val uLiteral = stringTemplate.toUElementOfType<ULiteralExpression>()
+ assertNull(uLiteral)
+ }
+ }
+
+ @Test fun testNameContainingFile() {
+ doTest("NameContainingFile") { _, file ->
+ val foo = file.findElementByText<UClass>("class Foo")
+ assertEquals(file.psi, foo.nameIdentifier!!.containingFile)
+
+ val bar = file.findElementByText<UMethod>("fun bar() {}")
+ assertEquals(file.psi, bar.nameIdentifier!!.containingFile)
+
+ val xyzzy = file.findElementByText<UVariable>("val xyzzy: Int = 0")
+ assertEquals(file.psi, xyzzy.nameIdentifier!!.containingFile)
+ }
+ }
+
+ @Test fun testInterfaceMethodWithBody() {
+ doTest("DefaultImpls") { _, file ->
+ val bar = file.findElementByText<UMethod>("fun bar() = \"Hello!\"")
+ assertFalse(bar.containingFile.text!!, bar.psi.modifierList.hasExplicitModifier(PsiModifier.DEFAULT))
+ assertTrue(bar.containingFile.text!!, bar.psi.modifierList.hasModifierProperty(PsiModifier.DEFAULT))
+ }
+ }
+
+ @Test fun testSAM() {
+ doTest("SAM") { _, file ->
+ assertNull(file.findElementByText<ULambdaExpression>("{ /* Not SAM */ }").functionalInterfaceType)
+
+ assertEquals("java.lang.Runnable",
+ file.findElementByText<ULambdaExpression>("{/* Variable */}").functionalInterfaceType?.canonicalText)
+
+ assertEquals("java.lang.Runnable",
+ file.findElementByText<ULambdaExpression>("{/* Assignment */}").functionalInterfaceType?.canonicalText)
+
+ assertEquals("java.lang.Runnable",
+ file.findElementByText<ULambdaExpression>("{/* Type Cast */}").functionalInterfaceType?.canonicalText)
+
+ assertEquals("java.lang.Runnable",
+ file.findElementByText<ULambdaExpression>("{/* Argument */}").functionalInterfaceType?.canonicalText)
+
+ assertEquals("java.lang.Runnable",
+ file.findElementByText<ULambdaExpression>("{/* Return */}").functionalInterfaceType?.canonicalText)
+
+ assertEquals(
+ "java.lang.Runnable",
+ file.findElementByText<ULambdaExpression>("{ /* SAM */ }").functionalInterfaceType?.canonicalText
+ )
+ }
+ }
+
+ @Test fun testParameterPropertyWithAnnotation() {
+ doTest("ParameterPropertyWithAnnotation") { _, file ->
+ val test1 = file.classes.find { it.name == "Test1" }!!
+
+ val constructor1 = test1.methods.find { it.name == "Test1" }!!
+ assertTrue(constructor1.uastParameters.first().annotations.any { it.qualifiedName == "MyAnnotation" })
+
+ val getter1 = test1.methods.find { it.name == "getBar" }!!
+ assertFalse(getter1.annotations.any { it.qualifiedName == "MyAnnotation" })
+
+ val setter1 = test1.methods.find { it.name == "setBar" }!!
+ assertFalse(setter1.annotations.any { it.qualifiedName == "MyAnnotation" })
+ assertFalse(setter1.uastParameters.first().annotations.any { it.qualifiedName == "MyAnnotation" })
+
+
+ val test2 = file.classes.find { it.name == "Test2" }!!
+ val constructor2 = test2.methods.find { it.name == "Test2" }!!
+ assertFalse(constructor2.uastParameters.first().annotations.any { it.qualifiedName?.startsWith("MyAnnotation") ?: false })
+
+ val getter2 = test2.methods.find { it.name == "getBar" }!!
+ getter2.annotations.single { it.qualifiedName == "MyAnnotation" }
+
+ val setter2 = test2.methods.find { it.name == "setBar" }!!
+ setter2.annotations.single { it.qualifiedName == "MyAnnotation2" }
+ setter2.uastParameters.first().annotations.single { it.qualifiedName == "MyAnnotation3" }
+
+ test2.fields.find { it.name == "bar" }!!.annotations.single { it.qualifiedName == "MyAnnotation5" }
+ }
+ }
+
+ @Test fun testConvertTypeInAnnotation() {
+ doTest("TypeInAnnotation") { _, file ->
+ val index = file.psi.text.indexOf("Test")
+ val element = file.psi.findElementAt(index)!!.getParentOfType<KtUserType>(false)!!
+ assertNotNull(element.getUastParentOfType(UAnnotation::class.java))
+ }
+ }
+
+ @Test fun testElvisType() {
+ doTest("ElvisType") { _, file ->
+ val elvisExpression = file.findElementByText<UExpression>("text ?: return")
+ assertEquals("String", elvisExpression.getExpressionType()!!.presentableText)
+ }
+ }
+
+ @Test fun testFindAttributeDefaultValue() {
+ doTest("AnnotationParameters") { _, file ->
+ val witDefaultValue = file.findElementByText<UAnnotation>("@WithDefaultValue")
+ assertEquals(42, witDefaultValue.findAttributeValue("value")!!.evaluate())
+ assertEquals(42, witDefaultValue.findAttributeValue(null)!!.evaluate())
+ }
+ }
+
+ @Test fun testIfCondition() {
+ doTest("IfStatement") { _, file ->
+ val psiFile = file.psi
+ val element = psiFile.findElementAt(psiFile.text.indexOf("\"abc\""))!!
+ val binaryExpression = element.getParentOfType<KtBinaryExpression>(false)!!
+ val uBinaryExpression = KotlinUastLanguagePlugin().convertElementWithParent(binaryExpression, null)!!
+ UsefulTestCase.assertInstanceOf(uBinaryExpression.uastParent, UIfExpression::class.java)
+ }
+ }
+
+ @Test
+ fun testWhenStringLiteral() {
+ doTest("WhenStringLiteral") { _, file ->
+
+ file.findElementByTextFromPsi<ULiteralExpression>("abc").let { literalExpression ->
+ val psi = literalExpression.psi!!
+ Assert.assertTrue(psi is KtLiteralStringTemplateEntry)
+ UsefulTestCase.assertInstanceOf(literalExpression.uastParent, USwitchClauseExpressionWithBody::class.java)
+ }
+
+ file.findElementByTextFromPsi<ULiteralExpression>("def").let { literalExpression ->
+ val psi = literalExpression.psi!!
+ Assert.assertTrue(psi is KtLiteralStringTemplateEntry)
+ UsefulTestCase.assertInstanceOf(literalExpression.uastParent, USwitchClauseExpressionWithBody::class.java)
+ }
+
+ file.findElementByTextFromPsi<ULiteralExpression>("def1").let { literalExpression ->
+ val psi = literalExpression.psi!!
+ Assert.assertTrue(psi is KtLiteralStringTemplateEntry)
+ UsefulTestCase.assertInstanceOf(literalExpression.uastParent, UBlockExpression::class.java)
+ }
+
+
+ }
+ }
+
+ @Test
+ fun testWhenAndDestructing() {
+ doTest("WhenAndDestructing") { _, file ->
+
+ file.findElementByTextFromPsi<UExpression>("val (bindingContext, statementFilter) = arr").let { e ->
+ val uBlockExpression = e.getParentOfType<UBlockExpression>()
+ Assert.assertNotNull(uBlockExpression)
+ val uMethod = uBlockExpression!!.getParentOfType<UMethod>()
+ Assert.assertNotNull(uMethod)
+ }
+
+ }
+ }
+
+ @Test
+ fun testBrokenMethodTypeResolve() {
+ doTest("BrokenMethod") { _, file ->
+
+ file.accept(object : AbstractUastVisitor() {
+ override fun visitCallExpression(node: UCallExpression): Boolean {
+ node.returnType
+ return false
+ }
+ })
+ }
+ }
+
+ @Test
+ fun testSimpleAnnotated() {
+ doTest("SimpleAnnotated") { _, file ->
+ file.findElementByTextFromPsi<UField>("@kotlin.SinceKotlin(\"1.0\")\n val property: String = \"Mary\"").let { field ->
+ val annotation = field.annotations.assertedFind("kotlin.SinceKotlin") { it.qualifiedName }
+ Assert.assertEquals("1.0", annotation.findDeclaredAttributeValue("version")?.evaluateString())
+ Assert.assertEquals("SinceKotlin", annotation.cast<UAnchorOwner>().uastAnchor?.sourcePsi?.text)
+ }
+ }
+ }
+
+
+ fun UFile.checkUastSuperTypes(refText: String, superTypes: List<String>) {
+ findElementByTextFromPsi<UClass>(refText, false).let {
+ assertEquals("base classes", superTypes, it.uastSuperTypes.map { it.getQualifiedName() })
+ }
+ }
+
+
+ @Test
+ fun testSuperTypes() {
+ doTest("SuperCalls") { _, file ->
+ file.checkUastSuperTypes("B", listOf("A"))
+ file.checkUastSuperTypes("O", listOf("A"))
+ file.checkUastSuperTypes("innerObject ", listOf("A"))
+ file.checkUastSuperTypes("InnerClass", listOf("A"))
+ file.checkUastSuperTypes("object : A(\"textForAnon\")", listOf("A"))
+ }
+ }
+
+ @Test
+ fun testAnonymousSuperTypes() {
+ doTest("Anonymous") { _, file ->
+ file.checkUastSuperTypes("object : Runnable { override fun run() {} }", listOf("java.lang.Runnable"))
+ file.checkUastSuperTypes(
+ "object : Runnable, Closeable { override fun close() {} override fun run() {} }",
+ listOf("java.lang.Runnable", "java.io.Closeable")
+ )
+ file.checkUastSuperTypes(
+ "object : InputStream(), Runnable { override fun read(): Int = 0; override fun run() {} }",
+ listOf("java.io.InputStream", "java.lang.Runnable")
+ )
+ }
+ }
+
+ @Test
+ fun testLiteralArraysTypes() {
+ doTest("AnnotationParameters") { _, file ->
+ file.findElementByTextFromPsi<UCallExpression>("intArrayOf(1, 2, 3)").let { field ->
+ Assert.assertEquals("PsiType:int[]", field.returnType.toString())
+ }
+ file.findElementByTextFromPsi<UCallExpression>("[1, 2, 3]").let { field ->
+ Assert.assertEquals("PsiType:int[]", field.returnType.toString())
+ Assert.assertEquals("PsiType:int", field.typeArguments.single().toString())
+ }
+ file.findElementByTextFromPsi<UCallExpression>("[\"a\", \"b\", \"c\"]").let { field ->
+ Assert.assertEquals("PsiType:String[]", field.returnType.toString())
+ Assert.assertEquals("PsiType:String", field.typeArguments.single().toString())
+ }
+
+ }
+ }
+
+ @Test
+ fun testTypeAliases() {
+ doTest("TypeAliases") { _, file ->
+ val g = (file.psi as KtFile).declarations.single { it.name == "G" } as KtTypeAlias
+ val originalType = g.getTypeReference()!!.typeElement as KtFunctionType
+ val originalTypeParameters = originalType.parameterList.toUElement() as UDeclarationsExpression
+ Assert.assertTrue((originalTypeParameters.declarations.single() as UParameter).type.isValid)
+ }
+ }
+
+ @Test
+ fun testNestedAnnotation() = doTest("AnnotationComplex") { _, file ->
+ file.findElementByTextFromPsi<UElement>("@AnnotationArray(value = Annotation())")
+ .findElementByTextFromPsi<UElement>("Annotation()")
+ .sourcePsiElement
+ .let { referenceExpression ->
+ val convertedUAnnotation = referenceExpression
+ .cast<KtReferenceExpression>()
+ .toUElementOfType<UAnnotation>()
+ ?: throw AssertionError("haven't got annotation from $referenceExpression(${referenceExpression?.javaClass})")
+
+ checkDescriptorsLeak(convertedUAnnotation)
+ assertEquals("Annotation", convertedUAnnotation.qualifiedName)
+ val lightAnnotation = convertedUAnnotation.getAsJavaPsiElement(PsiAnnotation::class.java)
+ ?: throw AssertionError("can't get lightAnnotation from $convertedUAnnotation")
+ assertEquals("Annotation", lightAnnotation.qualifiedName)
+ assertEquals("Annotation", (convertedUAnnotation as UAnchorOwner).uastAnchor?.sourcePsi?.text)
+ }
+ }
+
+
+ @Test
+ fun testParametersDisorder() = doTest("ParametersDisorder") { _, file ->
+
+ fun assertArguments(argumentsInPositionalOrder: List<String?>?, refText: String) =
+ file.findElementByTextFromPsi<UCallExpression>(refText).let { call ->
+ if (call !is UCallExpressionEx) throw AssertionError("${call.javaClass} is not a UCallExpressionEx")
+ Assert.assertEquals(
+ argumentsInPositionalOrder,
+ call.resolve()?.let { psiMethod ->
+ (0 until psiMethod.parameterList.parametersCount).map {
+ call.getArgumentForParameter(it)?.asRenderString()
+ }
+ }
+ )
+ }
+
+
+ assertArguments(listOf("2", "2.2"), "global(b = 2.2F, a = 2)")
+ assertArguments(listOf(null, "\"bbb\""), "withDefault(d = \"bbb\")")
+ assertArguments(listOf("1.3", "3.4"), "atan2(1.3, 3.4)")
+ assertArguments(null, "unresolvedMethod(\"param1\", \"param2\")")
+ assertArguments(listOf("\"%i %i %i\"", "varargs 1 : 2 : 3"), "format(\"%i %i %i\", 1, 2, 3)")
+ assertArguments(listOf("\"%i %i %i\"", "varargs arrayOf(1, 2, 3)"), "format(\"%i %i %i\", arrayOf(1, 2, 3))")
+ assertArguments(
+ listOf("\"%i %i %i\"", "varargs arrayOf(1, 2, 3) : arrayOf(4, 5, 6)"),
+ "format(\"%i %i %i\", arrayOf(1, 2, 3), arrayOf(4, 5, 6))"
+ )
+ assertArguments(listOf("\"%i %i %i\"", "\"\".chunked(2).toTypedArray()"), "format(\"%i %i %i\", *\"\".chunked(2).toTypedArray())")
+ assertArguments(listOf("\"def\"", "8", "7.0"), "with2Receivers(8, 7.0F)")
+ assertArguments(listOf("\"foo\"", "1"), "object : Parent(b = 1, a = \"foo\")\n")
+ }
+
+ @Test
+ fun testResolvedDeserializedMethod() = doTest("Resolve") { _, file ->
+ val barMethod = file.findElementByTextFromPsi<UElement>("bar").getParentOfType<UMethod>()!!
+
+ fun UElement.assertResolveCall(callText: String, methodName: String = callText.substringBefore("(")) {
+ this.findElementByTextFromPsi<UCallExpression>(callText).let {
+ val resolve = it.resolve().sure { "resolving '$callText'" }
+ assertEquals(methodName, resolve.name)
+ }
+ }
+ barMethod.assertResolveCall("foo()")
+ barMethod.assertResolveCall("inlineFoo()")
+ barMethod.assertResolveCall("forEach { println(it) }", "forEach")
+ barMethod.assertResolveCall("joinToString()")
+ barMethod.assertResolveCall("last()")
+ barMethod.assertResolveCall("setValue(\"123\")")
+ barMethod.assertResolveCall("contains(2 as Int)", "longRangeContains")
+ barMethod.assertResolveCall("IntRange(1, 2)")
+ }
+
+ @Test
+ fun testUtilsStreamLambda() {
+ doTest("Lambdas") { _, file ->
+ val lambda = file.findElementByTextFromPsi<ULambdaExpression>("{ it.isEmpty() }")
+ assertEquals(
+ "java.util.function.Predicate<? super java.lang.String>",
+ lambda.functionalInterfaceType?.canonicalText
+ )
+ assertEquals(
+ "kotlin.jvm.functions.Function1<? super java.lang.String,? extends java.lang.Boolean>",
+ lambda.getExpressionType()?.canonicalText
+ )
+ val uCallExpression = lambda.uastParent.assertedCast<UCallExpression> { "UCallExpression expected" }
+ assertTrue(uCallExpression.valueArguments.contains(lambda))
+ }
+ }
+
+ @Test
+ fun testLambdaParamCall() {
+ doTest("Lambdas") { _, file ->
+ val lambdaCall = file.findElementByTextFromPsi<UCallExpression>("selectItemFunction()")
+ assertEquals(
+ "UIdentifier (Identifier (selectItemFunction))",
+ lambdaCall.methodIdentifier?.asLogString()
+ )
+ assertEquals(
+ "selectItemFunction",
+ lambdaCall.methodIdentifier?.name
+ )
+ assertEquals(
+ "invoke",
+ lambdaCall.methodName
+ )
+ val receiver = lambdaCall.receiver ?: kotlin.test.fail("receiver expected")
+ assertEquals("UReferenceExpression", receiver.asLogString())
+ val uParameter = (receiver as UReferenceExpression).resolve().toUElement() ?: kotlin.test.fail("uelement expected")
+ assertEquals("UParameter (name = selectItemFunction)", uParameter.asLogString())
+ }
+ }
+
+ @Test
+ fun testLocalLambdaCall() {
+ doTest("Lambdas") { _, file ->
+ val lambdaCall = file.findElementByTextFromPsi<UCallExpression>("baz()")
+ assertEquals(
+ "UIdentifier (Identifier (baz))",
+ lambdaCall.methodIdentifier?.asLogString()
+ )
+ assertEquals(
+ "baz",
+ lambdaCall.methodIdentifier?.name
+ )
+ assertEquals(
+ "invoke",
+ lambdaCall.methodName
+ )
+ val receiver = lambdaCall.receiver ?: kotlin.test.fail("receiver expected")
+ assertEquals("UReferenceExpression", receiver.asLogString())
+ val uParameter = (receiver as UReferenceExpression).resolve().toUElement() ?: kotlin.test.fail("uelement expected")
+ assertEquals("ULocalVariable (name = baz)", uParameter.asLogString())
+ }
+ }
+
+ @Test
+ fun testLocalDeclarationCall() {
+ doTest("LocalDeclarations") { _, file ->
+ val localFunction = file.findElementByTextFromPsi<UElement>("bar() == Local()").
+ findElementByText<UCallExpression>("bar()")
+ assertEquals(
+ "UIdentifier (Identifier (bar))",
+ localFunction.methodIdentifier?.asLogString()
+ )
+ assertEquals(
+ "bar",
+ localFunction.methodIdentifier?.name
+ )
+ assertEquals(
+ "bar",
+ localFunction.methodName
+ )
+ assertNull(localFunction.resolve())
+ val receiver = localFunction.receiver ?: kotlin.test.fail("receiver expected")
+ assertEquals("UReferenceExpression", receiver.asLogString())
+ val uParameter = (receiver as UReferenceExpression).resolve().toUElement() ?: kotlin.test.fail("uelement expected")
+ assertEquals("ULambdaExpression", uParameter.asLogString())
+ }
+ }
+
+}
+
+fun <T, R> Iterable<T>.assertedFind(value: R, transform: (T) -> R): T =
+ find { transform(it) == value } ?: throw AssertionError("'$value' not found, only ${this.joinToString { transform(it).toString() }}")
diff --git a/usage-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/ProjectScopeStatsReporters.kt b/usage-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/ProjectScopeStatsReporters.kt
index a5556c3..e5183a7 100644
--- a/usage-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/ProjectScopeStatsReporters.kt
+++ b/usage-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/ProjectScopeStatsReporters.kt
@@ -5,21 +5,10 @@
package org.jetbrains.kotlin.statistics
-import com.intellij.ide.plugins.PluginManager
-import com.intellij.internal.statistic.service.fus.collectors.ApplicationUsageTriggerCollector
-import com.intellij.internal.statistic.service.fus.collectors.FUSApplicationUsageTrigger
-import com.intellij.internal.statistic.service.fus.collectors.FUSUsageContext
-import com.intellij.openapi.extensions.PluginId
-
-open class KotlinStatisticsTrigger(private val groupIdSufix: String) : ApplicationUsageTriggerCollector() {
- override fun getGroupId() = "statistics.kotlin.$groupIdSufix"
-
+open class KotlinStatisticsTrigger(private val groupIdSufix: String) {
companion object {
public fun trigger(clazz: Class<out KotlinStatisticsTrigger>, event: String) {
- val plugin = PluginManager.getPlugin(PluginId.getId("org.jetbrains.kotlin"))
- val version = plugin?.version ?: "undefined"
-
- FUSApplicationUsageTrigger.getInstance().trigger(clazz, event, FUSUsageContext.create(version))
+ // FUS is not working for 182
}
}
}
diff --git a/usage-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/ProjectScopeStatsReporters.kt.183 b/usage-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/ProjectScopeStatsReporters.kt.183
new file mode 100644
index 0000000..a5556c3
--- /dev/null
+++ b/usage-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/ProjectScopeStatsReporters.kt.183
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2010-2018 JetBrains s.r.o. 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.statistics
+
+import com.intellij.ide.plugins.PluginManager
+import com.intellij.internal.statistic.service.fus.collectors.ApplicationUsageTriggerCollector
+import com.intellij.internal.statistic.service.fus.collectors.FUSApplicationUsageTrigger
+import com.intellij.internal.statistic.service.fus.collectors.FUSUsageContext
+import com.intellij.openapi.extensions.PluginId
+
+open class KotlinStatisticsTrigger(private val groupIdSufix: String) : ApplicationUsageTriggerCollector() {
+ override fun getGroupId() = "statistics.kotlin.$groupIdSufix"
+
+ companion object {
+ public fun trigger(clazz: Class<out KotlinStatisticsTrigger>, event: String) {
+ val plugin = PluginManager.getPlugin(PluginId.getId("org.jetbrains.kotlin"))
+ val version = plugin?.version ?: "undefined"
+
+ FUSApplicationUsageTrigger.getInstance().trigger(clazz, event, FUSUsageContext.create(version))
+ }
+ }
+}
+
+open class KotlinIdeStatisticsTrigger(groupIdSufix: String) : KotlinStatisticsTrigger("ide.$groupIdSufix")
+
+open class KotlinGradlePluginStatisticsTrigger(groupIdSufix: String) : KotlinStatisticsTrigger("gradle.$groupIdSufix")
+open class KotlinMavenPluginStatisticsTrigger(groupIdSufix: String) : KotlinStatisticsTrigger("maven.$groupIdSufix")
+open class KotlinJPSPluginStatisticsTrigger(groupIdSufix: String) : KotlinStatisticsTrigger("jps.$groupIdSufix")
+
+class KotlinVersionTrigger : KotlinGradlePluginStatisticsTrigger("kotlin_version")
+
+class KotlinTargetTrigger : KotlinGradlePluginStatisticsTrigger("target")
+
+class KotlinMavenTargetTrigger : KotlinMavenPluginStatisticsTrigger("target")
+
+class KotlinJPSTargetTrigger : KotlinJPSPluginStatisticsTrigger("target")
+
+class KotlinProjectLibraryUsageTrigger : KotlinGradlePluginStatisticsTrigger("library")
+
+open class KotlinIdeActionTrigger(groupIdSufix: String? = null) : KotlinIdeStatisticsTrigger("action" + (if (groupIdSufix != null) ".$groupIdSufix" else ""))
+
+class KotlinIdeRefactoringTrigger : KotlinIdeActionTrigger("refactoring")
+
+class KotlinIdeNewFileTemplateTrigger : KotlinIdeStatisticsTrigger("newFileTempl")
\ No newline at end of file