Remove 181 bunch files
This commit is contained in:
@@ -1,195 +0,0 @@
|
||||
@file:Suppress("unused")
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ProjectDependency
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.internal.ConventionTask
|
||||
import org.gradle.api.plugins.ExtensionAware
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import java.io.File
|
||||
|
||||
fun Project.configureFormInstrumentation() {
|
||||
plugins.matching { it::class.java.canonicalName.startsWith("org.jetbrains.kotlin.gradle.plugin") }.all {
|
||||
// When we change the output classes directory, Gradle will automatically configure
|
||||
// the test compile tasks to use the instrumented classes. Normally this is fine,
|
||||
// however, it causes problems for Kotlin projects:
|
||||
|
||||
// The "internal" modifier can be used to restrict access to the same module.
|
||||
// To make it possible to use internal methods from the main source set in test classes,
|
||||
// the Kotlin Gradle plugin adds the original output directory of the Java task
|
||||
// as "friendly directory" which makes it possible to access internal members
|
||||
// of the main module. Also this directory should be available on classpath during compilation
|
||||
|
||||
// This fails when we change the classes dir. The easiest fix is to prepend the
|
||||
// classes from the "friendly directory" to the compile classpath.
|
||||
val testCompile = tasks.findByName("compileTestKotlin") as AbstractCompile?
|
||||
testCompile?.doFirst {
|
||||
testCompile.classpath = (testCompile.classpath
|
||||
- mainSourceSet.output.classesDirs
|
||||
+ files((mainSourceSet as ExtensionAware).extra.get("classesDirsCopy")))
|
||||
}
|
||||
}
|
||||
|
||||
val instrumentationClasspathCfg = configurations.create("instrumentationClasspath")
|
||||
|
||||
dependencies {
|
||||
instrumentationClasspathCfg(intellijDep()) { includeJars("javac2", "jdom", "asm-all", "jgoodies-forms", rootProject = rootProject) }
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
sourceSets.all { sourceSetParam ->
|
||||
// This copy will ignore filters, but they are unlikely to be used.
|
||||
val classesDirs = (sourceSetParam.output.classesDirs as ConfigurableFileCollection).from as Collection<Any>
|
||||
|
||||
val classesDirsCopy = project.files(classesDirs.toTypedArray()).filter { it.exists() }
|
||||
(sourceSetParam as ExtensionAware).extra.set("classesDirsCopy", classesDirsCopy)
|
||||
|
||||
logger.info("Saving old sources dir for project ${project.name}")
|
||||
val instrumentedClassesDir = File(project.buildDir, "classes/${sourceSetParam.name}-instrumented")
|
||||
(sourceSetParam.output.classesDirs as ConfigurableFileCollection).setFrom(instrumentedClassesDir)
|
||||
val instrumentTask =
|
||||
project.tasks.create(sourceSetParam.getTaskName("instrument", "classes"), IntelliJInstrumentCodeTask::class.java)
|
||||
instrumentTask.apply {
|
||||
dependsOn(sourceSetParam.classesTaskName).onlyIf { !classesDirsCopy.isEmpty }
|
||||
sourceSet = sourceSetParam
|
||||
instrumentationClasspath = instrumentationClasspathCfg
|
||||
originalClassesDirs = classesDirsCopy
|
||||
output = instrumentedClassesDir
|
||||
}
|
||||
|
||||
instrumentTask.outputs.dir(instrumentedClassesDir)
|
||||
// Ensure that our task is invoked when the source set is built
|
||||
sourceSetParam.compiledBy(instrumentTask)
|
||||
@Suppress("UNUSED_EXPRESSION")
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@CacheableTask
|
||||
open class IntelliJInstrumentCodeTask : ConventionTask() {
|
||||
companion object {
|
||||
private const val FILTER_ANNOTATION_REGEXP_CLASS = "com.intellij.ant.ClassFilterAnnotationRegexp"
|
||||
private const val LOADER_REF = "java2.loader"
|
||||
}
|
||||
|
||||
var sourceSet: SourceSet? = null
|
||||
|
||||
var instrumentationClasspath: Configuration? = null
|
||||
|
||||
@Input
|
||||
var originalClassesDirs: FileCollection? = null
|
||||
|
||||
@get:Input
|
||||
var instrumentNotNull: Boolean = false
|
||||
|
||||
@get:InputFiles
|
||||
val sourceDirs: FileCollection
|
||||
get() = project.files(sourceSet!!.allSource.srcDirs.filter { !sourceSet!!.resources.contains(it) && it.exists() })
|
||||
|
||||
@get:OutputDirectory
|
||||
lateinit var output: File
|
||||
|
||||
@TaskAction
|
||||
fun instrumentClasses() {
|
||||
logger.info(
|
||||
"input files are: ${originalClassesDirs?.joinToString(
|
||||
"; ",
|
||||
transform = { "'${it.name}'${if (it.exists()) "" else " (does not exists)"}" })}"
|
||||
)
|
||||
output.deleteRecursively()
|
||||
copyOriginalClasses()
|
||||
|
||||
val classpath = instrumentationClasspath!!
|
||||
|
||||
ant.withGroovyBuilder {
|
||||
"taskdef"(
|
||||
"name" to "instrumentIdeaExtensions",
|
||||
"classpath" to classpath.asPath,
|
||||
"loaderref" to LOADER_REF,
|
||||
"classname" to "com.intellij.ant.InstrumentIdeaExtensions"
|
||||
)
|
||||
}
|
||||
|
||||
logger.info("Compiling forms and instrumenting code with nullability preconditions")
|
||||
if (instrumentNotNull) {
|
||||
prepareNotNullInstrumenting(classpath.asPath)
|
||||
}
|
||||
|
||||
instrumentCode(sourceDirs, instrumentNotNull)
|
||||
}
|
||||
|
||||
private fun copyOriginalClasses() {
|
||||
project.copy {
|
||||
from(originalClassesDirs)
|
||||
into(output)
|
||||
}
|
||||
}
|
||||
|
||||
private fun prepareNotNullInstrumenting(classpath: String) {
|
||||
ant.withGroovyBuilder {
|
||||
"typedef"(
|
||||
"name" to "skip",
|
||||
"classpath" to classpath,
|
||||
"loaderref" to LOADER_REF,
|
||||
"classname" to FILTER_ANNOTATION_REGEXP_CLASS
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun instrumentCode(srcDirs: FileCollection, instrumentNotNull: Boolean) {
|
||||
val headlessOldValue = System.setProperty("java.awt.headless", "true")
|
||||
|
||||
// Instrumentation needs to have access to sources of forms for inclusion
|
||||
val depSourceDirectorySets = project.configurations["compile"].dependencies.withType(ProjectDependency::class.java)
|
||||
.map { p -> p.dependencyProject.mainSourceSet.allSource.sourceDirectories }
|
||||
val instrumentationClasspath =
|
||||
depSourceDirectorySets.fold(sourceSet!!.compileClasspath) { acc, v -> acc + v }.asPath.also {
|
||||
logger.info("Using following dependency source dirs: $it")
|
||||
}
|
||||
|
||||
logger.info("Running instrumentIdeaExtensions with srcdir=${srcDirs.asPath}}, destdir=$output and classpath=$instrumentationClasspath")
|
||||
|
||||
ant.withGroovyBuilder {
|
||||
"instrumentIdeaExtensions"(
|
||||
"srcdir" to srcDirs.asPath,
|
||||
"destdir" to output,
|
||||
"classpath" to instrumentationClasspath,
|
||||
"includeantruntime" to false,
|
||||
"instrumentNotNull" to instrumentNotNull
|
||||
) {
|
||||
if (instrumentNotNull) {
|
||||
ant.withGroovyBuilder {
|
||||
"skip"("pattern" to "kotlin/Metadata")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (headlessOldValue != null) {
|
||||
System.setProperty("java.awt.headless", headlessOldValue)
|
||||
} else {
|
||||
System.clearProperty("java.awt.headless")
|
||||
}
|
||||
}
|
||||
}
|
||||
-54
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import jdk.internal.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.load.kotlin.getContainingKotlinJvmBinaryClass
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
|
||||
// KLUDGE: Inline suspend function built with compiler version less than 1.1.4/1.2-M1 did not contain proper
|
||||
// before/after suspension point marks, so we detect those functions here and insert the corresponding marks
|
||||
|
||||
fun insertLegacySuspendInlineMarks(node: MethodNode) {
|
||||
with (node.instructions) {
|
||||
// look for return instruction before the end and insert "afterSuspendMarker" there
|
||||
insertBefore(findLastReturn(last) ?: return, produceSuspendMarker(false).instructions)
|
||||
// insert "beforeSuspendMarker" at the beginning
|
||||
insertBefore(first, produceSuspendMarker(true).instructions)
|
||||
}
|
||||
node.maxStack = node.maxStack.coerceAtLeast(2) // min stack need for suspend marker before return
|
||||
}
|
||||
|
||||
fun findLastReturn(node: AbstractInsnNode?): AbstractInsnNode? {
|
||||
var cur = node
|
||||
while (cur != null && cur.opcode != Opcodes.ARETURN) cur = cur.previous
|
||||
return cur
|
||||
}
|
||||
|
||||
private fun produceSuspendMarker(isStartNotEnd: Boolean): MethodNode =
|
||||
MethodNode().also { addSuspendMarker(InstructionAdapter(it), isStartNotEnd) }
|
||||
|
||||
fun isLegacySuspendInlineFunction(descriptor: CallableMemberDescriptor): Boolean {
|
||||
if (descriptor !is FunctionDescriptor) return false
|
||||
if (!descriptor.isSuspend || !descriptor.isInline) return false
|
||||
val jvmBytecodeVersion = descriptor.getContainingKotlinJvmBinaryClass()?.classHeader?.bytecodeVersion ?: return false
|
||||
return !jvmBytecodeVersion.isAtLeast(1, 0, 2)
|
||||
}
|
||||
@@ -1,237 +0,0 @@
|
||||
-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
|
||||
|
||||
# Annotations from intellijCore/annotations.jar that not presented in org.jetbrains.annotations
|
||||
-dontwarn org.jetbrains.annotations.Async*
|
||||
-dontwarn org.jetbrains.annotations.Nls$Capitalization
|
||||
|
||||
# Depends on apache batik which has lots of dependencies
|
||||
-dontwarn com.intellij.util.SVGLoader*
|
||||
|
||||
# The appropriate jar is either loaded separately or added explicitly to the classpath then needed
|
||||
-dontwarn org.jetbrains.kotlin.scripting.compiler.plugin.ScriptingCompilerConfigurationComponentRegistrar
|
||||
|
||||
#-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.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(...); }
|
||||
|
||||
# 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.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 { *; }
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.fir
|
||||
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElementFinder
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.backend.Fir2IrConverter
|
||||
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
|
||||
import org.jetbrains.kotlin.fir.resolve.FirProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer
|
||||
import org.jetbrains.kotlin.ir.AbstractIrTextTestCase
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractFir2IrTextTest : AbstractIrTextTestCase() {
|
||||
|
||||
private fun prepareProjectExtensions(project: Project) {
|
||||
}
|
||||
|
||||
override fun doTest(filePath: String?) {
|
||||
if (filePath != null) {
|
||||
val originalTextPath = filePath.replace(".kt", ".txt")
|
||||
val firTextPath = filePath.replace(".kt", ".fir.txt")
|
||||
val originalText = File(originalTextPath)
|
||||
val firText = File(firTextPath)
|
||||
if (originalText.exists() && firText.exists()) {
|
||||
val originalLines = originalText.readLines()
|
||||
val firLines = firText.readLines()
|
||||
TestCase.assertFalse(
|
||||
"Dumps via FIR & via old FE are the same. Please delete .fir.txt dump and add // FIR_IDENTICAL to test source",
|
||||
firLines.withIndex().all { (index, line) ->
|
||||
val trimmed = line.trim()
|
||||
val originalTrimmed = originalLines.getOrNull(index)?.trim()
|
||||
trimmed.isEmpty() && originalTrimmed?.isEmpty() != false || trimmed == originalTrimmed
|
||||
} && originalLines.withIndex().all { (index, line) ->
|
||||
index < firLines.size || line.trim().isEmpty()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
super.doTest(filePath)
|
||||
}
|
||||
|
||||
override fun getExpectedTextFileName(testFile: TestFile, name: String): String {
|
||||
// NB: replace with if (true) to make test against old FE results
|
||||
if ("// FIR_IDENTICAL" in testFile.content.split("\n")) {
|
||||
return super.getExpectedTextFileName(testFile, name)
|
||||
}
|
||||
return name.replace(".txt", ".fir.txt").replace(".kt", ".fir.txt")
|
||||
}
|
||||
|
||||
override fun generateIrModule(ignoreErrors: Boolean): IrModuleFragment {
|
||||
val psiFiles = myFiles.psiFiles
|
||||
|
||||
val project = psiFiles.first().project
|
||||
prepareProjectExtensions(project)
|
||||
|
||||
val scope = GlobalSearchScope.filesScope(project, psiFiles.map { it.virtualFile })
|
||||
.uniteWith(TopDownAnalyzerFacadeForJVM.AllJavaSourcesInProjectScope(project))
|
||||
val session = createSession(myEnvironment, scope)
|
||||
|
||||
val builder = RawFirBuilder(session, stubMode = false)
|
||||
|
||||
val resolveTransformer = FirTotalResolveTransformer()
|
||||
val firFiles = psiFiles.map {
|
||||
val firFile = builder.buildFirFile(it)
|
||||
(session.service<FirProvider>() as FirProviderImpl).recordFile(firFile)
|
||||
firFile
|
||||
}.also {
|
||||
try {
|
||||
resolveTransformer.processFiles(it)
|
||||
} catch (e: Exception) {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
return Fir2IrConverter.createModuleFragment(session, firFiles, myEnvironment.configuration.languageVersionSettings)
|
||||
}
|
||||
}
|
||||
-159
@@ -1,159 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.fir
|
||||
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import com.intellij.psi.PsiElementFinder
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
|
||||
import org.jetbrains.kotlin.checkers.BaseDiagnosticsTest
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
|
||||
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.java.FirJavaModuleBasedSession
|
||||
import org.jetbrains.kotlin.fir.java.FirLibrarySession
|
||||
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.FirProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.MultiTargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
abstract class AbstractFirDiagnosticsSmokeTest : BaseDiagnosticsTest() {
|
||||
override fun analyzeAndCheck(testDataFile: File, files: List<TestFile>) {
|
||||
try {
|
||||
analyzeAndCheckUnhandled(files)
|
||||
} catch (t: AssertionError) {
|
||||
throw t
|
||||
} catch (t: Throwable) {
|
||||
throw t
|
||||
}
|
||||
}
|
||||
|
||||
private fun analyzeAndCheckUnhandled(files: List<TestFile>) {
|
||||
|
||||
val groupedByModule = files.groupBy(TestFile::module)
|
||||
|
||||
val modules = createModules(groupedByModule)
|
||||
|
||||
val sessionProvider = FirProjectSessionProvider(project)
|
||||
|
||||
//For BuiltIns, registered in sessionProvider automatically
|
||||
val allProjectScope = GlobalSearchScope.allScope(project)
|
||||
FirLibrarySession.create(
|
||||
builtInsModuleInfo, sessionProvider, allProjectScope,
|
||||
environment
|
||||
)
|
||||
|
||||
val configToSession = modules.mapValues { (config, info) ->
|
||||
val moduleFiles = groupedByModule.getValue(config)
|
||||
val scope = TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, moduleFiles.mapNotNull { it.ktFile })
|
||||
FirJavaModuleBasedSession(info, sessionProvider, scope)
|
||||
}
|
||||
|
||||
val firFiles = mutableListOf<FirFile>()
|
||||
|
||||
for ((testModule, testFilesInModule) in groupedByModule) {
|
||||
val ktFiles = getKtFiles(testFilesInModule, true)
|
||||
|
||||
val session = configToSession.getValue(testModule)
|
||||
|
||||
|
||||
val firBuilder = RawFirBuilder(session, false)
|
||||
|
||||
ktFiles.mapTo(firFiles) {
|
||||
val firFile = firBuilder.buildFirFile(it)
|
||||
|
||||
(session.service<FirProvider>() as FirProviderImpl).recordFile(firFile)
|
||||
|
||||
firFile
|
||||
}
|
||||
}
|
||||
|
||||
doFirResolveTestBench(firFiles, FirTotalResolveTransformer().transformers, gc = false)
|
||||
|
||||
}
|
||||
|
||||
|
||||
private fun createModules(
|
||||
groupedByModule: Map<TestModule?, List<TestFile>>
|
||||
): MutableMap<TestModule?, ModuleInfo> {
|
||||
val modules = HashMap<TestModule?, ModuleInfo>()
|
||||
|
||||
for (testModule in groupedByModule.keys) {
|
||||
val module = if (testModule == null)
|
||||
createSealedModule()
|
||||
else
|
||||
createModule(testModule.name)
|
||||
|
||||
modules[testModule] = module
|
||||
}
|
||||
|
||||
for (testModule in groupedByModule.keys) {
|
||||
if (testModule == null) continue
|
||||
|
||||
val module = modules[testModule]!!
|
||||
val dependencies = ArrayList<ModuleInfo>()
|
||||
dependencies.add(module)
|
||||
for (dependency in testModule.getDependencies()) {
|
||||
dependencies.add(modules[dependency]!!)
|
||||
}
|
||||
|
||||
|
||||
dependencies.add(builtInsModuleInfo)
|
||||
//dependencies.addAll(getAdditionalDependencies(module))
|
||||
(module as TestModuleInfo).dependencies.addAll(dependencies)
|
||||
}
|
||||
|
||||
return modules
|
||||
}
|
||||
|
||||
private val builtInsModuleInfo = BuiltInModuleInfo(Name.special("<built-ins>"))
|
||||
|
||||
protected open fun createModule(moduleName: String): TestModuleInfo {
|
||||
val nameSuffix = moduleName.substringAfterLast("-", "")
|
||||
// TODO: use platform
|
||||
@Suppress("UNUSED_VARIABLE")
|
||||
val platform =
|
||||
when {
|
||||
nameSuffix.isEmpty() -> null
|
||||
nameSuffix == "common" -> MultiTargetPlatform.Common
|
||||
else -> MultiTargetPlatform.Specific(nameSuffix.toUpperCase())
|
||||
}
|
||||
return TestModuleInfo(Name.special("<$moduleName>"))
|
||||
}
|
||||
|
||||
class BuiltInModuleInfo(override val name: Name) : ModuleInfo {
|
||||
override val platform: TargetPlatform?
|
||||
get() = JvmPlatform
|
||||
|
||||
override fun dependencies(): List<ModuleInfo> {
|
||||
return listOf(this)
|
||||
}
|
||||
}
|
||||
|
||||
protected class TestModuleInfo(override val name: Name) : ModuleInfo {
|
||||
override val platform: TargetPlatform?
|
||||
get() = JvmPlatform
|
||||
|
||||
val dependencies = mutableListOf<ModuleInfo>(this)
|
||||
override fun dependencies(): List<ModuleInfo> {
|
||||
return dependencies
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun createSealedModule(): TestModuleInfo =
|
||||
createModule("test-module").apply {
|
||||
dependencies += builtInsModuleInfo
|
||||
}
|
||||
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* 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.fir
|
||||
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElementFinder
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
|
||||
import org.jetbrains.kotlin.fir.java.FirJavaModuleBasedSession
|
||||
import org.jetbrains.kotlin.fir.java.FirLibrarySession
|
||||
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
|
||||
import org.jetbrains.kotlin.test.KotlinTestWithEnvironment
|
||||
|
||||
abstract class AbstractFirResolveWithSessionTestCase : KotlinTestWithEnvironment() {
|
||||
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
|
||||
prepareProjectExtensions(project)
|
||||
}
|
||||
|
||||
protected fun prepareProjectExtensions(project: Project) {
|
||||
// No relevant API in 181
|
||||
// Extensions.getArea(project)
|
||||
// .getExtensionPoint(PsiElementFinder.EP_NAME)
|
||||
// .unregisterExtension(JavaElementFinder::class.java)
|
||||
}
|
||||
}
|
||||
-235
@@ -1,235 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.fir.java
|
||||
|
||||
import com.intellij.lang.java.JavaLanguage
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.text.StringUtilRt
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.PsiFileFactoryImpl
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.testFramework.LightVirtualFile
|
||||
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
|
||||
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
|
||||
import org.jetbrains.kotlin.fir.FirRenderer
|
||||
import org.jetbrains.kotlin.fir.createSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
|
||||
import org.jetbrains.kotlin.fir.java.declarations.FirJavaConstructor
|
||||
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
|
||||
import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod
|
||||
import org.jetbrains.kotlin.fir.java.scopes.JavaClassEnhancementScope
|
||||
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.impl.FirCompositeSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope
|
||||
import org.jetbrains.kotlin.fir.service
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType
|
||||
import org.jetbrains.kotlin.test.*
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils.getAnnotationsJar
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils.newConfiguration
|
||||
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
abstract class AbstractFirTypeEnhancementTest : KtUsefulTestCase() {
|
||||
private lateinit var javaFilesDir: File
|
||||
|
||||
private lateinit var environment: KotlinCoreEnvironment
|
||||
|
||||
val project: Project
|
||||
get() {
|
||||
return environment.project
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
javaFilesDir = KotlinTestUtils.tmpDirForTest(this)
|
||||
}
|
||||
|
||||
override fun tearDown() {
|
||||
FileUtil.delete(javaFilesDir)
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
private fun createJarWithForeignAnnotations(): File =
|
||||
MockLibraryUtil.compileJavaFilesLibraryToJar(FOREIGN_ANNOTATIONS_SOURCES_PATH, "foreign-annotations")
|
||||
|
||||
private fun createEnvironment(content: String): KotlinCoreEnvironment {
|
||||
val classpath = mutableListOf(getAnnotationsJar(), ForTestCompileRuntime.runtimeJarForTests())
|
||||
if (InTextDirectivesUtils.isDirectiveDefined(content, "ANDROID_ANNOTATIONS")) {
|
||||
classpath.add(ForTestCompileRuntime.androidAnnotationsForTests())
|
||||
}
|
||||
if (InTextDirectivesUtils.isDirectiveDefined(content, "JVM_ANNOTATIONS")) {
|
||||
classpath.add(ForTestCompileRuntime.jvmAnnotationsForTests())
|
||||
}
|
||||
if (InTextDirectivesUtils.isDirectiveDefined(content, "FOREIGN_ANNOTATIONS")) {
|
||||
classpath.add(createJarWithForeignAnnotations())
|
||||
}
|
||||
return KotlinCoreEnvironment.createForTests(
|
||||
testRootDisposable,
|
||||
newConfiguration(
|
||||
ConfigurationKind.JDK_NO_RUNTIME, TestJdkKind.FULL_JDK, classpath, listOf(javaFilesDir)
|
||||
),
|
||||
EnvironmentConfigFiles.JVM_CONFIG_FILES
|
||||
)
|
||||
}
|
||||
|
||||
fun doTest(path: String) {
|
||||
val javaFile = File(path)
|
||||
val javaLines = javaFile.readLines()
|
||||
val content = javaLines.joinToString(separator = "\n")
|
||||
if (InTextDirectivesUtils.isDirectiveDefined(content, "SKIP_IN_FIR_TEST")) return
|
||||
|
||||
val srcFiles = KotlinTestUtils.createTestFiles<Void, File>(
|
||||
javaFile.name, FileUtil.loadFile(javaFile, true),
|
||||
object : KotlinTestUtils.TestFileFactoryNoModules<File>() {
|
||||
override fun create(fileName: String, text: String, directives: Map<String, String>): File {
|
||||
var currentDir = javaFilesDir
|
||||
if ("/" !in fileName) {
|
||||
val packageFqName =
|
||||
text.split("\n").firstOrNull {
|
||||
it.startsWith("package")
|
||||
}?.substringAfter("package")?.trim()?.substringBefore(";")?.let { name ->
|
||||
FqName(name)
|
||||
} ?: FqName.ROOT
|
||||
for (segment in packageFqName.pathSegments()) {
|
||||
currentDir = File(currentDir, segment.asString()).apply { mkdir() }
|
||||
}
|
||||
}
|
||||
val targetFile = File(currentDir, fileName)
|
||||
try {
|
||||
FileUtil.writeToFile(targetFile, text)
|
||||
} catch (e: IOException) {
|
||||
throw AssertionError(e)
|
||||
}
|
||||
|
||||
return targetFile
|
||||
}
|
||||
}, ""
|
||||
)
|
||||
environment = createEnvironment(content)
|
||||
val virtualFiles = srcFiles.map {
|
||||
object : LightVirtualFile(
|
||||
it.name, JavaLanguage.INSTANCE, StringUtilRt.convertLineSeparators(it.readText())
|
||||
) {
|
||||
override fun getPath(): String {
|
||||
//TODO: patch LightVirtualFile
|
||||
return "/${it.name}"
|
||||
}
|
||||
}
|
||||
}
|
||||
val factory = PsiFileFactory.getInstance(project) as PsiFileFactoryImpl
|
||||
val psiFiles = virtualFiles.map { factory.trySetupPsiForFile(it, JavaLanguage.INSTANCE, true, false)!! }
|
||||
|
||||
val scope = GlobalSearchScope.filesScope(project, virtualFiles)
|
||||
.uniteWith(TopDownAnalyzerFacadeForJVM.AllJavaSourcesInProjectScope(project))
|
||||
val session = createSession(environment, scope)
|
||||
|
||||
val topPsiClasses = psiFiles.flatMap { it.getChildrenOfType<PsiClass>().toList() }
|
||||
|
||||
val javaFirDump = StringBuilder().also { builder ->
|
||||
val renderer = FirRenderer(builder)
|
||||
val symbolProvider = session.service<FirSymbolProvider>() as FirCompositeSymbolProvider
|
||||
val javaProvider = symbolProvider.providers.filterIsInstance<JavaSymbolProvider>().first()
|
||||
|
||||
fun processClassWithChildren(psiClass: PsiClass, parentFqName: FqName) {
|
||||
val psiFile = psiClass.containingFile
|
||||
val packageStatement = psiFile.children.filterIsInstance<PsiPackageStatement>().firstOrNull()
|
||||
val packageName = packageStatement?.packageName
|
||||
val fqName = parentFqName.child(Name.identifier(psiClass.name!!))
|
||||
val classId = ClassId(packageName?.let { FqName(it) } ?: FqName.ROOT, fqName, false)
|
||||
javaProvider.getClassLikeSymbolByFqName(classId)
|
||||
?: throw AssertionError(classId.asString())
|
||||
psiClass.innerClasses.forEach {
|
||||
processClassWithChildren(psiClass = it, parentFqName = fqName)
|
||||
}
|
||||
}
|
||||
for (psiClass in topPsiClasses) {
|
||||
processClassWithChildren(psiClass, FqName.ROOT)
|
||||
}
|
||||
|
||||
val processedJavaClasses = mutableSetOf<FirJavaClass>()
|
||||
for (javaClass in javaProvider.getJavaTopLevelClasses().sortedBy { it.name }) {
|
||||
if (javaClass !is FirJavaClass || javaClass in processedJavaClasses) continue
|
||||
val enhancementScope = javaClass.buildClassSpecificUseSiteScope(session).let {
|
||||
when (it) {
|
||||
is FirCompositeScope -> it.scopes.filterIsInstance<JavaClassEnhancementScope>().first()
|
||||
is JavaClassEnhancementScope -> it
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
if (enhancementScope == null) {
|
||||
javaClass.accept(renderer, null)
|
||||
} else {
|
||||
renderer.visitMemberDeclaration(javaClass)
|
||||
renderer.renderSupertypes(javaClass)
|
||||
renderer.renderInBraces {
|
||||
val renderedDeclarations = mutableListOf<FirDeclaration>()
|
||||
for (declaration in javaClass.declarations) {
|
||||
if (declaration in renderedDeclarations) continue
|
||||
when (declaration) {
|
||||
is FirJavaConstructor -> enhancementScope.processFunctionsByName(javaClass.name) { symbol ->
|
||||
val enhanced = (symbol as? FirFunctionSymbol)?.fir
|
||||
if (enhanced != null && enhanced !in renderedDeclarations) {
|
||||
enhanced.accept(renderer, null)
|
||||
renderer.newLine()
|
||||
renderedDeclarations += enhanced
|
||||
}
|
||||
ProcessorAction.NEXT
|
||||
}
|
||||
is FirJavaMethod -> enhancementScope.processFunctionsByName(declaration.name) { symbol ->
|
||||
val enhanced = (symbol as? FirFunctionSymbol)?.fir
|
||||
if (enhanced != null && enhanced !in renderedDeclarations) {
|
||||
enhanced.accept(renderer, null)
|
||||
renderer.newLine()
|
||||
renderedDeclarations += enhanced
|
||||
}
|
||||
ProcessorAction.NEXT
|
||||
}
|
||||
is FirJavaField -> enhancementScope.processPropertiesByName(declaration.name) { symbol ->
|
||||
val enhanced = (symbol as? FirPropertySymbol)?.fir
|
||||
if (enhanced != null && enhanced !in renderedDeclarations) {
|
||||
enhanced.accept(renderer, null)
|
||||
renderer.newLine()
|
||||
renderedDeclarations += enhanced
|
||||
}
|
||||
ProcessorAction.NEXT
|
||||
}
|
||||
else -> {
|
||||
declaration.accept(renderer, null)
|
||||
renderer.newLine()
|
||||
renderedDeclarations += declaration
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
processedJavaClasses += javaClass
|
||||
}
|
||||
}.toString()
|
||||
|
||||
val expectedFile = File(javaFile.absolutePath.replace(".java", ".fir.txt"))
|
||||
KotlinTestUtils.assertEqualsToFile(expectedFile, javaFirDump)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val FOREIGN_ANNOTATIONS_SOURCES_PATH = "third-party/annotations"
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AbstractOwnFirTypeEnhancementTest : AbstractFirTypeEnhancementTest()
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.psi
|
||||
|
||||
import com.intellij.psi.JavaCodeFragment
|
||||
import com.intellij.psi.PsiClass
|
||||
|
||||
interface KtCodeFragmentBase : JavaCodeFragment {
|
||||
override fun importClass(aClass: PsiClass?): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* 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.psi
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
import com.intellij.navigation.ItemPresentationProviders
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinPlaceHolderStub
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtPlaceHolderStubElementType
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
||||
|
||||
abstract class KtConstructor<T : KtConstructor<T>> : KtDeclarationStub<KotlinPlaceHolderStub<T>>, KtFunction {
|
||||
protected constructor(node: ASTNode) : super(node)
|
||||
protected constructor(stub: KotlinPlaceHolderStub<T>, nodeType: KtPlaceHolderStubElementType<T>) : super(stub, nodeType)
|
||||
|
||||
abstract fun getContainingClassOrObject(): KtClassOrObject
|
||||
|
||||
override fun isLocal() = false
|
||||
|
||||
override fun getValueParameterList() = getStubOrPsiChild(KtStubElementTypes.VALUE_PARAMETER_LIST)
|
||||
|
||||
override fun getValueParameters() = valueParameterList?.parameters ?: emptyList()
|
||||
|
||||
override fun getReceiverTypeReference() = null
|
||||
|
||||
override fun getTypeReference() = null
|
||||
|
||||
@Throws(IncorrectOperationException::class)
|
||||
override fun setTypeReference(typeRef: KtTypeReference?) = throw IncorrectOperationException("setTypeReference to constructor")
|
||||
|
||||
override fun getColon() = findChildByType<PsiElement>(KtTokens.COLON)
|
||||
|
||||
override fun getBodyExpression(): KtBlockExpression? = null
|
||||
|
||||
override fun getEqualsToken() = null
|
||||
|
||||
override fun hasBlockBody() = bodyExpression != null
|
||||
|
||||
override fun hasBody() = bodyExpression != null
|
||||
|
||||
override fun hasDeclaredReturnType() = false
|
||||
|
||||
override fun getTypeParameterList() = null
|
||||
|
||||
override fun getTypeConstraintList() = null
|
||||
|
||||
override fun getTypeConstraints() = emptyList<KtTypeConstraint>()
|
||||
|
||||
override fun getTypeParameters() = emptyList<KtTypeParameter>()
|
||||
|
||||
override fun getName(): String? = getContainingClassOrObject().name
|
||||
|
||||
override fun getNameAsSafeName() = KtPsiUtil.safeName(name)
|
||||
|
||||
override fun getFqName() = null
|
||||
|
||||
override fun getNameAsName() = nameAsSafeName
|
||||
|
||||
override fun getNameIdentifier() = null
|
||||
|
||||
@Throws(IncorrectOperationException::class)
|
||||
override fun setName(name: String): PsiElement = throw IncorrectOperationException("setName to constructor")
|
||||
|
||||
override fun getPresentation() = ItemPresentationProviders.getItemPresentation(this)
|
||||
|
||||
open fun getConstructorKeyword(): PsiElement? = findChildByType(KtTokens.CONSTRUCTOR_KEYWORD)
|
||||
|
||||
fun hasConstructorKeyword(): Boolean = stub != null || getConstructorKeyword() != null
|
||||
|
||||
override fun getTextOffset(): Int {
|
||||
return getConstructorKeyword()?.textOffset
|
||||
?: valueParameterList?.textOffset
|
||||
?: super.getTextOffset()
|
||||
}
|
||||
|
||||
override fun getUseScope(): SearchScope {
|
||||
return getContainingClassOrObject().useScope
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.psi
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinObjectStub
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
||||
|
||||
class KtObjectDeclaration : KtClassOrObject {
|
||||
constructor(node: ASTNode) : super(node)
|
||||
constructor(stub: KotlinObjectStub) : super(stub, KtStubElementTypes.OBJECT_DECLARATION)
|
||||
|
||||
private val _stub: KotlinObjectStub?
|
||||
get() = stub as? KotlinObjectStub
|
||||
|
||||
override fun getName(): String? {
|
||||
super.getName()?.let { return it }
|
||||
|
||||
if (isCompanion() && !isTopLevel()) {
|
||||
//NOTE: a hack in PSI that simplifies writing frontend code
|
||||
return SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT.toString()
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
override fun setName(@NonNls name: String): PsiElement {
|
||||
return if (nameIdentifier == null) {
|
||||
val psiFactory = KtPsiFactory(project)
|
||||
val result = addAfter(psiFactory.createIdentifier(name), getObjectKeyword()!!)
|
||||
addAfter(psiFactory.createWhiteSpace(), getObjectKeyword()!!)
|
||||
|
||||
result
|
||||
} else {
|
||||
super.setName(name)
|
||||
}
|
||||
}
|
||||
|
||||
fun isCompanion(): Boolean = _stub?.isCompanion() ?: hasModifier(KtTokens.COMPANION_KEYWORD)
|
||||
|
||||
override fun getTextOffset(): Int = nameIdentifier?.textRange?.startOffset
|
||||
?: getObjectKeyword()!!.textRange.startOffset
|
||||
|
||||
override fun <R, D> accept(visitor: KtVisitor<R, D>, data: D): R {
|
||||
return visitor.visitObjectDeclaration(this, data)
|
||||
}
|
||||
|
||||
fun isObjectLiteral(): Boolean = _stub?.isObjectLiteral() ?: (parent is KtObjectLiteralExpression)
|
||||
|
||||
fun getObjectKeyword(): PsiElement? = findChildByType(KtTokens.OBJECT_KEYWORD)
|
||||
|
||||
override fun getCompanionObjects(): List<KtObjectDeclaration> = emptyList()
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* 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.util
|
||||
|
||||
import com.intellij.openapi.util.ThrowableComputable
|
||||
import com.intellij.psi.PsiFile
|
||||
|
||||
/**
|
||||
* Absent in 181. Methods were renamed in 183.
|
||||
*
|
||||
* BUNCH: 182
|
||||
*/
|
||||
@Suppress("IncompatibleAPI", "MissingRecentApi")
|
||||
object AstLoadingFilter {
|
||||
@JvmStatic
|
||||
fun <T, E : Throwable> forceAllowTreeLoading(psiFile: PsiFile, computable: ThrowableComputable<out T, E>): T {
|
||||
return computable.compute()
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
versions.intellijSdk=181.5540.7
|
||||
versions.androidBuildTools=r23.0.1
|
||||
versions.idea.NodeJS=181.3494.12
|
||||
versions.jar.guava=21.0
|
||||
versions.jar.groovy-all=2.4.12
|
||||
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.5
|
||||
versions.jar.gson=2.8.2
|
||||
versions.jar.oro=2.0.8
|
||||
versions.jar.snappy-in-java=0.5.1
|
||||
versions.gradle-api=4.4
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* 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.compatibility
|
||||
|
||||
import com.intellij.util.Processor
|
||||
|
||||
/**
|
||||
* Processor<T> till IDEA 181 and Processor<in T> since 182.
|
||||
* BUNCH: 181
|
||||
*/
|
||||
typealias ExecutorProcessor<T> = Processor<T>
|
||||
-132
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* 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.compiler.configuration
|
||||
|
||||
import com.intellij.openapi.components.PersistentStateComponent
|
||||
import com.intellij.openapi.components.StoragePathMacros.PROJECT_CONFIG_DIR
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Comparing
|
||||
import com.intellij.openapi.util.JDOMUtil
|
||||
import com.intellij.util.ReflectionUtil
|
||||
import com.intellij.util.messages.Topic
|
||||
import com.intellij.util.xmlb.Accessor
|
||||
import com.intellij.util.xmlb.SerializationFilterBase
|
||||
import com.intellij.util.xmlb.XmlSerializer
|
||||
import gnu.trove.THashMap
|
||||
import org.jdom.Element
|
||||
import org.jetbrains.kotlin.cli.common.arguments.*
|
||||
import org.jetbrains.kotlin.config.SettingConstants
|
||||
import org.jetbrains.kotlin.idea.syncPublisherWithDisposeCheck
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
abstract class BaseKotlinCompilerSettings<T : Freezable> protected constructor(private val project: Project) : PersistentStateComponent<Element>, Cloneable {
|
||||
// Based on com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters
|
||||
private object DefaultValuesFilter : SerializationFilterBase() {
|
||||
private val defaultBeans = THashMap<Class<*>, Any>()
|
||||
|
||||
private fun createDefaultBean(beanClass: Class<Any>): Any {
|
||||
return ReflectionUtil.newInstance<Any>(beanClass).apply {
|
||||
if (this is K2JSCompilerArguments) {
|
||||
sourceMapPrefix = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDefaultValue(accessor: Accessor, bean: Any): Any? {
|
||||
if (bean is K2JSCompilerArguments && accessor.name == K2JSCompilerArguments::sourceMapEmbedSources.name) {
|
||||
return if (bean.sourceMap) K2JsArgumentConstants.SOURCE_MAP_SOURCE_CONTENT_INLINING else null
|
||||
}
|
||||
|
||||
val beanClass = bean.javaClass
|
||||
val defaultBean = defaultBeans.getOrPut(beanClass) { createDefaultBean(beanClass) }
|
||||
return accessor.read(defaultBean)
|
||||
}
|
||||
|
||||
override fun accepts(accessor: Accessor, bean: Any, beanValue: Any?): Boolean {
|
||||
val defValue = getDefaultValue(accessor, bean)
|
||||
return if (defValue is Element && beanValue is Element) {
|
||||
!JDOMUtil.areElementsEqual(beanValue, defValue)
|
||||
} else {
|
||||
!Comparing.equal(beanValue, defValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("LeakingThis", "UNCHECKED_CAST")
|
||||
private var _settings: T = createSettings().frozen() as T
|
||||
private set(value) {
|
||||
field = value.frozen() as T
|
||||
}
|
||||
|
||||
var settings: T
|
||||
get() = _settings
|
||||
set(value) {
|
||||
validateNewSettings(value)
|
||||
_settings = value
|
||||
|
||||
project.syncPublisherWithDisposeCheck(KotlinCompilerSettingsListener.TOPIC).settingsChanged(value)
|
||||
}
|
||||
|
||||
fun update(changer: T.() -> Unit) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
settings = (settings.unfrozen() as T).apply { changer() }
|
||||
}
|
||||
|
||||
protected fun validateInheritedFieldsUnchanged(settings: T) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val inheritedProperties = collectProperties<T>(settings::class as KClass<T>, true)
|
||||
val defaultInstance = createSettings()
|
||||
val invalidFields = inheritedProperties.filter { it.get(settings) != it.get(defaultInstance) }
|
||||
if (invalidFields.isNotEmpty()) {
|
||||
throw IllegalArgumentException("Following fields are expected to be left unchanged in ${settings.javaClass}: ${invalidFields.joinToString { it.name }}")
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun validateNewSettings(settings: T) {
|
||||
|
||||
}
|
||||
|
||||
protected abstract fun createSettings(): T
|
||||
|
||||
override fun getState() = XmlSerializer.serialize(_settings, DefaultValuesFilter)
|
||||
|
||||
override fun loadState(state: Element) {
|
||||
_settings = ReflectionUtil.newInstance(_settings.javaClass).apply {
|
||||
if (this is CommonCompilerArguments) {
|
||||
freeArgs = mutableListOf()
|
||||
internalArguments = mutableListOf()
|
||||
}
|
||||
XmlSerializer.deserializeInto(this, state)
|
||||
}
|
||||
|
||||
project.syncPublisherWithDisposeCheck(KotlinCompilerSettingsListener.TOPIC).settingsChanged(settings)
|
||||
}
|
||||
|
||||
public override fun clone(): Any = super.clone()
|
||||
|
||||
companion object {
|
||||
const val KOTLIN_COMPILER_SETTINGS_PATH = PROJECT_CONFIG_DIR + "/" + SettingConstants.KOTLIN_COMPILER_SETTINGS_FILE
|
||||
}
|
||||
}
|
||||
|
||||
interface KotlinCompilerSettingsListener {
|
||||
fun <T> settingsChanged(newSettings: T)
|
||||
|
||||
companion object {
|
||||
val TOPIC = Topic.create("KotlinCompilerSettingsListener", KotlinCompilerSettingsListener::class.java)
|
||||
}
|
||||
}
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.compiler.configuration
|
||||
|
||||
import com.intellij.openapi.components.*
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
|
||||
import org.jetbrains.kotlin.config.SettingConstants.KOTLIN_TO_JS_COMPILER_ARGUMENTS_SECTION
|
||||
import org.jetbrains.kotlin.idea.compiler.configuration.BaseKotlinCompilerSettings.Companion.KOTLIN_COMPILER_SETTINGS_PATH
|
||||
|
||||
@State(name = KOTLIN_TO_JS_COMPILER_ARGUMENTS_SECTION,
|
||||
storages = arrayOf(Storage(file = StoragePathMacros.PROJECT_FILE),
|
||||
Storage(file = KOTLIN_COMPILER_SETTINGS_PATH, scheme = StorageScheme.DIRECTORY_BASED)))
|
||||
class Kotlin2JsCompilerArgumentsHolder(project: Project) : BaseKotlinCompilerSettings<K2JSCompilerArguments>(project) {
|
||||
override fun createSettings() = K2JSCompilerArguments()
|
||||
|
||||
override fun validateNewSettings(settings: K2JSCompilerArguments) {
|
||||
validateInheritedFieldsUnchanged(settings)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getInstance(project: Project) = ServiceManager.getService(project, Kotlin2JsCompilerArgumentsHolder::class.java)!!
|
||||
|
||||
}
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.compiler.configuration
|
||||
|
||||
import com.intellij.openapi.components.*
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||
import org.jetbrains.kotlin.config.SettingConstants.KOTLIN_TO_JVM_COMPILER_ARGUMENTS_SECTION
|
||||
import org.jetbrains.kotlin.idea.compiler.configuration.BaseKotlinCompilerSettings.Companion.KOTLIN_COMPILER_SETTINGS_PATH
|
||||
|
||||
@State(name = KOTLIN_TO_JVM_COMPILER_ARGUMENTS_SECTION,
|
||||
storages = arrayOf(Storage(file = StoragePathMacros.PROJECT_FILE),
|
||||
Storage(file = KOTLIN_COMPILER_SETTINGS_PATH, scheme = StorageScheme.DIRECTORY_BASED)))
|
||||
class Kotlin2JvmCompilerArgumentsHolder(project: Project) : BaseKotlinCompilerSettings<K2JVMCompilerArguments>(project) {
|
||||
override fun createSettings() = K2JVMCompilerArguments()
|
||||
|
||||
override fun validateNewSettings(settings: K2JVMCompilerArguments) {
|
||||
validateInheritedFieldsUnchanged(settings)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getInstance(project: Project) = ServiceManager.getService(project, Kotlin2JvmCompilerArgumentsHolder::class.java)!!
|
||||
}
|
||||
}
|
||||
-56
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.compiler.configuration
|
||||
|
||||
import com.intellij.openapi.components.*
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.util.text.VersionComparatorUtil
|
||||
import org.jdom.Element
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||
import org.jetbrains.kotlin.cli.common.arguments.setApiVersionToLanguageVersionIfNeeded
|
||||
import org.jetbrains.kotlin.config.SettingConstants.KOTLIN_COMMON_COMPILER_ARGUMENTS_SECTION
|
||||
import org.jetbrains.kotlin.config.detectVersionAutoAdvance
|
||||
import org.jetbrains.kotlin.config.dropVersionsIfNecessary
|
||||
|
||||
@State(name = KOTLIN_COMMON_COMPILER_ARGUMENTS_SECTION,
|
||||
storages = arrayOf(Storage(file = StoragePathMacros.PROJECT_FILE),
|
||||
Storage(file = BaseKotlinCompilerSettings.KOTLIN_COMPILER_SETTINGS_PATH,
|
||||
scheme = StorageScheme.DIRECTORY_BASED)))
|
||||
class KotlinCommonCompilerArgumentsHolder(project: Project) : BaseKotlinCompilerSettings<CommonCompilerArguments>(project) {
|
||||
override fun getState(): Element {
|
||||
return super.getState().apply {
|
||||
dropVersionsIfNecessary(settings)
|
||||
}
|
||||
}
|
||||
|
||||
override fun loadState(state: Element) {
|
||||
super.loadState(state)
|
||||
|
||||
update {
|
||||
// To fix earlier configurations with incorrect combination of language and API version
|
||||
setApiVersionToLanguageVersionIfNeeded()
|
||||
detectVersionAutoAdvance()
|
||||
}
|
||||
}
|
||||
|
||||
override fun createSettings() = CommonCompilerArguments.DummyImpl()
|
||||
|
||||
companion object {
|
||||
fun getInstance(project: Project) =
|
||||
ServiceManager.getService<KotlinCommonCompilerArgumentsHolder>(project, KotlinCommonCompilerArgumentsHolder::class.java)!!
|
||||
}
|
||||
}
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* 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.compiler.configuration
|
||||
|
||||
import com.intellij.openapi.components.*
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.config.CompilerSettings
|
||||
import org.jetbrains.kotlin.config.SettingConstants.KOTLIN_COMPILER_SETTINGS_SECTION
|
||||
|
||||
@State(name = KOTLIN_COMPILER_SETTINGS_SECTION,
|
||||
storages = arrayOf(Storage(file = StoragePathMacros.PROJECT_FILE),
|
||||
Storage(file = BaseKotlinCompilerSettings.KOTLIN_COMPILER_SETTINGS_PATH, scheme = StorageScheme.DIRECTORY_BASED)))
|
||||
class KotlinCompilerSettings(project: Project) : BaseKotlinCompilerSettings<CompilerSettings>(project) {
|
||||
override fun createSettings() = CompilerSettings()
|
||||
|
||||
|
||||
|
||||
companion object {
|
||||
fun getInstance(project: Project) = ServiceManager.getService(project, KotlinCompilerSettings::class.java)!!
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
/*
|
||||
* 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.idea.highlighter;
|
||||
|
||||
public class ErrorIconUtil {
|
||||
public static String getErrorIconUrl() {
|
||||
return "/general/error.png";
|
||||
}
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* 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.idea.highlighter
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
|
||||
object OutsidersPsiFileSupportWrapper {
|
||||
fun isOutsiderFile(virtualFile: VirtualFile): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
fun getOriginalFilePath(virtualFile: VirtualFile): String? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.idea.util.compat
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.PsiSearchHelper
|
||||
|
||||
// BUNCH: 181
|
||||
@Suppress("IncompatibleAPI", "MissingRecentApi")
|
||||
fun psiSearchHelperInstance(project: Project): PsiSearchHelper {
|
||||
return PsiSearchHelper.SERVICE.getInstance(project)
|
||||
}
|
||||
-65
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.android.configure
|
||||
|
||||
import com.android.tools.idea.gradle.project.model.JavaModuleModel
|
||||
import com.android.tools.idea.gradle.project.sync.idea.data.service.AndroidProjectKeys
|
||||
import com.android.tools.idea.gradle.util.FilePaths
|
||||
import com.intellij.openapi.externalSystem.model.DataNode
|
||||
import com.intellij.openapi.externalSystem.model.project.ModuleData
|
||||
import com.intellij.openapi.externalSystem.model.project.ProjectData
|
||||
import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.AbstractProjectDataService
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.OrderRootType
|
||||
import com.intellij.openapi.roots.impl.libraries.LibraryEx
|
||||
import com.intellij.openapi.roots.libraries.Library
|
||||
import org.jetbrains.kotlin.idea.configuration.detectPlatformKindByPlugin
|
||||
import org.jetbrains.kotlin.idea.framework.detectLibraryKind
|
||||
import org.jetbrains.kotlin.idea.platform.tooling
|
||||
import java.io.File
|
||||
|
||||
class KotlinAndroidGradleLibraryDataService : AbstractProjectDataService<JavaModuleModel, Void>() {
|
||||
override fun getTargetDataKey() = AndroidProjectKeys.JAVA_MODULE_MODEL
|
||||
|
||||
override fun postProcess(
|
||||
toImport: MutableCollection<DataNode<JavaModuleModel>>,
|
||||
projectData: ProjectData?,
|
||||
project: Project,
|
||||
modelsProvider: IdeModifiableModelsProvider
|
||||
) {
|
||||
for (dataNode in toImport) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val targetLibraryKind = detectPlatformKindByPlugin(dataNode.parent as DataNode<ModuleData>)?.tooling?.libraryKind
|
||||
if (targetLibraryKind != null) {
|
||||
for (dep in dataNode.data.jarLibraryDependencies) {
|
||||
val library = modelsProvider.findLibraryByBinaryPath(dep.binaryPath) as LibraryEx? ?: continue
|
||||
if (library.kind == null) {
|
||||
val model = modelsProvider.getModifiableLibraryModel(library) as LibraryEx.ModifiableModelEx
|
||||
detectLibraryKind(model.getFiles(OrderRootType.CLASSES))?.let { model.kind = it }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun IdeModifiableModelsProvider.findLibraryByBinaryPath(path: File?): Library? {
|
||||
if (path == null) return null
|
||||
val url = FilePaths.pathToIdeaUrl(path)
|
||||
return allLibraries.firstOrNull { url in getModifiableLibraryModel(it).getUrls(OrderRootType.CLASSES) }
|
||||
}
|
||||
}
|
||||
-236
@@ -1,236 +0,0 @@
|
||||
/*
|
||||
* 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.android.configure
|
||||
|
||||
import com.android.tools.idea.gradle.project.sync.idea.data.service.AndroidProjectKeys
|
||||
import com.android.tools.idea.gradle.util.ContentEntries.findParentContentEntry
|
||||
import com.android.tools.idea.gradle.util.FilePaths
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.externalSystem.ExternalSystemModulePropertyManager
|
||||
import com.intellij.openapi.externalSystem.model.DataNode
|
||||
import com.intellij.openapi.externalSystem.model.ProjectKeys
|
||||
import com.intellij.openapi.externalSystem.model.project.ModuleData
|
||||
import com.intellij.openapi.externalSystem.model.project.ProjectData
|
||||
import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.AbstractProjectDataService
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.ContentRootDataService.CREATE_EMPTY_DIRECTORIES
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.DependencyScope
|
||||
import com.intellij.openapi.roots.ModifiableRootModel
|
||||
import com.intellij.openapi.vfs.VfsUtil
|
||||
import com.intellij.util.SmartList
|
||||
import com.intellij.util.containers.stream
|
||||
import org.jetbrains.jps.model.java.JavaResourceRootType
|
||||
import org.jetbrains.jps.model.java.JavaSourceRootType
|
||||
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
|
||||
import org.jetbrains.kotlin.gradle.KotlinCompilation
|
||||
import org.jetbrains.kotlin.gradle.KotlinPlatform
|
||||
import org.jetbrains.kotlin.gradle.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.idea.addModuleDependencyIfNeeded
|
||||
import org.jetbrains.kotlin.idea.configuration.*
|
||||
import org.jetbrains.kotlin.idea.facet.KotlinFacet
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import org.jetbrains.kotlin.idea.configuration.kotlinSourceSet
|
||||
|
||||
class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService<ModuleData, Void>() {
|
||||
override fun getTargetDataKey() = ProjectKeys.MODULE
|
||||
|
||||
private fun shouldCreateEmptySourceRoots(
|
||||
moduleDataNode: DataNode<ModuleData>,
|
||||
module: Module
|
||||
): Boolean {
|
||||
val projectDataNode = ExternalSystemApiUtil.findParent(moduleDataNode, ProjectKeys.PROJECT) ?: return false
|
||||
if (projectDataNode.getUserData<Boolean>(CREATE_EMPTY_DIRECTORIES) == true) return true
|
||||
|
||||
val projectSystemId = projectDataNode.data.owner
|
||||
val externalSystemSettings = ExternalSystemApiUtil.getSettings(module.project, projectSystemId)
|
||||
|
||||
val path = ExternalSystemModulePropertyManager.getInstance(module).getRootProjectPath() ?: return false
|
||||
return externalSystemSettings.getLinkedProjectSettings(path)?.isCreateEmptyContentRootDirectories ?: false
|
||||
}
|
||||
|
||||
override fun postProcess(
|
||||
toImport: MutableCollection<DataNode<ModuleData>>,
|
||||
projectData: ProjectData?,
|
||||
project: Project,
|
||||
modelsProvider: IdeModifiableModelsProvider
|
||||
) {
|
||||
for (nodeToImport in toImport) {
|
||||
val projectNode = ExternalSystemApiUtil.findParent(nodeToImport, ProjectKeys.PROJECT) ?: continue
|
||||
val moduleData = nodeToImport.data
|
||||
val module = modelsProvider.findIdeModule(moduleData) ?: continue
|
||||
val shouldCreateEmptySourceRoots = shouldCreateEmptySourceRoots(nodeToImport, module)
|
||||
val rootModel = modelsProvider.getModifiableRootModel(module)
|
||||
val kotlinAndroidSourceSets = nodeToImport.kotlinAndroidSourceSets ?: emptyList()
|
||||
for (sourceSetInfo in kotlinAndroidSourceSets) {
|
||||
val compilation = sourceSetInfo.kotlinModule as? KotlinCompilation ?: continue
|
||||
for (sourceSet in compilation.sourceSets) {
|
||||
if (sourceSet.platform == KotlinPlatform.ANDROID) {
|
||||
val sourceType = if (sourceSet.isTestModule) JavaSourceRootType.TEST_SOURCE else JavaSourceRootType.SOURCE
|
||||
val resourceType = if (sourceSet.isTestModule) JavaResourceRootType.TEST_RESOURCE else JavaResourceRootType.RESOURCE
|
||||
sourceSet.sourceDirs.forEach { addSourceRoot(it, sourceType, rootModel, shouldCreateEmptySourceRoots) }
|
||||
sourceSet.resourceDirs.forEach { addSourceRoot(it, resourceType, rootModel, shouldCreateEmptySourceRoots) }
|
||||
}
|
||||
}
|
||||
}
|
||||
addExtraDependeeModules(nodeToImport, projectNode, modelsProvider, rootModel, false)
|
||||
addExtraDependeeModules(nodeToImport, projectNode, modelsProvider, rootModel, true)
|
||||
|
||||
if (nodeToImport.kotlinAndroidSourceSets == null) {
|
||||
continue
|
||||
}
|
||||
|
||||
val androidModel = getAndroidModuleModel(nodeToImport) ?: continue
|
||||
val variantName = androidModel.selectedVariant.name
|
||||
val activeSourceSetInfos = nodeToImport.kotlinAndroidSourceSets?.filter { it.kotlinModule.name.startsWith(variantName) } ?: emptyList()
|
||||
for (activeSourceSetInfo in activeSourceSetInfos) {
|
||||
val activeCompilation = activeSourceSetInfo.kotlinModule as? KotlinCompilation ?: continue
|
||||
for (sourceSet in activeCompilation.sourceSets) {
|
||||
if (sourceSet.platform != KotlinPlatform.ANDROID) {
|
||||
val sourceSetId = activeSourceSetInfo.sourceSetIdsByName[sourceSet.name] ?: continue
|
||||
val sourceSetNode = ExternalSystemApiUtil.findFirstRecursively(projectNode) {
|
||||
(it.data as? ModuleData)?.id == sourceSetId
|
||||
} as? DataNode<out ModuleData>? ?: continue
|
||||
val sourceSetData = sourceSetNode.data as? ModuleData ?: continue
|
||||
val sourceSetModule = modelsProvider.findIdeModule(sourceSetData) ?: continue
|
||||
addModuleDependencyIfNeeded(
|
||||
rootModel,
|
||||
sourceSetModule,
|
||||
activeSourceSetInfo.isTestModule,
|
||||
sourceSetNode.kotlinSourceSet?.isTestModule ?: false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val mainSourceSetInfo = activeSourceSetInfos.firstOrNull { it.kotlinModule.name == variantName }
|
||||
if (mainSourceSetInfo != null) {
|
||||
KotlinSourceSetDataService.configureFacet(moduleData, mainSourceSetInfo, nodeToImport, module, modelsProvider)
|
||||
}
|
||||
|
||||
val kotlinFacet = KotlinFacet.get(module)
|
||||
if (kotlinFacet != null) {
|
||||
GradleProjectImportHandler.getInstances(project).forEach { it.importByModule(kotlinFacet, nodeToImport) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDependeeModuleNodes(
|
||||
moduleNode: DataNode<ModuleData>,
|
||||
projectNode: DataNode<ProjectData>,
|
||||
modelsProvider: IdeModifiableModelsProvider,
|
||||
testScope: Boolean
|
||||
): List<DataNode<out ModuleData>> {
|
||||
val androidModel = getAndroidModuleModel(moduleNode)
|
||||
if (androidModel != null) {
|
||||
val dependencies = if (testScope) {
|
||||
androidModel.selectedAndroidTestCompileDependencies
|
||||
} else {
|
||||
androidModel.selectedMainCompileLevel2Dependencies
|
||||
} ?: return emptyList()
|
||||
return dependencies
|
||||
.moduleDependencies
|
||||
.mapNotNull { projectNode.findChildModuleById(it.projectPath) }
|
||||
}
|
||||
|
||||
val javaModel = getJavaModuleModel(moduleNode)
|
||||
if (javaModel != null) {
|
||||
val scope = if (testScope) DependencyScope.TEST.name else DependencyScope.COMPILE.name
|
||||
val moduleNames = javaModel
|
||||
.javaModuleDependencies
|
||||
.filter { scope == it.scope ?: DependencyScope.COMPILE.name }
|
||||
.mapTo(HashSet()) { it.moduleName }
|
||||
return ExternalSystemApiUtil
|
||||
.getChildren(projectNode, ProjectKeys.MODULE)
|
||||
.filter { modelsProvider.findIdeModule(it.data)?.name in moduleNames }
|
||||
}
|
||||
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
private fun List<DataNode<GradleSourceSetData>>.firstByPlatformOrNull(platform: KotlinPlatform) = firstOrNull {
|
||||
it.kotlinSourceSet?.platform == platform
|
||||
}
|
||||
|
||||
private fun addExtraDependeeModules(
|
||||
moduleNode: DataNode<ModuleData>,
|
||||
projectNode: DataNode<ProjectData>,
|
||||
modelsProvider: IdeModifiableModelsProvider,
|
||||
rootModel: ModifiableRootModel,
|
||||
testScope: Boolean
|
||||
) {
|
||||
val dependeeModuleNodes = getDependeeModuleNodes(moduleNode, projectNode, modelsProvider, testScope)
|
||||
val relevantNodes = dependeeModuleNodes
|
||||
.flatMap { ExternalSystemApiUtil.getChildren(it, GradleSourceSetData.KEY) }
|
||||
.filter {
|
||||
val ktModule = it.kotlinSourceSet?.kotlinModule
|
||||
ktModule != null && ktModule.isTestModule == testScope
|
||||
}
|
||||
val commonSourceSetName = KotlinSourceSet.commonName(testScope)
|
||||
val isAndroidModule = getAndroidModuleModel(moduleNode) != null
|
||||
|
||||
val gradleSourceSetDataNodes = SmartList<DataNode<GradleSourceSetData>>()
|
||||
.apply {
|
||||
addIfNotNull(
|
||||
(if (isAndroidModule) relevantNodes.firstByPlatformOrNull(KotlinPlatform.ANDROID) else null)
|
||||
?: relevantNodes.firstByPlatformOrNull(KotlinPlatform.JVM)
|
||||
)
|
||||
addIfNotNull(
|
||||
relevantNodes.firstOrNull {
|
||||
it.kotlinSourceSet?.platform == KotlinPlatform.COMMON && it.kotlinSourceSet?.kotlinModule?.name == commonSourceSetName
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
val testKotlinModules =
|
||||
gradleSourceSetDataNodes.filter { it.kotlinSourceSet?.isTestModule ?: false }.mapNotNull { modelsProvider.findIdeModule(it.data) }
|
||||
.toSet()
|
||||
|
||||
gradleSourceSetDataNodes.forEach { node ->
|
||||
val module = modelsProvider.findIdeModule(node.data) ?: return
|
||||
addModuleDependencyIfNeeded(rootModel, module, testScope, node.kotlinSourceSet?.isTestModule ?: false)
|
||||
val dependeeRootModel = modelsProvider.getModifiableRootModel(module)
|
||||
dependeeRootModel.getModuleDependencies(testScope).forEach { transitiveDependee ->
|
||||
addModuleDependencyIfNeeded(rootModel, transitiveDependee, testScope, testKotlinModules.contains(transitiveDependee))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAndroidModuleModel(moduleNode: DataNode<ModuleData>) =
|
||||
ExternalSystemApiUtil.getChildren(moduleNode, AndroidProjectKeys.ANDROID_MODEL).firstOrNull()?.data
|
||||
|
||||
private fun getJavaModuleModel(moduleNode: DataNode<ModuleData>) =
|
||||
ExternalSystemApiUtil.getChildren(moduleNode, AndroidProjectKeys.JAVA_MODULE_MODEL).firstOrNull()?.data
|
||||
|
||||
private fun addSourceRoot(
|
||||
sourceRoot: File,
|
||||
type: JpsModuleSourceRootType<*>,
|
||||
rootModel: ModifiableRootModel,
|
||||
shouldCreateEmptySourceRoots: Boolean
|
||||
) {
|
||||
val parent = findParentContentEntry(sourceRoot, rootModel.contentEntries.stream()) ?: return
|
||||
val url = FilePaths.pathToIdeaUrl(sourceRoot)
|
||||
parent.addSourceFolder(url, type)
|
||||
if (shouldCreateEmptySourceRoots) {
|
||||
ExternalSystemApiUtil.doWriteAction {
|
||||
try {
|
||||
VfsUtil.createDirectoryIfMissing(sourceRoot.path)
|
||||
} catch (e: IOException) {
|
||||
LOG.warn(String.format("Unable to create directory for the path: %s", sourceRoot.path), e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val LOG = Logger.getInstance(KotlinAndroidGradleMPPModuleDataService::class.java)
|
||||
}
|
||||
}
|
||||
@@ -1,388 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.android;
|
||||
|
||||
import com.android.SdkConstants;
|
||||
import com.android.tools.idea.rendering.RenderSecurityManager;
|
||||
import com.android.tools.idea.startup.AndroidCodeStyleSettingsModifier;
|
||||
import com.intellij.analysis.AnalysisScope;
|
||||
import com.intellij.codeInspection.GlobalInspectionTool;
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.codeInspection.ex.GlobalInspectionToolWrapper;
|
||||
import com.intellij.codeInspection.ex.InspectionManagerEx;
|
||||
import com.intellij.facet.FacetManager;
|
||||
import com.intellij.facet.ModifiableFacetModel;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.projectRoots.ProjectJdkTable;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
|
||||
import com.intellij.openapi.roots.ModuleRootModificationUtil;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSchemes;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.testFramework.InspectionTestUtil;
|
||||
import com.intellij.testFramework.ThreadTracker;
|
||||
import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
|
||||
import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
|
||||
import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
|
||||
import com.intellij.testFramework.fixtures.JavaTestFixtureFactory;
|
||||
import com.intellij.testFramework.fixtures.TestFixtureBuilder;
|
||||
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl;
|
||||
import com.intellij.testFramework.fixtures.impl.GlobalInspectionContextForTests;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.android.facet.AndroidRootUtil;
|
||||
import org.jetbrains.android.formatter.AndroidXmlCodeStyleSettings;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.picocontainer.MutablePicoContainer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Copied from AS 2.3 sources
|
||||
*/
|
||||
@SuppressWarnings({"JUnitTestCaseWithNonTrivialConstructors"})
|
||||
public abstract class AndroidTestCase extends AndroidTestBase {
|
||||
protected Module myModule;
|
||||
protected List<Module> myAdditionalModules;
|
||||
|
||||
protected AndroidFacet myFacet;
|
||||
protected CodeStyleSettings mySettings;
|
||||
|
||||
private List<String> myAllowedRoots = new ArrayList<>();
|
||||
private boolean myUseCustomSettings;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
VfsRootAccess.allowRootAccess(KotlinTestUtils.getHomeDirectory());
|
||||
|
||||
TestFixtureBuilder<IdeaProjectTestFixture> projectBuilder = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getName());
|
||||
myFixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(projectBuilder.getFixture());
|
||||
JavaModuleFixtureBuilder moduleFixtureBuilder = projectBuilder.addModule(JavaModuleFixtureBuilder.class);
|
||||
File moduleRoot = new File(myFixture.getTempDirPath());
|
||||
|
||||
if (!moduleRoot.exists()) {
|
||||
assertTrue(moduleRoot.mkdirs());
|
||||
}
|
||||
initializeModuleFixtureBuilderWithSrcAndGen(moduleFixtureBuilder, moduleRoot.toString());
|
||||
|
||||
ArrayList<MyAdditionalModuleData> modules = new ArrayList<>();
|
||||
configureAdditionalModules(projectBuilder, modules);
|
||||
|
||||
myFixture.setUp();
|
||||
myFixture.setTestDataPath(getTestDataPath());
|
||||
myModule = moduleFixtureBuilder.getFixture().getModule();
|
||||
|
||||
// Must be done before addAndroidFacet, and must always be done, even if a test provides
|
||||
// its own custom manifest file. However, in that case, we will delete it shortly below.
|
||||
createManifest();
|
||||
|
||||
myFacet = addAndroidFacet(myModule);
|
||||
|
||||
LanguageLevel languageLevel = getLanguageLevel();
|
||||
if (languageLevel != null) {
|
||||
LanguageLevelProjectExtension extension = LanguageLevelProjectExtension.getInstance(myModule.getProject());
|
||||
if (extension != null) {
|
||||
extension.setLanguageLevel(languageLevel);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: myFixture.copyDirectoryToProject(getResDir(), "res");
|
||||
|
||||
myAdditionalModules = new ArrayList<>();
|
||||
for (MyAdditionalModuleData data : modules) {
|
||||
Module additionalModule = data.myModuleFixtureBuilder.getFixture().getModule();
|
||||
myAdditionalModules.add(additionalModule);
|
||||
AndroidFacet facet = addAndroidFacet(additionalModule);
|
||||
facet.setProjectType(data.myProjectType);
|
||||
String rootPath = getAdditionalModulePath(data.myDirName);
|
||||
myFixture.copyDirectoryToProject(getResDir(), rootPath + "/res");
|
||||
myFixture.copyFileToProject(SdkConstants.FN_ANDROID_MANIFEST_XML, rootPath + '/' + SdkConstants.FN_ANDROID_MANIFEST_XML);
|
||||
if (data.myIsMainModuleDependency) {
|
||||
ModuleRootModificationUtil.addDependency(myModule, additionalModule);
|
||||
}
|
||||
}
|
||||
|
||||
if (providesCustomManifest()) {
|
||||
deleteManifest();
|
||||
}
|
||||
|
||||
if (RenderSecurityManager.RESTRICT_READS) {
|
||||
// Unit test class loader includes disk directories which security manager does not allow access to
|
||||
RenderSecurityManager.sEnabled = false;
|
||||
}
|
||||
|
||||
ArrayList<String> allowedRoots = new ArrayList<>();
|
||||
collectAllowedRoots(allowedRoots);
|
||||
// TODO: registerAllowedRoots(allowedRoots, myTestRootDisposable);
|
||||
mySettings = CodeStyleSettingsManager.getSettings(getProject()).clone();
|
||||
AndroidCodeStyleSettingsModifier.modify(mySettings);
|
||||
CodeStyleSettingsManager.getInstance(getProject()).setTemporarySettings(mySettings);
|
||||
myUseCustomSettings = getAndroidCodeStyleSettings().USE_CUSTOM_SETTINGS;
|
||||
getAndroidCodeStyleSettings().USE_CUSTOM_SETTINGS = true;
|
||||
|
||||
// Layoutlib rendering thread will be shutdown when the app is closed so do not report it as a leak
|
||||
ThreadTracker.longRunningThreadCreated(ApplicationManager.getApplication(), "Layoutlib");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
try {
|
||||
Sdk androidSdk = ProjectJdkTable.getInstance().findJdk(ANDROID_SDK_NAME);
|
||||
if (androidSdk != null) {
|
||||
ApplicationManager.getApplication().runWriteAction(() -> ProjectJdkTable.getInstance().removeJdk(androidSdk));
|
||||
}
|
||||
|
||||
CodeStyleSettingsManager.getInstance(getProject()).dropTemporarySettings();
|
||||
myModule = null;
|
||||
myAdditionalModules = null;
|
||||
myFixture.tearDown();
|
||||
myFixture = null;
|
||||
myFacet = null;
|
||||
getAndroidCodeStyleSettings().USE_CUSTOM_SETTINGS = myUseCustomSettings;
|
||||
if (RenderSecurityManager.RESTRICT_READS) {
|
||||
RenderSecurityManager.sEnabled = true;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
super.tearDown();
|
||||
VfsRootAccess.disallowRootAccess(KotlinTestUtils.getHomeDirectory());
|
||||
}
|
||||
}
|
||||
|
||||
private static void initializeModuleFixtureBuilderWithSrcAndGen(JavaModuleFixtureBuilder moduleFixtureBuilder, String moduleRoot) {
|
||||
moduleFixtureBuilder.addContentRoot(moduleRoot);
|
||||
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
new File(moduleRoot + "/src/").mkdir();
|
||||
moduleFixtureBuilder.addSourceRoot("src");
|
||||
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
new File(moduleRoot + "/gen/").mkdir();
|
||||
moduleFixtureBuilder.addSourceRoot("gen");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path that any additional modules registered by
|
||||
* {@link #configureAdditionalModules(TestFixtureBuilder, List)} or
|
||||
* {@link #addModuleWithAndroidFacet(TestFixtureBuilder, List, String, int, boolean)} are
|
||||
* installed into.
|
||||
*/
|
||||
protected static String getAdditionalModulePath(@NotNull String moduleName) {
|
||||
return "/additionalModules/" + moduleName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this class provides its own {@code AndroidManifest.xml} for its tests. If
|
||||
* {@code true}, then {@link #setUp()} calls {@link #deleteManifest()} before finishing.
|
||||
*/
|
||||
protected boolean providesCustomManifest() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "res" directory for this SDK. Children classes can override this if they need to
|
||||
* provide a custom "res" location for tests.
|
||||
*/
|
||||
protected String getResDir() {
|
||||
return "res";
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the project level to set for the test project, or null to get the default language
|
||||
* level associated with the test project.
|
||||
*/
|
||||
@Nullable
|
||||
protected LanguageLevel getLanguageLevel() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static AndroidXmlCodeStyleSettings getAndroidCodeStyleSettings() {
|
||||
return AndroidXmlCodeStyleSettings.getInstance(CodeStyleSchemes.getInstance().getDefaultScheme().getCodeStyleSettings());
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook point for child test classes to register directories that can be safely accessed by all
|
||||
* of its tests.
|
||||
*
|
||||
* @see {@link VfsRootAccess}
|
||||
*/
|
||||
protected void collectAllowedRoots(List<String> roots) throws IOException {
|
||||
}
|
||||
|
||||
private void registerAllowedRoots(List<String> roots, @NotNull Disposable disposable) {
|
||||
List<String> newRoots = new ArrayList<>(roots);
|
||||
newRoots.removeAll(myAllowedRoots);
|
||||
|
||||
String[] newRootsArray = ArrayUtil.toStringArray(newRoots);
|
||||
VfsRootAccess.allowRootAccess(newRootsArray);
|
||||
myAllowedRoots.addAll(newRoots);
|
||||
|
||||
Disposer.register(disposable, () -> {
|
||||
VfsRootAccess.disallowRootAccess(newRootsArray);
|
||||
myAllowedRoots.removeAll(newRoots);
|
||||
});
|
||||
}
|
||||
|
||||
public static AndroidFacet addAndroidFacet(Module module) {
|
||||
return addAndroidFacet(module, true);
|
||||
}
|
||||
|
||||
private static AndroidFacet addAndroidFacet(Module module, boolean attachSdk) {
|
||||
FacetManager facetManager = FacetManager.getInstance(module);
|
||||
AndroidFacet facet = facetManager.createFacet(AndroidFacet.getFacetType(), "Android", null);
|
||||
|
||||
if (attachSdk) {
|
||||
addLatestAndroidSdk(module);
|
||||
}
|
||||
ModifiableFacetModel facetModel = facetManager.createModifiableModel();
|
||||
facetModel.addFacet(facet);
|
||||
ApplicationManager.getApplication().runWriteAction(facetModel::commit);
|
||||
return facet;
|
||||
}
|
||||
|
||||
protected void configureAdditionalModules(
|
||||
@NotNull TestFixtureBuilder<IdeaProjectTestFixture> projectBuilder, @NotNull List<MyAdditionalModuleData> modules) {
|
||||
}
|
||||
|
||||
protected final void addModuleWithAndroidFacet(
|
||||
@NotNull TestFixtureBuilder<IdeaProjectTestFixture> projectBuilder,
|
||||
@NotNull List<MyAdditionalModuleData> modules,
|
||||
@NotNull String dirName,
|
||||
int projectType) {
|
||||
// By default, created module is declared as a main module's dependency
|
||||
addModuleWithAndroidFacet(projectBuilder, modules, dirName, projectType, true);
|
||||
}
|
||||
|
||||
protected final void addModuleWithAndroidFacet(
|
||||
@NotNull TestFixtureBuilder<IdeaProjectTestFixture> projectBuilder,
|
||||
@NotNull List<MyAdditionalModuleData> modules,
|
||||
@NotNull String dirName,
|
||||
int projectType,
|
||||
boolean isMainModuleDependency) {
|
||||
JavaModuleFixtureBuilder moduleFixtureBuilder = projectBuilder.addModule(JavaModuleFixtureBuilder.class);
|
||||
String moduleDirPath = myFixture.getTempDirPath() + getAdditionalModulePath(dirName);
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
new File(moduleDirPath).mkdirs();
|
||||
initializeModuleFixtureBuilderWithSrcAndGen(moduleFixtureBuilder, moduleDirPath);
|
||||
modules.add(new MyAdditionalModuleData(moduleFixtureBuilder, dirName, projectType, isMainModuleDependency));
|
||||
}
|
||||
|
||||
protected void createManifest() throws IOException {
|
||||
myFixture.copyFileToProject(SdkConstants.FN_ANDROID_MANIFEST_XML, SdkConstants.FN_ANDROID_MANIFEST_XML);
|
||||
}
|
||||
|
||||
protected final void createProjectProperties() throws IOException {
|
||||
myFixture.copyFileToProject(SdkConstants.FN_PROJECT_PROPERTIES, SdkConstants.FN_PROJECT_PROPERTIES);
|
||||
}
|
||||
|
||||
protected final void deleteManifest() throws IOException {
|
||||
deleteManifest(myModule);
|
||||
}
|
||||
|
||||
protected final void deleteManifest(final Module module) throws IOException {
|
||||
AndroidFacet facet = AndroidFacet.getInstance(module);
|
||||
assertNotNull(facet);
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String manifestRelativePath = facet.getProperties().MANIFEST_FILE_RELATIVE_PATH;
|
||||
VirtualFile manifest = AndroidRootUtil.getFileByRelativeModulePath(module, manifestRelativePath, true);
|
||||
if (manifest != null) {
|
||||
try {
|
||||
manifest.delete(this);
|
||||
}
|
||||
catch (IOException e) {
|
||||
fail("Could not delete default manifest");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected final void doGlobalInspectionTest(
|
||||
@NotNull GlobalInspectionTool inspection, @NotNull String globalTestDir, @NotNull AnalysisScope scope) {
|
||||
doGlobalInspectionTest(new GlobalInspectionToolWrapper(inspection), globalTestDir, scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an inspection and a path to a directory that contains an "expected.xml" file, run the
|
||||
* inspection on the current test project and verify that its output matches that of the
|
||||
* expected file.
|
||||
*/
|
||||
protected final void doGlobalInspectionTest(
|
||||
@NotNull GlobalInspectionToolWrapper wrapper, @NotNull String globalTestDir, @NotNull AnalysisScope scope) {
|
||||
myFixture.enableInspections(wrapper.getTool());
|
||||
|
||||
scope.invalidate();
|
||||
|
||||
InspectionManagerEx inspectionManager = (InspectionManagerEx)InspectionManager.getInstance(getProject());
|
||||
GlobalInspectionContextForTests globalContext =
|
||||
CodeInsightTestFixtureImpl.createGlobalContextForTool(scope, getProject(), inspectionManager, wrapper);
|
||||
|
||||
InspectionTestUtil.runTool(wrapper, scope, globalContext);
|
||||
InspectionTestUtil.compareToolResults(globalContext, wrapper, false, getTestDataPath() + globalTestDir);
|
||||
}
|
||||
|
||||
protected static class MyAdditionalModuleData {
|
||||
final JavaModuleFixtureBuilder myModuleFixtureBuilder;
|
||||
final String myDirName;
|
||||
final int myProjectType;
|
||||
final boolean myIsMainModuleDependency;
|
||||
|
||||
private MyAdditionalModuleData(
|
||||
@NotNull JavaModuleFixtureBuilder moduleFixtureBuilder, @NotNull String dirName, int projectType, boolean isMainModuleDependency) {
|
||||
myModuleFixtureBuilder = moduleFixtureBuilder;
|
||||
myDirName = dirName;
|
||||
myProjectType = projectType;
|
||||
myIsMainModuleDependency = isMainModuleDependency;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected <T> T registerApplicationComponent(@NotNull Class<T> key, @NotNull T instance) throws Exception {
|
||||
MutablePicoContainer picoContainer = (MutablePicoContainer)ApplicationManager.getApplication().getPicoContainer();
|
||||
@SuppressWarnings("unchecked")
|
||||
T old = (T)picoContainer.getComponentInstance(key.getName());
|
||||
picoContainer.unregisterComponent(key.getName());
|
||||
picoContainer.registerComponentInstance(key.getName(), instance);
|
||||
return old;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected <T> T registerProjectComponent(@NotNull Class<T> key, @NotNull T instance) {
|
||||
MutablePicoContainer picoContainer = (MutablePicoContainer)getProject().getPicoContainer();
|
||||
@SuppressWarnings("unchecked")
|
||||
T old = (T)picoContainer.getComponentInstance(key.getName());
|
||||
picoContainer.unregisterComponent(key.getName());
|
||||
picoContainer.registerComponentInstance(key.getName(), instance);
|
||||
return old;
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.android;
|
||||
|
||||
|
||||
import com.android.annotations.NonNull;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Stub for com.android.testutils.TestUtils
|
||||
* stabbed to minimize changes in AndroidTestBase
|
||||
*/
|
||||
public class TestUtils {
|
||||
@NonNull
|
||||
public static File getSdk() {
|
||||
return KotlinTestUtils.findAndroidSdk();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static String getLatestAndroidPlatform() {
|
||||
return "android-26";
|
||||
}
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* 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.gradle
|
||||
|
||||
import org.jetbrains.kotlin.idea.configuration.KotlinGradleSharedMultiplatformModuleBuilder
|
||||
import org.jetbrains.kotlin.idea.configuration.KotlinGradleWebMultiplatformModuleBuilder
|
||||
import org.jetbrains.kotlin.idea.test.KotlinSdkCreationChecker
|
||||
import org.junit.Test
|
||||
|
||||
class GradleMultiplatformWizardTest : AbstractGradleMultiplatformWizardTest() {
|
||||
|
||||
lateinit var sdkCreationChecker: KotlinSdkCreationChecker
|
||||
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
sdkCreationChecker = KotlinSdkCreationChecker()
|
||||
}
|
||||
|
||||
override fun tearDown() {
|
||||
sdkCreationChecker.removeNewKotlinSdk()
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testWeb() {
|
||||
testImportFromBuilder(KotlinGradleWebMultiplatformModuleBuilder(), "SampleTests", "SampleTestsJVM")
|
||||
}
|
||||
}
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.gradle
|
||||
|
||||
import org.jetbrains.kotlin.idea.codeInsight.gradle.MultiplePluginVersionGradleImportingTestCase
|
||||
|
||||
//BUNCH 181
|
||||
fun MultiplatformProjectImportingTest.shouldRunTest(kotlinPluginVersion: String, gradleVersion: String): Boolean {
|
||||
return kotlinPluginVersion != MultiplePluginVersionGradleImportingTestCase.MINIMAL_SUPPORTED_VERSION
|
||||
}
|
||||
|
||||
fun NewMultiplatformProjectImportingTest.shouldRunTest(kotlinPluginVersion: String, gradleVersion: String): Boolean {
|
||||
return !gradleVersion.startsWith("3.")
|
||||
}
|
||||
-2524
File diff suppressed because it is too large
Load Diff
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* 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.idea.internal
|
||||
|
||||
import org.jetbrains.java.decompiler.main.decompiler.BaseDecompiler
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* `addSpace` method is deprecated in 182. `addSource` and `addLibrary` were introduced instead.
|
||||
* BUNCH: 181
|
||||
*/
|
||||
@Suppress("IncompatibleAPI")
|
||||
fun BaseDecompiler.addSpaceEx(file: File, isOwn: Boolean) {
|
||||
addSpace(file, isOwn)
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* 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.idea.core.platform.impl
|
||||
|
||||
import com.intellij.execution.PsiLocation
|
||||
import com.intellij.execution.actions.ConfigurationContext
|
||||
import com.intellij.execution.actions.RunConfigurationProducer
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.libraries.Library
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.gradle.KotlinPlatform
|
||||
import org.jetbrains.kotlin.idea.compiler.configuration.Kotlin2JsCompilerArgumentsHolder
|
||||
import org.jetbrains.kotlin.idea.framework.JSLibraryKind
|
||||
import org.jetbrains.kotlin.idea.framework.JSLibraryStdDescription
|
||||
import org.jetbrains.kotlin.idea.framework.JsLibraryStdDetectionUtil
|
||||
import org.jetbrains.kotlin.idea.highlighter.KotlinTestRunLineMarkerContributor.Companion.getTestStateIcon
|
||||
import org.jetbrains.kotlin.idea.js.KotlinJSRunConfigurationDataProvider
|
||||
import org.jetbrains.kotlin.idea.platform.IdePlatformKindTooling
|
||||
import org.jetbrains.kotlin.idea.util.string.joinWithEscape
|
||||
import org.jetbrains.kotlin.js.resolve.JsAnalyzerFacade
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.platform.impl.JsIdePlatformKind
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||
import org.jetbrains.kotlin.utils.PathUtil
|
||||
import org.jetbrains.kotlin.utils.ifEmpty
|
||||
import javax.swing.Icon
|
||||
|
||||
class JsIdePlatformKindTooling : IdePlatformKindTooling() {
|
||||
companion object {
|
||||
private const val MAVEN_OLD_JS_STDLIB_ID = "kotlin-js-library"
|
||||
|
||||
private val TEST_FQ_NAME = FqName("kotlin.test.Test")
|
||||
private val IGNORE_FQ_NAME = FqName("kotlin.test.Ignore")
|
||||
}
|
||||
|
||||
override val kind = JsIdePlatformKind
|
||||
|
||||
override fun compilerArgumentsForProject(project: Project) = Kotlin2JsCompilerArgumentsHolder.getInstance(project).settings
|
||||
|
||||
override val resolverForModuleFactory = JsAnalyzerFacade
|
||||
|
||||
override val mavenLibraryIds = listOf(PathUtil.JS_LIB_NAME, MAVEN_OLD_JS_STDLIB_ID)
|
||||
override val gradlePluginId = "kotlin-platform-js"
|
||||
override val gradlePlatformIds: List<KotlinPlatform> get() = listOf(KotlinPlatform.JS)
|
||||
|
||||
override val libraryKind = JSLibraryKind
|
||||
override fun getLibraryDescription(project: Project) = JSLibraryStdDescription(project)
|
||||
|
||||
override fun getLibraryVersionProvider(project: Project) = { library: Library ->
|
||||
JsLibraryStdDetectionUtil.getJsLibraryStdVersion(library, project)
|
||||
}
|
||||
|
||||
override fun getTestIcon(declaration: KtNamedDeclaration, descriptor: DeclarationDescriptor): Icon? {
|
||||
if (!descriptor.isTest()) return null
|
||||
|
||||
val contexts by lazy { computeConfigurationContexts(declaration) }
|
||||
|
||||
val runConfigData = RunConfigurationProducer
|
||||
.getProducers(declaration.project)
|
||||
.asSequence()
|
||||
.filterIsInstance<KotlinJSRunConfigurationDataProvider<*>>()
|
||||
.filter { it.isForTests }
|
||||
.flatMap { provider -> contexts.map { context -> provider.getConfigurationData(context) } }
|
||||
.firstOrNull { it != null } ?: return null
|
||||
|
||||
val locations = ArrayList<String>()
|
||||
|
||||
locations += FileUtil.toSystemDependentName(runConfigData.jsOutputFilePath)
|
||||
|
||||
val klass = when (declaration) {
|
||||
is KtClassOrObject -> declaration
|
||||
is KtNamedFunction -> declaration.containingClassOrObject ?: return null
|
||||
else -> return null
|
||||
}
|
||||
locations += klass.parentsWithSelf.filterIsInstance<KtNamedDeclaration>().mapNotNull { it.name }.toList().asReversed()
|
||||
|
||||
val testName = (declaration as? KtNamedFunction)?.name
|
||||
if (testName != null) {
|
||||
locations += "$testName"
|
||||
}
|
||||
|
||||
val prefix = if (testName != null) "test://" else "suite://"
|
||||
|
||||
val url = prefix + locations.joinWithEscape('.')
|
||||
|
||||
return getTestStateIcon(url, declaration.project)
|
||||
}
|
||||
|
||||
override fun acceptsAsEntryPoint(function: KtFunction): Boolean {
|
||||
val contexts by lazy { computeConfigurationContexts(function) }
|
||||
|
||||
return RunConfigurationProducer
|
||||
.getProducers(function.project)
|
||||
.asSequence()
|
||||
.filterIsInstance<KotlinJSRunConfigurationDataProvider<*>>()
|
||||
.filter { !it.isForTests }
|
||||
.flatMap { provider -> contexts.map { context -> provider.getConfigurationData(context) } }
|
||||
.any { it != null }
|
||||
}
|
||||
|
||||
private fun computeConfigurationContexts(declaration: KtNamedDeclaration): Sequence<ConfigurationContext> {
|
||||
return sequenceOf(ConfigurationContext(declaration))
|
||||
}
|
||||
|
||||
private fun DeclarationDescriptor.isIgnored(): Boolean =
|
||||
annotations.any { it.fqName == IGNORE_FQ_NAME } || ((containingDeclaration as? ClassDescriptor)?.isIgnored() ?: false)
|
||||
|
||||
private fun DeclarationDescriptor.isTest(): Boolean {
|
||||
if (isIgnored()) return false
|
||||
|
||||
if (annotations.any { it.fqName == TEST_FQ_NAME }) return true
|
||||
if (this is ClassDescriptorWithResolutionScopes) {
|
||||
return declaredCallableMembers.any { it.isTest() }
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* 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.idea.run
|
||||
|
||||
import com.intellij.openapi.module.Module
|
||||
import org.jetbrains.kotlin.idea.caches.project.implementingModules
|
||||
import org.jetbrains.kotlin.idea.project.platform
|
||||
import org.jetbrains.kotlin.platform.impl.isCommon
|
||||
import org.jetbrains.kotlin.platform.impl.isJvm
|
||||
|
||||
fun Module.asJvmModule(): Module? {
|
||||
if (platform.isJvm) return this
|
||||
|
||||
if (platform.isCommon) {
|
||||
return implementingModules.firstOrNull { it.platform.isJvm }
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.idea.scratch
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
|
||||
fun isScratchChanged(project: Project, file: VirtualFile) : Boolean {
|
||||
return true
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* 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.test;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public abstract class KotlinLightCodeInsightFixtureTestCaseBase extends LightCodeInsightFixtureTestCase {
|
||||
@NotNull
|
||||
@Override
|
||||
public Project getProject() {
|
||||
return super.getProject();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Editor getEditor() {
|
||||
return super.getEditor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiFile getFile() {
|
||||
return super.getFile();
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
|
||||
description = "Kotlin Gradle Tooling support"
|
||||
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("jps-compatible")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile(kotlinStdlib())
|
||||
compile(project(":compiler:cli-common"))
|
||||
compile(intellijPluginDep("gradle"))
|
||||
compileOnly(intellijDep()) { includeJars("slf4j-api-1.7.10") }
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
"main" { projectDefault() }
|
||||
"test" {}
|
||||
}
|
||||
|
||||
runtimeJar()
|
||||
@@ -1,445 +0,0 @@
|
||||
/*
|
||||
* 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.gradle
|
||||
|
||||
import org.gradle.api.Named
|
||||
import org.gradle.api.NamedDomainObjectContainer
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.Dependency
|
||||
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.file.SourceDirectorySet
|
||||
import org.gradle.api.logging.Logging
|
||||
import org.gradle.api.provider.Property
|
||||
import org.jetbrains.kotlin.gradle.KotlinMPPGradleModel.Companion.NO_KOTLIN_NATIVE_HOME
|
||||
import org.jetbrains.plugins.gradle.model.*
|
||||
import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder
|
||||
import org.jetbrains.plugins.gradle.tooling.ModelBuilderService
|
||||
import org.jetbrains.plugins.gradle.tooling.util.DependencyResolver
|
||||
import org.jetbrains.plugins.gradle.tooling.util.DependencyResolverImpl
|
||||
import org.jetbrains.plugins.gradle.tooling.util.SourceSetCachedFinder
|
||||
import java.io.File
|
||||
import java.lang.reflect.Method
|
||||
|
||||
class KotlinMPPGradleModelBuilder : ModelBuilderService {
|
||||
override fun getErrorMessageBuilder(project: Project, e: Exception): ErrorMessageBuilder {
|
||||
return ErrorMessageBuilder
|
||||
.create(project, e, "Gradle import errors")
|
||||
.withDescription("Unable to build Kotlin project configuration")
|
||||
}
|
||||
|
||||
override fun canBuild(modelName: String?): Boolean {
|
||||
return modelName == KotlinMPPGradleModel::class.java.name
|
||||
}
|
||||
|
||||
override fun buildAll(modelName: String, project: Project): Any? {
|
||||
val dependencyResolver = DependencyResolverImpl(
|
||||
project,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
SourceSetCachedFinder(project)
|
||||
)
|
||||
val sourceSets = buildSourceSets(dependencyResolver, project) ?: return null
|
||||
val sourceSetMap = sourceSets.map { it.name to it }.toMap()
|
||||
val targets = buildTargets(sourceSetMap, dependencyResolver, project) ?: return null
|
||||
computeSourceSetsDeferredInfo(sourceSets, targets)
|
||||
val coroutinesState = getCoroutinesState(project)
|
||||
reportUnresolvedDependencies(targets)
|
||||
val kotlinNativeHome = KotlinNativeHomeEvaluator.getKotlinNativeHome(project) ?: NO_KOTLIN_NATIVE_HOME
|
||||
return KotlinMPPGradleModelImpl(sourceSetMap, targets, ExtraFeaturesImpl(coroutinesState), kotlinNativeHome)
|
||||
}
|
||||
|
||||
private fun reportUnresolvedDependencies(targets: Collection<KotlinTarget>) {
|
||||
targets
|
||||
.asSequence()
|
||||
.flatMap { it.compilations.asSequence() }
|
||||
.flatMap { it.dependencies.asSequence() }
|
||||
.mapNotNull { (it as? UnresolvedExternalDependency)?.failureMessage }
|
||||
.toSet()
|
||||
.forEach { logger.warn(it) }
|
||||
}
|
||||
|
||||
private fun getCoroutinesState(project: Project): String? {
|
||||
val kotlinExt = project.extensions.findByName("kotlin") ?: return null
|
||||
val getExperimental = kotlinExt.javaClass.getMethodOrNull("getExperimental") ?: return null
|
||||
val experimentalExt = getExperimental(kotlinExt) ?: return null
|
||||
val getCoroutines = experimentalExt.javaClass.getMethodOrNull("getCoroutines") ?: return null
|
||||
return getCoroutines(experimentalExt) as? String
|
||||
}
|
||||
|
||||
private fun buildSourceSets(dependencyResolver: DependencyResolver, project: Project): Collection<KotlinSourceSetImpl>? {
|
||||
val kotlinExt = project.extensions.findByName("kotlin") ?: return null
|
||||
val getSourceSets = kotlinExt.javaClass.getMethodOrNull("getSourceSets") ?: return null
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val sourceSets =
|
||||
(getSourceSets(kotlinExt) as? NamedDomainObjectContainer<Named>)?.asMap?.values ?: emptyList<Named>()
|
||||
return sourceSets.mapNotNull { buildSourceSet(it, dependencyResolver, project) }
|
||||
}
|
||||
|
||||
private fun buildSourceSet(
|
||||
gradleSourceSet: Named,
|
||||
dependencyResolver: DependencyResolver,
|
||||
project: Project
|
||||
): KotlinSourceSetImpl? {
|
||||
val sourceSetClass = gradleSourceSet.javaClass
|
||||
val getLanguageSettings = sourceSetClass.getMethodOrNull("getLanguageSettings") ?: return null
|
||||
val getSourceDirSet = sourceSetClass.getMethodOrNull("getKotlin") ?: return null
|
||||
val getResourceDirSet = sourceSetClass.getMethodOrNull("getResources") ?: return null
|
||||
val getDependsOn = sourceSetClass.getMethodOrNull("getDependsOn") ?: return null
|
||||
val languageSettings = getLanguageSettings(gradleSourceSet)?.let { buildLanguageSettings(it) } ?: return null
|
||||
val sourceDirs = (getSourceDirSet(gradleSourceSet) as? SourceDirectorySet)?.srcDirs ?: emptySet()
|
||||
val resourceDirs = (getResourceDirSet(gradleSourceSet) as? SourceDirectorySet)?.srcDirs ?: emptySet()
|
||||
val dependencies = buildSourceSetDependencies(gradleSourceSet, dependencyResolver, project)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val dependsOnSourceSets = (getDependsOn(gradleSourceSet) as? Set<Named>)?.mapTo(LinkedHashSet()) { it.name } ?: emptySet<String>()
|
||||
return KotlinSourceSetImpl(gradleSourceSet.name, languageSettings, sourceDirs, resourceDirs, dependencies, dependsOnSourceSets)
|
||||
}
|
||||
|
||||
private fun buildLanguageSettings(gradleLanguageSettings: Any): KotlinLanguageSettings? {
|
||||
val languageSettingsClass = gradleLanguageSettings.javaClass
|
||||
val getLanguageVersion = languageSettingsClass.getMethodOrNull("getLanguageVersion") ?: return null
|
||||
val getApiVersion = languageSettingsClass.getMethodOrNull("getApiVersion") ?: return null
|
||||
val getProgressiveMode = languageSettingsClass.getMethodOrNull("getProgressiveMode") ?: return null
|
||||
val getEnabledLanguageFeatures = languageSettingsClass.getMethodOrNull("getEnabledLanguageFeatures") ?: return null
|
||||
val getExperimentalAnnotationsInUse = languageSettingsClass.getMethodOrNull("getExperimentalAnnotationsInUse")
|
||||
val getCompilerPluginArguments = languageSettingsClass.getMethodOrNull("getCompilerPluginArguments")
|
||||
val getCompilerPluginClasspath = languageSettingsClass.getMethodOrNull("getCompilerPluginClasspath")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return KotlinLanguageSettingsImpl(
|
||||
getLanguageVersion(gradleLanguageSettings) as? String,
|
||||
getApiVersion(gradleLanguageSettings) as? String,
|
||||
getProgressiveMode(gradleLanguageSettings) as? Boolean ?: false,
|
||||
getEnabledLanguageFeatures(gradleLanguageSettings) as? Set<String> ?: emptySet(),
|
||||
getExperimentalAnnotationsInUse?.invoke(gradleLanguageSettings) as? Set<String> ?: emptySet(),
|
||||
getCompilerPluginArguments?.invoke(gradleLanguageSettings) as? List<String> ?: emptyList(),
|
||||
(getCompilerPluginClasspath?.invoke(gradleLanguageSettings) as? FileCollection)?.files ?: emptySet()
|
||||
)
|
||||
}
|
||||
|
||||
private fun buildDependencies(
|
||||
dependencyHolder: Any,
|
||||
dependencyResolver: DependencyResolver,
|
||||
configurationNameAccessor: String,
|
||||
scope: String,
|
||||
project: Project
|
||||
): Collection<KotlinDependency> {
|
||||
val dependencyHolderClass = dependencyHolder.javaClass
|
||||
val getConfigurationName = dependencyHolderClass.getMethodOrNull(configurationNameAccessor) ?: return emptyList()
|
||||
val configurationName = getConfigurationName(dependencyHolder) as? String ?: return emptyList()
|
||||
val configuration = project.configurations.findByName(configurationName) ?: return emptyList()
|
||||
if (!configuration.isCanBeResolved) return emptyList()
|
||||
|
||||
val dependencyAdjuster = DependencyAdjuster(configuration, scope, project)
|
||||
|
||||
val resolvedDependencies = dependencyResolver
|
||||
.resolveDependencies(configuration)
|
||||
.apply {
|
||||
forEach<ExternalDependency?> { (it as? AbstractExternalDependency)?.scope = scope }
|
||||
}
|
||||
.flatMap(dependencyAdjuster::adjustDependency)
|
||||
val singleDependencyFiles = resolvedDependencies.mapNotNullTo(LinkedHashSet<File>()) {
|
||||
(it as? FileCollectionDependency)?.files?.singleOrNull()
|
||||
}
|
||||
// Workaround for duplicated dependencies specified as a file collection (KT-26675)
|
||||
// Drop this code when the issue is fixed in the platform
|
||||
return resolvedDependencies.filter { dependency ->
|
||||
if (dependency !is FileCollectionDependency) return@filter true
|
||||
val files = dependency.files
|
||||
if (files.size <= 1) return@filter true
|
||||
(files.any { it !in singleDependencyFiles })
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildTargets(
|
||||
sourceSetMap: Map<String, KotlinSourceSet>,
|
||||
dependencyResolver: DependencyResolver,
|
||||
project: Project
|
||||
): Collection<KotlinTarget>? {
|
||||
return project.getTargets()?.mapNotNull { buildTarget(it, sourceSetMap, dependencyResolver, project) }
|
||||
}
|
||||
|
||||
private fun buildTarget(
|
||||
gradleTarget: Named,
|
||||
sourceSetMap: Map<String, KotlinSourceSet>,
|
||||
dependencyResolver: DependencyResolver,
|
||||
project: Project
|
||||
): KotlinTarget? {
|
||||
val targetClass = gradleTarget.javaClass
|
||||
val getPlatformType = targetClass.getMethodOrNull("getPlatformType") ?: return null
|
||||
val getCompilations = targetClass.getMethodOrNull("getCompilations") ?: return null
|
||||
val getDisambiguationClassifier = targetClass.getMethodOrNull("getDisambiguationClassifier") ?: return null
|
||||
val platformId = (getPlatformType.invoke(gradleTarget) as? Named)?.name ?: return null
|
||||
val platform = KotlinPlatform.byId(platformId) ?: return null
|
||||
val disambiguationClassifier = getDisambiguationClassifier(gradleTarget) as? String
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val gradleCompilations =
|
||||
(getCompilations.invoke(gradleTarget) as? NamedDomainObjectContainer<Named>)?.asMap?.values ?: emptyList<Named>()
|
||||
val compilations = gradleCompilations.mapNotNull {
|
||||
buildCompilation(it, disambiguationClassifier, sourceSetMap, dependencyResolver, project)
|
||||
}
|
||||
val jar = buildTargetJar(gradleTarget, project)
|
||||
val target = KotlinTargetImpl(gradleTarget.name, null, disambiguationClassifier, platform, compilations, jar)
|
||||
compilations.forEach {
|
||||
it.disambiguationClassifier = target.disambiguationClassifier
|
||||
it.platform = target.platform
|
||||
}
|
||||
return target
|
||||
}
|
||||
|
||||
private fun buildTargetJar(gradleTarget: Named, project: Project): KotlinTargetJar? {
|
||||
val targetClass = gradleTarget.javaClass
|
||||
val getArtifactsTaskName = targetClass.getMethodOrNull("getArtifactsTaskName") ?: return null
|
||||
val artifactsTaskName = getArtifactsTaskName(gradleTarget) as? String ?: return null
|
||||
val jarTask = project.tasks.findByName(artifactsTaskName) ?: return null
|
||||
val jarTaskClass = jarTask.javaClass
|
||||
val getArchivePath = jarTaskClass.getMethodOrNull("getArchivePath")
|
||||
val archiveFile = getArchivePath?.invoke(jarTask) as? File?
|
||||
return KotlinTargetJarImpl(archiveFile)
|
||||
}
|
||||
|
||||
private fun buildCompilation(
|
||||
gradleCompilation: Named,
|
||||
classifier: String?,
|
||||
sourceSetMap: Map<String, KotlinSourceSet>,
|
||||
dependencyResolver: DependencyResolver,
|
||||
project: Project
|
||||
): KotlinCompilationImpl? {
|
||||
val compilationClass = gradleCompilation.javaClass
|
||||
val getKotlinSourceSets = compilationClass.getMethodOrNull("getKotlinSourceSets") ?: return null
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val kotlinGradleSourceSets = (getKotlinSourceSets(gradleCompilation) as? Collection<Named>) ?: return null
|
||||
val kotlinSourceSets = kotlinGradleSourceSets.mapNotNull { sourceSetMap[it.name] }
|
||||
val getCompileKotlinTaskName = compilationClass.getMethodOrNull("getCompileKotlinTaskName") ?: return null
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val compileKotlinTaskName = (getCompileKotlinTaskName(gradleCompilation) as? String) ?: return null
|
||||
val compileKotlinTask = project.tasks.findByName(compileKotlinTaskName) ?: return null
|
||||
val output = buildCompilationOutput(gradleCompilation, compileKotlinTask) ?: return null
|
||||
val arguments = buildCompilationArguments(compileKotlinTask) ?: return null
|
||||
val dependencyClasspath = buildDependencyClasspath(compileKotlinTask)
|
||||
val dependencies = buildCompilationDependencies(gradleCompilation, classifier, sourceSetMap, dependencyResolver, project)
|
||||
return KotlinCompilationImpl(gradleCompilation.name, kotlinSourceSets, dependencies, output, arguments, dependencyClasspath)
|
||||
}
|
||||
|
||||
private fun buildCompilationDependencies(
|
||||
gradleCompilation: Named,
|
||||
classifier: String?,
|
||||
sourceSetMap: Map<String, KotlinSourceSet>,
|
||||
dependencyResolver: DependencyResolver,
|
||||
project: Project
|
||||
): Set<KotlinDependency> {
|
||||
return LinkedHashSet<KotlinDependency>().apply {
|
||||
this += buildDependencies(
|
||||
gradleCompilation, dependencyResolver, "getCompileDependencyConfigurationName", "COMPILE", project
|
||||
)
|
||||
this += buildDependencies(
|
||||
gradleCompilation, dependencyResolver, "getRuntimeDependencyConfigurationName", "RUNTIME", project
|
||||
)
|
||||
this += sourceSetMap[compilationFullName(gradleCompilation.name, classifier)]?.dependencies ?: emptySet()
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildSourceSetDependencies(
|
||||
gradleSourceSet: Named,
|
||||
dependencyResolver: DependencyResolver,
|
||||
project: Project
|
||||
): Set<KotlinDependency> {
|
||||
return LinkedHashSet<KotlinDependency>().apply {
|
||||
this += buildDependencies(
|
||||
gradleSourceSet, dependencyResolver, "getApiMetadataConfigurationName", "COMPILE", project
|
||||
)
|
||||
this += buildDependencies(
|
||||
gradleSourceSet, dependencyResolver, "getImplementationMetadataConfigurationName", "COMPILE", project
|
||||
)
|
||||
this += buildDependencies(
|
||||
gradleSourceSet, dependencyResolver, "getCompileOnlyMetadataConfigurationName", "COMPILE", project
|
||||
)
|
||||
this += buildDependencies(
|
||||
gradleSourceSet, dependencyResolver, "getRuntimeOnlyMetadataConfigurationName", "RUNTIME", project
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun safelyGetArguments(compileKotlinTask: Task, accessor: Method?) = try {
|
||||
accessor?.invoke(compileKotlinTask) as? List<String>
|
||||
} catch (e: Exception) {
|
||||
logger.info(e.message ?: "Unexpected exception: $e", e)
|
||||
null
|
||||
} ?: emptyList()
|
||||
|
||||
private fun buildCompilationArguments(compileKotlinTask: Task): KotlinCompilationArguments? {
|
||||
val compileTaskClass = compileKotlinTask.javaClass
|
||||
val getCurrentArguments = compileTaskClass.getMethodOrNull("getSerializedCompilerArguments")
|
||||
val getDefaultArguments = compileTaskClass.getMethodOrNull("getDefaultSerializedCompilerArguments")
|
||||
val currentArguments = safelyGetArguments(compileKotlinTask, getCurrentArguments)
|
||||
val defaultArguments = safelyGetArguments(compileKotlinTask, getDefaultArguments)
|
||||
return KotlinCompilationArgumentsImpl(defaultArguments, currentArguments)
|
||||
}
|
||||
|
||||
private fun buildDependencyClasspath(compileKotlinTask: Task): List<String> {
|
||||
val abstractKotlinCompileClass =
|
||||
compileKotlinTask.javaClass.classLoader.loadClass(AbstractKotlinGradleModelBuilder.ABSTRACT_KOTLIN_COMPILE_CLASS)
|
||||
val getCompileClasspath =
|
||||
abstractKotlinCompileClass.getDeclaredMethodOrNull("getCompileClasspath") ?: return emptyList()
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return (getCompileClasspath(compileKotlinTask) as? Collection<File>)?.map { it.path } ?: emptyList()
|
||||
}
|
||||
|
||||
private fun buildCompilationOutput(
|
||||
gradleCompilation: Named,
|
||||
compileKotlinTask: Task
|
||||
): KotlinCompilationOutput? {
|
||||
val compilationClass = gradleCompilation.javaClass
|
||||
val getOutput = compilationClass.getMethodOrNull("getOutput") ?: return null
|
||||
val gradleOutput = getOutput(gradleCompilation) ?: return null
|
||||
val gradleOutputClass = gradleOutput.javaClass
|
||||
val getClassesDirs = gradleOutputClass.getMethodOrNull("getClassesDirs") ?: return null
|
||||
val getResourcesDir = gradleOutputClass.getMethodOrNull("getResourcesDir") ?: return null
|
||||
val compileKotlinTaskClass = compileKotlinTask.javaClass
|
||||
val getDestinationDir = compileKotlinTaskClass.getMethodOrNull("getDestinationDir")
|
||||
val getOutputFile = compileKotlinTaskClass.getMethodOrNull("getOutputFile")
|
||||
val classesDirs = getClassesDirs(gradleOutput) as? FileCollection ?: return null
|
||||
val resourcesDir = getResourcesDir(gradleOutput) as? File ?: return null
|
||||
val destinationDir =
|
||||
getDestinationDir?.invoke(compileKotlinTask) as? File
|
||||
//TODO: Hack for KotlinNativeCompile
|
||||
?: (getOutputFile?.invoke(compileKotlinTask) as? Property<File>)?.orNull?.parentFile
|
||||
?: return null
|
||||
return KotlinCompilationOutputImpl(classesDirs.files, destinationDir, resourcesDir)
|
||||
}
|
||||
|
||||
private fun computeSourceSetsDeferredInfo(
|
||||
sourceSets: Collection<KotlinSourceSetImpl>,
|
||||
targets: Collection<KotlinTarget>
|
||||
) {
|
||||
val sourceSetToCompilations = LinkedHashMap<KotlinSourceSet, MutableSet<KotlinCompilation>>()
|
||||
for (target in targets) {
|
||||
for (compilation in target.compilations) {
|
||||
for (sourceSet in compilation.sourceSets) {
|
||||
sourceSetToCompilations.getOrPut(sourceSet) { LinkedHashSet() } += compilation
|
||||
}
|
||||
}
|
||||
}
|
||||
for (sourceSet in sourceSets) {
|
||||
val name = sourceSet.name
|
||||
if (name == KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME) {
|
||||
sourceSet.platform = KotlinPlatform.COMMON
|
||||
sourceSet.isTestModule = false
|
||||
continue
|
||||
}
|
||||
if (name == KotlinSourceSet.COMMON_TEST_SOURCE_SET_NAME) {
|
||||
sourceSet.platform = KotlinPlatform.COMMON
|
||||
sourceSet.isTestModule = true
|
||||
continue
|
||||
}
|
||||
|
||||
val compilations = sourceSetToCompilations[sourceSet]
|
||||
if (compilations != null) {
|
||||
sourceSet.platform = compilations.map { it.platform }.distinct().singleOrNull() ?: KotlinPlatform.COMMON
|
||||
sourceSet.isTestModule = compilations.all { it.isTestModule }
|
||||
} else {
|
||||
// TODO: change me after design about it
|
||||
sourceSet.isTestModule = "Test" in sourceSet.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class DependencyAdjuster(
|
||||
private val configuration: Configuration,
|
||||
private val scope: String,
|
||||
private val project: Project
|
||||
) {
|
||||
private val adjustmentMap = HashMap<ExternalDependency, List<ExternalDependency>>()
|
||||
|
||||
val dependenciesByProjectPath by lazy {
|
||||
configuration
|
||||
.resolvedConfiguration
|
||||
.lenientConfiguration
|
||||
.allModuleDependencies
|
||||
.mapNotNull { dependency ->
|
||||
val artifact = dependency.moduleArtifacts.firstOrNull {
|
||||
it.id.componentIdentifier is ProjectComponentIdentifier
|
||||
} ?: return@mapNotNull null
|
||||
dependency to artifact
|
||||
}
|
||||
.groupBy { (it.second.id.componentIdentifier as ProjectComponentIdentifier).projectPath }
|
||||
}
|
||||
|
||||
private fun wrapDependency(dependency: ExternalProjectDependency, newConfigurationName: String): ExternalProjectDependency {
|
||||
return DefaultExternalProjectDependency(dependency).apply {
|
||||
this.configurationName = newConfigurationName
|
||||
|
||||
val nestedDependencies = this.dependencies.flatMap(::adjustDependency)
|
||||
this.dependencies.clear()
|
||||
this.dependencies.addAll(nestedDependencies)
|
||||
}
|
||||
}
|
||||
|
||||
fun adjustDependency(dependency: ExternalDependency): List<ExternalDependency> {
|
||||
return adjustmentMap.getOrPut(dependency) {
|
||||
if (dependency !is ExternalProjectDependency
|
||||
|| dependency.configurationName != Dependency.DEFAULT_CONFIGURATION
|
||||
) return@getOrPut listOf(dependency)
|
||||
val artifacts = dependenciesByProjectPath[dependency.projectPath] ?: return@getOrPut listOf(dependency)
|
||||
val artifactConfiguration = artifacts.mapTo(LinkedHashSet()) {
|
||||
it.first.configuration
|
||||
}.singleOrNull() ?: return@getOrPut listOf(dependency)
|
||||
val taskGetterName = when (scope) {
|
||||
"COMPILE" -> "getApiElementsConfigurationName"
|
||||
"RUNTIME" -> "getRuntimeElementsConfigurationName"
|
||||
else -> return@getOrPut listOf(dependency)
|
||||
}
|
||||
val dependencyProject =
|
||||
if (project.rootProject.path == dependency.projectPath)
|
||||
project.rootProject
|
||||
else
|
||||
project.rootProject.getChildProjectByPath(dependency.projectPath)
|
||||
|
||||
val targets = dependencyProject?.getTargets() ?: return@getOrPut listOf(dependency)
|
||||
val gradleTarget = targets.firstOrNull {
|
||||
val getter = it.javaClass.getMethodOrNull(taskGetterName) ?: return@firstOrNull false
|
||||
getter(it) == artifactConfiguration
|
||||
} ?: return@getOrPut listOf(dependency)
|
||||
val classifier = gradleTarget.javaClass.getMethodOrNull("getDisambiguationClassifier")?.invoke(gradleTarget) as? String
|
||||
?: return@getOrPut listOf(dependency)
|
||||
val platformDependency = if (classifier != KotlinTarget.METADATA_TARGET_NAME) {
|
||||
wrapDependency(dependency, compilationFullName(KotlinCompilation.MAIN_COMPILATION_NAME, classifier))
|
||||
} else null
|
||||
val commonDependency = wrapDependency(dependency, KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME)
|
||||
return if (platformDependency != null) listOf(platformDependency, commonDependency) else listOf(commonDependency)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val logger = Logging.getLogger(KotlinMPPGradleModelBuilder::class.java)
|
||||
|
||||
fun Project.getTargets(): Collection<Named>? {
|
||||
val kotlinExt = project.extensions.findByName("kotlin") ?: return null
|
||||
val getTargets = kotlinExt.javaClass.getMethodOrNull("getTargets") ?: return null
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return (getTargets.invoke(kotlinExt) as? NamedDomainObjectContainer<Named>)?.asMap?.values ?: emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Project.getChildProjectByPath(path: String): Project? {
|
||||
var project = this
|
||||
for (name in path.split(":").asSequence().drop(1)) {
|
||||
project = project.childProjects[name] ?: return null
|
||||
}
|
||||
return project
|
||||
}
|
||||
|
||||
private fun Project.getTargets(): Collection<Named>? {
|
||||
val kotlinExt = project.extensions.findByName("kotlin") ?: return null
|
||||
val getTargets = kotlinExt.javaClass.getMethodOrNull("getTargets") ?: return null
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return (getTargets.invoke(kotlinExt) as? NamedDomainObjectContainer<Named>)?.asMap?.values ?: emptyList()
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
<idea-plugin>
|
||||
<extensions defaultExtensionNs="Git4Idea">
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -1,96 +0,0 @@
|
||||
<idea-plugin>
|
||||
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
|
||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJavaFrameworkSupportProvider"/>
|
||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSFrameworkSupportProvider"/>
|
||||
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJavaFrameworkSupportProvider"/>
|
||||
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSFrameworkSupportProvider"/>
|
||||
<pluginDescriptions implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradlePluginDescription"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectResolverExtension" order="first"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.kapt.idea.KaptProjectResolverExtension" order="last"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.allopen.ide.AllOpenProjectResolverExtension" order="last"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.noarg.ide.NoArgProjectResolverExtension" order="last"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.samWithReceiver.ide.SamWithReceiverProjectResolverExtension" order="last"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinMPPGradleProjectResolver"/>
|
||||
</extensions>
|
||||
|
||||
<extensionPoints>
|
||||
<extensionPoint qualifiedName="org.jetbrains.kotlin.gradleProjectImportHandler" area="IDEA_PROJECT"
|
||||
interface="org.jetbrains.kotlin.idea.configuration.GradleProjectImportHandler"/>
|
||||
|
||||
<extensionPoint qualifiedName="org.jetbrains.kotlin.gradleModelFacade"
|
||||
interface="org.jetbrains.kotlin.idea.inspections.gradle.KotlinGradleModelFacade"/>
|
||||
</extensionPoints>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleSourceSetDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleLibraryDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinSourceSetDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinTargetDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectSettingsDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.KotlinJavaMPPSourceSetDataService"/>
|
||||
<externalSystemTaskNotificationListener implementation="org.jetbrains.kotlin.idea.core.script.ReloadGradleTemplatesOnSync"/>
|
||||
|
||||
<localInspection
|
||||
implementationClass="org.jetbrains.kotlin.idea.inspections.gradle.DifferentKotlinGradleVersionInspection"
|
||||
displayName="Kotlin Gradle and IDE plugins versions are different"
|
||||
groupName="Kotlin"
|
||||
enabledByDefault="true"
|
||||
language="Groovy"
|
||||
hasStaticDescription="true"
|
||||
level="WARNING"/>
|
||||
|
||||
<localInspection
|
||||
implementationClass="org.jetbrains.kotlin.idea.inspections.gradle.DifferentStdlibGradleVersionInspection"
|
||||
displayName="Kotlin library and Gradle plugin versions are different"
|
||||
groupName="Kotlin"
|
||||
enabledByDefault="true"
|
||||
language="Groovy"
|
||||
hasStaticDescription="true"
|
||||
level="WARNING"/>
|
||||
|
||||
<localInspection
|
||||
implementationClass="org.jetbrains.kotlin.idea.inspections.gradle.DeprecatedGradleDependencyInspection"
|
||||
displayName="Deprecated library is used in Gradle"
|
||||
groupName="Kotlin"
|
||||
enabledByDefault="true"
|
||||
cleanupTool="true"
|
||||
language="Groovy"
|
||||
hasStaticDescription="true"
|
||||
level="WARNING"/>
|
||||
|
||||
<localInspection
|
||||
implementationClass="org.jetbrains.kotlin.idea.inspections.gradle.GradleKotlinxCoroutinesDeprecationInspection"
|
||||
displayName="Incompatible kotlinx.coroutines dependency is used with Kotlin 1.3+ in Gradle"
|
||||
groupPath="Kotlin,Migration"
|
||||
groupName="Gradle"
|
||||
enabledByDefault="true"
|
||||
language="Groovy"
|
||||
hasStaticDescription="true"
|
||||
level="ERROR"/>
|
||||
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinTestClassGradleConfigurationProducer"/>
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinTestMethodGradleConfigurationProducer"/>
|
||||
<orderEnumerationHandlerFactory implementation="org.jetbrains.kotlin.android.KotlinAndroidGradleOrderEnumerationHandler$FactoryImpl" order="first"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="org.jetbrains.kotlin">
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.allopen.ide.AllOpenGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.scripting.idea.plugin.ScriptingGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.kapt.idea.KaptGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.noarg.ide.NoArgGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.samWithReceiver.ide.SamWithReceiverGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlinx.serialization.idea.KotlinSerializationGradleImportHandler"/>
|
||||
|
||||
<projectConfigurator implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleModuleConfigurator"/>
|
||||
<projectConfigurator implementation="org.jetbrains.kotlin.idea.configuration.KotlinJsGradleModuleConfigurator"/>
|
||||
<gradleModelFacade implementation="org.jetbrains.kotlin.idea.inspections.gradle.DefaultGradleModelFacade"/>
|
||||
|
||||
<scriptDefinitionContributor implementation="org.jetbrains.kotlin.idea.core.script.GradleScriptDefinitionsContributor" order="first"/>
|
||||
<scriptAdditionalIdeaDependenciesProvider implementation="org.jetbrains.kotlin.idea.core.script.GradleScriptAdditionalIdeaDependenciesProvider"/>
|
||||
|
||||
<moduleBuilder implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleWebMultiplatformModuleBuilder"/>
|
||||
|
||||
<buildSystemTypeDetector implementation="org.jetbrains.kotlin.idea.configuration.GradleDetector"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -1,192 +0,0 @@
|
||||
<idea-plugin>
|
||||
<extensionPoints>
|
||||
<extensionPoint qualifiedName="org.jetbrains.kotlin.platformGradleDetector"
|
||||
interface="org.jetbrains.kotlin.idea.inspections.gradle.KotlinPlatformGradleDetector"/>
|
||||
</extensionPoints>
|
||||
|
||||
<application-components>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.kotlin.idea.JvmPluginStartupComponent</implementation-class>
|
||||
</component>
|
||||
</application-components>
|
||||
|
||||
<project-components>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.kotlin.idea.compiler.KotlinCompilerManager</implementation-class>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.kotlin.idea.configuration.ui.KotlinConfigurationCheckerComponent</implementation-class>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.kotlin.idea.scratch.ui.ScratchFileHook</implementation-class>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.kotlin.idea.scratch.ScratchFileModuleInfoProvider</implementation-class>
|
||||
</component>
|
||||
</project-components>
|
||||
|
||||
<actions>
|
||||
<!-- Kotlin Console REPL-->
|
||||
<action id="KotlinConsoleREPL" class="org.jetbrains.kotlin.console.actions.RunKotlinConsoleAction"
|
||||
text="Kotlin REPL"
|
||||
icon="/org/jetbrains/kotlin/idea/icons/kotlin_launch_configuration.png">
|
||||
<add-to-group group-id="KotlinToolsGroup" anchor="last"/>
|
||||
</action>
|
||||
|
||||
<action id="ConfigureKotlinInProject" class="org.jetbrains.kotlin.idea.actions.ConfigureKotlinJavaInProjectAction"
|
||||
text="Configure Kotlin in Project">
|
||||
<add-to-group group-id="KotlinToolsGroup"/>
|
||||
</action>
|
||||
|
||||
<action id="ConfigureKotlinJsInProject" class="org.jetbrains.kotlin.idea.actions.ConfigureKotlinJsInProjectAction"
|
||||
text="Configure Kotlin (JavaScript) in Project">
|
||||
<add-to-group group-id="KotlinToolsGroup"/>
|
||||
</action>
|
||||
|
||||
<action id="ShowKotlinBytecode" class="org.jetbrains.kotlin.idea.actions.ShowKotlinBytecodeAction"
|
||||
text="Show Kotlin Bytecode">
|
||||
<add-to-group group-id="KotlinToolsGroup"/>
|
||||
</action>
|
||||
|
||||
<action id="CreateIncrementalCompilationBackup"
|
||||
class="org.jetbrains.kotlin.idea.internal.makeBackup.CreateIncrementalCompilationBackup" internal="true">
|
||||
<add-to-group group-id="KotlinInternalGroup"/>
|
||||
</action>
|
||||
|
||||
<action id="ReactivePostOpenProjectActionsAction" class="org.jetbrains.kotlin.idea.actions.internal.ReactivePostOpenProjectActionsAction"
|
||||
text="Kotlin Project Post-Open Activity" internal="true">
|
||||
<add-to-group group-id="KotlinInternalGroup"/>
|
||||
</action>
|
||||
|
||||
<action id="AddToProblemApiInspection" class="org.jetbrains.kotlin.idea.inspections.api.AddIncompatibleApiAction"
|
||||
text="Report as incompatible API">
|
||||
</action>
|
||||
|
||||
<group id="Kotlin.XDebugger.Actions">
|
||||
<action id="Kotlin.XDebugger.ToggleKotlinVariableView"
|
||||
class="org.jetbrains.kotlin.idea.debugger.ToggleKotlinVariablesView"
|
||||
icon="/org/jetbrains/kotlin/idea/icons/kotlin.png"/>
|
||||
</group>
|
||||
|
||||
<group id="Kotlin.XDebugger.Watches.Tree.Toolbar">
|
||||
<reference ref="Kotlin.XDebugger.ToggleKotlinVariableView"/>
|
||||
<add-to-group group-id="XDebugger.Watches.Tree.Toolbar" relative-to-action="XDebugger.SwitchWatchesInVariables" anchor="after"/>
|
||||
</group>
|
||||
</actions>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.console.KotlinConsoleKeeper"
|
||||
serviceImplementation="org.jetbrains.kotlin.console.KotlinConsoleKeeper"/>
|
||||
|
||||
<buildProcess.parametersProvider implementation="org.jetbrains.kotlin.idea.compiler.configuration.KotlinBuildProcessParametersProvider"/>
|
||||
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches"
|
||||
serviceImplementation="org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches"/>
|
||||
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.idea.scratch.ScratchFileAutoRunner"
|
||||
serviceImplementation="org.jetbrains.kotlin.idea.scratch.ScratchFileAutoRunner"/>
|
||||
|
||||
<projectService serviceImplementation="org.jetbrains.kotlin.idea.versions.SuppressNotificationState"/>
|
||||
|
||||
<applicationService serviceImplementation="org.jetbrains.kotlin.idea.debugger.ToggleKotlinVariablesState"/>
|
||||
|
||||
<debugger.jvmSmartStepIntoHandler implementation="org.jetbrains.kotlin.idea.debugger.stepping.KotlinSmartStepIntoHandler"/>
|
||||
<debugger.positionManagerFactory implementation="org.jetbrains.kotlin.idea.debugger.KotlinPositionManagerFactory"/>
|
||||
<debugger.codeFragmentFactory implementation="org.jetbrains.kotlin.idea.debugger.evaluate.KotlinCodeFragmentFactory"/>
|
||||
<debuggerEditorTextProvider language="kotlin" implementationClass="org.jetbrains.kotlin.idea.debugger.KotlinEditorTextProvider"/>
|
||||
<debuggerClassFilterProvider implementation="org.jetbrains.kotlin.idea.debugger.filter.KotlinDebuggerInternalClassesFilterProvider"/>
|
||||
<debugger.nodeRenderer implementation="org.jetbrains.kotlin.idea.debugger.render.KotlinClassWithDelegatedPropertyRenderer"/>
|
||||
<debugger.sourcePositionProvider implementation="org.jetbrains.kotlin.idea.debugger.KotlinSourcePositionProvider"/>
|
||||
<debugger.sourcePositionHighlighter implementation="org.jetbrains.kotlin.idea.debugger.KotlinSourcePositionHighlighter"/>
|
||||
<debugger.frameExtraVarsProvider implementation="org.jetbrains.kotlin.idea.debugger.KotlinFrameExtraVariablesProvider"/>
|
||||
<debugger.extraSteppingFilter implementation="org.jetbrains.kotlin.idea.KotlinExtraSteppingFilter"/>
|
||||
<xdebugger.settings implementation="org.jetbrains.kotlin.idea.debugger.KotlinDebuggerSettings"/>
|
||||
<xdebugger.breakpointType implementation="org.jetbrains.kotlin.idea.debugger.breakpoints.KotlinFieldBreakpointType"/>
|
||||
<xdebugger.breakpointType implementation="org.jetbrains.kotlin.idea.debugger.breakpoints.KotlinLineBreakpointType" order="first"/>
|
||||
<debugger.syntheticProvider implementation="org.jetbrains.kotlin.idea.debugger.filter.KotlinSyntheticTypeComponentProvider"/>
|
||||
<debugger.javaBreakpointHandlerFactory implementation="org.jetbrains.kotlin.idea.debugger.breakpoints.KotlinFieldBreakpointHandlerFactory"/>
|
||||
<debugger.javaBreakpointHandlerFactory implementation="org.jetbrains.kotlin.idea.debugger.breakpoints.KotlinLineBreakpointHandlerFactory"/>
|
||||
<debugger.jvmSteppingCommandProvider implementation="org.jetbrains.kotlin.idea.debugger.stepping.KotlinSteppingCommandProvider"/>
|
||||
<debugger.simplePropertyGetterProvider implementation="org.jetbrains.kotlin.idea.debugger.stepping.KotlinSimpleGetterProvider"/>
|
||||
|
||||
<framework.type implementation="org.jetbrains.kotlin.idea.framework.JavaFrameworkType"/>
|
||||
<projectTemplatesFactory implementation="org.jetbrains.kotlin.idea.framework.KotlinTemplatesFactory" />
|
||||
|
||||
<library.presentationProvider implementation="org.jetbrains.kotlin.idea.framework.JavaRuntimePresentationProvider"/>
|
||||
|
||||
<configurationType implementation="org.jetbrains.kotlin.idea.run.KotlinRunConfigurationType"/>
|
||||
<configurationType implementation="org.jetbrains.kotlin.idea.run.script.standalone.KotlinStandaloneScriptRunConfigurationType"/>
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinRunConfigurationProducer"/>
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.script.standalone.KotlinStandaloneScriptRunConfigurationProducer"/>
|
||||
|
||||
<library.type implementation="org.jetbrains.kotlin.idea.framework.JSLibraryType"/>
|
||||
<library.javaSourceRootDetector implementation="org.jetbrains.kotlin.idea.configuration.KotlinSourceRootDetector"/>
|
||||
|
||||
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.configuration.KotlinSetupEnvironmentNotificationProvider"/>
|
||||
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.debugger.KotlinAlternativeSourceNotificationProvider"/>
|
||||
|
||||
<consoleFilterProvider implementation="org.jetbrains.kotlin.idea.run.KotlinConsoleFilterProvider"/>
|
||||
|
||||
<exceptionFilter implementation="org.jetbrains.kotlin.idea.filters.KotlinExceptionFilterFactory" order="first"/>
|
||||
|
||||
<externalSystemTaskNotificationListener implementation="org.jetbrains.kotlin.idea.configuration.KotlinExternalSystemSyncListener"/>
|
||||
|
||||
<lang.surroundDescriptor language="kotlin"
|
||||
implementationClass="org.jetbrains.kotlin.idea.debugger.surroundWith.KotlinDebuggerExpressionSurroundDescriptor"/>
|
||||
|
||||
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.versions.UnsupportedAbiVersionNotificationPanelProvider"/>
|
||||
|
||||
<localInspection
|
||||
groupName="Plugin DevKit"
|
||||
shortName="IncompatibleAPI"
|
||||
enabledByDefault="false"
|
||||
level="ERROR"
|
||||
displayName="Incompatible API usage"
|
||||
implementationClass="org.jetbrains.kotlin.idea.inspections.api.IncompatibleAPIInspection"/>
|
||||
|
||||
<projectService serviceInterface="org.jetbrains.uast.kotlin.KotlinUastResolveProviderService"
|
||||
serviceImplementation="org.jetbrains.uast.kotlin.internal.IdeaKotlinUastResolveProviderService"/>
|
||||
|
||||
<applicationService
|
||||
serviceInterface="org.jetbrains.kotlin.platform.DefaultIdeTargetPlatformKindProvider"
|
||||
serviceImplementation="org.jetbrains.kotlin.platform.impl.IdeaDefaultIdeTargetPlatformKindProvider"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="org.jetbrains.uast">
|
||||
<uastLanguagePlugin implementation="org.jetbrains.uast.kotlin.KotlinUastLanguagePlugin"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="org.jetbrains.kotlin">
|
||||
<diagnosticSuppressor implementation="org.jetbrains.kotlin.idea.debugger.DiagnosticSuppressorForDebugger"/>
|
||||
|
||||
<storageComponentContainerContributor implementation="org.jetbrains.kotlin.samWithReceiver.ide.IdeSamWithReceiverComponentContributor"/>
|
||||
|
||||
<declarationAttributeAltererExtension implementation="org.jetbrains.kotlin.allopen.ide.IdeAllOpenDeclarationAttributeAltererExtension"/>
|
||||
|
||||
<storageComponentContainerContributor implementation="org.jetbrains.kotlin.noarg.ide.IdeNoArgComponentContainerContributor"/>
|
||||
<expressionCodegenExtension implementation="org.jetbrains.kotlin.noarg.NoArgExpressionCodegenExtension"/>
|
||||
<defaultErrorMessages implementation="org.jetbrains.kotlin.noarg.diagnostic.DefaultErrorMessagesNoArg"/>
|
||||
|
||||
<completionExtension implementation="org.jetbrains.kotlin.idea.properties.PropertyKeyCompletion"/>
|
||||
<newFileHook implementation="org.jetbrains.kotlin.idea.configuration.NewKotlinFileConfigurationHook"/>
|
||||
<quickFixContributor implementation="org.jetbrains.kotlin.idea.quickfix.JvmQuickFixRegistrar"/>
|
||||
<clearBuildState implementation="org.jetbrains.kotlin.idea.compiler.configuration.ClearBuildManagerState"/>
|
||||
<facetValidatorCreator implementation="org.jetbrains.kotlin.idea.facet.KotlinLibraryValidatorCreator"/>
|
||||
|
||||
<gradleFrameworkSupport implementation="org.jetbrains.kotlin.gradle.kdsl.frameworkSupport.GradleJavaFrameworkSupportProvider" />
|
||||
<gradleFrameworkSupport implementation="org.jetbrains.kotlin.gradle.kdsl.frameworkSupport.GradleKotlinDSLKotlinJavaFrameworkSupportProvider" />
|
||||
<gradleFrameworkSupport implementation="org.jetbrains.kotlin.gradle.kdsl.frameworkSupport.GradleKotlinDSLKotlinJSFrameworkSupportProvider" />
|
||||
<gradleFrameworkSupport implementation="org.jetbrains.kotlin.gradle.kdsl.frameworkSupport.GradleGroovyFrameworkSupportProvider" />
|
||||
|
||||
<idePlatformKind implementation="org.jetbrains.kotlin.platform.impl.JvmIdePlatformKind"/>
|
||||
<idePlatformKind implementation="org.jetbrains.kotlin.platform.impl.JsIdePlatformKind"/>
|
||||
|
||||
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.JvmIdePlatformKindTooling"/>
|
||||
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.JsIdePlatformKindTooling"/>
|
||||
|
||||
<syntheticScopeProviderExtension implementation="org.jetbrains.kotlin.idea.debugger.evaluate.DebuggerFieldSyntheticScopeProvider"/>
|
||||
<expressionCodegenExtension implementation="org.jetbrains.kotlin.idea.debugger.evaluate.DebuggerFieldExpressionCodegenExtension"/>
|
||||
<completionInformationProvider implementation="org.jetbrains.kotlin.idea.debugger.evaluate.DebuggerFieldCompletionInformationProvider" />
|
||||
<kotlinIndicesHelperExtension implementation="org.jetbrains.kotlin.idea.debugger.evaluate.DebuggerFieldKotlinIndicesHelperExtension"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -1,74 +0,0 @@
|
||||
<idea-plugin xmlns:xi="http://www.w3.org/2001/XInclude" version="2" url="http://kotlinlang.org" allow-bundled-update="true">
|
||||
<id>org.jetbrains.kotlin</id>
|
||||
|
||||
<name>Kotlin</name>
|
||||
<description><![CDATA[
|
||||
The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
|
||||
<br>
|
||||
<a href="http://kotlinlang.org/docs/tutorials/getting-started.html">Getting Started in IntelliJ IDEA</a><br>
|
||||
<a href="http://kotlinlang.org/docs/tutorials/kotlin-android.html">Getting Started in Android Studio</a><br>
|
||||
<a href="http://slack.kotlinlang.org/">Public Slack</a><br>
|
||||
<a href="https://youtrack.jetbrains.com/issues/KT">Issue tracker</a><br>
|
||||
]]></description>
|
||||
<version>@snapshot@</version>
|
||||
<vendor url="http://www.jetbrains.com">JetBrains</vendor>
|
||||
|
||||
<idea-version since-build="181.3" until-build="181.*"/>
|
||||
|
||||
<depends>com.intellij.modules.platform</depends>
|
||||
<depends>com.intellij.modules.remoteServers</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="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.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="tipsAndTricks.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<xi:include href="extensions/ide.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<project-components>
|
||||
<component>
|
||||
<!-- This is a workaround for IDEA < 183. For details, see IDEA-200525. -->
|
||||
<implementation-class>org.jetbrains.kotlin.idea.caches.ProjectRootModificationTrackerFixer</implementation-class>
|
||||
</component>
|
||||
</project-components>
|
||||
|
||||
<extensionPoints>
|
||||
<xi:include href="extensions/compiler.xml" xpointer="xpointer(/idea-plugin/extensionPoints/*)"/>
|
||||
|
||||
<extensionPoint qualifiedName="org.jetbrains.kotlin.pluginUpdateVerifier"
|
||||
interface="org.jetbrains.kotlin.idea.update.PluginUpdateVerifier"/>
|
||||
</extensionPoints>
|
||||
|
||||
<xi:include href="plugin-kotlin-extensions.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.idea.core.script.ScriptModificationListener"
|
||||
serviceImplementation="org.jetbrains.kotlin.idea.core.script.ScriptModificationListener"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 460 B |
Binary file not shown.
|
Before Width: | Height: | Size: 714 B |
@@ -1,243 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.actions
|
||||
|
||||
import com.intellij.codeInsight.navigation.NavigationUtil
|
||||
import com.intellij.ide.highlighter.JavaFileType
|
||||
import com.intellij.ide.scratch.ScratchFileService
|
||||
import com.intellij.ide.scratch.ScratchRootType
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.MessageType
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import com.intellij.openapi.ui.ex.MessagesEx
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory
|
||||
import com.intellij.openapi.vfs.VfsUtilCore
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.VirtualFileVisitor
|
||||
import com.intellij.openapi.wm.WindowManager
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiErrorElement
|
||||
import com.intellij.psi.PsiJavaFile
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices
|
||||
import org.jetbrains.kotlin.idea.j2k.JavaToKotlinConverterFactory
|
||||
import org.jetbrains.kotlin.idea.refactoring.toPsiFile
|
||||
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||
import org.jetbrains.kotlin.idea.util.application.progressIndicatorNullable
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.j2k.ConverterSettings
|
||||
import org.jetbrains.kotlin.j2k.FilesResult
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
|
||||
class JavaToKotlinAction : AnAction() {
|
||||
companion object {
|
||||
private fun uniqueKotlinFileName(javaFile: VirtualFile): String {
|
||||
val ioFile = File(javaFile.path.replace('/', File.separatorChar))
|
||||
|
||||
var i = 0
|
||||
while (true) {
|
||||
val fileName = javaFile.nameWithoutExtension + (if (i > 0) i else "") + ".kt"
|
||||
if (!ioFile.resolveSibling(fileName).exists()) return fileName
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
val title = "Convert Java to Kotlin"
|
||||
|
||||
private fun saveResults(javaFiles: List<PsiJavaFile>, convertedTexts: List<String>): List<VirtualFile> {
|
||||
val result = ArrayList<VirtualFile>()
|
||||
for ((psiFile, text) in javaFiles.zip(convertedTexts)) {
|
||||
try {
|
||||
val document = PsiDocumentManager.getInstance(psiFile.project).getDocument(psiFile)
|
||||
if (document == null) {
|
||||
MessagesEx.error(psiFile.project, "Failed to save conversion result: couldn't find document for " + psiFile.name).showLater()
|
||||
continue
|
||||
}
|
||||
document.replaceString(0, document.textLength, text)
|
||||
FileDocumentManager.getInstance().saveDocument(document)
|
||||
|
||||
val virtualFile = psiFile.virtualFile
|
||||
if (ScratchRootType.getInstance().containsFile(virtualFile)) {
|
||||
val mapping = ScratchFileService.getInstance().scratchesMapping
|
||||
mapping.setMapping(virtualFile, KotlinFileType.INSTANCE.language)
|
||||
}
|
||||
else {
|
||||
val fileName = uniqueKotlinFileName(virtualFile)
|
||||
virtualFile.rename(this, fileName)
|
||||
}
|
||||
}
|
||||
catch (e: IOException) {
|
||||
MessagesEx.error(psiFile.project, e.message ?: "").showLater()
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun convertFiles(
|
||||
javaFiles: List<PsiJavaFile>, project: Project,
|
||||
enableExternalCodeProcessing: Boolean = true,
|
||||
askExternalCodeProcessing: Boolean = true
|
||||
): List<KtFile> {
|
||||
var converterResult: FilesResult? = null
|
||||
fun convert() {
|
||||
val converter =
|
||||
JavaToKotlinConverterFactory.createJavaToKotlinConverter(
|
||||
project,
|
||||
ConverterSettings.defaultSettings,
|
||||
IdeaJavaToKotlinServices
|
||||
)
|
||||
converterResult = converter.filesToKotlin(
|
||||
javaFiles,
|
||||
JavaToKotlinConverterFactory.createPostProcessor(formatCode = true),
|
||||
ProgressManager.getInstance().progressIndicatorNullable!!
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(
|
||||
::convert,
|
||||
title,
|
||||
true,
|
||||
project)) return emptyList()
|
||||
|
||||
|
||||
var externalCodeUpdate: (() -> Unit)? = null
|
||||
|
||||
if (enableExternalCodeProcessing && converterResult!!.externalCodeProcessing != null) {
|
||||
val question = "Some code in the rest of your project may require corrections after performing this conversion. Do you want to find such code and correct it too?"
|
||||
if (!askExternalCodeProcessing || (Messages.showYesNoDialog(project, question, title, Messages.getQuestionIcon()) == Messages.YES)) {
|
||||
ProgressManager.getInstance().runProcessWithProgressSynchronously(
|
||||
{
|
||||
runReadAction {
|
||||
externalCodeUpdate = converterResult!!.externalCodeProcessing!!.prepareWriteOperation(
|
||||
ProgressManager.getInstance().progressIndicatorNullable!!
|
||||
)
|
||||
}
|
||||
},
|
||||
title,
|
||||
true,
|
||||
project)
|
||||
}
|
||||
}
|
||||
|
||||
return project.executeWriteCommand("Convert files from Java to Kotlin", null) {
|
||||
CommandProcessor.getInstance().markCurrentCommandAsGlobal(project)
|
||||
|
||||
val newFiles = saveResults(javaFiles, converterResult!!.results)
|
||||
|
||||
externalCodeUpdate?.invoke()
|
||||
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
||||
|
||||
newFiles.singleOrNull()?.let {
|
||||
FileEditorManager.getInstance(project).openFile(it, true)
|
||||
}
|
||||
|
||||
newFiles.map { it.toPsiFile(project) as KtFile }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val javaFiles = selectedJavaFiles(e).filter { it.isWritable }.toList()
|
||||
val project = CommonDataKeys.PROJECT.getData(e.dataContext)!!
|
||||
|
||||
if (javaFiles.isEmpty()) {
|
||||
val statusBar = WindowManager.getInstance().getStatusBar(project)
|
||||
JBPopupFactory.getInstance()
|
||||
.createHtmlTextBalloonBuilder("Nothing to convert:<br>No writable Java files found", MessageType.ERROR, null)
|
||||
.createBalloon()
|
||||
.showInCenterOf(statusBar.component)
|
||||
}
|
||||
|
||||
val firstSyntaxError = javaFiles.asSequence().map { PsiTreeUtil.findChildOfType(it, PsiErrorElement::class.java) }.firstOrNull()
|
||||
|
||||
if (firstSyntaxError != null) {
|
||||
val count = javaFiles.filter { PsiTreeUtil.hasErrorElements(it) }.count()
|
||||
val question = firstSyntaxError.containingFile.name +
|
||||
(if (count > 1) " and ${count - 1} more Java files" else " file") +
|
||||
" contain syntax errors, the conversion result may be incorrect"
|
||||
|
||||
val okText = "Investigate Errors"
|
||||
val cancelText = "Proceed with Conversion"
|
||||
if (Messages.showOkCancelDialog(
|
||||
project,
|
||||
question,
|
||||
title,
|
||||
okText,
|
||||
cancelText,
|
||||
Messages.getWarningIcon()
|
||||
) == Messages.OK) {
|
||||
NavigationUtil.activateFileWithPsiElement(firstSyntaxError.navigationElement)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
convertFiles(javaFiles, project)
|
||||
}
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
val virtualFiles = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY) ?: return
|
||||
val project = e.project ?: return
|
||||
|
||||
e.presentation.isEnabled = isAnyJavaFileSelected(project, virtualFiles)
|
||||
}
|
||||
|
||||
private fun isAnyJavaFileSelected(project: Project, files: Array<VirtualFile>): Boolean {
|
||||
if (files.any { it.isDirectory }) return true // Giving up on directories
|
||||
val manager = PsiManager.getInstance(project)
|
||||
return files.any { it.extension == JavaFileType.DEFAULT_EXTENSION && manager.findFile(it) is PsiJavaFile && it.isWritable }
|
||||
}
|
||||
|
||||
private fun selectedJavaFiles(e: AnActionEvent): Sequence<PsiJavaFile> {
|
||||
val virtualFiles = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY) ?: return sequenceOf()
|
||||
val project = e.project ?: return sequenceOf()
|
||||
return allJavaFiles(virtualFiles, project)
|
||||
}
|
||||
|
||||
private fun allJavaFiles(filesOrDirs: Array<VirtualFile>, project: Project): Sequence<PsiJavaFile> {
|
||||
val manager = PsiManager.getInstance(project)
|
||||
return allFiles(filesOrDirs)
|
||||
.asSequence()
|
||||
.mapNotNull { manager.findFile(it) as? PsiJavaFile }
|
||||
}
|
||||
|
||||
private fun allFiles(filesOrDirs: Array<VirtualFile>): Collection<VirtualFile> {
|
||||
val result = ArrayList<VirtualFile>()
|
||||
for (file in filesOrDirs) {
|
||||
VfsUtilCore.visitChildrenRecursively(file, object : VirtualFileVisitor<Unit>() {
|
||||
override fun visitFile(file: VirtualFile): Boolean {
|
||||
result.add(file)
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* 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.idea.inspections
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.codeInsight.intention.QuickFixFactory
|
||||
import com.intellij.openapi.project.Project
|
||||
|
||||
fun createAddToDependencyInjectionAnnotationsFix(project: Project, fqName: String): IntentionAction {
|
||||
return QuickFixFactory.getInstance().createAddToDependencyInjectionAnnotationsFix(project, fqName, "declarations")
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.js
|
||||
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.roots.CompilerModuleExtension
|
||||
import org.jetbrains.jps.util.JpsPathUtil
|
||||
import org.jetbrains.kotlin.analyzer.common.CommonPlatform
|
||||
import org.jetbrains.kotlin.idea.caches.project.implementingModules
|
||||
import org.jetbrains.kotlin.idea.facet.KotlinFacet
|
||||
import org.jetbrains.kotlin.idea.framework.isGradleModule
|
||||
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatform
|
||||
import org.jetbrains.plugins.gradle.settings.GradleSystemRunningSettings
|
||||
|
||||
val Module.jsTestOutputFilePath: String?
|
||||
get() {
|
||||
KotlinFacet.get(this)?.configuration?.settings?.testOutputPath?.let { return it }
|
||||
|
||||
if (!shouldUseJpsOutput) return null
|
||||
|
||||
val compilerExtension = CompilerModuleExtension.getInstance(this)
|
||||
val outputDir = compilerExtension?.compilerOutputUrlForTests ?: return null
|
||||
return JpsPathUtil.urlToPath("$outputDir/${name}_test.js")
|
||||
}
|
||||
|
||||
val Module.jsProductionOutputFilePath: String?
|
||||
get() {
|
||||
KotlinFacet.get(this)?.configuration?.settings?.productionOutputPath?.let { return it }
|
||||
|
||||
if (!shouldUseJpsOutput) return null
|
||||
|
||||
val compilerExtension = CompilerModuleExtension.getInstance(this)
|
||||
val outputDir = compilerExtension?.compilerOutputUrl ?: return null
|
||||
return JpsPathUtil.urlToPath("$outputDir/$name.js")
|
||||
}
|
||||
|
||||
fun Module.asJsModule(): Module? = when (TargetPlatformDetector.getPlatform(this)) {
|
||||
is CommonPlatform -> implementingModules.firstOrNull { TargetPlatformDetector.getPlatform(it) is JsPlatform }
|
||||
is JsPlatform -> this
|
||||
else -> null
|
||||
}
|
||||
|
||||
val Module.shouldUseJpsOutput: Boolean
|
||||
get() = !(isGradleModule() && GradleSystemRunningSettings.getInstance().isUseGradleAwareMake)
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.quickfix
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixActionRegistrarImpl
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.psi.PsiReferenceBase
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference.ShorteningMode
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||
import org.jetbrains.kotlin.idea.util.runWhenSmart
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElement
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
|
||||
object KotlinAddOrderEntryActionFactory : KotlinIntentionActionsFactory() {
|
||||
override fun doCreateActions(diagnostic: Diagnostic): List<IntentionAction> {
|
||||
val simpleExpression = diagnostic.psiElement as? KtSimpleNameExpression ?: return emptyList()
|
||||
val refElement = simpleExpression.getQualifiedElement()
|
||||
|
||||
val reference = object: PsiReferenceBase<KtElement>(refElement) {
|
||||
override fun resolve() = null
|
||||
|
||||
override fun getVariants() = PsiReference.EMPTY_ARRAY
|
||||
|
||||
override fun getRangeInElement(): TextRange? {
|
||||
val offset = simpleExpression.startOffset - refElement.startOffset
|
||||
return TextRange(offset, offset + simpleExpression.textLength)
|
||||
}
|
||||
|
||||
override fun getCanonicalText() = refElement.text
|
||||
|
||||
override fun bindToElement(element: PsiElement): PsiElement {
|
||||
val project = element.project
|
||||
project.runWhenSmart {
|
||||
project.executeWriteCommand("") {
|
||||
simpleExpression.mainReference.bindToElement(element, ShorteningMode.FORCED_SHORTENING)
|
||||
}
|
||||
}
|
||||
return element
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return OrderEntryFix.registerFixes(QuickFixActionRegistrarImpl(null), reference) as List<IntentionAction>? ?: emptyList()
|
||||
}
|
||||
}
|
||||
-410
@@ -1,410 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.quickfix.crossLanguage
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.codeInsight.intention.QuickFixFactory
|
||||
import com.intellij.lang.jvm.JvmClass
|
||||
import com.intellij.lang.jvm.JvmElement
|
||||
import com.intellij.lang.jvm.JvmModifier
|
||||
import com.intellij.lang.jvm.JvmModifiersOwner
|
||||
import com.intellij.lang.jvm.actions.*
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.codeStyle.SuggestedNameInfo
|
||||
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
|
||||
import org.jetbrains.kotlin.asJava.toLightMethods
|
||||
import org.jetbrains.kotlin.asJava.unwrapped
|
||||
import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.MutablePackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.core.appendModifier
|
||||
import org.jetbrains.kotlin.idea.quickfix.AddModifierFix
|
||||
import org.jetbrains.kotlin.idea.quickfix.RemoveModifierFix
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.*
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createCallable.CreateCallableFromUsageFix
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.util.approximateFlexibleTypes
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.load.java.components.TypeUsage
|
||||
import org.jetbrains.kotlin.load.java.lazy.JavaResolverComponents
|
||||
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
||||
import org.jetbrains.kotlin.load.java.lazy.TypeParameterResolver
|
||||
import org.jetbrains.kotlin.load.java.lazy.child
|
||||
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaTypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.load.java.lazy.types.JavaTypeAttributes
|
||||
import org.jetbrains.kotlin.load.java.lazy.types.JavaTypeResolver
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
|
||||
import org.jetbrains.kotlin.load.java.structure.impl.JavaTypeImpl
|
||||
import org.jetbrains.kotlin.load.java.structure.impl.JavaTypeParameterImpl
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
|
||||
import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.typeUtil.supertypes
|
||||
|
||||
class KotlinElementActionsFactory : JvmElementActionsFactory() {
|
||||
companion object {
|
||||
val javaPsiModifiersMapping = mapOf(
|
||||
JvmModifier.PRIVATE to KtTokens.PRIVATE_KEYWORD,
|
||||
JvmModifier.PUBLIC to KtTokens.PUBLIC_KEYWORD,
|
||||
JvmModifier.PROTECTED to KtTokens.PUBLIC_KEYWORD,
|
||||
JvmModifier.ABSTRACT to KtTokens.ABSTRACT_KEYWORD
|
||||
)
|
||||
}
|
||||
|
||||
private class FakeExpressionFromParameter(private val psiParam: PsiParameter) : PsiReferenceExpressionImpl() {
|
||||
override fun getText(): String = psiParam.name!!
|
||||
override fun getProject(): Project = psiParam.project
|
||||
override fun getParent(): PsiElement = psiParam.parent
|
||||
override fun getType(): PsiType? = psiParam.type
|
||||
override fun isValid(): Boolean = true
|
||||
override fun getContainingFile(): PsiFile = psiParam.containingFile
|
||||
override fun getReferenceName(): String? = psiParam.name
|
||||
override fun resolve(): PsiElement? = psiParam
|
||||
}
|
||||
|
||||
private class ModifierBuilder(
|
||||
private val targetContainer: KtElement,
|
||||
private val allowJvmStatic: Boolean = true
|
||||
) {
|
||||
private val psiFactory = KtPsiFactory(targetContainer.project)
|
||||
|
||||
val modifierList = psiFactory.createEmptyModifierList()
|
||||
|
||||
private fun JvmModifier.transformAndAppend(): Boolean {
|
||||
javaPsiModifiersMapping[this]?.let {
|
||||
modifierList.appendModifier(it)
|
||||
return true
|
||||
}
|
||||
|
||||
when (this) {
|
||||
JvmModifier.STATIC -> {
|
||||
if (allowJvmStatic && targetContainer is KtClassOrObject) {
|
||||
addAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME)
|
||||
}
|
||||
}
|
||||
JvmModifier.ABSTRACT -> modifierList.appendModifier(KtTokens.ABSTRACT_KEYWORD)
|
||||
JvmModifier.FINAL -> modifierList.appendModifier(KtTokens.FINAL_KEYWORD)
|
||||
else -> return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
var isValid = true
|
||||
private set
|
||||
|
||||
fun addJvmModifier(modifier: JvmModifier) {
|
||||
isValid = isValid && modifier.transformAndAppend()
|
||||
}
|
||||
|
||||
fun addJvmModifiers(modifiers: Iterable<JvmModifier>) {
|
||||
modifiers.forEach { addJvmModifier(it) }
|
||||
}
|
||||
|
||||
fun addAnnotation(fqName: FqName) {
|
||||
if (!isValid) return
|
||||
modifierList.add(psiFactory.createAnnotationEntry("@${fqName.asString()}"))
|
||||
}
|
||||
}
|
||||
|
||||
class CreatePropertyFix(
|
||||
private val targetClass: JvmClass,
|
||||
contextElement: KtElement,
|
||||
propertyInfo: PropertyInfo
|
||||
) : CreateCallableFromUsageFix<KtElement>(contextElement, listOf(propertyInfo)) {
|
||||
override fun getFamilyName() = "Add property"
|
||||
override fun getText(): String {
|
||||
val info = callableInfos.first() as PropertyInfo
|
||||
return buildString {
|
||||
append("Add '")
|
||||
if (info.isLateinitPreferred) {
|
||||
append("lateinit ")
|
||||
}
|
||||
append(if (info.writable) "var" else "val")
|
||||
append("' property '${info.name}' to '${targetClass.name}'")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun JvmClass.toKtClassOrFile(): KtElement? {
|
||||
val psi = sourceElement
|
||||
return when (psi) {
|
||||
is KtClassOrObject -> psi
|
||||
is KtLightClassForSourceDeclaration -> psi.kotlinOrigin
|
||||
is KtLightClassForFacade -> psi.files.firstOrNull()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified T : KtElement> JvmElement.toKtElement() = sourceElement?.unwrapped as? T
|
||||
|
||||
private fun fakeParametersExpressions(parameters: List<Pair<SuggestedNameInfo, List<ExpectedType>>>, project: Project): Array<PsiExpression>? =
|
||||
when {
|
||||
parameters.isEmpty() -> emptyArray()
|
||||
else -> JavaPsiFacade
|
||||
.getElementFactory(project)
|
||||
.createParameterList(
|
||||
parameters.map { it.first.names.firstOrNull() }.toTypedArray(),
|
||||
parameters.map { JvmPsiConversionHelper.getInstance(project).asPsiType(it) ?: return null }.toTypedArray()
|
||||
)
|
||||
.parameters
|
||||
.map(::FakeExpressionFromParameter)
|
||||
.toTypedArray()
|
||||
}
|
||||
|
||||
private fun PsiType.collectTypeParameters(): List<PsiTypeParameter> {
|
||||
val results = ArrayList<PsiTypeParameter>()
|
||||
accept(
|
||||
object : PsiTypeVisitor<Unit>() {
|
||||
override fun visitArrayType(arrayType: PsiArrayType) {
|
||||
arrayType.componentType.accept(this)
|
||||
}
|
||||
|
||||
override fun visitClassType(classType: PsiClassType) {
|
||||
(classType.resolve() as? PsiTypeParameter)?.let { results += it }
|
||||
classType.parameters.forEach { it.accept(this) }
|
||||
}
|
||||
|
||||
override fun visitWildcardType(wildcardType: PsiWildcardType) {
|
||||
wildcardType.bound?.accept(this)
|
||||
}
|
||||
}
|
||||
)
|
||||
return results
|
||||
}
|
||||
|
||||
private fun PsiType.resolveToKotlinType(resolutionFacade: ResolutionFacade): KotlinType? {
|
||||
val typeParameters = collectTypeParameters()
|
||||
val components = resolutionFacade.getFrontendService(JavaResolverComponents::class.java)
|
||||
val rootContext = LazyJavaResolverContext(components, TypeParameterResolver.EMPTY) { null }
|
||||
val dummyPackageDescriptor = MutablePackageFragmentDescriptor(resolutionFacade.moduleDescriptor, FqName("dummy"))
|
||||
val dummyClassDescriptor = ClassDescriptorImpl(
|
||||
dummyPackageDescriptor,
|
||||
Name.identifier("Dummy"),
|
||||
Modality.FINAL,
|
||||
ClassKind.CLASS,
|
||||
emptyList(),
|
||||
SourceElement.NO_SOURCE,
|
||||
false,
|
||||
LockBasedStorageManager.NO_LOCKS
|
||||
)
|
||||
val typeParameterResolver = object : TypeParameterResolver {
|
||||
override fun resolveTypeParameter(javaTypeParameter: JavaTypeParameter): TypeParameterDescriptor? {
|
||||
val psiTypeParameter = (javaTypeParameter as JavaTypeParameterImpl).psi
|
||||
val index = typeParameters.indexOf(psiTypeParameter)
|
||||
if (index < 0) return null
|
||||
return LazyJavaTypeParameterDescriptor(rootContext.child(this), javaTypeParameter, index, dummyClassDescriptor)
|
||||
}
|
||||
}
|
||||
val typeResolver = JavaTypeResolver(rootContext, typeParameterResolver)
|
||||
val attributes = JavaTypeAttributes(TypeUsage.COMMON)
|
||||
return typeResolver.transformJavaType(JavaTypeImpl.create(this), attributes).approximateFlexibleTypes(preferNotNull = true)
|
||||
}
|
||||
|
||||
private fun ExpectedTypes.toKotlinTypeInfo(resolutionFacade: ResolutionFacade): TypeInfo {
|
||||
val candidateTypes = flatMapTo(LinkedHashSet<KotlinType>()) {
|
||||
val ktType = (it.theType as? PsiType)?.resolveToKotlinType(resolutionFacade) ?: return@flatMapTo emptyList()
|
||||
when (it.theKind) {
|
||||
ExpectedType.Kind.EXACT, ExpectedType.Kind.SUBTYPE -> listOf(ktType)
|
||||
ExpectedType.Kind.SUPERTYPE -> listOf(ktType) + ktType.supertypes()
|
||||
}
|
||||
}
|
||||
if (candidateTypes.isEmpty()) {
|
||||
val nullableAnyType = resolutionFacade.moduleDescriptor.builtIns.nullableAnyType
|
||||
return TypeInfo(nullableAnyType, Variance.INVARIANT)
|
||||
}
|
||||
return TypeInfo.ByExplicitCandidateTypes(candidateTypes.toList())
|
||||
}
|
||||
|
||||
override fun createChangeModifierActions(target: JvmModifiersOwner, request: MemberRequest.Modifier): List<IntentionAction> {
|
||||
val kModifierOwner = target.toKtElement<KtModifierListOwner>() ?: return emptyList()
|
||||
|
||||
val modifier = request.modifier
|
||||
val shouldPresent = request.shouldPresent
|
||||
//TODO: make similar to `createAddMethodActions`
|
||||
val (kToken, shouldPresentMapped) = when {
|
||||
modifier == JvmModifier.FINAL -> KtTokens.OPEN_KEYWORD to !shouldPresent
|
||||
modifier == JvmModifier.PUBLIC && shouldPresent ->
|
||||
kModifierOwner.visibilityModifierType()
|
||||
?.takeIf { it != KtTokens.DEFAULT_VISIBILITY_KEYWORD }
|
||||
?.let { it to false } ?: return emptyList()
|
||||
else -> javaPsiModifiersMapping[modifier] to shouldPresent
|
||||
}
|
||||
if (kToken == null) return emptyList()
|
||||
|
||||
val action = if (shouldPresentMapped)
|
||||
AddModifierFix.createIfApplicable(kModifierOwner, kToken)
|
||||
else
|
||||
RemoveModifierFix(kModifierOwner, kToken, false)
|
||||
return listOfNotNull(action)
|
||||
}
|
||||
|
||||
override fun createAddConstructorActions(targetClass: JvmClass, request: CreateConstructorRequest): List<IntentionAction> {
|
||||
val targetKtClass = targetClass.toKtClassOrFile() as? KtClass ?: return emptyList()
|
||||
|
||||
val modifierBuilder = ModifierBuilder(targetKtClass).apply { addJvmModifiers(request.modifiers) }
|
||||
if (!modifierBuilder.isValid) return emptyList()
|
||||
val resolutionFacade = targetKtClass.getResolutionFacade()
|
||||
val nullableAnyType = resolutionFacade.moduleDescriptor.builtIns.nullableAnyType
|
||||
val helper = JvmPsiConversionHelper.getInstance(targetKtClass.project)
|
||||
val parameters = request.parameters as List<Pair<SuggestedNameInfo, List<ExpectedType>>>
|
||||
val parameterInfos = parameters.mapIndexed { index, param: Pair<SuggestedNameInfo, List<ExpectedType>> ->
|
||||
val ktType = helper.asPsiType(param)?.resolveToKotlinType(resolutionFacade) ?: nullableAnyType
|
||||
val name = param.first.names.firstOrNull() ?: "arg${index + 1}"
|
||||
ParameterInfo(TypeInfo(ktType, Variance.IN_VARIANCE), listOf(name))
|
||||
}
|
||||
val needPrimary = !targetKtClass.hasExplicitPrimaryConstructor()
|
||||
val constructorInfo = ConstructorInfo(
|
||||
parameterInfos,
|
||||
targetKtClass,
|
||||
isPrimary = needPrimary,
|
||||
modifierList = modifierBuilder.modifierList,
|
||||
withBody = true
|
||||
)
|
||||
val targetClassName = targetClass.name
|
||||
val addConstructorAction = object : CreateCallableFromUsageFix<KtElement>(targetKtClass, listOf(constructorInfo)) {
|
||||
override fun getFamilyName() = "Add method"
|
||||
override fun getText() = "Add ${if (needPrimary) "primary" else "secondary"} constructor to '$targetClassName'"
|
||||
}
|
||||
|
||||
val changePrimaryConstructorAction = run {
|
||||
val primaryConstructor = targetKtClass.primaryConstructor ?: return@run null
|
||||
val lightMethod = primaryConstructor.toLightMethods().firstOrNull() ?: return@run null
|
||||
val project = targetKtClass.project
|
||||
val fakeParametersExpressions = fakeParametersExpressions(parameters, project) ?: return@run null
|
||||
QuickFixFactory.getInstance()
|
||||
.createChangeMethodSignatureFromUsageFix(
|
||||
lightMethod,
|
||||
fakeParametersExpressions,
|
||||
PsiSubstitutor.EMPTY,
|
||||
targetKtClass,
|
||||
false,
|
||||
2
|
||||
).takeIf { it.isAvailable(project, null, targetKtClass.containingFile) }
|
||||
}
|
||||
|
||||
return listOfNotNull(changePrimaryConstructorAction, addConstructorAction)
|
||||
}
|
||||
|
||||
override fun createAddPropertyActions(targetClass: JvmClass, request: MemberRequest.Property): List<IntentionAction> {
|
||||
val targetContainer = targetClass.toKtClassOrFile() ?: return emptyList()
|
||||
|
||||
val modifierBuilder = ModifierBuilder(targetContainer).apply { addJvmModifier(request.visibilityModifier) }
|
||||
if (!modifierBuilder.isValid) return emptyList()
|
||||
|
||||
val resolutionFacade = targetContainer.getResolutionFacade()
|
||||
val nullableAnyType = resolutionFacade.moduleDescriptor.builtIns.nullableAnyType
|
||||
val ktType = (request.propertyType as? PsiType)?.resolveToKotlinType(resolutionFacade) ?: nullableAnyType
|
||||
val propertyInfo = PropertyInfo(
|
||||
request.propertyName,
|
||||
TypeInfo.Empty,
|
||||
TypeInfo(ktType, Variance.INVARIANT),
|
||||
request.setterRequired,
|
||||
listOf(targetContainer),
|
||||
modifierList = modifierBuilder.modifierList,
|
||||
withInitializer = true
|
||||
)
|
||||
val propertyInfos = if (request.setterRequired) {
|
||||
listOf(propertyInfo, propertyInfo.copyProperty(isLateinitPreferred = true))
|
||||
}
|
||||
else {
|
||||
listOf(propertyInfo)
|
||||
}
|
||||
return propertyInfos.map { CreatePropertyFix(targetClass, targetContainer, it) }
|
||||
}
|
||||
|
||||
override fun createAddFieldActions(targetClass: JvmClass, request: CreateFieldRequest): List<IntentionAction> {
|
||||
val targetContainer = targetClass.toKtClassOrFile() ?: return emptyList()
|
||||
|
||||
val modifierBuilder = ModifierBuilder(targetContainer, allowJvmStatic = false).apply {
|
||||
addJvmModifiers(request.modifiers)
|
||||
addAnnotation(JVM_FIELD_ANNOTATION_FQ_NAME)
|
||||
}
|
||||
if (!modifierBuilder.isValid) return emptyList()
|
||||
|
||||
val resolutionFacade = targetContainer.getResolutionFacade()
|
||||
val typeInfo = request.fieldType.toKotlinTypeInfo(resolutionFacade)
|
||||
val writable = JvmModifier.FINAL !in request.modifiers
|
||||
val propertyInfo = PropertyInfo(
|
||||
request.fieldName,
|
||||
TypeInfo.Empty,
|
||||
typeInfo,
|
||||
writable,
|
||||
listOf(targetContainer),
|
||||
isForCompanion = JvmModifier.STATIC in request.modifiers,
|
||||
modifierList = modifierBuilder.modifierList,
|
||||
withInitializer = true
|
||||
)
|
||||
val propertyInfos = if (writable) {
|
||||
listOf(propertyInfo, propertyInfo.copyProperty(isLateinitPreferred = true))
|
||||
}
|
||||
else {
|
||||
listOf(propertyInfo)
|
||||
}
|
||||
return propertyInfos.map { CreatePropertyFix(targetClass, targetContainer, it) }
|
||||
}
|
||||
|
||||
override fun createAddMethodActions(targetClass: JvmClass, request: CreateMethodRequest): List<IntentionAction> {
|
||||
val targetContainer = targetClass.toKtClassOrFile() ?: return emptyList()
|
||||
|
||||
val modifierBuilder = ModifierBuilder(targetContainer).apply { addJvmModifiers(request.modifiers) }
|
||||
if (!modifierBuilder.isValid) return emptyList()
|
||||
|
||||
val resolutionFacade = KotlinCacheService.getInstance(targetContainer.project)
|
||||
.getResolutionFacadeByFile(targetContainer.containingFile, JvmPlatform) ?: return emptyList()
|
||||
val returnTypeInfo = request.returnType.toKotlinTypeInfo(resolutionFacade)
|
||||
val parameters = request.parameters as List<Pair<SuggestedNameInfo, List<ExpectedType>>>
|
||||
val parameterInfos = parameters.map { (suggestedNames, expectedTypes) ->
|
||||
ParameterInfo(expectedTypes.toKotlinTypeInfo(resolutionFacade), suggestedNames.names.toList())
|
||||
}
|
||||
val methodName = request.methodName
|
||||
val functionInfo = FunctionInfo(
|
||||
methodName,
|
||||
TypeInfo.Empty,
|
||||
returnTypeInfo,
|
||||
listOf(targetContainer),
|
||||
parameterInfos,
|
||||
isForCompanion = JvmModifier.STATIC in request.modifiers,
|
||||
modifierList = modifierBuilder.modifierList,
|
||||
preferEmptyBody = true
|
||||
)
|
||||
val targetClassName = targetClass.name
|
||||
val action = object : CreateCallableFromUsageFix<KtElement>(targetContainer, listOf(functionInfo)) {
|
||||
override fun getFamilyName() = "Add method"
|
||||
override fun getText() = "Add method '$methodName' to '$targetClassName'"
|
||||
}
|
||||
return listOf(action)
|
||||
}
|
||||
}
|
||||
|
||||
private fun JvmPsiConversionHelper.asPsiType(param: Pair<SuggestedNameInfo, List<ExpectedType>>): PsiType? =
|
||||
param.second.firstOrNull()?.theType?.let { convertType(it) }
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.rename
|
||||
|
||||
import com.intellij.openapi.actionSystem.DataContext
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.refactoring.rename.RenameHandler
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import java.util.*
|
||||
|
||||
class KotlinRenameDispatcherHandler : RenameHandler {
|
||||
companion object {
|
||||
val EP_NAME = ExtensionPointName<RenameHandler>("org.jetbrains.kotlin.renameHandler")
|
||||
|
||||
private val handlers: Array<out RenameHandler> get() = Extensions.getExtensions(EP_NAME)
|
||||
}
|
||||
|
||||
internal fun getRenameHandler(dataContext: DataContext?): RenameHandler? {
|
||||
val availableHandlers = handlers.filterTo(LinkedHashSet()) { it.isRenaming(dataContext) }
|
||||
availableHandlers.singleOrNull()?.let { return it }
|
||||
availableHandlers.firstIsInstanceOrNull<KotlinMemberInplaceRenameHandler>()?.let { availableHandlers -= it }
|
||||
return availableHandlers.firstOrNull()
|
||||
}
|
||||
|
||||
override fun isAvailableOnDataContext(dataContext: DataContext?) = handlers.any { it.isAvailableOnDataContext(dataContext) }
|
||||
|
||||
override fun isRenaming(dataContext: DataContext?) = isAvailableOnDataContext(dataContext)
|
||||
|
||||
override fun invoke(project: Project, editor: Editor?, file: PsiFile?, dataContext: DataContext?) {
|
||||
getRenameHandler(dataContext)?.invoke(project, editor, file, dataContext)
|
||||
}
|
||||
|
||||
override fun invoke(project: Project, elements: Array<out PsiElement>, dataContext: DataContext?) {
|
||||
getRenameHandler(dataContext)?.invoke(project, elements, dataContext)
|
||||
}
|
||||
}
|
||||
-71
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-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.idea.refactoring.rename
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.refactoring.RefactoringActionHandler
|
||||
import com.intellij.refactoring.rename.inplace.VariableInplaceRenameHandler
|
||||
import com.intellij.refactoring.rename.inplace.VariableInplaceRenamer
|
||||
import org.jetbrains.kotlin.idea.core.unquote
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
open class KotlinVariableInplaceRenameHandler : VariableInplaceRenameHandler() {
|
||||
companion object {
|
||||
fun isInplaceRenameAvailable(element: PsiElement): Boolean {
|
||||
when (element) {
|
||||
is KtTypeParameter -> return true
|
||||
is KtDestructuringDeclarationEntry -> return true
|
||||
is KtParameter -> {
|
||||
val parent = element.parent
|
||||
if (parent is KtForExpression) {
|
||||
return true
|
||||
}
|
||||
if (parent is KtParameterList) {
|
||||
val grandparent = parent.parent
|
||||
return grandparent is KtCatchClause || grandparent is KtFunctionLiteral
|
||||
}
|
||||
}
|
||||
is KtLabeledExpression, is KtImportAlias -> return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
protected open class RenamerImpl : VariableInplaceRenamer {
|
||||
constructor(elementToRename: PsiNamedElement, editor: Editor): super(elementToRename, editor)
|
||||
constructor(
|
||||
elementToRename: PsiNamedElement,
|
||||
editor: Editor,
|
||||
currentName: String,
|
||||
oldName: String
|
||||
) : super(elementToRename, editor, editor.project, currentName, oldName)
|
||||
|
||||
override fun acceptReference(reference: PsiReference): Boolean {
|
||||
val refElement = reference.element
|
||||
val textRange = reference.rangeInElement
|
||||
val referenceText = refElement.text.substring(textRange.startOffset, textRange.endOffset).unquote()
|
||||
return referenceText == myElementToRename.name
|
||||
}
|
||||
|
||||
override fun startsOnTheSameElement(handler: RefactoringActionHandler?, element: PsiElement?): Boolean {
|
||||
return variable == element && (handler is VariableInplaceRenameHandler || handler is KotlinRenameDispatcherHandler)
|
||||
}
|
||||
|
||||
override fun createInplaceRenamerToRestart(variable: PsiNamedElement, editor: Editor, initialName: String): VariableInplaceRenamer {
|
||||
return RenamerImpl(variable, editor, initialName, myOldName)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createRenamer(elementToRename: PsiElement, editor: Editor): VariableInplaceRenamer? {
|
||||
val currentElementToRename = elementToRename as PsiNameIdentifierOwner
|
||||
val currentName = currentElementToRename.nameIdentifier?.text ?: ""
|
||||
return RenamerImpl(currentElementToRename, editor, currentName, currentName)
|
||||
}
|
||||
|
||||
override public fun isAvailable(element: PsiElement?, editor: Editor, file: PsiFile) =
|
||||
editor.settings.isVariableInplaceRenameEnabled && element != null && isInplaceRenameAvailable(element)
|
||||
}
|
||||
-45
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.rename
|
||||
|
||||
import com.intellij.openapi.actionSystem.DataContext
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
|
||||
class RenameBackingFieldReferenceHandler: KotlinVariableInplaceRenameHandler() {
|
||||
override fun isAvailable(element: PsiElement?, editor: Editor, file: PsiFile): Boolean {
|
||||
val refExpression = file.findElementForRename<KtSimpleNameExpression>(editor.caretModel.offset) ?: return false
|
||||
if (refExpression.text != "field") return false
|
||||
return refExpression.resolveToCall()?.resultingDescriptor is SyntheticFieldDescriptor
|
||||
}
|
||||
|
||||
override fun invoke(project: Project, editor: Editor?, file: PsiFile?, dataContext: DataContext) {
|
||||
editor?.let {
|
||||
CodeInsightUtils.showErrorHint(project, editor, "Rename is not applicable to backing field reference", "Rename", null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun invoke(project: Project, elements: Array<out PsiElement>, dataContext: DataContext) {
|
||||
// Do nothing: this method is called not from editor
|
||||
}
|
||||
}
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.rename
|
||||
|
||||
import com.intellij.openapi.actionSystem.DataContext
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic
|
||||
|
||||
class RenameDynamicMemberHandler: KotlinVariableInplaceRenameHandler() {
|
||||
override fun isAvailable(element: PsiElement?, editor: Editor, file: PsiFile): Boolean {
|
||||
val callee = PsiTreeUtil.findElementOfClassAtOffset(
|
||||
file, editor.caretModel.offset, KtSimpleNameExpression::class.java, false
|
||||
) ?: return false
|
||||
val calleeDescriptor = callee.resolveToCall()?.resultingDescriptor ?: return false
|
||||
return calleeDescriptor.isDynamic()
|
||||
}
|
||||
|
||||
override fun invoke(project: Project, editor: Editor?, file: PsiFile?, dataContext: DataContext) {
|
||||
super.invoke(project, editor, file, dataContext)
|
||||
editor?.let {
|
||||
CodeInsightUtils.showErrorHint(project, editor, "Rename is not applicable to dynamically invoked members", "Rename", null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun invoke(project: Project, elements: Array<out PsiElement>, dataContext: DataContext) {
|
||||
// Do nothing: this method is called not from editor
|
||||
}
|
||||
}
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.rename
|
||||
|
||||
import com.intellij.openapi.actionSystem.DataContext
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.idea.intentions.ReplaceItWithExplicitFunctionLiteralParamIntention
|
||||
import org.jetbrains.kotlin.idea.intentions.isAutoCreatedItUsage
|
||||
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||
|
||||
class RenameKotlinImplicitLambdaParameter : KotlinVariableInplaceRenameHandler() {
|
||||
override fun isAvailable(element: PsiElement?, editor: Editor, file: PsiFile): Boolean {
|
||||
val nameExpression = file.findElementForRename<KtNameReferenceExpression>(editor.caretModel.offset)
|
||||
|
||||
return nameExpression != null && isAutoCreatedItUsage(nameExpression)
|
||||
}
|
||||
|
||||
override fun invoke(project: Project, editor: Editor?, file: PsiFile?, dataContext: DataContext) {
|
||||
val intention = ReplaceItWithExplicitFunctionLiteralParamIntention()
|
||||
project.executeWriteCommand("Convert 'it' to explicit lambda parameter") {
|
||||
file?.let {
|
||||
intention.invoke(project, editor, file)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun invoke(project: Project, elements: Array<out PsiElement>, dataContext: DataContext) {
|
||||
// Do nothing: this method is called not from editor
|
||||
}
|
||||
}
|
||||
-54
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.rename
|
||||
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||
import com.intellij.openapi.actionSystem.DataContext
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.refactoring.rename.RenameHandler
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
|
||||
class RenameOnSecondaryConstructorHandler : RenameHandler {
|
||||
override fun isAvailableOnDataContext(dataContext: DataContext?): Boolean {
|
||||
if (dataContext == null) return false
|
||||
|
||||
val editor = CommonDataKeys.EDITOR.getData(dataContext) ?: return false
|
||||
val file = CommonDataKeys.PSI_FILE.getData(dataContext) ?: return false
|
||||
|
||||
val element = PsiTreeUtil.findElementOfClassAtOffsetWithStopSet(
|
||||
file, editor.caretModel.offset, KtSecondaryConstructor::class.java, false,
|
||||
KtBlockExpression::class.java, KtValueArgumentList::class.java, KtParameterList::class.java, KtConstructorDelegationCall::class.java
|
||||
)
|
||||
return element != null
|
||||
}
|
||||
|
||||
override fun isRenaming(dataContext: DataContext?): Boolean = isAvailableOnDataContext(dataContext)
|
||||
|
||||
override fun invoke(project: Project, editor: Editor, file: PsiFile, dataContext: DataContext?) {
|
||||
CodeInsightUtils.showErrorHint(project, editor, "Rename is not applicable to secondary constructors", "Rename", null)
|
||||
}
|
||||
|
||||
override fun invoke(project: Project, elements: Array<out PsiElement>, dataContext: DataContext?) {
|
||||
// Do nothing: this method is called not from editor
|
||||
}
|
||||
}
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-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.idea.refactoring.rename
|
||||
|
||||
import org.jetbrains.kotlin.idea.statistics.KotlinStatisticsTrigger
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||
import com.intellij.openapi.actionSystem.DataContext
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.refactoring.rename.RenameHandler
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.isSynthesized
|
||||
import org.jetbrains.kotlin.idea.statistics.KotlinEventTrigger
|
||||
|
||||
class RenameSyntheticDeclarationByReferenceHandler : RenameHandler {
|
||||
override fun isAvailableOnDataContext(dataContext: DataContext?): Boolean {
|
||||
if (dataContext == null) return false
|
||||
val file = CommonDataKeys.PSI_FILE.getData(dataContext) ?: return false
|
||||
val editor = CommonDataKeys.EDITOR.getData(dataContext) ?: return false
|
||||
val refExpression = file.findElementForRename<KtSimpleNameExpression>(editor.caretModel.offset) ?: return false
|
||||
return (refExpression.resolveToCall()?.resultingDescriptor)?.isSynthesized ?: false
|
||||
}
|
||||
|
||||
override fun isRenaming(dataContext: DataContext?) = isAvailableOnDataContext(dataContext)
|
||||
|
||||
override fun invoke(project: Project, editor: Editor, file: PsiFile, dataContext: DataContext?) {
|
||||
CodeInsightUtils.showErrorHint(project, editor, "Rename is not applicable to synthetic declaration", "Rename", null)
|
||||
KotlinStatisticsTrigger.trigger(KotlinEventTrigger.KotlinIdeRefactoringTrigger, this::class.java.name)
|
||||
}
|
||||
|
||||
override fun invoke(project: Project, elements: Array<out PsiElement>, dataContext: DataContext?) {
|
||||
// Do nothing: this method is not called from editor
|
||||
}
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.slicer
|
||||
|
||||
import com.intellij.analysis.AnalysisScope
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.wm.ToolWindowId
|
||||
import com.intellij.openapi.wm.ToolWindowManager
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.slicer.DuplicateMap
|
||||
import com.intellij.slicer.SliceAnalysisParams
|
||||
import com.intellij.slicer.SlicePanel
|
||||
import com.intellij.slicer.SliceRootNode
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import com.intellij.usageView.UsageViewBundle
|
||||
import com.intellij.usages.PsiElementUsageTarget
|
||||
import com.intellij.usages.UsageContextPanel
|
||||
import com.intellij.usages.UsageView
|
||||
import com.intellij.usages.UsageViewPresentation
|
||||
import com.intellij.usages.impl.UsageContextPanelBase
|
||||
import com.intellij.usages.impl.UsageViewImpl
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import java.awt.BorderLayout
|
||||
import javax.swing.JLabel
|
||||
import javax.swing.JPanel
|
||||
import javax.swing.SwingConstants
|
||||
|
||||
sealed class KotlinUsageContextDataFlowPanelBase(
|
||||
project: Project,
|
||||
presentation: UsageViewPresentation,
|
||||
private val isInflow: Boolean
|
||||
) : UsageContextPanelBase(project, presentation) {
|
||||
private var panel: JPanel? = null
|
||||
|
||||
abstract class ProviderBase : UsageContextPanel.Provider {
|
||||
override fun isAvailableFor(usageView: UsageView): Boolean {
|
||||
val target = (usageView as UsageViewImpl).targets.firstOrNull() ?: return false
|
||||
val element = (target as? PsiElementUsageTarget)?.element
|
||||
return element is KtDeclaration && element.isValid
|
||||
}
|
||||
}
|
||||
|
||||
private fun createParams(element: PsiElement): SliceAnalysisParams {
|
||||
return SliceAnalysisParams().apply {
|
||||
scope = AnalysisScope(element.project)
|
||||
dataFlowToThis = isInflow
|
||||
showInstanceDereferences = true
|
||||
}
|
||||
}
|
||||
|
||||
protected fun createPanel(element: PsiElement, dataFlowToThis: Boolean): JPanel {
|
||||
val toolWindow = ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.FIND)
|
||||
val params = createParams(element)
|
||||
|
||||
val rootNode = SliceRootNode(myProject, DuplicateMap(), KotlinSliceUsage(element, params))
|
||||
|
||||
return object : SlicePanel(myProject, dataFlowToThis, rootNode, false, toolWindow) {
|
||||
override fun isToShowAutoScrollButton() = false
|
||||
|
||||
override fun isToShowPreviewButton() = false
|
||||
|
||||
override fun isToShowCloseButton() = false
|
||||
|
||||
override fun isAutoScroll() = false
|
||||
|
||||
override fun setAutoScroll(autoScroll: Boolean) {}
|
||||
|
||||
override fun isPreview() = false
|
||||
|
||||
override fun setPreview(preview: Boolean) {}
|
||||
}
|
||||
}
|
||||
|
||||
public override fun updateLayoutLater(infos: List<UsageInfo>?) {
|
||||
if (infos == null) {
|
||||
removeAll()
|
||||
val title = UsageViewBundle.message("select.the.usage.to.preview", myPresentation.usagesWord)
|
||||
add(JLabel(title, SwingConstants.CENTER), BorderLayout.CENTER)
|
||||
}
|
||||
else {
|
||||
val element = infos.firstOrNull()?.element ?: return
|
||||
if (panel != null) {
|
||||
Disposer.dispose(panel as Disposable)
|
||||
}
|
||||
|
||||
val panel = createPanel(element, isInflow)
|
||||
Disposer.register(this, panel as Disposable)
|
||||
removeAll()
|
||||
add(panel, BorderLayout.CENTER)
|
||||
this.panel = panel
|
||||
}
|
||||
revalidate()
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
super.dispose()
|
||||
panel = null
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinUsageContextDataInflowPanel(
|
||||
project: Project,
|
||||
presentation: UsageViewPresentation
|
||||
) : KotlinUsageContextDataFlowPanelBase(project, presentation, true) {
|
||||
class Provider : ProviderBase() {
|
||||
override fun create(usageView: UsageView): UsageContextPanel {
|
||||
return KotlinUsageContextDataInflowPanel((usageView as UsageViewImpl).project, usageView.getPresentation())
|
||||
}
|
||||
|
||||
override fun getTabTitle() = "Dataflow to Here"
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinUsageContextDataOutflowPanel(
|
||||
project: Project,
|
||||
presentation: UsageViewPresentation
|
||||
) : KotlinUsageContextDataFlowPanelBase(project, presentation, false) {
|
||||
class Provider : ProviderBase() {
|
||||
override fun create(usageView: UsageView): UsageContextPanel {
|
||||
return KotlinUsageContextDataOutflowPanel((usageView as UsageViewImpl).project, usageView.getPresentation())
|
||||
}
|
||||
|
||||
override fun getTabTitle() = "Dataflow from Here"
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.idea.util
|
||||
|
||||
import com.intellij.openapi.ui.popup.PopupChooserBuilder
|
||||
import javax.swing.JList
|
||||
|
||||
// BUNCH: 181
|
||||
@Suppress("IncompatibleAPI")
|
||||
class PopupChooserBuilderWrapper<T>(list: JList<T>) : PopupChooserBuilder(list)
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.
|
||||
*/
|
||||
|
||||
@file:Suppress("MissingRecentApi", "IncompatibleAPI")
|
||||
|
||||
package org.jetbrains.kotlin.idea.util.compat
|
||||
|
||||
import com.intellij.codeInspection.dataFlow.Nullness
|
||||
import com.intellij.codeInspection.dataFlow.DfaUtil
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.psi.PsiVariable
|
||||
import com.intellij.slicer.SliceLanguageSupportProvider
|
||||
import com.intellij.slicer.SliceLeafEquality
|
||||
import com.intellij.slicer.SliceNullnessAnalyzerBase
|
||||
|
||||
// BUNCH: 181
|
||||
typealias Nullability = Nullness
|
||||
|
||||
// BUNCH: 181
|
||||
fun dfaCheckNullability(variable: PsiVariable?, context: PsiElement?): Nullability =
|
||||
DfaUtil.checkNullness(variable, context)
|
||||
|
||||
// BUNCH: 181
|
||||
fun dfaInferMethodNullability(method: PsiMethod): Nullability =
|
||||
DfaUtil.inferMethodNullity(method)
|
||||
|
||||
// BUNCH: 181
|
||||
abstract class SliceNullnessAnalyzerBaseEx(
|
||||
leafEquality: SliceLeafEquality,
|
||||
provider: SliceLanguageSupportProvider
|
||||
) : SliceNullnessAnalyzerBase(leafEquality, provider) {
|
||||
override fun checkNullness(element: PsiElement?): Nullability {
|
||||
return checkNullabilityEx(element)
|
||||
}
|
||||
|
||||
abstract fun checkNullabilityEx(element: PsiElement?): Nullability
|
||||
}
|
||||
-193
@@ -1,193 +0,0 @@
|
||||
// INSPECTION_CLASS: com.android.tools.idea.lint.AndroidLintDrawAllocationInspection
|
||||
// INSPECTION_CLASS2: com.android.tools.idea.lint.AndroidLintUseSparseArraysInspection
|
||||
// INSPECTION_CLASS3: com.android.tools.idea.lint.AndroidLintUseValueOfInspection
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import java.util.HashMap
|
||||
import android.content.Context
|
||||
import android.graphics.*
|
||||
import android.util.AttributeSet
|
||||
import android.util.SparseArray
|
||||
import android.widget.Button
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Suppress("UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION", "UNNECESSARY_NOT_NULL_ASSERTION", "NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
|
||||
class JavaPerformanceTest(context: Context, attrs: AttributeSet, defStyle: Int) : Button(context, attrs, defStyle) {
|
||||
|
||||
private var cachedRect: Rect? = null
|
||||
private var shader: LinearGradient? = null
|
||||
private var lastHeight: Int = 0
|
||||
private var lastWidth: Int = 0
|
||||
|
||||
override fun onDraw(canvas: android.graphics.Canvas) {
|
||||
super.onDraw(canvas)
|
||||
|
||||
// Various allocations:
|
||||
<warning descr="Avoid object allocations during draw/layout operations (preallocate and reuse instead)">java.lang.String("foo")</warning>
|
||||
val s = <warning descr="Avoid object allocations during draw/layout operations (preallocate and reuse instead)">java.lang.String("bar")</warning>
|
||||
|
||||
// This one should not be reported:
|
||||
@SuppressLint("DrawAllocation")
|
||||
val i = 5
|
||||
|
||||
// Cached object initialized lazily: should not complain about these
|
||||
if (cachedRect == null) {
|
||||
cachedRect = Rect(0, 0, 100, 100)
|
||||
}
|
||||
if (cachedRect == null || cachedRect!!.width() != 50) {
|
||||
cachedRect = Rect(0, 0, 50, 100)
|
||||
}
|
||||
|
||||
val b = java.lang.Boolean.valueOf(true)!! // auto-boxing
|
||||
dummy(1, 2)
|
||||
|
||||
// Non-allocations
|
||||
super.animate()
|
||||
dummy2(1, 2)
|
||||
|
||||
// This will involve allocations, but we don't track
|
||||
// inter-procedural stuff here
|
||||
someOtherMethod()
|
||||
}
|
||||
|
||||
internal fun dummy(foo: Int?, bar: Int) {
|
||||
dummy2(foo!!, bar)
|
||||
}
|
||||
|
||||
internal fun dummy2(foo: Int, bar: Int) {
|
||||
}
|
||||
|
||||
internal fun someOtherMethod() {
|
||||
// Allocations are okay here
|
||||
java.lang.String("foo")
|
||||
val s = java.lang.String("bar")
|
||||
val b = java.lang.Boolean.valueOf(true)!! // auto-boxing
|
||||
|
||||
|
||||
// Sparse array candidates
|
||||
val myMap = <warning descr="Use `new SparseArray<String>(...)` instead for better performance">HashMap<Int, String>()</warning>
|
||||
// Should use SparseBooleanArray
|
||||
val myBoolMap = <warning descr="Use `new SparseBooleanArray(...)` instead for better performance">HashMap<Int, Boolean>()</warning>
|
||||
// Should use SparseIntArray
|
||||
val myIntMap = <warning descr="Use new `SparseIntArray(...)` instead for better performance">java.util.HashMap<Int, Int>()</warning>
|
||||
|
||||
// This one should not be reported:
|
||||
@SuppressLint("UseSparseArrays")
|
||||
val myOtherMap = <warning descr="Use `new SparseArray<Object>(...)` instead for better performance">HashMap<Int, Any>()</warning>
|
||||
}
|
||||
|
||||
protected fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int,
|
||||
x: Boolean) {
|
||||
// wrong signature
|
||||
java.lang.String("not an error")
|
||||
}
|
||||
|
||||
protected fun onMeasure(widthMeasureSpec: Int) {
|
||||
// wrong signature
|
||||
java.lang.String("not an error")
|
||||
}
|
||||
|
||||
protected fun onLayout(changed: Boolean, left: Int, top: Int, right: Int,
|
||||
bottom: Int, wrong: Int) {
|
||||
// wrong signature
|
||||
java.lang.String("not an error")
|
||||
}
|
||||
|
||||
protected fun onLayout(changed: Boolean, left: Int, top: Int, right: Int) {
|
||||
// wrong signature
|
||||
java.lang.String("not an error")
|
||||
}
|
||||
|
||||
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int,
|
||||
bottom: Int) {
|
||||
<warning descr="Avoid object allocations during draw/layout operations (preallocate and reuse instead)">java.lang.String("flag me")</warning>
|
||||
}
|
||||
|
||||
@SuppressWarnings("null") // not real code
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
<warning descr="Avoid object allocations during draw/layout operations (preallocate and reuse instead)">java.lang.String("flag me")</warning>
|
||||
|
||||
// Forbidden factory methods:
|
||||
<warning descr="Avoid object allocations during draw/layout operations (preallocate and reuse instead)">Bitmap.createBitmap(100, 100, null)</warning>
|
||||
<warning descr="Avoid object allocations during draw/layout operations (preallocate and reuse instead)">android.graphics.Bitmap.createScaledBitmap(null, 100, 100, false)</warning>
|
||||
<warning descr="Avoid object allocations during draw/layout operations (preallocate and reuse instead)">BitmapFactory.decodeFile(null)</warning>
|
||||
val canvas: Canvas? = null
|
||||
<warning descr="Avoid object allocations during draw operations: Use `Canvas.getClipBounds(Rect)` instead of `Canvas.getClipBounds()` which allocates a temporary `Rect`">canvas!!.getClipBounds()</warning> // allocates on your behalf
|
||||
<warning descr="Avoid object allocations during draw operations: Use `Canvas.getClipBounds(Rect)` instead of `Canvas.getClipBounds()` which allocates a temporary `Rect`">canvas.clipBounds</warning> // allocates on your behalf
|
||||
canvas.getClipBounds(null) // NOT an error
|
||||
|
||||
val layoutWidth = width
|
||||
val layoutHeight = height
|
||||
if (mAllowCrop && (mOverlay == null || mOverlay!!.width != layoutWidth ||
|
||||
mOverlay!!.height != layoutHeight)) {
|
||||
mOverlay = Bitmap.createBitmap(layoutWidth, layoutHeight, Bitmap.Config.ARGB_8888)
|
||||
mOverlayCanvas = Canvas(mOverlay!!)
|
||||
}
|
||||
|
||||
if (widthMeasureSpec == 42) {
|
||||
throw IllegalStateException("Test") // NOT an allocation
|
||||
}
|
||||
|
||||
// More lazy init tests
|
||||
var initialized = false
|
||||
if (!initialized) {
|
||||
java.lang.String("foo")
|
||||
initialized = true
|
||||
}
|
||||
|
||||
// NOT lazy initialization
|
||||
if (!initialized || mOverlay == null) {
|
||||
<warning descr="Avoid object allocations during draw/layout operations (preallocate and reuse instead)">java.lang.String("foo")</warning>
|
||||
}
|
||||
}
|
||||
|
||||
internal fun factories() {
|
||||
val i1 = 42
|
||||
val l1 = 42L
|
||||
val b1 = true
|
||||
val c1 = 'c'
|
||||
val f1 = 1.0f
|
||||
val d1 = 1.0
|
||||
|
||||
// The following should not generate errors:
|
||||
val i3 = Integer.valueOf(42)
|
||||
}
|
||||
|
||||
private val mAllowCrop: Boolean = false
|
||||
private var mOverlayCanvas: Canvas? = null
|
||||
private var mOverlay: Bitmap? = null
|
||||
|
||||
override fun layout(l: Int, t: Int, r: Int, b: Int) {
|
||||
// Using "this." to reference fields
|
||||
if (this.shader == null)
|
||||
this.shader = LinearGradient(0f, 0f, width.toFloat(), 0f, intArrayOf(0), null,
|
||||
Shader.TileMode.REPEAT)
|
||||
|
||||
val width = width
|
||||
val height = height
|
||||
|
||||
if (shader == null || lastWidth != width || lastHeight != height) {
|
||||
lastWidth = width
|
||||
lastHeight = height
|
||||
|
||||
shader = LinearGradient(0f, 0f, width.toFloat(), 0f, intArrayOf(0), null, Shader.TileMode.REPEAT)
|
||||
}
|
||||
}
|
||||
|
||||
fun inefficientSparseArray() {
|
||||
<warning descr="Use `new SparseIntArray(...)` instead for better performance">SparseArray<Int>()</warning> // Use SparseIntArray instead
|
||||
SparseArray<Long>() // Use SparseLongArray instead
|
||||
<warning descr="Use `new SparseBooleanArray(...)` instead for better performance">SparseArray<Boolean>()</warning> // Use SparseBooleanArray instead
|
||||
SparseArray<Any>() // OK
|
||||
}
|
||||
|
||||
fun longSparseArray() {
|
||||
// but only minSdkVersion >= 17 or if has v4 support lib
|
||||
val myStringMap = HashMap<Long, String>()
|
||||
}
|
||||
|
||||
fun byteSparseArray() {
|
||||
// bytes easily apply to ints
|
||||
val myByteMap = <warning descr="Use `new SparseArray<String>(...)` instead for better performance">HashMap<Byte, String>()</warning>
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
// ALLOW_MULTIPLE_EXPRESSIONS
|
||||
fun bar(x: (Int) -> String) = x(1)
|
||||
fun foo() {
|
||||
val bar = bar() { y: Int -> "abc" }
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
LineBreakpoint created at smartStepIntoInlinedFunLiteral.kt:6
|
||||
Run Java
|
||||
Connected to the target VM
|
||||
smartStepIntoInlinedFunLiteral.kt:6
|
||||
smartStepIntoInlinedFunLiteral.kt:11
|
||||
smartStepIntoInlinedFunLiteral.kt:12
|
||||
smartStepIntoInlinedFunLiteral.kt:17
|
||||
smartStepIntoInlinedFunLiteral.kt:18
|
||||
smartStepIntoInlinedFunLiteral.kt:1
|
||||
Disconnected from the target VM
|
||||
|
||||
Process finished with exit code 0
|
||||
Vendored
-12
@@ -1,12 +0,0 @@
|
||||
LineBreakpoint created at smartStepIntoInlinedFunctionalExpression.kt:6
|
||||
Run Java
|
||||
Connected to the target VM
|
||||
smartStepIntoInlinedFunctionalExpression.kt:6
|
||||
smartStepIntoInlinedFunctionalExpression.kt:11
|
||||
smartStepIntoInlinedFunctionalExpression.kt:12
|
||||
smartStepIntoInlinedFunctionalExpression.kt:17
|
||||
smartStepIntoInlinedFunctionalExpression.kt:18
|
||||
smartStepIntoInlinedFunctionalExpression.kt:1
|
||||
Disconnected from the target VM
|
||||
|
||||
Process finished with exit code 0
|
||||
@@ -1,8 +0,0 @@
|
||||
fun testing() {
|
||||
<caret>SomeClass<List<String>>()
|
||||
}
|
||||
|
||||
//INFO: <div class='definition'><pre>public class <b>SomeClass</b><T extends <a href="psi_element://java.util.List"><code>List</code></a>>
|
||||
//INFO: extends <a href="psi_element://java.lang.Object"><code>Object</code></a></pre></div><div class='content'>
|
||||
//INFO: Some Java Class
|
||||
//INFO: </div><table class='sections'><p><tr><td valign='top' class='section'><p>Type parameters:</td><td><T> – </td></table>
|
||||
@@ -1,9 +0,0 @@
|
||||
class A : OverrideMe() {
|
||||
override fun <caret>overrideMe() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//INFO: <div class='definition'><pre><a href="psi_element://A"><code>A</code></a><br>protected open fun <b>overrideMe</b>(): Unit</pre></div></pre></div><table class='sections'><p><tr><td valign='top' class='section'><p>Description copied from class:</td><td><p><a href="psi_element://OverrideMe"><code>OverrideMe</code></a><br>
|
||||
//INFO: Some comment
|
||||
//INFO: </td><tr><td valign='top' class='section'><p>Overrides:</td><td><p><a href="psi_element://OverrideMe#overrideMe()"><code>overrideMe</code></a> in class <a href="psi_element://OverrideMe"><code>OverrideMe</code></a></td></table>
|
||||
@@ -1,9 +0,0 @@
|
||||
class A : OverrideMe {
|
||||
override fun <caret>overrideMe() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//INFO: <div class='definition'><pre><a href="psi_element://A"><code>A</code></a><br>public open fun <b>overrideMe</b>(): Unit</pre></div></pre></div><table class='sections'><p><tr><td valign='top' class='section'><p>Description copied from interface:</td><td><p><a href="psi_element://OverrideMe"><code>OverrideMe</code></a><br>
|
||||
//INFO: Some comment
|
||||
//INFO: </td><tr><td valign='top' class='section'><p>Specified by:</td><td><p><a href="psi_element://OverrideMe#overrideMe()"><code>overrideMe</code></a> in interface <a href="psi_element://OverrideMe"><code>OverrideMe</code></a></td></table>
|
||||
@@ -1,9 +0,0 @@
|
||||
fun ktTest() {
|
||||
Test.<caret>foo("SomeTest")
|
||||
}
|
||||
|
||||
//INFO: <div class='definition'><pre><a href="psi_element://Test"><code>Test</code></a><br><i>@Contract(pure = true)</i>
|
||||
//INFO: <i>@<a href="psi_element://org.jetbrains.annotations.NotNull"><code>NotNull</code></a></i>
|
||||
//INFO: public static <a href="psi_element://java.lang.Object"><code>Object</code></a>[] <b>foo</b>(<a href="psi_element://java.lang.String"><code>String</code></a> param)</pre></div><div class='content'>
|
||||
//INFO: Java Method
|
||||
//INFO: <p></div><table class='sections'><p><tr><td valign='top' class='section'><p><i>Inferred</i> annotations:</td><td><p><i>@org.jetbrains.annotations.Contract(pure = true)</i> <i>@<a href="psi_element://org.jetbrains.annotations.NotNull"><code>org.jetbrains.annotations.NotNull</code></a></i></td></table>
|
||||
@@ -1,12 +0,0 @@
|
||||
enum class E {
|
||||
A
|
||||
}
|
||||
|
||||
fun use() {
|
||||
E.valueOf<caret>("A")
|
||||
}
|
||||
|
||||
|
||||
//INFO: <div class='definition'><pre><a href="psi_element://E"><code>E</code></a><br>public final fun <b>valueOf</b>(
|
||||
//INFO: value: String
|
||||
//INFO: ): <a href="psi_element://E">E</a></pre></div><div class='content'><p>Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)</p></div><table class='sections'><tr><td valign='top' class='section'><p>Throws:</td><td><p><code>IllegalArgumentException</code> - if this enum type has no constant with the specified name</td></table>
|
||||
@@ -1,18 +0,0 @@
|
||||
package test
|
||||
|
||||
/**
|
||||
|
||||
*
|
||||
*
|
||||
* Test function
|
||||
|
||||
*
|
||||
* @param first Some
|
||||
* @param second Other
|
||||
*/
|
||||
fun <caret>testFun(first: String, second: Int) = 12
|
||||
|
||||
//INFO: <div class='definition'><pre><a href="psi_element://test"><code>test</code></a> <font color="808080"><i>OnFunctionDeclarationWithPackage.kt</i></font><br>public fun <b>testFun</b>(
|
||||
//INFO: first: String,
|
||||
//INFO: second: Int
|
||||
//INFO: ): Int</pre></div><div class='content'><p>Test function</p></div><table class='sections'><tr><td valign='top' class='section'><p>Params:</td><td><p><code>first</code> - Some<p><code>second</code> - Other</td></table>
|
||||
@@ -1,18 +0,0 @@
|
||||
/**
|
||||
Some documentation
|
||||
|
||||
* @param a Some int
|
||||
* @param b String
|
||||
*/
|
||||
fun testMethod(a: Int, b: String) {
|
||||
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>testMethod(1, "value")
|
||||
}
|
||||
|
||||
//INFO: <div class='definition'><pre><font color="808080"><i>OnMethodUsage.kt</i></font><br>public fun <b>testMethod</b>(
|
||||
//INFO: a: Int,
|
||||
//INFO: b: String
|
||||
//INFO: ): Unit</pre></div><div class='content'><p>Some documentation</p></div><table class='sections'><tr><td valign='top' class='section'><p>Params:</td><td><p><code>a</code> - Some int<p><code>b</code> - String</td></table>
|
||||
@@ -1,18 +0,0 @@
|
||||
/**
|
||||
Some documentation
|
||||
|
||||
* @param[a] Some int
|
||||
* @param[b] String
|
||||
*/
|
||||
fun testMethod(a: Int, b: String) {
|
||||
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>testMethod(1, "value")
|
||||
}
|
||||
|
||||
//INFO: <div class='definition'><pre><font color="808080"><i>OnMethodUsageWithBracketsInParam.kt</i></font><br>public fun <b>testMethod</b>(
|
||||
//INFO: a: Int,
|
||||
//INFO: b: String
|
||||
//INFO: ): Unit</pre></div><div class='content'><p>Some documentation</p></div><table class='sections'><tr><td valign='top' class='section'><p>Params:</td><td><p><code>a</code> - Some int<p><code>b</code> - String</td></table>
|
||||
@@ -1,17 +0,0 @@
|
||||
/**
|
||||
* Some documentation
|
||||
* on two lines.
|
||||
*
|
||||
* @param test String
|
||||
* on two lines
|
||||
*/
|
||||
fun testMethod(test: String) {
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>testMethod("")
|
||||
}
|
||||
|
||||
//INFO: <div class='definition'><pre><font color="808080"><i>OnMethodUsageWithMultilineParam.kt</i></font><br>public fun <b>testMethod</b>(
|
||||
//INFO: test: String
|
||||
//INFO: ): Unit</pre></div><div class='content'><p>Some documentation on two lines.</p></div><table class='sections'><tr><td valign='top' class='section'><p>Params:</td><td><p><code>test</code> - String on two lines</td></table>
|
||||
@@ -1,18 +0,0 @@
|
||||
/**
|
||||
Some documentation
|
||||
|
||||
* @receiver Some int
|
||||
* @param b String
|
||||
* @return Return [a] and nothing else
|
||||
*/
|
||||
fun Int.testMethod(b: String) {
|
||||
|
||||
}
|
||||
|
||||
fun test() {
|
||||
1.<caret>testMethod("value")
|
||||
}
|
||||
|
||||
//INFO: <div class='definition'><pre><font color="808080"><i>OnMethodUsageWithReceiver.kt</i></font><br>public fun Int.<b>testMethod</b>(
|
||||
//INFO: b: String
|
||||
//INFO: ): Unit</pre></div><div class='content'><p>Some documentation</p></div><table class='sections'><tr><td valign='top' class='section'><p>Receiver:</td><td>Some int</td><tr><td valign='top' class='section'><p>Params:</td><td><p><code>b</code> - String</td><tr><td valign='top' class='section'><p>Returns:</td><td>Return <a href="psi_element://a">a</a> and nothing else</td></table>
|
||||
@@ -1,19 +0,0 @@
|
||||
/**
|
||||
Some documentation
|
||||
|
||||
* @param a Some int
|
||||
* @param b String
|
||||
* @return Return [a] and nothing else
|
||||
*/
|
||||
fun testMethod(a: Int, b: String) {
|
||||
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>testMethod(1, "value")
|
||||
}
|
||||
|
||||
//INFO: <div class='definition'><pre><font color="808080"><i>OnMethodUsageWithReturnAndLink.kt</i></font><br>public fun <b>testMethod</b>(
|
||||
//INFO: a: Int,
|
||||
//INFO: b: String
|
||||
//INFO: ): Unit</pre></div><div class='content'><p>Some documentation</p></div><table class='sections'><tr><td valign='top' class='section'><p>Params:</td><td><p><code>a</code> - Some int<p><code>b</code> - String</td><tr><td valign='top' class='section'><p>Returns:</td><td>Return <a href="psi_element://a">a</a> and nothing else</td></table>
|
||||
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
Some documentation
|
||||
|
||||
* @param a Some int
|
||||
* @param b String
|
||||
* @return Return value
|
||||
* @throws IllegalArgumentException if the weather is bad
|
||||
*/
|
||||
fun testMethod(a: Int, b: String) {
|
||||
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>testMethod(1, "value")
|
||||
}
|
||||
|
||||
//INFO: <div class='definition'><pre><font color="808080"><i>OnMethodUsageWithReturnAndThrows.kt</i></font><br>public fun <b>testMethod</b>(
|
||||
//INFO: a: Int,
|
||||
//INFO: b: String
|
||||
//INFO: ): Unit</pre></div><div class='content'><p>Some documentation</p></div><table class='sections'><tr><td valign='top' class='section'><p>Params:</td><td><p><code>a</code> - Some int<p><code>b</code> - String</td><tr><td valign='top' class='section'><p>Returns:</td><td>Return value</td><tr><td valign='top' class='section'><p>Throws:</td><td><p><code>IllegalArgumentException</code> - if the weather is bad</td></table>
|
||||
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* @see C
|
||||
* @see D
|
||||
* @see <a href="https://kotl.in">kotlin</a>
|
||||
*/
|
||||
fun testMethod() {
|
||||
|
||||
}
|
||||
|
||||
class C {
|
||||
}
|
||||
|
||||
class D {
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>testMethod(1, "value")
|
||||
}
|
||||
|
||||
//INFO: <div class='definition'><pre><font color="808080"><i>OnMethodUsageWithSee.kt</i></font><br>public fun <b>testMethod</b>(): Unit</pre></div><div class='content'></div><table class='sections'><tr><td valign='top' class='section'><p>See Also:</td><td><a href="psi_element://C"><code>C</code></a>, <a href="psi_element://D"><code>D</code></a>, <a href="https://kotl.in">kotlin</a></td></table>
|
||||
@@ -1,19 +0,0 @@
|
||||
/**
|
||||
Some documentation
|
||||
|
||||
* @param T the type parameter
|
||||
* @param a Some int
|
||||
* @param b String
|
||||
*/
|
||||
fun <T> testMethod(a: Int, b: String) {
|
||||
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>testMethod(1, "value")
|
||||
}
|
||||
|
||||
//INFO: <div class='definition'><pre><font color="808080"><i>OnMethodUsageWithTypeParameter.kt</i></font><br>public fun <T> <b>testMethod</b>(
|
||||
//INFO: a: Int,
|
||||
//INFO: b: String
|
||||
//INFO: ): Unit</pre></div><div class='content'><p>Some documentation</p></div><table class='sections'><tr><td valign='top' class='section'><p>Params:</td><td><p><code>T</code> - the type parameter<p><code>a</code> - Some int<p><code>b</code> - String</td></table>
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
package magic
|
||||
|
||||
object Samples {
|
||||
fun sampleMagic() {
|
||||
castTextSpell("[asd] [dse] [asz]")
|
||||
}
|
||||
}
|
||||
|
||||
fun sampleScroll() {
|
||||
val reader = Scroll("[asd] [dse] [asz]").reader()
|
||||
castTextSpell(reader.readAll())
|
||||
}
|
||||
|
||||
/**
|
||||
* @sample Samples.sampleMagic
|
||||
* @sample sampleScroll
|
||||
*/
|
||||
fun <caret>castTextSpell(spell: String) {
|
||||
throw SecurityException("Magic prohibited outside Hogwarts")
|
||||
}
|
||||
|
||||
//INFO: <div class='definition'><pre><a href="psi_element://magic"><code>magic</code></a> <font color="808080"><i>Samples.kt</i></font><br>public fun <b>castTextSpell</b>(
|
||||
//INFO: spell: String
|
||||
//INFO: ): Unit</pre></div><div class='content'></div><table class='sections'><tr><td valign='top' class='section'><p>Samples:</td><td><p><a href="psi_element://Samples.sampleMagic"><code>Samples.sampleMagic</code></a><pre><code>
|
||||
//INFO: castTextSpell("[asd] [dse] [asz]")
|
||||
//INFO: </code></pre><p><a href="psi_element://sampleScroll"><code>sampleScroll</code></a><pre><code>
|
||||
//INFO: val reader = Scroll("[asd] [dse] [asz]").reader()
|
||||
//INFO: castTextSpell(reader.readAll())
|
||||
//INFO: </code></pre></td></table>
|
||||
@@ -1,18 +0,0 @@
|
||||
/**
|
||||
* @sample samples.SampleGroup.mySample
|
||||
* @sample samples.megasamples.MegaSamplesGroup.megaSample
|
||||
* @sample samples.notindir.NotInDirSamples.sssample
|
||||
* @sample smaplez.a.b.c.Samplez.sssample
|
||||
*/
|
||||
fun some<caret>() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
//INFO: <div class='definition'><pre><font color="808080"><i>usage.kt</i></font><br>public fun <b>some</b>(): Unit</pre></div><div class='content'></div><table class='sections'><tr><td valign='top' class='section'><p>Samples:</td><td><p><a href="psi_element://samples.SampleGroup.mySample"><code>samples.SampleGroup.mySample</code></a><pre><code>
|
||||
//INFO: println("Hello, world")
|
||||
//INFO: </code></pre><p><a href="psi_element://samples.megasamples.MegaSamplesGroup.megaSample"><code>samples.megasamples.MegaSamplesGroup.megaSample</code></a><pre><code>
|
||||
//INFO: println("...---...")
|
||||
//INFO: </code></pre><p><a href="psi_element://samples.notindir.NotInDirSamples.sssample"><code>samples.notindir.NotInDirSamples.sssample</code></a><pre><code>
|
||||
//INFO: println("location is samplesTest/")
|
||||
//INFO: </code></pre><p><a href="psi_element://smaplez.a.b.c.Samplez.sssample"><code>smaplez.a.b.c.Samplez.sssample</code></a><pre><code>// Unresolved</code></pre></td></table>
|
||||
@@ -1,10 +0,0 @@
|
||||
/**
|
||||
* @sample samples.sample
|
||||
*/
|
||||
fun some<caret>() {
|
||||
|
||||
}
|
||||
|
||||
//INFO: <div class='definition'><pre><font color="808080"><i>usage.kt</i></font><br>public fun <b>some</b>(): Unit</pre></div><div class='content'></div><table class='sections'><tr><td valign='top' class='section'><p>Samples:</td><td><p><a href="psi_element://samples.sample"><code>samples.sample</code></a><pre><code>
|
||||
//INFO: println("Hello, world")
|
||||
//INFO: </code></pre></td></table>
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
package test;
|
||||
import foo.A;
|
||||
|
||||
public class ThrowsOnGenericMethod {
|
||||
public static void main(String[] args) {
|
||||
new A().<error descr="Unhandled exception: java.io.IOException">foo("");</error>
|
||||
}
|
||||
}
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
// "Remove function body" "true"
|
||||
abstract class A() {
|
||||
/*1*/
|
||||
abstract fun foo() // 3
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
// "Surround with lambda" "false"
|
||||
// ERROR: Type mismatch: inferred type is Object but () -> String was expected
|
||||
// ACTION: Annotate constructor 'Object' as @Deprecated
|
||||
// ACTION: Change parameter 'block' type of function 'str' to 'Object'
|
||||
// ACTION: Create function 'str'
|
||||
// ACTION: Edit method contract of 'Object'
|
||||
// ACTION: Introduce import alias
|
||||
fun fn() {
|
||||
str(<caret>Object())
|
||||
}
|
||||
|
||||
fun str(block: () -> String) {}
|
||||
@@ -1,7 +0,0 @@
|
||||
// "Suppress for declarations annotated by 'xxx.XXX'" "true"
|
||||
package xxx
|
||||
|
||||
annotation class XXX
|
||||
|
||||
@XXX
|
||||
class <caret>UnusedClass
|
||||
@@ -1,7 +0,0 @@
|
||||
// "Suppress for declarations annotated by 'xxx.XXX'" "true"
|
||||
package xxx
|
||||
|
||||
annotation class XXX
|
||||
|
||||
@XXX
|
||||
class <caret>UnusedClass
|
||||
-240
@@ -1,240 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.idea.configuration
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.PathMacros
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.projectRoots.ProjectJdkTable
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.roots.ProjectRootManager
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.io.FileUtilRt
|
||||
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess
|
||||
import com.intellij.testFramework.PlatformTestCase
|
||||
import com.intellij.testFramework.UsefulTestCase
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.kotlin.idea.configuration.KotlinWithLibraryConfigurator.FileState
|
||||
import org.jetbrains.kotlin.idea.framework.KotlinSdkType
|
||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.jetbrains.kotlin.utils.PathUtil
|
||||
import java.io.File
|
||||
import java.nio.file.Path
|
||||
|
||||
abstract class AbstractConfigureKotlinTest : PlatformTestCase() {
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
|
||||
VfsRootAccess.allowRootAccess(KotlinTestUtils.getHomeDirectory())
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
override fun tearDown() {
|
||||
VfsRootAccess.disallowRootAccess(KotlinTestUtils.getHomeDirectory())
|
||||
PathMacros.getInstance().removeMacro(TEMP_DIR_MACRO_KEY)
|
||||
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
override fun initApplication() {
|
||||
super.initApplication()
|
||||
|
||||
KotlinSdkType.setUpIfNeeded()
|
||||
|
||||
ApplicationManager.getApplication().runWriteAction {
|
||||
ProjectJdkTable.getInstance().addJdk(PluginTestCaseBase.mockJdk6())
|
||||
ProjectJdkTable.getInstance().addJdk(PluginTestCaseBase.mockJdk8())
|
||||
ProjectJdkTable.getInstance().addJdk(PluginTestCaseBase.mockJdk9())
|
||||
}
|
||||
|
||||
PluginTestCaseBase.clearSdkTable(testRootDisposable)
|
||||
|
||||
val tempLibDir = FileUtil.createTempDirectory("temp", null)
|
||||
PathMacros.getInstance().setMacro(TEMP_DIR_MACRO_KEY, FileUtilRt.toSystemDependentName(tempLibDir.absolutePath))
|
||||
}
|
||||
|
||||
protected fun doTestConfigureModulesWithNonDefaultSetup(configurator: KotlinWithLibraryConfigurator) {
|
||||
assertNoFilesInDefaultPaths()
|
||||
|
||||
val modules = modules
|
||||
for (module in modules) {
|
||||
assertNotConfigured(module, configurator)
|
||||
}
|
||||
|
||||
configurator.configure(myProject, emptyList())
|
||||
|
||||
assertNoFilesInDefaultPaths()
|
||||
|
||||
for (module in modules) {
|
||||
assertProperlyConfigured(module, configurator)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun doTestOneJavaModule(jarState: FileState) {
|
||||
doTestOneModule(jarState, JAVA_CONFIGURATOR)
|
||||
}
|
||||
|
||||
protected fun doTestOneJsModule(jarState: FileState) {
|
||||
doTestOneModule(jarState, JS_CONFIGURATOR)
|
||||
}
|
||||
|
||||
private fun doTestOneModule(jarState: FileState, configurator: KotlinWithLibraryConfigurator) {
|
||||
val module = module
|
||||
|
||||
assertNotConfigured(module, configurator)
|
||||
configure(module, jarState, configurator)
|
||||
assertProperlyConfigured(module, configurator)
|
||||
}
|
||||
|
||||
override fun getModule(): Module {
|
||||
val modules = ModuleManager.getInstance(myProject).modules
|
||||
assert(modules.size == 1) { "One module should be loaded " + modules.size }
|
||||
myModule = modules[0]
|
||||
return super.getModule()
|
||||
}
|
||||
|
||||
val modules: Array<Module>
|
||||
get() = ModuleManager.getInstance(myProject).modules
|
||||
|
||||
override fun getProjectDirOrFile(): Path {
|
||||
val projectFilePath = projectRoot + "/projectFile.ipr"
|
||||
TestCase.assertTrue("Project file should exists " + projectFilePath, File(projectFilePath).exists())
|
||||
return File(projectFilePath).toPath()
|
||||
}
|
||||
|
||||
override fun doCreateProject(projectFile: Path): Project {
|
||||
return myProjectManager.loadProject(projectFile.toFile().path)!!
|
||||
}
|
||||
|
||||
private val projectName: String
|
||||
get() {
|
||||
val testName = getTestName(true)
|
||||
return if (testName.contains("_")) {
|
||||
testName.substring(0, testName.indexOf("_"))
|
||||
}
|
||||
else testName
|
||||
}
|
||||
|
||||
protected val projectRoot: String
|
||||
get() = BASE_PATH + projectName
|
||||
|
||||
override fun setUpModule() {}
|
||||
|
||||
private fun assertNoFilesInDefaultPaths() {
|
||||
UsefulTestCase.assertDoesntExist(File(JAVA_CONFIGURATOR.getDefaultPathToJarFile(project)))
|
||||
UsefulTestCase.assertDoesntExist(File(JS_CONFIGURATOR.getDefaultPathToJarFile(project)))
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val BASE_PATH = "idea/testData/configuration/"
|
||||
private val TEMP_DIR_MACRO_KEY = "TEMP_TEST_DIR"
|
||||
protected val JAVA_CONFIGURATOR: KotlinJavaModuleConfigurator by lazy {
|
||||
object : KotlinJavaModuleConfigurator() {
|
||||
override fun getDefaultPathToJarFile(project: Project) = getPathRelativeToTemp("default_jvm_lib")
|
||||
}
|
||||
}
|
||||
|
||||
protected val JS_CONFIGURATOR: KotlinJsModuleConfigurator by lazy {
|
||||
object : KotlinJsModuleConfigurator() {
|
||||
override fun getDefaultPathToJarFile(project: Project) = getPathRelativeToTemp("default_js_lib")
|
||||
}
|
||||
}
|
||||
|
||||
private fun configure(
|
||||
modules: List<Module>,
|
||||
runtimeState: FileState,
|
||||
configurator: KotlinWithLibraryConfigurator,
|
||||
jarFromDist: String,
|
||||
jarFromTemp: String
|
||||
) {
|
||||
val project = modules.first().project
|
||||
val collector = createConfigureKotlinNotificationCollector(project)
|
||||
|
||||
val pathToJar = getPathToJar(runtimeState, jarFromDist, jarFromTemp)
|
||||
for (module in modules) {
|
||||
configurator.configureModule(module, pathToJar, pathToJar, collector, runtimeState)
|
||||
}
|
||||
collector.showNotification()
|
||||
}
|
||||
|
||||
private fun getPathToJar(runtimeState: FileState, jarFromDist: String, jarFromTemp: String) = when (runtimeState) {
|
||||
KotlinWithLibraryConfigurator.FileState.EXISTS -> jarFromDist
|
||||
KotlinWithLibraryConfigurator.FileState.COPY -> jarFromTemp
|
||||
KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY -> jarFromDist
|
||||
}
|
||||
|
||||
protected fun configure(module: Module, jarState: FileState, configurator: KotlinProjectConfigurator) {
|
||||
if (configurator is KotlinJavaModuleConfigurator) {
|
||||
configure(listOf(module), jarState,
|
||||
configurator as KotlinWithLibraryConfigurator,
|
||||
pathToExistentRuntimeJar, pathToNonexistentRuntimeJar)
|
||||
}
|
||||
if (configurator is KotlinJsModuleConfigurator) {
|
||||
configure(listOf(module), jarState,
|
||||
configurator as KotlinWithLibraryConfigurator,
|
||||
pathToExistentJsJar, pathToNonexistentJsJar)
|
||||
}
|
||||
}
|
||||
|
||||
private val pathToNonexistentRuntimeJar: String
|
||||
get() {
|
||||
val pathToTempKotlinRuntimeJar = FileUtil.getTempDirectory() + "/" + PathUtil.KOTLIN_JAVA_STDLIB_JAR
|
||||
PlatformTestCase.myFilesToDelete.add(File(pathToTempKotlinRuntimeJar))
|
||||
return pathToTempKotlinRuntimeJar
|
||||
}
|
||||
|
||||
private val pathToNonexistentJsJar: String
|
||||
get() {
|
||||
val pathToTempKotlinRuntimeJar = FileUtil.getTempDirectory() + "/" + PathUtil.JS_LIB_JAR_NAME
|
||||
PlatformTestCase.myFilesToDelete.add(File(pathToTempKotlinRuntimeJar))
|
||||
return pathToTempKotlinRuntimeJar
|
||||
}
|
||||
|
||||
private val pathToExistentRuntimeJar: String
|
||||
get() = PathUtil.kotlinPathsForDistDirectory.stdlibPath.parent
|
||||
|
||||
private val pathToExistentJsJar: String
|
||||
get() = PathUtil.kotlinPathsForDistDirectory.jsStdLibJarPath.parent
|
||||
|
||||
protected fun assertNotConfigured(module: Module, configurator: KotlinWithLibraryConfigurator) {
|
||||
TestCase.assertFalse(
|
||||
String.format("Module %s should not be configured as %s Module", module.name, configurator.presentableText),
|
||||
configurator.isConfigured(module))
|
||||
}
|
||||
|
||||
protected fun assertConfigured(module: Module, configurator: KotlinWithLibraryConfigurator) {
|
||||
TestCase.assertTrue(String.format("Module %s should be configured with configurator '%s'", module.name,
|
||||
configurator.presentableText),
|
||||
configurator.isConfigured(module))
|
||||
}
|
||||
|
||||
protected fun assertProperlyConfigured(module: Module, configurator: KotlinWithLibraryConfigurator) {
|
||||
assertConfigured(module, configurator)
|
||||
assertNotConfigured(module, getOppositeConfigurator(configurator))
|
||||
}
|
||||
|
||||
private fun getOppositeConfigurator(configurator: KotlinWithLibraryConfigurator): KotlinWithLibraryConfigurator {
|
||||
if (configurator === JAVA_CONFIGURATOR) return JS_CONFIGURATOR
|
||||
if (configurator === JS_CONFIGURATOR) return JAVA_CONFIGURATOR
|
||||
|
||||
throw IllegalArgumentException("Only JS_CONFIGURATOR and JAVA_CONFIGURATOR are supported")
|
||||
}
|
||||
|
||||
private fun getPathRelativeToTemp(relativePath: String): String {
|
||||
val tempPath = PathMacros.getInstance().getValue(TEMP_DIR_MACRO_KEY)
|
||||
return tempPath + '/' + relativePath
|
||||
}
|
||||
}
|
||||
|
||||
override fun getTestProjectJdk(): Sdk {
|
||||
val projectRootManager = ProjectRootManager.getInstance(project)
|
||||
return projectRootManager.projectSdk ?: throw IllegalStateException("SDK ${projectRootManager.projectSdkName} was not found")
|
||||
}
|
||||
}
|
||||
@@ -1,379 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.idea.configuration;
|
||||
|
||||
import com.intellij.jarRepository.RepositoryLibraryType;
|
||||
import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProviderImpl;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.LibraryOrderEntry;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.OrderRootType;
|
||||
import com.intellij.openapi.roots.RootPolicy;
|
||||
import com.intellij.openapi.roots.impl.libraries.LibraryEx;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiJavaModule;
|
||||
import com.intellij.psi.PsiRequiresStatement;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.kotlin.cli.common.arguments.InternalArgument;
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments;
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments;
|
||||
import org.jetbrains.kotlin.config.*;
|
||||
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCommonCompilerArgumentsHolder;
|
||||
import org.jetbrains.kotlin.idea.facet.FacetUtilsKt;
|
||||
import org.jetbrains.kotlin.idea.facet.KotlinFacet;
|
||||
import org.jetbrains.kotlin.idea.framework.JSLibraryKind;
|
||||
import org.jetbrains.kotlin.idea.framework.JsLibraryStdDetectionUtil;
|
||||
import org.jetbrains.kotlin.idea.framework.LibraryEffectiveKindProviderKt;
|
||||
import org.jetbrains.kotlin.idea.project.PlatformKt;
|
||||
import org.jetbrains.kotlin.idea.util.Java9StructureUtilKt;
|
||||
import org.jetbrains.kotlin.idea.versions.KotlinRuntimeLibraryUtilKt;
|
||||
import org.jetbrains.kotlin.platform.impl.JsIdePlatformKind;
|
||||
import org.jetbrains.kotlin.platform.impl.JvmIdePlatformKind;
|
||||
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleKt;
|
||||
import org.jetbrains.kotlin.utils.PathUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
public class ConfigureKotlinTest extends AbstractConfigureKotlinTest {
|
||||
public void testNewLibrary_copyJar() {
|
||||
doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.COPY);
|
||||
|
||||
ModuleRootManager.getInstance(getModule()).orderEntries().forEachLibrary(library -> {
|
||||
assertSameElements(
|
||||
Arrays.stream(library.getRootProvider().getFiles(OrderRootType.CLASSES)).map(VirtualFile::getName).toArray(),
|
||||
PathUtil.KOTLIN_JAVA_STDLIB_JAR, PathUtil.KOTLIN_JAVA_REFLECT_JAR, PathUtil.KOTLIN_TEST_JAR);
|
||||
|
||||
assertSameElements(
|
||||
Arrays.stream(library.getRootProvider().getFiles(OrderRootType.SOURCES)).map(VirtualFile::getName).toArray(),
|
||||
PathUtil.KOTLIN_JAVA_STDLIB_SRC_JAR, PathUtil.KOTLIN_REFLECT_SRC_JAR, PathUtil.KOTLIN_TEST_SRC_JAR);
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public void testNewLibrary_doNotCopyJar() {
|
||||
doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY);
|
||||
}
|
||||
|
||||
public void testLibraryWithoutPaths_jarExists() {
|
||||
doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.EXISTS);
|
||||
}
|
||||
|
||||
public void testNewLibrary_jarExists() {
|
||||
doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.EXISTS);
|
||||
}
|
||||
|
||||
public void testLibraryWithoutPaths_copyJar() {
|
||||
doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.COPY);
|
||||
}
|
||||
|
||||
public void testLibraryWithoutPaths_doNotCopyJar() {
|
||||
doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY);
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void testTwoModules_exists() {
|
||||
Module[] modules = getModules();
|
||||
for (Module module : modules) {
|
||||
if (module.getName().equals("module1")) {
|
||||
Companion.configure(module, KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY, Companion.getJAVA_CONFIGURATOR());
|
||||
Companion.assertConfigured(module, Companion.getJAVA_CONFIGURATOR());
|
||||
}
|
||||
else if (module.getName().equals("module2")) {
|
||||
Companion.assertNotConfigured(module, Companion.getJAVA_CONFIGURATOR());
|
||||
Companion.configure(module, KotlinWithLibraryConfigurator.FileState.EXISTS, Companion.getJAVA_CONFIGURATOR());
|
||||
Companion.assertConfigured(module, Companion.getJAVA_CONFIGURATOR());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testLibraryNonDefault_libExistInDefault() throws IOException {
|
||||
Module module = getModule();
|
||||
|
||||
// Move fake runtime jar to default library path to pretend library is already configured
|
||||
FileUtil.copy(
|
||||
new File(getProject().getBasePath() + "/lib/" + PathUtil.KOTLIN_JAVA_STDLIB_JAR),
|
||||
new File(Companion.getJAVA_CONFIGURATOR().getDefaultPathToJarFile(getProject()) + "/" + PathUtil.KOTLIN_JAVA_STDLIB_JAR));
|
||||
|
||||
Companion.assertNotConfigured(module, Companion.getJAVA_CONFIGURATOR());
|
||||
Companion.getJAVA_CONFIGURATOR().configure(myProject, Collections.<Module>emptyList());
|
||||
Companion.assertProperlyConfigured(module, Companion.getJAVA_CONFIGURATOR());
|
||||
}
|
||||
|
||||
public void testTwoModulesWithNonDefaultPath_doNotCopyInDefault() throws IOException {
|
||||
doTestConfigureModulesWithNonDefaultSetup(Companion.getJAVA_CONFIGURATOR());
|
||||
assertEmpty(ConfigureKotlinInProjectUtilsKt.getCanBeConfiguredModules(myProject, Companion.getJS_CONFIGURATOR()));
|
||||
}
|
||||
|
||||
public void testTwoModulesWithJSNonDefaultPath_doNotCopyInDefault() throws IOException {
|
||||
doTestConfigureModulesWithNonDefaultSetup(Companion.getJS_CONFIGURATOR());
|
||||
assertEmpty(ConfigureKotlinInProjectUtilsKt.getCanBeConfiguredModules(myProject, Companion.getJAVA_CONFIGURATOR()));
|
||||
}
|
||||
|
||||
public void testNewLibrary_jarExists_js() {
|
||||
doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.EXISTS);
|
||||
}
|
||||
|
||||
public void testNewLibrary_copyJar_js() {
|
||||
doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.COPY);
|
||||
}
|
||||
|
||||
public void testNewLibrary_doNotCopyJar_js() {
|
||||
doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY);
|
||||
}
|
||||
|
||||
public void testJsLibraryWithoutPaths_jarExists() {
|
||||
doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.EXISTS);
|
||||
}
|
||||
|
||||
public void testJsLibraryWithoutPaths_copyJar() {
|
||||
doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.COPY);
|
||||
}
|
||||
|
||||
public void testJsLibraryWithoutPaths_doNotCopyJar() {
|
||||
doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY);
|
||||
}
|
||||
|
||||
public void testJsLibraryWrongKind() {
|
||||
AbstractConfigureKotlinTest.Companion.assertProperlyConfigured(getModule(), AbstractConfigureKotlinTest.Companion.getJS_CONFIGURATOR());
|
||||
assertEquals(1, ModuleRootManager.getInstance(getModule()).orderEntries().process(new LibraryCountingRootPolicy(), 0).intValue());
|
||||
}
|
||||
|
||||
public void testProjectWithoutFacetWithRuntime106WithoutLanguageLevel() {
|
||||
assertEquals(LanguageVersion.KOTLIN_1_0, PlatformKt.getLanguageVersionSettings(getModule()).getLanguageVersion());
|
||||
assertEquals(LanguageVersion.KOTLIN_1_0, PlatformKt.getLanguageVersionSettings(myProject, null).getLanguageVersion());
|
||||
}
|
||||
|
||||
public void testProjectWithoutFacetWithRuntime11WithoutLanguageLevel() {
|
||||
assertEquals(LanguageVersion.KOTLIN_1_1, PlatformKt.getLanguageVersionSettings(getModule()).getLanguageVersion());
|
||||
assertEquals(LanguageVersion.KOTLIN_1_1, PlatformKt.getLanguageVersionSettings(myProject, null).getLanguageVersion());
|
||||
}
|
||||
|
||||
public void testProjectWithoutFacetWithRuntime11WithLanguageLevel10() {
|
||||
assertEquals(LanguageVersion.KOTLIN_1_0, PlatformKt.getLanguageVersionSettings(getModule()).getLanguageVersion());
|
||||
assertEquals(LanguageVersion.KOTLIN_1_0, PlatformKt.getLanguageVersionSettings(myProject, null).getLanguageVersion());
|
||||
}
|
||||
|
||||
public void testProjectWithFacetWithRuntime11WithLanguageLevel10() {
|
||||
assertEquals(LanguageVersion.KOTLIN_1_0, PlatformKt.getLanguageVersionSettings(getModule()).getLanguageVersion());
|
||||
assertEquals(LanguageVersion.LATEST_STABLE, PlatformKt.getLanguageVersionSettings(myProject, null).getLanguageVersion());
|
||||
}
|
||||
|
||||
public void testJsLibraryVersion11() {
|
||||
Library jsRuntime = KotlinRuntimeLibraryUtilKt.findAllUsedLibraries(myProject).keySet().iterator().next();
|
||||
String version = JsLibraryStdDetectionUtil.INSTANCE.getJsLibraryStdVersion(jsRuntime, myProject);
|
||||
assertEquals("1.1.0", version);
|
||||
}
|
||||
|
||||
public void testJsLibraryVersion106() {
|
||||
Library jsRuntime = KotlinRuntimeLibraryUtilKt.findAllUsedLibraries(myProject).keySet().iterator().next();
|
||||
String version = JsLibraryStdDetectionUtil.INSTANCE.getJsLibraryStdVersion(jsRuntime, myProject);
|
||||
assertEquals("1.0.6", version);
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void testMavenProvidedTestJsKind() {
|
||||
LibraryEx jsTest = (LibraryEx) ContainerUtil.find(
|
||||
KotlinRuntimeLibraryUtilKt.findAllUsedLibraries(myProject).keySet(),
|
||||
(library) -> library.getName().contains("kotlin-test-js")
|
||||
);
|
||||
assertEquals(RepositoryLibraryType.REPOSITORY_LIBRARY_KIND, jsTest.getKind());
|
||||
assertEquals(JSLibraryKind.INSTANCE, LibraryEffectiveKindProviderKt.effectiveKind(jsTest, myProject));
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void testJvmProjectWithV1FacetConfig() {
|
||||
KotlinFacetSettings settings = KotlinFacetSettingsProvider.Companion.getInstance(myProject).getInitializedSettings(getModule());
|
||||
K2JVMCompilerArguments arguments = (K2JVMCompilerArguments) settings.getCompilerArguments();
|
||||
assertEquals(false, settings.getUseProjectSettings());
|
||||
assertEquals("1.1", settings.getLanguageLevel().getDescription());
|
||||
assertEquals("1.0", settings.getApiLevel().getDescription());
|
||||
assertEquals(new JvmIdePlatformKind.Platform(JvmTarget.JVM_1_8), settings.getPlatform());
|
||||
assertEquals("1.1", arguments.getLanguageVersion());
|
||||
assertEquals("1.0", arguments.getApiVersion());
|
||||
assertEquals(LanguageFeature.State.ENABLED_WITH_WARNING, CoroutineSupport.byCompilerArguments(arguments));
|
||||
assertEquals("1.7", arguments.getJvmTarget());
|
||||
assertEquals("-version -Xallow-kotlin-package -Xskip-metadata-version-check", settings.getCompilerSettings().getAdditionalArguments());
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void testJsProjectWithV1FacetConfig() {
|
||||
KotlinFacetSettings settings = KotlinFacetSettingsProvider.Companion.getInstance(myProject).getInitializedSettings(getModule());
|
||||
K2JSCompilerArguments arguments = (K2JSCompilerArguments) settings.getCompilerArguments();
|
||||
assertEquals(false, settings.getUseProjectSettings());
|
||||
assertEquals("1.1", settings.getLanguageLevel().getDescription());
|
||||
assertEquals("1.0", settings.getApiLevel().getDescription());
|
||||
assertEquals(JsIdePlatformKind.Platform.INSTANCE, settings.getPlatform());
|
||||
assertEquals("1.1", arguments.getLanguageVersion());
|
||||
assertEquals("1.0", arguments.getApiVersion());
|
||||
assertEquals(LanguageFeature.State.ENABLED_WITH_WARNING, CoroutineSupport.byCompilerArguments(arguments));
|
||||
assertEquals("amd", arguments.getModuleKind());
|
||||
assertEquals("-version -meta-info", settings.getCompilerSettings().getAdditionalArguments());
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void testJvmProjectWithV2FacetConfig() {
|
||||
KotlinFacetSettings settings = KotlinFacetSettingsProvider.Companion.getInstance(myProject).getInitializedSettings(getModule());
|
||||
K2JVMCompilerArguments arguments = (K2JVMCompilerArguments) settings.getCompilerArguments();
|
||||
assertEquals(false, settings.getUseProjectSettings());
|
||||
assertEquals("1.1", settings.getLanguageLevel().getDescription());
|
||||
assertEquals("1.0", settings.getApiLevel().getDescription());
|
||||
assertEquals(new JvmIdePlatformKind.Platform(JvmTarget.JVM_1_8), settings.getPlatform());
|
||||
assertEquals("1.1", arguments.getLanguageVersion());
|
||||
assertEquals("1.0", arguments.getApiVersion());
|
||||
assertEquals(LanguageFeature.State.ENABLED, CoroutineSupport.byCompilerArguments(arguments));
|
||||
assertEquals("1.7", arguments.getJvmTarget());
|
||||
assertEquals("-version -Xallow-kotlin-package -Xskip-metadata-version-check", settings.getCompilerSettings().getAdditionalArguments());
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void testJsProjectWithV2FacetConfig() {
|
||||
KotlinFacetSettings settings = KotlinFacetSettingsProvider.Companion.getInstance(myProject).getInitializedSettings(getModule());
|
||||
K2JSCompilerArguments arguments = (K2JSCompilerArguments) settings.getCompilerArguments();
|
||||
assertEquals(false, settings.getUseProjectSettings());
|
||||
assertEquals("1.1", settings.getLanguageLevel().getDescription());
|
||||
assertEquals("1.0", settings.getApiLevel().getDescription());
|
||||
assertEquals(JsIdePlatformKind.Platform.INSTANCE, settings.getPlatform());
|
||||
assertEquals("1.1", arguments.getLanguageVersion());
|
||||
assertEquals("1.0", arguments.getApiVersion());
|
||||
assertEquals(LanguageFeature.State.ENABLED_WITH_ERROR, CoroutineSupport.byCompilerArguments(arguments));
|
||||
assertEquals("amd", arguments.getModuleKind());
|
||||
assertEquals("-version -meta-info", settings.getCompilerSettings().getAdditionalArguments());
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void testJvmProjectWithV3FacetConfig() {
|
||||
KotlinFacetSettings settings = KotlinFacetSettingsProvider.Companion.getInstance(myProject).getInitializedSettings(getModule());
|
||||
K2JVMCompilerArguments arguments = (K2JVMCompilerArguments) settings.getCompilerArguments();
|
||||
assertEquals(false, settings.getUseProjectSettings());
|
||||
assertEquals("1.1", settings.getLanguageLevel().getDescription());
|
||||
assertEquals("1.0", settings.getApiLevel().getDescription());
|
||||
assertEquals(new JvmIdePlatformKind.Platform(JvmTarget.JVM_1_8), settings.getPlatform());
|
||||
assertEquals("1.1", arguments.getLanguageVersion());
|
||||
assertEquals("1.0", arguments.getApiVersion());
|
||||
assertEquals(LanguageFeature.State.ENABLED, CoroutineSupport.byCompilerArguments(arguments));
|
||||
assertEquals("1.7", arguments.getJvmTarget());
|
||||
assertEquals("-version -Xallow-kotlin-package -Xskip-metadata-version-check", settings.getCompilerSettings().getAdditionalArguments());
|
||||
}
|
||||
|
||||
public void testJvmProjectWithJvmTarget11() {
|
||||
KotlinFacetSettings settings = KotlinFacetSettingsProvider.Companion.getInstance(myProject).getInitializedSettings(getModule());
|
||||
assertEquals(new JvmIdePlatformKind.Platform(JvmTarget.JVM_11), settings.getPlatform());
|
||||
}
|
||||
|
||||
public void testImplementsDependency() {
|
||||
ModuleManager moduleManager = ModuleManager.getInstance(myProject);
|
||||
|
||||
Module module1 = moduleManager.findModuleByName("module1");
|
||||
assert module1 != null;
|
||||
|
||||
Module module2 = moduleManager.findModuleByName("module2");
|
||||
assert module2 != null;
|
||||
|
||||
assertEquals(KotlinFacet.Companion.get(module1).getConfiguration().getSettings().getImplementedModuleNames(), emptyList());
|
||||
assertEquals(KotlinFacet.Companion.get(module2).getConfiguration().getSettings().getImplementedModuleNames(), singletonList("module1"));
|
||||
}
|
||||
|
||||
public void testJava9WithModuleInfo() {
|
||||
checkAddStdlibModule();
|
||||
}
|
||||
|
||||
public void testJava9WithModuleInfoWithStdlibAlready() {
|
||||
checkAddStdlibModule();
|
||||
}
|
||||
|
||||
public void testProjectWithFreeArgs() {
|
||||
assertEquals(
|
||||
Collections.singletonList("true"),
|
||||
KotlinCommonCompilerArgumentsHolder.Companion.getInstance(myProject).getSettings().getFreeArgs()
|
||||
);
|
||||
}
|
||||
|
||||
public void testProjectWithInternalArgs() {
|
||||
List<InternalArgument> internalArguments =
|
||||
KotlinCommonCompilerArgumentsHolder.Companion.getInstance(myProject).getSettings().getInternalArguments();
|
||||
assertEquals(
|
||||
0,
|
||||
internalArguments.size()
|
||||
);
|
||||
}
|
||||
|
||||
private void checkAddStdlibModule() {
|
||||
doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.COPY);
|
||||
|
||||
Module module = getModule();
|
||||
Sdk moduleSdk = ModuleRootManager.getInstance(getModule()).getSdk();
|
||||
assertNotNull("Module SDK is not defined", moduleSdk);
|
||||
|
||||
PsiJavaModule javaModule = Java9StructureUtilKt.findFirstPsiJavaModule(module);
|
||||
assertNotNull(javaModule);
|
||||
|
||||
PsiRequiresStatement stdlibDirective =
|
||||
Java9StructureUtilKt.findRequireDirective(javaModule, JavaModuleKt.KOTLIN_STDLIB_MODULE_NAME);
|
||||
assertNotNull("Require directive for " + JavaModuleKt.KOTLIN_STDLIB_MODULE_NAME + " is expected",
|
||||
stdlibDirective);
|
||||
|
||||
long numberOfStdlib = StreamSupport.stream(javaModule.getRequires().spliterator(), false)
|
||||
.filter((statement) -> JavaModuleKt.KOTLIN_STDLIB_MODULE_NAME.equals(statement.getModuleName()))
|
||||
.count();
|
||||
|
||||
assertTrue("Only one standard library directive is expected", numberOfStdlib == 1);
|
||||
}
|
||||
|
||||
private void configureFacetAndCheckJvm(JvmTarget jvmTarget) {
|
||||
IdeModifiableModelsProviderImpl modelsProvider = new IdeModifiableModelsProviderImpl(getProject());
|
||||
try {
|
||||
KotlinFacet facet = FacetUtilsKt.getOrCreateFacet(getModule(), modelsProvider, false, null, false);
|
||||
JvmIdePlatformKind.Platform platform = new JvmIdePlatformKind.Platform(jvmTarget);
|
||||
FacetUtilsKt.configureFacet(
|
||||
facet,
|
||||
"1.1",
|
||||
LanguageFeature.State.ENABLED,
|
||||
platform,
|
||||
modelsProvider
|
||||
);
|
||||
assertEquals(platform, facet.getConfiguration().getSettings().getPlatform());
|
||||
assertEquals(jvmTarget.getDescription(),
|
||||
((K2JVMCompilerArguments) facet.getConfiguration().getSettings().getCompilerArguments()).getJvmTarget());
|
||||
}
|
||||
finally {
|
||||
modelsProvider.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void testJvm8InProjectJvm6InModule() {
|
||||
configureFacetAndCheckJvm(JvmTarget.JVM_1_6);
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void testJvm6InProjectJvm8InModule() {
|
||||
configureFacetAndCheckJvm(JvmTarget.JVM_1_8);
|
||||
}
|
||||
|
||||
public void testProjectWithoutFacetWithJvmTarget18() {
|
||||
assertEquals(new JvmIdePlatformKind.Platform(JvmTarget.JVM_1_8), PlatformKt.getPlatform(getModule()));
|
||||
}
|
||||
|
||||
private static class LibraryCountingRootPolicy extends RootPolicy<Integer> {
|
||||
@Override
|
||||
public Integer visitLibraryOrderEntry(LibraryOrderEntry libraryOrderEntry, Integer value) {
|
||||
return value + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.idea.debugger
|
||||
|
||||
import com.intellij.debugger.impl.OutputChecker
|
||||
import com.intellij.idea.IdeaLogger
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.io.FileUtilRt
|
||||
import com.intellij.openapi.util.text.StringUtilRt
|
||||
import com.intellij.openapi.vfs.CharsetToolkit
|
||||
import org.junit.Assert
|
||||
import java.io.File
|
||||
|
||||
internal class KotlinOutputChecker(
|
||||
private val testDir: String,
|
||||
appPath: String, outputPath: String) : OutputChecker(appPath, outputPath) {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
private val LOG = Logger.getInstance(KotlinOutputChecker::class.java)
|
||||
|
||||
private val CONNECT_PREFIX = "Connected to the target VM"
|
||||
private val DISCONNECT_PREFIX = "Disconnected from the target VM"
|
||||
private val RUN_JAVA = "Run Java"
|
||||
|
||||
//ERROR: JDWP Unable to get JNI 1.2 environment, jvm->GetEnv() return code = -2
|
||||
private val JDI_BUG_OUTPUT_PATTERN_1 = Regex("ERROR:\\s+JDWP\\s+Unable\\s+to\\s+get\\s+JNI\\s+1\\.2\\s+environment,\\s+jvm->GetEnv\\(\\)\\s+return\\s+code\\s+=\\s+-2")
|
||||
//JDWP exit error AGENT_ERROR_NO_JNI_ENV(183): [../../../src/share/back/util.c:820]
|
||||
private val JDI_BUG_OUTPUT_PATTERN_2 = Regex("JDWP\\s+exit\\s+error\\s+AGENT_ERROR_NO_JNI_ENV.*]")
|
||||
}
|
||||
|
||||
// Copied from the base OutputChecker.checkValid(). Need to intercept call to base preprocessBuffer() method
|
||||
override fun checkValid(jdk: Sdk, sortClassPath: Boolean) {
|
||||
if (IdeaLogger.ourErrorsOccurred != null) {
|
||||
throw IdeaLogger.ourErrorsOccurred
|
||||
}
|
||||
|
||||
val actual = preprocessBuffer(buildOutputString())
|
||||
|
||||
val outDir = File(testDir)
|
||||
var outFile = File(outDir, myTestName + ".out")
|
||||
if (!outFile.exists()) {
|
||||
if (SystemInfo.isWindows) {
|
||||
val winOut = File(outDir, myTestName + ".win.out")
|
||||
if (winOut.exists()) {
|
||||
outFile = winOut
|
||||
}
|
||||
}
|
||||
else if (SystemInfo.isUnix) {
|
||||
val unixOut = File(outDir, myTestName + ".unx.out")
|
||||
if (unixOut.exists()) {
|
||||
outFile = unixOut
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!outFile.exists()) {
|
||||
FileUtil.writeToFile(outFile, actual)
|
||||
LOG.error("Test file created ${outFile.path}\n**************** Don't forget to put it into VCS! *******************")
|
||||
}
|
||||
else {
|
||||
val originalText = FileUtilRt.loadFile(outFile, CharsetToolkit.UTF8)
|
||||
val expected = StringUtilRt.convertLineSeparators(originalText)
|
||||
if (expected != actual) {
|
||||
println("expected:")
|
||||
println(originalText)
|
||||
println("actual:")
|
||||
println(actual)
|
||||
|
||||
val len = Math.min(expected.length, actual.length)
|
||||
if (expected.length != actual.length) {
|
||||
println("Text sizes differ: expected " + expected.length + " but actual: " + actual.length)
|
||||
}
|
||||
if (expected.length > len) {
|
||||
println("Rest from expected text is: \"" + expected.substring(len) + "\"")
|
||||
}
|
||||
else if (actual.length > len) {
|
||||
println("Rest from actual text is: \"" + actual.substring(len) + "\"")
|
||||
}
|
||||
|
||||
Assert.assertEquals(originalText, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun preprocessBuffer(buffer: String): String {
|
||||
val lines = buffer.lines().toMutableList()
|
||||
|
||||
val connectedIndex = lines.indexOfFirst { it.startsWith(CONNECT_PREFIX) }
|
||||
lines[connectedIndex] = CONNECT_PREFIX
|
||||
|
||||
val runCommandIndex = connectedIndex - 1
|
||||
lines[runCommandIndex] = RUN_JAVA
|
||||
|
||||
val disconnectedIndex = lines.indexOfFirst { it.startsWith(DISCONNECT_PREFIX) }
|
||||
lines[disconnectedIndex] = DISCONNECT_PREFIX
|
||||
|
||||
return lines.filter { !(it.matches(JDI_BUG_OUTPUT_PATTERN_1) || it.matches(JDI_BUG_OUTPUT_PATTERN_2)) }.joinToString("\n")
|
||||
}
|
||||
|
||||
private fun buildOutputString(): String {
|
||||
// Call base method with reflection
|
||||
val m = OutputChecker::class.java.getDeclaredMethod("buildOutputString")!!
|
||||
val isAccessible = m.isAccessible
|
||||
|
||||
try {
|
||||
m.isAccessible = true
|
||||
return m.invoke(this) as String
|
||||
}
|
||||
finally {
|
||||
m.isAccessible = isAccessible
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.idea.folding;
|
||||
|
||||
import com.intellij.codeInsight.folding.JavaCodeFoldingSettings;
|
||||
import com.intellij.codeInsight.folding.impl.JavaCodeFoldingSettingsImpl;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.PlatformTestCase;
|
||||
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase;
|
||||
import org.jetbrains.kotlin.test.SettingsConfigurator;
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public abstract class AbstractKotlinFoldingTest extends KotlinLightCodeInsightFixtureTestCase {
|
||||
protected void doTest(@NotNull String path) {
|
||||
myFixture.testFolding(path);
|
||||
}
|
||||
|
||||
protected void doSettingsFoldingTest(@NotNull String path) throws IOException{
|
||||
String fileText = FileUtil.loadFile(new File(path), true);
|
||||
|
||||
String directText = fileText.replaceAll("~true~", "true").replaceAll("~false~", "false");
|
||||
directText += "\n\n// Generated from: " + path;
|
||||
|
||||
Consumer<String> doExpandSettingsTestFunction = this::doExpandSettingsTest;
|
||||
|
||||
doTestWithSettings(directText, doExpandSettingsTestFunction);
|
||||
|
||||
String invertedText = fileText
|
||||
.replaceAll("~false~", "true").replaceAll("~true~", "false")
|
||||
.replaceAll(SettingsConfigurator.SET_TRUE_DIRECTIVE, "~TEMP_TRUE_DIRECTIVE~")
|
||||
.replaceAll(SettingsConfigurator.SET_FALSE_DIRECTIVE, SettingsConfigurator.SET_TRUE_DIRECTIVE)
|
||||
.replaceAll("~TEMP_TRUE_DIRECTIVE~", SettingsConfigurator.SET_FALSE_DIRECTIVE);
|
||||
invertedText += "\n\n// Generated from: " + path + " with !INVERTED! settings";
|
||||
|
||||
doTestWithSettings(invertedText, doExpandSettingsTestFunction);
|
||||
}
|
||||
|
||||
protected static void doTestWithSettings(@NotNull String fileText, @NotNull Consumer<String> runnable) {
|
||||
JavaCodeFoldingSettings settings = JavaCodeFoldingSettings.getInstance();
|
||||
JavaCodeFoldingSettingsImpl restoreSettings = new JavaCodeFoldingSettingsImpl();
|
||||
restoreSettings.loadState((JavaCodeFoldingSettingsImpl) settings);
|
||||
|
||||
try {
|
||||
SettingsConfigurator configurator = new SettingsConfigurator(fileText, settings);
|
||||
configurator.configureSettings();
|
||||
|
||||
runnable.accept(fileText);
|
||||
}
|
||||
finally {
|
||||
((JavaCodeFoldingSettingsImpl) JavaCodeFoldingSettings.getInstance()).loadState(restoreSettings);
|
||||
}
|
||||
}
|
||||
|
||||
private void doExpandSettingsTest(String fileText) {
|
||||
try {
|
||||
VirtualFile tempFile = PlatformTestCase.createTempFile("kt", null, fileText, Charset.defaultCharset());
|
||||
assertFoldingRegionsForFile(tempFile.getPath());
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Rewritten version of CodeInsightTestFixtureImpl.testFoldingRegions(verificationFileName, true).
|
||||
// Configure test with custom file name to force creating different editors for normal and inverted tests.
|
||||
private void assertFoldingRegionsForFile(String verificationFileName) {
|
||||
String START_FOLD = "<fold\\stext=\'[^\']*\'(\\sexpand=\'[^\']*\')*>";
|
||||
String END_FOLD = "</fold>";
|
||||
|
||||
String expectedContent;
|
||||
File file = new File(verificationFileName);
|
||||
|
||||
try {
|
||||
expectedContent = FileUtil.loadFile(file);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
Assert.assertNotNull(expectedContent);
|
||||
|
||||
expectedContent = StringUtil.replace(expectedContent, "\r", "");
|
||||
String cleanContent = expectedContent.replaceAll(START_FOLD, "").replaceAll(END_FOLD, "");
|
||||
|
||||
myFixture.configureByText(file.getName(), cleanContent);
|
||||
String actual = ((CodeInsightTestFixtureImpl)myFixture).getFoldingDescription(true);
|
||||
|
||||
Assert.assertEquals(expectedContent, actual);
|
||||
}
|
||||
}
|
||||
@@ -1,215 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.idea.multiplatform
|
||||
|
||||
import com.intellij.openapi.command.WriteCommandAction
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.StdModuleTypes
|
||||
import com.intellij.openapi.roots.CompilerModuleExtension
|
||||
import com.intellij.openapi.roots.ModuleRootModificationUtil
|
||||
import com.intellij.openapi.vfs.LocalFileSystem
|
||||
import com.intellij.testFramework.PlatformTestCase
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.idea.framework.CommonLibraryKind
|
||||
import org.jetbrains.kotlin.idea.framework.JSLibraryKind
|
||||
import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest
|
||||
import org.jetbrains.kotlin.idea.stubs.createFacet
|
||||
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
|
||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
||||
import org.jetbrains.kotlin.platform.IdePlatform
|
||||
import org.jetbrains.kotlin.platform.impl.*
|
||||
import org.jetbrains.kotlin.test.TestJdkKind
|
||||
import java.io.File
|
||||
|
||||
// allows to configure a test mpp project
|
||||
// testRoot is supposed to contain several directories which contain module sources roots
|
||||
// configuration is based on those directories names
|
||||
fun AbstractMultiModuleTest.setupMppProjectFromDirStructure(testRoot: File) {
|
||||
assert(testRoot.isDirectory) { testRoot.absolutePath + " must be a directory" }
|
||||
val dirs = testRoot.listFiles().filter { it.isDirectory }
|
||||
val rootInfos = dirs.map { parseDirName(it) }
|
||||
val infosByModuleId = rootInfos.groupBy { it.moduleId }
|
||||
val modulesById = infosByModuleId.mapValues { (moduleId, infos) ->
|
||||
createModuleWithRoots(moduleId, infos)
|
||||
}
|
||||
|
||||
infosByModuleId.entries.forEach { (id, rootInfos) ->
|
||||
val module = modulesById[id]!!
|
||||
rootInfos.flatMap { it.dependencies }.forEach {
|
||||
val platform = id.platform
|
||||
when (it) {
|
||||
is ModuleDependency -> module.addDependency(modulesById[it.moduleId]!!)
|
||||
is StdlibDependency -> {
|
||||
when {
|
||||
platform.isCommon -> module.addLibrary(
|
||||
ForTestCompileRuntime.stdlibCommonForTests(), kind = CommonLibraryKind
|
||||
)
|
||||
platform.isJvm -> module.addLibrary(ForTestCompileRuntime.runtimeJarForTests())
|
||||
platform.isJavaScript -> module.addLibrary(ForTestCompileRuntime.stdlibJsForTests(), kind = JSLibraryKind)
|
||||
else -> error("Unknown platform $this")
|
||||
}
|
||||
}
|
||||
is FullJdkDependency -> {
|
||||
ConfigLibraryUtil.configureSdk(module, PluginTestCaseBase.addJdk(testRootDisposable) {
|
||||
PluginTestCaseBase.jdk(TestJdkKind.FULL_JDK)
|
||||
})
|
||||
}
|
||||
is CoroutinesDependency -> module.enableCoroutines()
|
||||
is KotlinTestDependency -> when {
|
||||
platform.isJvm -> module.addLibrary(ForTestCompileRuntime.kotlinTestJUnitJarForTests())
|
||||
platform.isJavaScript -> module.addLibrary(ForTestCompileRuntime.kotlinTestJsJarForTests(), kind = JSLibraryKind)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
modulesById.forEach { (nameAndPlatform, module) ->
|
||||
val (name, platform) = nameAndPlatform
|
||||
when {
|
||||
platform.isCommon -> module.createFacet(platform, useProjectSettings = false)
|
||||
else -> {
|
||||
val commonModuleId = ModuleId(name, CommonIdePlatformKind.Platform)
|
||||
|
||||
module.createFacet(platform, implementedModuleName = commonModuleId.ideaModuleName())
|
||||
module.enableMultiPlatform()
|
||||
|
||||
modulesById[commonModuleId]?.let { commonModule ->
|
||||
module.addDependency(commonModule)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun AbstractMultiModuleTest.createModuleWithRoots(
|
||||
moduleId: ModuleId,
|
||||
infos: List<RootInfo>
|
||||
): Module {
|
||||
val module = createModule(moduleId.ideaModuleName())
|
||||
for ((_, isTestRoot, moduleRoot) in infos) {
|
||||
addRoot(module, moduleRoot, isTestRoot)
|
||||
|
||||
if (moduleId.platform.isJavaScript && isTestRoot) {
|
||||
setupJsTestOutput(module)
|
||||
}
|
||||
}
|
||||
return module
|
||||
}
|
||||
|
||||
// test line markers for JS do not work without additional setup
|
||||
private fun setupJsTestOutput(module: Module) {
|
||||
ModuleRootModificationUtil.updateModel(module) {
|
||||
with(it.getModuleExtension(CompilerModuleExtension::class.java)!!) {
|
||||
inheritCompilerOutputPath(false)
|
||||
setCompilerOutputPathForTests("js_out")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun AbstractMultiModuleTest.createModule(name: String): Module {
|
||||
val moduleDir = PlatformTestCase.createTempDir("")
|
||||
val module = createModule(moduleDir.toString() + "/" + name, StdModuleTypes.JAVA)
|
||||
val root = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(moduleDir)
|
||||
TestCase.assertNotNull(root)
|
||||
object : WriteCommandAction.Simple<Unit>(module.project) {
|
||||
@Throws(Throwable::class)
|
||||
override fun run() {
|
||||
root!!.refresh(false, true)
|
||||
}
|
||||
}.execute().throwException()
|
||||
return module
|
||||
}
|
||||
|
||||
private val testSuffixes = setOf("test", "tests")
|
||||
private val platformNames = mapOf(
|
||||
listOf("header", "common", "expect") to CommonIdePlatformKind.Platform,
|
||||
listOf("java", "jvm") to JvmIdePlatformKind.defaultPlatform,
|
||||
listOf("java8", "jvm8") to JvmIdePlatformKind.Platform(JvmTarget.JVM_1_8),
|
||||
listOf("java6", "jvm6") to JvmIdePlatformKind.Platform(JvmTarget.JVM_1_6),
|
||||
listOf("js", "javascript") to JsIdePlatformKind.Platform
|
||||
)
|
||||
|
||||
private fun parseDirName(dir: File): RootInfo {
|
||||
val parts = dir.name.split("_")
|
||||
return RootInfo(parseModuleId(parts), parseIsTestRoot(parts), dir, parseDependencies(parts))
|
||||
}
|
||||
|
||||
private fun parseDependencies(parts: List<String>) =
|
||||
parts.filter { it.startsWith("dep(") && it.endsWith(")") }.map {
|
||||
parseDependency(it)
|
||||
}
|
||||
|
||||
private fun parseDependency(it: String): Dependency {
|
||||
val dependencyString = it.removePrefix("dep(").removeSuffix(")")
|
||||
|
||||
return when {
|
||||
dependencyString.equals("stdlib", ignoreCase = true) -> StdlibDependency
|
||||
dependencyString.equals("fulljdk", ignoreCase = true) -> FullJdkDependency
|
||||
dependencyString.equals("coroutines", ignoreCase = true) -> CoroutinesDependency
|
||||
dependencyString.equals("kotlin-test", ignoreCase = true) -> KotlinTestDependency
|
||||
else -> ModuleDependency(parseModuleId(dependencyString.split("-")))
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseModuleId(parts: List<String>): ModuleId {
|
||||
val platform = parsePlatform(parts)
|
||||
val name = parseModuleName(parts)
|
||||
val id = parseIndex(parts) ?: 0
|
||||
assert(id == 0 || !platform.isCommon)
|
||||
return ModuleId(name, platform, id)
|
||||
}
|
||||
|
||||
private fun parsePlatform(parts: List<String>) =
|
||||
platformNames.entries.single { (names, _) ->
|
||||
names.any { name -> parts.any { part -> part.equals(name, ignoreCase = true) } }
|
||||
}.value
|
||||
|
||||
private fun parseModuleName(parts: List<String>) = when {
|
||||
parts.size > 1 -> parts.first()
|
||||
else -> "testModule"
|
||||
}
|
||||
|
||||
private fun parseIsTestRoot(parts: List<String>) =
|
||||
testSuffixes.any { suffix -> parts.any { it.equals(suffix, ignoreCase = true) } }
|
||||
|
||||
private fun parseIndex(parts: List<String>): Int? {
|
||||
return parts.singleOrNull() { it.startsWith("id") }?.substringAfter("id")?.toInt()
|
||||
}
|
||||
|
||||
private data class ModuleId(
|
||||
val groupName: String,
|
||||
val platform: IdePlatform<*, *>,
|
||||
val index: Int = 0
|
||||
) {
|
||||
fun ideaModuleName(): String {
|
||||
val suffix = "_$index".takeIf { index != 0 } ?: ""
|
||||
return "${groupName}_${platform.presentableName}$suffix"
|
||||
}
|
||||
}
|
||||
|
||||
private val IdePlatform<*, *>.presentableName: String
|
||||
get() = when {
|
||||
isCommon -> "Common"
|
||||
isJvm -> "JVM"
|
||||
isJavaScript -> "JS"
|
||||
else -> error("Unknown platform $this")
|
||||
}
|
||||
|
||||
private data class RootInfo(
|
||||
val moduleId: ModuleId,
|
||||
val isTestRoot: Boolean,
|
||||
val moduleRoot: File,
|
||||
val dependencies: List<Dependency>
|
||||
)
|
||||
|
||||
private sealed class Dependency
|
||||
private class ModuleDependency(val moduleId: ModuleId) : Dependency()
|
||||
private object StdlibDependency : Dependency()
|
||||
private object FullJdkDependency : Dependency()
|
||||
private object CoroutinesDependency : Dependency()
|
||||
private object KotlinTestDependency : Dependency()
|
||||
@@ -1,422 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.idea.quickfix
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.lang.jvm.JvmElement
|
||||
import com.intellij.lang.jvm.JvmModifier
|
||||
import com.intellij.lang.jvm.actions.*
|
||||
import com.intellij.lang.jvm.types.JvmSubstitutor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Pair.pair
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import com.intellij.psi.PsiJvmSubstitutor
|
||||
import com.intellij.psi.PsiSubstitutor
|
||||
import com.intellij.psi.PsiType
|
||||
import com.intellij.psi.codeStyle.SuggestedNameInfo
|
||||
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
|
||||
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase
|
||||
import org.jetbrains.kotlin.idea.search.allScope
|
||||
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
||||
import org.jetbrains.uast.UParameter
|
||||
import org.jetbrains.uast.UastContext
|
||||
import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner
|
||||
import org.jetbrains.uast.toUElement
|
||||
import org.junit.Assert
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(JUnit3WithIdeaConfigurationRunner::class)
|
||||
class CommonIntentionActionsTest : LightPlatformCodeInsightFixtureTestCase() {
|
||||
private class SimpleMethodRequest(
|
||||
project: Project,
|
||||
private val methodName: String,
|
||||
private val modifiers: Collection<JvmModifier> = emptyList(),
|
||||
private val returnType: ExpectedTypes = emptyList(),
|
||||
private val annotations: Collection<AnnotationRequest> = emptyList(),
|
||||
private val parameters: List<Pair<SuggestedNameInfo, List<ExpectedType>>> = emptyList(),
|
||||
private val targetSubstitutor: JvmSubstitutor = PsiJvmSubstitutor(project, PsiSubstitutor.EMPTY)
|
||||
) : CreateMethodRequest {
|
||||
override fun getTargetSubstitutor(): JvmSubstitutor = targetSubstitutor
|
||||
|
||||
override fun getModifiers() = modifiers
|
||||
|
||||
override fun getMethodName() = methodName
|
||||
|
||||
override fun getAnnotations() = annotations
|
||||
|
||||
override fun getParameters() = parameters
|
||||
|
||||
override fun getReturnType() = returnType
|
||||
|
||||
override fun isValid(): Boolean = true
|
||||
|
||||
}
|
||||
|
||||
private class NameInfo(vararg names: String) : SuggestedNameInfo(names)
|
||||
|
||||
override fun getProjectDescriptor() = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE_FULL_JDK
|
||||
|
||||
fun testMakeNotFinal() {
|
||||
myFixture.configureByText("foo.kt", """
|
||||
class Foo {
|
||||
fun bar<caret>(){}
|
||||
}
|
||||
""")
|
||||
|
||||
myFixture.launchAction(
|
||||
createModifierActions(
|
||||
myFixture.atCaret(), MemberRequest.Modifier(JvmModifier.FINAL, false)
|
||||
).findWithText("Make 'bar' open")
|
||||
)
|
||||
myFixture.checkResult("""
|
||||
class Foo {
|
||||
open fun bar(){}
|
||||
}
|
||||
""")
|
||||
}
|
||||
|
||||
fun testMakePrivate() {
|
||||
myFixture.configureByText("foo.kt", """
|
||||
class Foo<caret> {
|
||||
fun bar(){}
|
||||
}
|
||||
""")
|
||||
|
||||
myFixture.launchAction(
|
||||
createModifierActions(
|
||||
myFixture.atCaret(), MemberRequest.Modifier(JvmModifier.PRIVATE, true)
|
||||
).findWithText("Make 'Foo' private")
|
||||
)
|
||||
myFixture.checkResult("""
|
||||
private class Foo {
|
||||
fun bar(){}
|
||||
}
|
||||
""")
|
||||
}
|
||||
|
||||
fun testMakeNotPrivate() {
|
||||
myFixture.configureByText("foo.kt", """
|
||||
private class Foo<caret> {
|
||||
fun bar(){}
|
||||
}
|
||||
""".trim())
|
||||
|
||||
myFixture.launchAction(
|
||||
createModifierActions(
|
||||
myFixture.atCaret(), MemberRequest.Modifier(JvmModifier.PRIVATE, false)
|
||||
).findWithText("Remove 'private' modifier")
|
||||
)
|
||||
myFixture.checkResult("""
|
||||
class Foo {
|
||||
fun bar(){}
|
||||
}
|
||||
""".trim(), true)
|
||||
}
|
||||
|
||||
fun testMakePrivatePublic() {
|
||||
myFixture.configureByText(
|
||||
"foo.kt", """class Foo {
|
||||
| private fun <caret>bar(){}
|
||||
|}""".trim().trimMargin()
|
||||
)
|
||||
|
||||
myFixture.launchAction(
|
||||
createModifierActions(
|
||||
myFixture.atCaret(), MemberRequest.Modifier(JvmModifier.PUBLIC, true)
|
||||
).findWithText("Remove 'private' modifier")
|
||||
)
|
||||
myFixture.checkResult(
|
||||
"""class Foo {
|
||||
| fun <caret>bar(){}
|
||||
|}""".trim().trimMargin(), true
|
||||
)
|
||||
}
|
||||
|
||||
fun testMakeProtectedPublic() {
|
||||
myFixture.configureByText(
|
||||
"foo.kt", """open class Foo {
|
||||
| protected fun <caret>bar(){}
|
||||
|}""".trim().trimMargin()
|
||||
)
|
||||
|
||||
myFixture.launchAction(
|
||||
createModifierActions(
|
||||
myFixture.atCaret(), MemberRequest.Modifier(JvmModifier.PUBLIC, true)
|
||||
).findWithText("Remove 'protected' modifier")
|
||||
)
|
||||
myFixture.checkResult(
|
||||
"""open class Foo {
|
||||
| fun <caret>bar(){}
|
||||
|}""".trim().trimMargin(), true
|
||||
)
|
||||
}
|
||||
|
||||
fun testMakeInternalPublic() {
|
||||
myFixture.configureByText(
|
||||
"foo.kt", """class Foo {
|
||||
| internal fun <caret>bar(){}
|
||||
|}""".trim().trimMargin()
|
||||
)
|
||||
|
||||
myFixture.launchAction(
|
||||
createModifierActions(
|
||||
myFixture.atCaret(), MemberRequest.Modifier(JvmModifier.PUBLIC, true)
|
||||
).findWithText("Remove 'internal' modifier")
|
||||
)
|
||||
myFixture.checkResult(
|
||||
"""class Foo {
|
||||
| fun <caret>bar(){}
|
||||
|}""".trim().trimMargin(), true
|
||||
)
|
||||
}
|
||||
|
||||
fun testDontMakePublicPublic() {
|
||||
myFixture.configureByText(
|
||||
"foo.kt", """class Foo {
|
||||
| fun <caret>bar(){}
|
||||
|}""".trim().trimMargin()
|
||||
)
|
||||
|
||||
assertEmpty(createModifierActions(myFixture.atCaret(), MemberRequest.Modifier(JvmModifier.PUBLIC, true)))
|
||||
}
|
||||
|
||||
fun testDontMakeFunInObjectsOpen() {
|
||||
myFixture.configureByText("foo.kt", """
|
||||
object Foo {
|
||||
fun bar<caret>(){}
|
||||
}
|
||||
""".trim())
|
||||
assertEmpty(createModifierActions(myFixture.atCaret(), MemberRequest.Modifier(JvmModifier.FINAL, false)))
|
||||
}
|
||||
|
||||
fun testAddVoidVoidMethod() {
|
||||
myFixture.configureByText("foo.kt", """
|
||||
|class Foo<caret> {
|
||||
| fun bar() {}
|
||||
|}
|
||||
""".trim().trimMargin())
|
||||
|
||||
myFixture.launchAction(
|
||||
createMethodActions(
|
||||
myFixture.atCaret(),
|
||||
methodRequest(project, "baz", JvmModifier.PRIVATE, PsiType.VOID)
|
||||
).findWithText("Add method 'baz' to 'Foo'")
|
||||
)
|
||||
myFixture.checkResult("""
|
||||
|class Foo {
|
||||
| fun bar() {}
|
||||
| private fun baz() {
|
||||
|
|
||||
| }
|
||||
|}
|
||||
""".trim().trimMargin(), true)
|
||||
}
|
||||
|
||||
fun testAddIntIntMethod() {
|
||||
myFixture.configureByText("foo.kt", """
|
||||
|class Foo<caret> {
|
||||
| fun bar() {}
|
||||
|}
|
||||
""".trim().trimMargin())
|
||||
|
||||
myFixture.launchAction(
|
||||
createMethodActions(
|
||||
myFixture.atCaret(),
|
||||
SimpleMethodRequest(project,
|
||||
methodName = "baz",
|
||||
modifiers = listOf(JvmModifier.PUBLIC),
|
||||
returnType = expectedTypes(PsiType.INT),
|
||||
parameters = expectedParams(PsiType.INT))
|
||||
).findWithText("Add method 'baz' to 'Foo'")
|
||||
)
|
||||
myFixture.checkResult("""
|
||||
|class Foo {
|
||||
| fun bar() {}
|
||||
| fun baz(param0: Int): Int {
|
||||
| TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
| }
|
||||
|}
|
||||
""".trim().trimMargin(), true)
|
||||
}
|
||||
|
||||
fun testAddIntPrimaryConstructor() {
|
||||
myFixture.configureByText("foo.kt", """
|
||||
|class Foo<caret> {
|
||||
|}
|
||||
""".trim().trimMargin())
|
||||
|
||||
myFixture.launchAction(
|
||||
createConstructorActions(
|
||||
myFixture.atCaret(), constructorRequest(project, listOf(pair("param0", PsiType.INT as PsiType)))
|
||||
).findWithText("Add primary constructor to 'Foo'")
|
||||
)
|
||||
myFixture.checkResult("""
|
||||
|class Foo(param0: Int) {
|
||||
|}
|
||||
""".trim().trimMargin(), true)
|
||||
}
|
||||
|
||||
fun testAddIntSecondaryConstructor() {
|
||||
myFixture.configureByText("foo.kt", """
|
||||
|class <caret>Foo() {
|
||||
|}
|
||||
""".trim().trimMargin())
|
||||
|
||||
myFixture.launchAction(
|
||||
createConstructorActions(
|
||||
myFixture.atCaret(),
|
||||
constructorRequest(project, listOf(pair("param0", PsiType.INT as PsiType)))
|
||||
).findWithText("Add secondary constructor to 'Foo'")
|
||||
)
|
||||
myFixture.checkResult("""
|
||||
|class Foo() {
|
||||
| constructor(param0: Int) {
|
||||
|
|
||||
| }
|
||||
|}
|
||||
""".trim().trimMargin(), true)
|
||||
}
|
||||
|
||||
fun testChangePrimaryConstructorInt() {
|
||||
myFixture.configureByText("foo.kt", """
|
||||
|class <caret>Foo() {
|
||||
|}
|
||||
""".trim().trimMargin())
|
||||
|
||||
myFixture.launchAction(
|
||||
createConstructorActions(
|
||||
myFixture.atCaret(),
|
||||
constructorRequest(project, listOf(pair("param0", PsiType.INT as PsiType)))
|
||||
).findWithText("Add 'int' as 1st parameter to method 'Foo'")
|
||||
)
|
||||
myFixture.checkResult("""
|
||||
|class Foo(param0: Int) {
|
||||
|}
|
||||
""".trim().trimMargin(), true)
|
||||
}
|
||||
|
||||
fun testRemoveConstructorParameters() {
|
||||
myFixture.configureByText("foo.kt", """
|
||||
|class <caret>Foo(i: Int) {
|
||||
|}
|
||||
""".trim().trimMargin())
|
||||
|
||||
myFixture.launchAction(
|
||||
createConstructorActions(
|
||||
myFixture.atCaret(),
|
||||
constructorRequest(project, emptyList())
|
||||
).findWithText("Remove 1st parameter from method 'Foo'")
|
||||
)
|
||||
myFixture.checkResult("""
|
||||
|class Foo() {
|
||||
|}
|
||||
""".trim().trimMargin(), true)
|
||||
}
|
||||
|
||||
fun testAddStringVarProperty() {
|
||||
myFixture.configureByText("foo.kt", """
|
||||
|class Foo<caret> {
|
||||
| fun bar() {}
|
||||
|}
|
||||
""".trim().trimMargin())
|
||||
|
||||
myFixture.launchAction(
|
||||
createPropertyActions(
|
||||
myFixture.atCaret(),
|
||||
MemberRequest.Property(
|
||||
propertyName = "baz",
|
||||
visibilityModifier = JvmModifier.PUBLIC,
|
||||
propertyType = PsiType.getTypeByName("java.lang.String", project, project.allScope()),
|
||||
getterRequired = true,
|
||||
setterRequired = true
|
||||
)
|
||||
).findWithText("Add 'var' property 'baz' to 'Foo'")
|
||||
)
|
||||
myFixture.checkResult("""
|
||||
|class Foo {
|
||||
| var baz: String = TODO("initialize me")
|
||||
|
|
||||
| fun bar() {}
|
||||
|}
|
||||
""".trim().trimMargin(), true)
|
||||
}
|
||||
|
||||
fun testAddLateInitStringVarProperty() {
|
||||
myFixture.configureByText("foo.kt", """
|
||||
|class Foo<caret> {
|
||||
| fun bar() {}
|
||||
|}
|
||||
""".trim().trimMargin())
|
||||
|
||||
myFixture.launchAction(
|
||||
createPropertyActions(
|
||||
myFixture.atCaret(),
|
||||
MemberRequest.Property(
|
||||
propertyName = "baz",
|
||||
visibilityModifier = JvmModifier.PUBLIC,
|
||||
propertyType = PsiType.getTypeByName("java.lang.String", project, project.allScope()),
|
||||
getterRequired = true,
|
||||
setterRequired = true
|
||||
)
|
||||
).findWithText("Add 'lateinit var' property 'baz' to 'Foo'")
|
||||
)
|
||||
myFixture.checkResult("""
|
||||
|class Foo {
|
||||
| lateinit var baz: String
|
||||
|
|
||||
| fun bar() {}
|
||||
|}
|
||||
""".trim().trimMargin(), true)
|
||||
}
|
||||
|
||||
fun testAddStringValProperty() {
|
||||
myFixture.configureByText("foo.kt", """
|
||||
|class Foo<caret> {
|
||||
| fun bar() {}
|
||||
|}
|
||||
""".trim().trimMargin())
|
||||
|
||||
myFixture.launchAction(
|
||||
createPropertyActions(
|
||||
myFixture.atCaret(),
|
||||
MemberRequest.Property(
|
||||
propertyName = "baz",
|
||||
visibilityModifier = JvmModifier.PUBLIC,
|
||||
propertyType = PsiType.getTypeByName("java.lang.String", project, project.allScope()),
|
||||
getterRequired = true,
|
||||
setterRequired = false
|
||||
)
|
||||
).findWithText("Add 'val' property 'baz' to 'Foo'")
|
||||
)
|
||||
myFixture.checkResult("""
|
||||
|class Foo {
|
||||
| val baz: String = TODO("initialize me")
|
||||
|
|
||||
| fun bar() {}
|
||||
|}
|
||||
""".trim().trimMargin(), true)
|
||||
}
|
||||
|
||||
private fun makeParams(vararg psyTypes: PsiType): List<UParameter> {
|
||||
val uastContext = UastContext(myFixture.project)
|
||||
val factory = JavaPsiFacade.getElementFactory(myFixture.project)
|
||||
val parameters = psyTypes.mapIndexed { index, psiType -> factory.createParameter("param$index", psiType) }
|
||||
return parameters.map { uastContext.convertElement(it, null, UParameter::class.java) as UParameter }
|
||||
}
|
||||
|
||||
private fun expectedTypes(vararg psiTypes: PsiType) = psiTypes.map { expectedType(it) }
|
||||
|
||||
private fun expectedParams(vararg psyTypes: PsiType) =
|
||||
psyTypes.mapIndexed { index, psiType -> NameInfo("param$index") to expectedTypes(psiType) }
|
||||
|
||||
private inline fun <reified T : JvmElement> CodeInsightTestFixture.atCaret() = elementAtCaret.toUElement() as T
|
||||
|
||||
@Suppress("CAST_NEVER_SUCCEEDS")
|
||||
private fun List<IntentionAction>.findWithText(text: String): IntentionAction =
|
||||
this.firstOrNull { it.text == text } ?:
|
||||
Assert.fail("intention with text '$text' was not found, only ${this.joinToString { "\"${it.text}\"" }} available") as Nothing
|
||||
}
|
||||
|
||||
-208
@@ -1,208 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.idea.refactoring.move
|
||||
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.testFramework.PlatformTestCase
|
||||
import com.intellij.testFramework.PsiTestUtil
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.MoveKotlinDeclarationsHandler
|
||||
import org.jetbrains.kotlin.idea.refactoring.toPsiDirectory
|
||||
import org.jetbrains.kotlin.idea.refactoring.toPsiFile
|
||||
import org.jetbrains.kotlin.idea.test.KotlinMultiFileTestCase
|
||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
||||
import org.jetbrains.kotlin.idea.test.extractMultipleMarkerOffsets
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(JUnit3WithIdeaConfigurationRunner::class)
|
||||
class MoveKotlinDeclarationsHandlerTest : KotlinMultiFileTestCase() {
|
||||
override fun getTestDataPath() = PluginTestCaseBase.getTestDataPathBase()
|
||||
|
||||
override fun getTestRoot() = "/refactoring/moveHandler/declarations"
|
||||
|
||||
private fun doTest(action: (rootDir: VirtualFile, handler: MoveKotlinDeclarationsHandler) -> Unit) {
|
||||
val path = "$testDataPath$testRoot/${getTestName(true)}"
|
||||
val rootDir = PsiTestUtil.createTestProjectStructure(myProject, myModule, path, PlatformTestCase.myFilesToDelete, false)
|
||||
prepareProject(rootDir)
|
||||
PsiDocumentManager.getInstance(myProject).commitAllDocuments()
|
||||
action(rootDir, MoveKotlinDeclarationsHandler())
|
||||
}
|
||||
|
||||
private fun getPsiDirectory(rootDir: VirtualFile, path: String) = rootDir.findFileByRelativePath(path)!!.toPsiDirectory(project)!!
|
||||
|
||||
private fun getPsiFile(rootDir: VirtualFile, path: String) = rootDir.findFileByRelativePath(path)!!.toPsiFile(project)!!
|
||||
|
||||
private fun getElementAtCaret(rootDir: VirtualFile, path: String) = getElementsAtCarets(rootDir, path).single()
|
||||
|
||||
private fun getElementsAtCarets(rootDir: VirtualFile, path: String): List<PsiElement> {
|
||||
val file = getPsiFile(rootDir, path)
|
||||
val document = FileDocumentManager.getInstance().getDocument(file.virtualFile)!!
|
||||
return document.extractMultipleMarkerOffsets(project).map { file.findElementAt(it)!! }
|
||||
}
|
||||
|
||||
fun testObjectLiteral() = doTest { rootDir, handler ->
|
||||
val objectDeclaration = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtObjectDeclaration>()!!
|
||||
assert(!handler.canMove(arrayOf<PsiElement>(objectDeclaration), null))
|
||||
}
|
||||
|
||||
fun testLocalClass() = doTest { rootDir, handler ->
|
||||
val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!
|
||||
assert(!handler.canMove(arrayOf<PsiElement>(klass), null))
|
||||
}
|
||||
|
||||
fun testLocalFun() = doTest { rootDir, handler ->
|
||||
val function = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtNamedFunction>()!!
|
||||
assert(!handler.canMove(arrayOf<PsiElement>(function), null))
|
||||
}
|
||||
|
||||
fun testLocalVal() = doTest { rootDir, handler ->
|
||||
val property = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtProperty>()!!
|
||||
assert(!handler.canMove(arrayOf<PsiElement>(property), null))
|
||||
}
|
||||
|
||||
fun testMemberFun() = doTest { rootDir, handler ->
|
||||
val function = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtNamedFunction>()!!
|
||||
assert(!handler.canMove(arrayOf<PsiElement>(function), null))
|
||||
}
|
||||
|
||||
fun testMemberVal() = doTest { rootDir, handler ->
|
||||
val property = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtProperty>()!!
|
||||
assert(!handler.canMove(arrayOf<PsiElement>(property), null))
|
||||
}
|
||||
|
||||
fun testNestedClass() = doTest { rootDir, handler ->
|
||||
val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!
|
||||
assert(handler.canMove(arrayOf<PsiElement>(klass), null))
|
||||
}
|
||||
|
||||
fun testInnerClass() = doTest { rootDir, handler ->
|
||||
val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!
|
||||
assert(handler.canMove(arrayOf<PsiElement>(klass), null))
|
||||
}
|
||||
|
||||
fun testTopLevelClass() = doTest { rootDir, handler ->
|
||||
val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!
|
||||
assert(handler.canMove(arrayOf<PsiElement>(klass), null))
|
||||
}
|
||||
|
||||
fun testTopLevelFun() = doTest { rootDir, handler ->
|
||||
val function = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtNamedFunction>()!!
|
||||
assert(handler.canMove(arrayOf<PsiElement>(function), null))
|
||||
}
|
||||
|
||||
fun testTopLevelVal() = doTest { rootDir, handler ->
|
||||
val property = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtProperty>()!!
|
||||
assert(handler.canMove(arrayOf<PsiElement>(property), null))
|
||||
}
|
||||
|
||||
fun testMultipleNestedClasses() = doTest { rootDir, handler ->
|
||||
val classes = getElementsAtCarets(rootDir, "test.kt").map { it.getNonStrictParentOfType<KtClass>()!! }
|
||||
assert(handler.canMove(classes.toTypedArray(), null))
|
||||
}
|
||||
|
||||
fun testNestedAndTopLevelClass() = doTest { rootDir, handler ->
|
||||
val classes = getElementsAtCarets(rootDir, "test.kt").map { it.getNonStrictParentOfType<KtClass>()!! }
|
||||
assert(!handler.canMove(classes.toTypedArray(), null))
|
||||
}
|
||||
|
||||
fun testMultipleTopLevelDeclarations() = doTest { rootDir, handler ->
|
||||
val declarations = getElementsAtCarets(rootDir, "test.kt").map { it.getNonStrictParentOfType<KtNamedDeclaration>()!! }
|
||||
assert(handler.canMove(declarations.toTypedArray(), null))
|
||||
}
|
||||
|
||||
fun testMultipleTopLevelDeclarationsInDifferentFiles() = doTest { rootDir, handler ->
|
||||
val declarations = listOf("test.kt", "test2.kt")
|
||||
.flatMap { getElementsAtCarets(rootDir, it) }
|
||||
.map { it.getNonStrictParentOfType<KtNamedDeclaration>()!! }
|
||||
assert(handler.canMove(declarations.toTypedArray(), null))
|
||||
|
||||
val files = listOf("test.kt", "test2.kt").map { getPsiFile(rootDir, it) }
|
||||
assert(handler.canMove(files.toTypedArray(), null))
|
||||
}
|
||||
|
||||
fun testMultipleTopLevelDeclarationsInDifferentDirs() = doTest { rootDir, handler ->
|
||||
val declarations = listOf("test1/test.kt", "test2/test2.kt")
|
||||
.flatMap { getElementsAtCarets(rootDir, it) }
|
||||
.map { it.getNonStrictParentOfType<KtNamedDeclaration>()!! }
|
||||
assert(!handler.canMove(declarations.toTypedArray(), null))
|
||||
|
||||
val files = listOf("test1/test.kt", "test2/test2.kt").map { getPsiFile(rootDir, it) }
|
||||
assert(!handler.canMove(files.toTypedArray(), null))
|
||||
}
|
||||
|
||||
fun testFileAndTopLevelDeclarations() = doTest { rootDir, handler ->
|
||||
val elements = getElementsAtCarets(rootDir, "test.kt").map { it.getNonStrictParentOfType<KtNamedDeclaration>()!! } +
|
||||
getPsiFile(rootDir, "test2.kt")
|
||||
assert(!handler.canMove(elements.toTypedArray(), null))
|
||||
}
|
||||
|
||||
fun testCommonTargets() = doTest { rootDir, handler ->
|
||||
val elementsToMove = arrayOf<PsiElement>(getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!)
|
||||
|
||||
val targetPackage = JavaPsiFacade.getInstance(project).findPackage("pack")!!
|
||||
assert(handler.canMove(elementsToMove, targetPackage))
|
||||
|
||||
val targetDirectory = getPsiDirectory(rootDir, "pack")
|
||||
assert(handler.canMove(elementsToMove, targetDirectory))
|
||||
|
||||
val targetFile = getPsiFile(rootDir, "pack/test2.kt")
|
||||
assert(handler.canMove(elementsToMove, targetFile))
|
||||
}
|
||||
|
||||
fun testTopLevelClassToClass() = doTest { rootDir, handler ->
|
||||
val elementsToMove = arrayOf<PsiElement>(getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!)
|
||||
val targetFile = getPsiFile(rootDir, "test2.kt") as KtFile
|
||||
|
||||
val topLevelTarget = targetFile.declarations.firstIsInstance<KtClass>()
|
||||
assert(topLevelTarget.name == "B")
|
||||
assert(!handler.canMove(elementsToMove, topLevelTarget))
|
||||
|
||||
val annotationTarget = targetFile.declarations.first { it.name == "Ann" } as KtClass
|
||||
assert(!handler.canMove(elementsToMove, annotationTarget))
|
||||
|
||||
val nestedTarget = topLevelTarget.declarations.firstIsInstance<KtClass>()
|
||||
assert(nestedTarget.name == "C")
|
||||
assert(!handler.canMove(elementsToMove, nestedTarget))
|
||||
}
|
||||
|
||||
fun testNestedClassToClass() = doTest { rootDir, handler ->
|
||||
val elementsToMove = arrayOf<PsiElement>(getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!)
|
||||
val targetFile = getPsiFile(rootDir, "test2.kt") as KtFile
|
||||
|
||||
val topLevelTarget = targetFile.declarations.firstIsInstance<KtClass>()
|
||||
assert(topLevelTarget.name == "B")
|
||||
assert(handler.canMove(elementsToMove, topLevelTarget))
|
||||
|
||||
val annotationTarget = targetFile.declarations.first { it.name == "Ann" } as KtClass
|
||||
assert(!handler.canMove(elementsToMove, annotationTarget))
|
||||
|
||||
val nestedTarget = topLevelTarget.declarations.firstIsInstance<KtClass>()
|
||||
assert(nestedTarget.name == "C")
|
||||
assert(handler.canMove(elementsToMove, nestedTarget))
|
||||
}
|
||||
|
||||
fun testTypeAlias() = doTest { rootDir, handler ->
|
||||
val typeAlias = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtTypeAlias>()!!
|
||||
assert(handler.canMove(arrayOf<PsiElement>(typeAlias), null))
|
||||
}
|
||||
|
||||
fun testTopLevelFunInScript() = doTest { rootDir, handler ->
|
||||
val function = getElementAtCaret(rootDir, "test.kts").getNonStrictParentOfType<KtNamedFunction>()!!
|
||||
assert(handler.canMove(arrayOf<PsiElement>(function), null))
|
||||
}
|
||||
|
||||
fun testTopLevelValInScript() = doTest { rootDir, handler ->
|
||||
val property = getElementAtCaret(rootDir, "test.kts").getNonStrictParentOfType<KtProperty>()!!
|
||||
assert(handler.canMove(arrayOf<PsiElement>(property), null))
|
||||
}
|
||||
}
|
||||
@@ -1,297 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.idea.run
|
||||
|
||||
import com.intellij.execution.Location
|
||||
import com.intellij.execution.PsiLocation
|
||||
import com.intellij.execution.actions.ConfigurationContext
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.roots.ModuleRootModificationUtil
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import com.intellij.psi.PsiComment
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.refactoring.RefactoringFactory
|
||||
import com.intellij.testFramework.MapDataContext
|
||||
import com.intellij.testFramework.PlatformTestCase
|
||||
import com.intellij.testFramework.PsiTestUtil
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||
import org.jetbrains.kotlin.idea.MainFunctionDetector
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.search.allScope
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinFullClassNameIndex
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelFunctionFqnNameIndex
|
||||
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
|
||||
import org.jetbrains.kotlin.idea.test.KotlinCodeInsightTestCase
|
||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase.*
|
||||
import org.jetbrains.kotlin.idea.test.configureLanguageAndApiVersion
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.allChildren
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner
|
||||
import org.junit.Assert
|
||||
import org.junit.runner.RunWith
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
private val RUN_PREFIX = "// RUN:"
|
||||
|
||||
@RunWith(JUnit3WithIdeaConfigurationRunner::class)
|
||||
class RunConfigurationTest: KotlinCodeInsightTestCase() {
|
||||
fun getTestProject() = myProject!!
|
||||
override fun getModule() = myModule!!
|
||||
|
||||
fun testMainInTest() {
|
||||
val createResult = configureModule(moduleDirPath("module"), getTestProject().baseDir!!)
|
||||
configureLanguageAndApiVersion(
|
||||
createResult.module.project, createResult.module, LanguageVersionSettingsImpl.DEFAULT.languageVersion.versionString
|
||||
)
|
||||
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(createResult.module, addJdk(testRootDisposable, ::mockJdk))
|
||||
|
||||
val runConfiguration = createConfigurationFromMain("some.main")
|
||||
val javaParameters = getJavaRunParameters(runConfiguration)
|
||||
|
||||
Assert.assertTrue(javaParameters.classPath.rootDirs.contains(createResult.srcOutputDir))
|
||||
Assert.assertTrue(javaParameters.classPath.rootDirs.contains(createResult.testOutputDir))
|
||||
|
||||
fun functionVisitor(function: KtNamedFunction) {
|
||||
val options = function.bodyExpression?.allChildren?.filterIsInstance<PsiComment>()?.map { it.text.trim().replace("//", "").trim() }?.filter { it.isNotBlank() }?.toList() ?: emptyList()
|
||||
if (options.isNotEmpty()) {
|
||||
val assertIsMain = "yes" in options
|
||||
val assertIsNotMain = "no" in options
|
||||
|
||||
val isMainFunction =
|
||||
MainFunctionDetector(LanguageVersionSettingsImpl.DEFAULT) { it.resolveToDescriptorIfAny() }.isMain(function)
|
||||
|
||||
if (assertIsMain) {
|
||||
Assert.assertTrue("The function ${function.fqName?.asString()} should be main", isMainFunction)
|
||||
}
|
||||
if (assertIsNotMain) {
|
||||
Assert.assertFalse("The function ${function.fqName?.asString()} should NOT be main", isMainFunction)
|
||||
}
|
||||
|
||||
if (isMainFunction) {
|
||||
createConfigurationFromMain(function.fqName?.asString()!!).checkConfiguration()
|
||||
|
||||
Assert.assertNotNull("Kotlin configuration producer should produce configuration for ${function.fqName?.asString()}",
|
||||
KotlinRunConfigurationProducer.getEntryPointContainer(function))
|
||||
} else {
|
||||
try {
|
||||
createConfigurationFromMain(function.fqName?.asString()!!).checkConfiguration()
|
||||
Assert.fail("configuration for function ${function.fqName?.asString()} at least shouldn't pass checkConfiguration()")
|
||||
} catch (expected: Throwable) {
|
||||
}
|
||||
|
||||
if (function.containingFile.text.startsWith("// entryPointExists")) {
|
||||
Assert.assertNotNull(
|
||||
"Kotlin configuration producer should produce configuration for ${function.fqName?.asString()}",
|
||||
KotlinRunConfigurationProducer.getEntryPointContainer(function)
|
||||
)
|
||||
} else {
|
||||
Assert.assertNull(
|
||||
"Kotlin configuration producer shouldn't produce configuration for ${function.fqName?.asString()}",
|
||||
KotlinRunConfigurationProducer.getEntryPointContainer(function)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createResult.srcDir.children.filter { it.extension == "kt" }.forEach {
|
||||
val psiFile = PsiManager.getInstance(createResult.module.project).findFile(it)
|
||||
if (psiFile is KtFile) {
|
||||
psiFile.acceptChildren(object : KtVisitorVoid() {
|
||||
override fun visitNamedFunction(function: KtNamedFunction) {
|
||||
functionVisitor(function)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun testDependencyModuleClasspath() {
|
||||
val dependencyModuleSrcDir = configureModule(moduleDirPath("module"), getTestProject().baseDir!!).srcOutputDir
|
||||
|
||||
val moduleWithDependencyDir = runWriteAction { getTestProject().baseDir!!.createChildDirectory(this, "moduleWithDependency") }
|
||||
|
||||
val moduleWithDependency = createModule("moduleWithDependency")
|
||||
ModuleRootModificationUtil.setModuleSdk(moduleWithDependency, testProjectJdk)
|
||||
|
||||
val moduleWithDependencySrcDir = configureModule(
|
||||
moduleDirPath("moduleWithDependency"), moduleWithDependencyDir, configModule = moduleWithDependency).srcOutputDir
|
||||
|
||||
ModuleRootModificationUtil.addDependency(moduleWithDependency, module)
|
||||
|
||||
val kotlinRunConfiguration = createConfigurationFromMain("some.test.main")
|
||||
kotlinRunConfiguration.setModule(moduleWithDependency)
|
||||
|
||||
val javaParameters = getJavaRunParameters(kotlinRunConfiguration)
|
||||
|
||||
Assert.assertTrue(javaParameters.classPath.rootDirs.contains(dependencyModuleSrcDir))
|
||||
Assert.assertTrue(javaParameters.classPath.rootDirs.contains(moduleWithDependencySrcDir))
|
||||
}
|
||||
|
||||
fun testLongCommandLine() {
|
||||
val myModule = configureModule(moduleDirPath("module"), getTestProject().baseDir).module
|
||||
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(module, addJdk(testRootDisposable, ::mockJdk))
|
||||
|
||||
ModuleRootModificationUtil.addDependency(myModule, createLibraryWithLongPaths(project))
|
||||
|
||||
val kotlinRunConfiguration = createConfigurationFromMain("some.test.main")
|
||||
kotlinRunConfiguration.setModule(myModule)
|
||||
|
||||
val javaParameters = getJavaRunParameters(kotlinRunConfiguration)
|
||||
val commandLine = javaParameters.toCommandLine().commandLineString
|
||||
Assert.assertTrue(commandLine.length < javaParameters.classPath.pathList.joinToString().length)
|
||||
}
|
||||
|
||||
fun testClassesAndObjects() {
|
||||
doTest(ConfigLibraryUtil::configureKotlinRuntimeAndSdk)
|
||||
}
|
||||
|
||||
fun testInJsModule() {
|
||||
doTest(ConfigLibraryUtil::configureKotlinJsRuntimeAndSdk)
|
||||
}
|
||||
|
||||
fun testUpdateOnClassRename() {
|
||||
val createModuleResult = configureModule(moduleDirPath("module"), getTestProject().baseDir!!)
|
||||
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(createModuleResult.module, addJdk(testRootDisposable, ::mockJdk))
|
||||
|
||||
val runConfiguration = createConfigurationFromObject("renameTest.Foo", save = true)
|
||||
|
||||
val obj = KotlinFullClassNameIndex.getInstance().get("renameTest.Foo", getTestProject(), getTestProject().allScope()).single()
|
||||
val rename = RefactoringFactory.getInstance(getTestProject()).createRename(obj, "Bar")
|
||||
rename.run()
|
||||
|
||||
Assert.assertEquals("renameTest.Bar", runConfiguration.MAIN_CLASS_NAME)
|
||||
}
|
||||
|
||||
fun testUpdateOnPackageRename() {
|
||||
val createModuleResult = configureModule(moduleDirPath("module"), getTestProject().baseDir!!)
|
||||
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(createModuleResult.module, addJdk(testRootDisposable, ::mockJdk))
|
||||
|
||||
val runConfiguration = createConfigurationFromObject("renameTest.Foo", save = true)
|
||||
|
||||
val pkg = JavaPsiFacade.getInstance(getTestProject()).findPackage("renameTest")!!
|
||||
val rename = RefactoringFactory.getInstance(getTestProject()).createRename(pkg, "afterRenameTest")
|
||||
rename.run()
|
||||
|
||||
Assert.assertEquals("afterRenameTest.Foo", runConfiguration.MAIN_CLASS_NAME)
|
||||
}
|
||||
|
||||
fun testWithModuleForJdk6() {
|
||||
checkModuleInfoName(null, addJdk(testRootDisposable, ::mockJdk))
|
||||
}
|
||||
|
||||
fun testWithModuleForJdk9() {
|
||||
checkModuleInfoName("MAIN", addJdk(testRootDisposable, ::mockJdk9))
|
||||
}
|
||||
|
||||
fun testWithModuleForJdk9WithoutModuleInfo() {
|
||||
checkModuleInfoName(null, addJdk(testRootDisposable, ::mockJdk9))
|
||||
}
|
||||
|
||||
private fun checkModuleInfoName(moduleName: String?, sdk: Sdk) {
|
||||
val module = configureModule(moduleDirPath("module"), getTestProject().baseDir!!).module
|
||||
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(module, sdk)
|
||||
|
||||
val javaParameters = getJavaRunParameters(createConfigurationFromMain("some.main"))
|
||||
|
||||
Assert.assertEquals(moduleName, javaParameters.moduleName)
|
||||
}
|
||||
|
||||
private fun doTest(configureRuntime: (Module, Sdk) -> Unit) {
|
||||
val baseDir = getTestProject().baseDir!!
|
||||
val createModuleResult = configureModule(moduleDirPath("module"), baseDir)
|
||||
val srcDir = createModuleResult.srcDir
|
||||
|
||||
configureRuntime(createModuleResult.module, addJdk(testRootDisposable, ::mockJdk))
|
||||
|
||||
try {
|
||||
val expectedClasses = ArrayList<String>()
|
||||
val actualClasses = ArrayList<String>()
|
||||
|
||||
val testFile = PsiManager.getInstance(getTestProject()).findFile(srcDir.findFileByRelativePath("test.kt")!!)!!
|
||||
testFile.accept(
|
||||
object : KtTreeVisitorVoid() {
|
||||
override fun visitComment(comment: PsiComment) {
|
||||
val declaration = comment.getStrictParentOfType<KtNamedDeclaration>()!!
|
||||
val text = comment.text ?: return
|
||||
if (!text.startsWith(RUN_PREFIX)) return
|
||||
|
||||
val expectedClass = text.substring(RUN_PREFIX.length).trim()
|
||||
if (expectedClass.isNotEmpty()) expectedClasses.add(expectedClass)
|
||||
|
||||
val dataContext = MapDataContext()
|
||||
dataContext.put(Location.DATA_KEY, PsiLocation(getTestProject(), declaration))
|
||||
val context = ConfigurationContext.getFromContext(dataContext)
|
||||
val actualClass = (context.configuration?.configuration as? KotlinRunConfiguration)?.runClass
|
||||
if (actualClass != null) {
|
||||
actualClasses.add(actualClass)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
Assert.assertEquals(expectedClasses, actualClasses)
|
||||
}
|
||||
finally {
|
||||
ConfigLibraryUtil.unConfigureKotlinRuntimeAndSdk(createModuleResult.module, mockJdk())
|
||||
}
|
||||
}
|
||||
|
||||
private fun createConfigurationFromMain(mainFqn: String): KotlinRunConfiguration {
|
||||
val mainFunction = KotlinTopLevelFunctionFqnNameIndex.getInstance().get(mainFqn, getTestProject(), getTestProject().allScope()).first()
|
||||
|
||||
return createConfigurationFromElement(mainFunction) as KotlinRunConfiguration
|
||||
}
|
||||
|
||||
private fun createConfigurationFromObject(objectFqn: String, save: Boolean = false): KotlinRunConfiguration {
|
||||
val obj = KotlinFullClassNameIndex.getInstance().get(objectFqn, getTestProject(), getTestProject().allScope()).single()
|
||||
val mainFunction = obj.declarations.single { it is KtFunction && it.getName() == "main" }
|
||||
return createConfigurationFromElement(mainFunction, save) as KotlinRunConfiguration
|
||||
}
|
||||
|
||||
private fun configureModule(moduleDir: String, outputParentDir: VirtualFile, configModule: Module = module): CreateModuleResult {
|
||||
val srcPath = moduleDir + "/src"
|
||||
val srcDir = PsiTestUtil.createTestProjectStructure(project, configModule, srcPath, PlatformTestCase.myFilesToDelete, true)
|
||||
|
||||
val testPath = moduleDir + "/test"
|
||||
if (File(testPath).exists()) {
|
||||
val testDir = PsiTestUtil.createTestProjectStructure(project, configModule, testPath, PlatformTestCase.myFilesToDelete, false)
|
||||
PsiTestUtil.addSourceRoot(module, testDir, true)
|
||||
}
|
||||
|
||||
val (srcOutDir, testOutDir) = runWriteAction {
|
||||
val outDir = outputParentDir.createChildDirectory(this, "out")
|
||||
val srcOutDir = outDir.createChildDirectory(this, "production")
|
||||
val testOutDir = outDir.createChildDirectory(this, "test")
|
||||
|
||||
PsiTestUtil.setCompilerOutputPath(configModule, srcOutDir.url, false)
|
||||
PsiTestUtil.setCompilerOutputPath(configModule, testOutDir.url, true)
|
||||
|
||||
Pair(srcOutDir, testOutDir)
|
||||
}
|
||||
|
||||
PsiDocumentManager.getInstance(getTestProject()).commitAllDocuments()
|
||||
|
||||
return CreateModuleResult(configModule, srcDir, srcOutDir, testOutDir)
|
||||
}
|
||||
|
||||
private fun moduleDirPath(moduleName: String) = "${testDataPath}${getTestName(false)}/$moduleName"
|
||||
|
||||
override fun getTestDataPath() = getTestDataPathBase() + "/run/"
|
||||
override fun getTestProjectJdk() = mockJdk()
|
||||
|
||||
private class CreateModuleResult(
|
||||
val module: Module,
|
||||
val srcDir: VirtualFile,
|
||||
val srcOutputDir: VirtualFile,
|
||||
val testOutputDir: VirtualFile
|
||||
)
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.test
|
||||
|
||||
// BUNCH: 181
|
||||
@Suppress("IncompatibleAPI")
|
||||
class HierarchyViewTestFixture : HierarchyViewTestFixtureCompat()
|
||||
-128
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.j2k
|
||||
|
||||
import com.intellij.codeInsight.ContainerProvider
|
||||
import com.intellij.codeInsight.NullableNotNullManager
|
||||
import com.intellij.codeInsight.runner.JavaMainMethodProvider
|
||||
import com.intellij.core.CoreApplicationEnvironment
|
||||
import com.intellij.core.JavaCoreApplicationEnvironment
|
||||
import com.intellij.core.JavaCoreProjectEnvironment
|
||||
import com.intellij.lang.MetaLanguage
|
||||
import com.intellij.lang.jvm.facade.JvmElementProvider
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import com.intellij.openapi.extensions.ExtensionsArea
|
||||
import com.intellij.openapi.fileTypes.FileTypeExtensionPoint
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.augment.PsiAugmentProvider
|
||||
import com.intellij.psi.augment.TypeAnnotationModifier
|
||||
import com.intellij.psi.compiled.ClassFileDecompilers
|
||||
import com.intellij.psi.impl.JavaClassSupersImpl
|
||||
import com.intellij.psi.impl.PsiTreeChangePreprocessor
|
||||
import com.intellij.psi.impl.compiled.ClsCustomNavigationPolicy
|
||||
import com.intellij.psi.meta.MetaDataContributor
|
||||
import com.intellij.psi.stubs.BinaryFileStubBuilders
|
||||
import com.intellij.psi.util.JavaClassSupers
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.kotlin.utils.PathUtil
|
||||
import java.io.File
|
||||
import java.net.URLClassLoader
|
||||
|
||||
abstract class AbstractJavaToKotlinConverterForWebDemoTest : TestCase() {
|
||||
val DISPOSABLE = Disposer.newDisposable()
|
||||
|
||||
fun doTest(javaPath: String) {
|
||||
try {
|
||||
val fileContents = FileUtil.loadFile(File(javaPath), true)
|
||||
val javaCoreEnvironment: JavaCoreProjectEnvironment = setUpJavaCoreEnvironment()
|
||||
translateToKotlin(fileContents, javaCoreEnvironment.project)
|
||||
}
|
||||
finally {
|
||||
Disposer.dispose(DISPOSABLE)
|
||||
}
|
||||
}
|
||||
|
||||
fun setUpJavaCoreEnvironment(): JavaCoreProjectEnvironment {
|
||||
Extensions.cleanRootArea(DISPOSABLE)
|
||||
val area = Extensions.getRootArea()
|
||||
|
||||
registerExtensionPoints(area)
|
||||
|
||||
val applicationEnvironment = JavaCoreApplicationEnvironment(DISPOSABLE)
|
||||
val javaCoreEnvironment = object : JavaCoreProjectEnvironment(DISPOSABLE, applicationEnvironment) {
|
||||
override fun preregisterServices() {
|
||||
val projectArea = Extensions.getArea(project)
|
||||
CoreApplicationEnvironment.registerExtensionPoint(projectArea, PsiTreeChangePreprocessor.EP_NAME, PsiTreeChangePreprocessor::class.java)
|
||||
CoreApplicationEnvironment.registerExtensionPoint(projectArea, PsiElementFinder.EP_NAME, PsiElementFinder::class.java)
|
||||
CoreApplicationEnvironment.registerExtensionPoint(projectArea, JvmElementProvider.EP_NAME, JvmElementProvider::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
javaCoreEnvironment.project.registerService(NullableNotNullManager::class.java, object : NullableNotNullManager(javaCoreEnvironment.project) {
|
||||
override fun isNullable(owner: PsiModifierListOwner, checkBases: Boolean) = !isNotNull(owner, checkBases)
|
||||
override fun isNotNull(owner: PsiModifierListOwner, checkBases: Boolean) = true
|
||||
override fun hasHardcodedContracts(element: PsiElement): Boolean = false
|
||||
override fun getPredefinedNotNulls() = emptyList<String>()
|
||||
})
|
||||
|
||||
applicationEnvironment.application.registerService(JavaClassSupers::class.java, JavaClassSupersImpl::class.java)
|
||||
|
||||
for (root in PathUtil.getJdkClassesRootsFromCurrentJre()) {
|
||||
javaCoreEnvironment.addJarToClassPath(root)
|
||||
}
|
||||
val annotations: File? = findAnnotations()
|
||||
if (annotations != null && annotations.exists()) {
|
||||
javaCoreEnvironment.addJarToClassPath(annotations)
|
||||
}
|
||||
return javaCoreEnvironment
|
||||
}
|
||||
|
||||
private fun registerExtensionPoints(area: ExtensionsArea) {
|
||||
CoreApplicationEnvironment.registerExtensionPoint(area, BinaryFileStubBuilders.EP_NAME, FileTypeExtensionPoint::class.java)
|
||||
CoreApplicationEnvironment.registerExtensionPoint(area, FileContextProvider.EP_NAME, FileContextProvider::class.java)
|
||||
|
||||
CoreApplicationEnvironment.registerExtensionPoint(area, MetaDataContributor.EP_NAME, MetaDataContributor::class.java)
|
||||
CoreApplicationEnvironment.registerExtensionPoint(area, PsiAugmentProvider.EP_NAME, PsiAugmentProvider::class.java)
|
||||
CoreApplicationEnvironment.registerExtensionPoint(area, JavaMainMethodProvider.EP_NAME, JavaMainMethodProvider::class.java)
|
||||
|
||||
CoreApplicationEnvironment.registerExtensionPoint(area, ContainerProvider.EP_NAME, ContainerProvider::class.java)
|
||||
CoreApplicationEnvironment.registerExtensionPoint(area, ClsCustomNavigationPolicy.EP_NAME, ClsCustomNavigationPolicy::class.java)
|
||||
CoreApplicationEnvironment.registerExtensionPoint(area, ClassFileDecompilers.EP_NAME, ClassFileDecompilers.Decompiler::class.java)
|
||||
|
||||
CoreApplicationEnvironment.registerExtensionPoint(area, TypeAnnotationModifier.EP_NAME, TypeAnnotationModifier::class.java)
|
||||
CoreApplicationEnvironment.registerExtensionPoint(area, MetaLanguage.EP_NAME, MetaLanguage::class.java)
|
||||
CoreApplicationEnvironment.registerExtensionPoint(area, JavaModuleSystem.EP_NAME, JavaModuleSystem::class.java)
|
||||
}
|
||||
|
||||
fun findAnnotations(): File? {
|
||||
var classLoader = JavaToKotlinTranslator::class.java.classLoader
|
||||
while (classLoader != null) {
|
||||
val loader = classLoader
|
||||
if (loader is URLClassLoader) {
|
||||
for (url in loader.urLs) {
|
||||
if ("file" == url.protocol && url.file!!.endsWith("/annotations.jar")) {
|
||||
return File(url.file!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
classLoader = classLoader.parent
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
* 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.jps.build
|
||||
|
||||
import org.jetbrains.jps.incremental.CompileContext
|
||||
import org.jetbrains.jps.incremental.messages.CompilerMessage
|
||||
|
||||
fun jpsReportInternalBuilderError(context: CompileContext, error: Throwable) {
|
||||
KotlinBuilder.LOG.info(error)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user