diff --git a/TeamCityBuild.xml.as32 b/TeamCityBuild.xml.as32
new file mode 100644
index 00000000000..52adddc64bb
--- /dev/null
+++ b/TeamCityBuild.xml.as32
@@ -0,0 +1,144 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ @{prop}=${@{prop}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/buildSrc/gradle.properties.as32 b/buildSrc/gradle.properties.as32
new file mode 100644
index 00000000000..5f8abd5de3c
--- /dev/null
+++ b/buildSrc/gradle.properties.as32
@@ -0,0 +1,9 @@
+org.gradle.daemon=true
+org.gradle.parallel=false
+org.gradle.configureondemand=false
+org.gradle.jvmargs=-Duser.country=US -Dkotlin.daemon.jvm.options=-Xmx1600m
+
+#buildSrc.kotlin.repo=https://jcenter.bintray.com
+#buildSrc.kotlin.version=1.1.50
+
+intellijUltimateEnabled=false
diff --git a/compiler/android-tests/tests/org/jetbrains/kotlin/android/tests/AndroidJpsBuildTestCase.java.as32 b/compiler/android-tests/tests/org/jetbrains/kotlin/android/tests/AndroidJpsBuildTestCase.java.as32
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/compiler/android-tests/tests/org/jetbrains/kotlin/android/tests/AndroidRunner.java.as32 b/compiler/android-tests/tests/org/jetbrains/kotlin/android/tests/AndroidRunner.java.as32
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/ClasspathRootsResolver.kt.as32 b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/ClasspathRootsResolver.kt.as32
new file mode 100644
index 00000000000..5478ad70e2a
--- /dev/null
+++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/ClasspathRootsResolver.kt.as32
@@ -0,0 +1,335 @@
+/*
+ * 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.cli.jvm.compiler
+
+import com.intellij.openapi.vfs.StandardFileSystems
+import com.intellij.openapi.vfs.VfsUtilCore
+import com.intellij.openapi.vfs.VirtualFile
+import com.intellij.psi.PsiJavaModule
+import com.intellij.openapi.vfs.VirtualFileManager
+import com.intellij.psi.PsiManager
+import com.intellij.psi.impl.light.LightJavaModule
+import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
+import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
+import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
+import org.jetbrains.kotlin.cli.common.messages.MessageCollector
+import org.jetbrains.kotlin.cli.common.messages.MessageUtil
+import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot
+import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
+import org.jetbrains.kotlin.cli.jvm.config.JvmContentRoot
+import org.jetbrains.kotlin.cli.jvm.config.JvmModulePathRoot
+import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
+import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleFinder
+import org.jetbrains.kotlin.cli.jvm.modules.JavaModuleGraph
+import org.jetbrains.kotlin.config.ContentRoot
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.name.isValidJavaFqName
+import org.jetbrains.kotlin.resolve.jvm.modules.JavaModule
+import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleInfo
+import org.jetbrains.kotlin.resolve.jvm.modules.KOTLIN_STDLIB_MODULE_NAME
+import java.io.IOException
+import java.util.jar.Attributes
+import java.util.jar.Manifest
+import kotlin.LazyThreadSafetyMode.NONE
+
+class ClasspathRootsResolver(
+ private val psiManager: PsiManager,
+ private val messageCollector: MessageCollector?,
+ private val additionalModules: List,
+ private val contentRootToVirtualFile: (JvmContentRoot) -> VirtualFile?,
+ private val javaModuleFinder: CliJavaModuleFinder,
+ private val requireStdlibModule: Boolean,
+ private val outputDirectory: VirtualFile?
+) {
+ val javaModuleGraph = JavaModuleGraph(javaModuleFinder)
+
+ data class RootsAndModules(val roots: List, val modules: List)
+
+ private data class RootWithPrefix(val root: VirtualFile, val packagePrefix: String?)
+
+ fun convertClasspathRoots(contentRoots: List): RootsAndModules {
+ val javaSourceRoots = mutableListOf()
+ val jvmClasspathRoots = mutableListOf()
+ val jvmModulePathRoots = mutableListOf()
+
+ for (contentRoot in contentRoots) {
+ if (contentRoot !is JvmContentRoot) continue
+ val root = contentRootToVirtualFile(contentRoot) ?: continue
+ when (contentRoot) {
+ is JavaSourceRoot -> javaSourceRoots += RootWithPrefix(root, contentRoot.packagePrefix)
+ is JvmClasspathRoot -> jvmClasspathRoots += root
+ is JvmModulePathRoot -> jvmModulePathRoots += root
+ else -> error("Unknown root type: $contentRoot")
+ }
+ }
+
+ return computeRoots(javaSourceRoots, jvmClasspathRoots, jvmModulePathRoots)
+ }
+
+ private fun computeRoots(
+ javaSourceRoots: List,
+ jvmClasspathRoots: List,
+ jvmModulePathRoots: List
+ ): RootsAndModules {
+ val result = mutableListOf()
+ val modules = mutableListOf()
+
+ val hasOutputDirectoryInClasspath = outputDirectory in jvmClasspathRoots || outputDirectory in jvmModulePathRoots
+
+ for ((root, packagePrefix) in javaSourceRoots) {
+ val modularRoot = modularSourceRoot(root, hasOutputDirectoryInClasspath)
+ if (modularRoot != null) {
+ modules += modularRoot
+ }
+ else {
+ result += JavaRoot(root, JavaRoot.RootType.SOURCE, packagePrefix?.let { prefix ->
+ if (isValidJavaFqName(prefix)) FqName(prefix)
+ else null.also {
+ report(STRONG_WARNING, "Invalid package prefix name is ignored: $prefix")
+ }
+ })
+ }
+ }
+
+ for (root in jvmClasspathRoots) {
+ result += JavaRoot(root, JavaRoot.RootType.BINARY)
+ }
+
+ val outputDirectoryAddedAsPartOfModule = modules.any { module -> module.moduleRoots.any { it.file == outputDirectory } }
+
+ for (root in jvmModulePathRoots) {
+ // Do not add output directory as a separate module if we're compiling an explicit named module.
+ // It's going to be included as a root of our module in modularSourceRoot.
+ if (outputDirectoryAddedAsPartOfModule && root == outputDirectory) continue
+
+ val module = modularBinaryRoot(root)
+ if (module != null) {
+ modules += module
+ }
+ }
+
+ addModularRoots(modules, result)
+
+ return RootsAndModules(result, modules)
+ }
+
+/*
+ private fun findSourceModuleInfo(root: VirtualFile): Pair? {
+ val moduleInfoFile =
+ when {
+ root.isDirectory -> root.findChild(PsiJavaModule.MODULE_INFO_FILE)
+ root.name == PsiJavaModule.MODULE_INFO_FILE -> root
+ else -> null
+ } ?: return null
+
+ val psiFile = psiManager.findFile(moduleInfoFile) ?: return null
+ val psiJavaModule = psiFile.children.singleOrNull { it is PsiJavaModule } as? PsiJavaModule ?: return null
+
+ return moduleInfoFile to psiJavaModule
+ }
+ */
+
+ private fun modularSourceRoot(root: VirtualFile, hasOutputDirectoryInClasspath: Boolean): JavaModule.Explicit? {
+ /*
+ val (moduleInfoFile, psiJavaModule) = findSourceModuleInfo(root) ?: return null
+ val sourceRoot = JavaModule.Root(root, isBinary = false)
+ val roots =
+ if (hasOutputDirectoryInClasspath)
+ listOf(sourceRoot, JavaModule.Root(outputDirectory!!, isBinary = true))
+ else listOf(sourceRoot)
+ return JavaModule.Explicit(JavaModuleInfo.create(psiJavaModule), roots, moduleInfoFile)
+ */
+ return null
+ }
+
+ private fun modularBinaryRoot(root: VirtualFile): JavaModule? {
+ val isJar = root.fileSystem.protocol == StandardFileSystems.JAR_PROTOCOL
+ val manifest: Attributes? by lazy(NONE) { readManifestAttributes(root) }
+
+ /*
+ val moduleInfoFile =
+ root.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE)
+ ?: root.takeIf { isJar }?.findFileByRelativePath(MULTI_RELEASE_MODULE_INFO_CLS_FILE)?.takeIf {
+ manifest?.getValue(IS_MULTI_RELEASE)?.equals("true", ignoreCase = true) == true
+ }
+
+ if (moduleInfoFile != null) {
+ val moduleInfo = JavaModuleInfo.read(moduleInfoFile) ?: return null
+ return JavaModule.Explicit(moduleInfo, listOf(JavaModule.Root(root, isBinary = true)), moduleInfoFile)
+ }
+ */
+
+ // Only .jar files can be automatic modules
+ if (isJar) {
+ val moduleRoot = listOf(JavaModule.Root(root, isBinary = true))
+
+ val automaticModuleName = manifest?.getValue(AUTOMATIC_MODULE_NAME)
+ if (automaticModuleName != null) {
+ return JavaModule.Automatic(automaticModuleName, moduleRoot)
+ }
+
+ val originalFile = VfsUtilCore.virtualToIoFile(root)
+ val moduleName = LightJavaModule.moduleName(originalFile.nameWithoutExtension)
+ if (moduleName.isEmpty()) {
+ report(ERROR, "Cannot infer automatic module name for the file", VfsUtilCore.getVirtualFileForJar(root) ?: root)
+ return null
+ }
+ return JavaModule.Automatic(moduleName, moduleRoot)
+ }
+
+ return null
+ }
+
+ private fun readManifestAttributes(jarRoot: VirtualFile): Attributes? {
+ val manifestFile = jarRoot.findChild("META-INF")?.findChild("MANIFEST.MF")
+ return try {
+ manifestFile?.inputStream?.let(::Manifest)?.mainAttributes
+ }
+ catch (e: IOException) {
+ null
+ }
+ }
+
+ private fun addModularRoots(modules: List, result: MutableList) {
+ // In current implementation, at most one source module is supported. This can be relaxed in the future if we support another
+ // compilation mode, similar to java's --module-source-path
+ val sourceModules = modules.filterIsInstance().filter(JavaModule::isSourceModule)
+ if (sourceModules.size > 1) {
+ for (module in sourceModules) {
+ report(ERROR, "Too many source module declarations found", module.moduleInfoFile)
+ }
+ return
+ }
+
+ for (module in modules) {
+ val existing = javaModuleFinder.findModule(module.name)
+ if (existing == null) {
+ javaModuleFinder.addUserModule(module)
+ }
+ else if (module.moduleRoots != existing.moduleRoots) {
+ fun JavaModule.getRootFile() =
+ moduleRoots.firstOrNull()?.file?.let { VfsUtilCore.getVirtualFileForJar(it) ?: it }
+
+ val thisFile = module.getRootFile()
+ val existingFile = existing.getRootFile()
+ val atExistingPath = if (existingFile == null) "" else " at: ${existingFile.path}"
+ report(STRONG_WARNING, "The root is ignored because a module with the same name '${module.name}' " +
+ "has been found earlier on the module path$atExistingPath", thisFile)
+ }
+ }
+
+ if (javaModuleFinder.allObservableModules.none()) return
+
+ val sourceModule = sourceModules.singleOrNull()
+ val addAllModulePathToRoots = "ALL-MODULE-PATH" in additionalModules
+ if (addAllModulePathToRoots && sourceModule != null) {
+ report(ERROR, "-Xadd-modules=ALL-MODULE-PATH can only be used when compiling the unnamed module")
+ return
+ }
+
+ val rootModules = when {
+ sourceModule != null -> listOf(sourceModule.name) + additionalModules
+ addAllModulePathToRoots -> modules.map(JavaModule::name)
+ else -> computeDefaultRootModules() + additionalModules
+ }
+
+ val allDependencies = javaModuleGraph.getAllDependencies(rootModules)
+ if (allDependencies.any { moduleName -> javaModuleFinder.findModule(moduleName) is JavaModule.Automatic }) {
+ // According to java.lang.module javadoc, if at least one automatic module is added to the module graph,
+ // all observable automatic modules should be added.
+ // There are no automatic modules in the JDK, so we select all automatic modules out of user modules
+ for (module in modules) {
+ if (module is JavaModule.Automatic) {
+ allDependencies += module.name
+ }
+ }
+ }
+
+ report(LOGGING, "Loading modules: $allDependencies")
+
+ for (moduleName in allDependencies) {
+ val module = javaModuleFinder.findModule(moduleName)
+ if (module == null) {
+ report(ERROR, "Module $moduleName cannot be found in the module graph")
+ }
+ else {
+ for ((root, isBinary) in module.moduleRoots) {
+ result.add(JavaRoot(root, if (isBinary) JavaRoot.RootType.BINARY else JavaRoot.RootType.SOURCE))
+ }
+ }
+ }
+
+ if (requireStdlibModule && sourceModule != null && !javaModuleGraph.reads(sourceModule.name, KOTLIN_STDLIB_MODULE_NAME)) {
+ report(
+ ERROR,
+ "The Kotlin standard library is not found in the module graph. " +
+ "Please ensure you have the 'requires $KOTLIN_STDLIB_MODULE_NAME' clause in your module definition",
+ sourceModule.moduleInfoFile
+ )
+ }
+ }
+
+ // See http://openjdk.java.net/jeps/261
+ private fun computeDefaultRootModules(): List {
+ val result = arrayListOf()
+
+ val systemModules = javaModuleFinder.systemModules.associateBy(JavaModule::name)
+ val javaSeExists = "java.se" in systemModules
+ if (javaSeExists) {
+ // The java.se module is a root, if it exists.
+ result.add("java.se")
+ }
+
+ fun JavaModule.Explicit.exportsAtLeastOnePackageUnqualified(): Boolean = moduleInfo.exports.any { it.toModules.isEmpty() }
+
+ if (!javaSeExists) {
+ // If it does not exist then every java.* module on the upgrade module path or among the system modules
+ // that exports at least one package, without qualification, is a root.
+ for ((name, module) in systemModules) {
+ if (name.startsWith("java.") && module.exportsAtLeastOnePackageUnqualified()) {
+ result.add(name)
+ }
+ }
+ }
+
+ for ((name, module) in systemModules) {
+ // Every non-java.* module on the upgrade module path or among the system modules that exports at least one package,
+ // without qualification, is also a root.
+ if (!name.startsWith("java.") && module.exportsAtLeastOnePackageUnqualified()) {
+ result.add(name)
+ }
+ }
+
+ return result
+ }
+
+ private fun report(severity: CompilerMessageSeverity, message: String, file: VirtualFile? = null) {
+ if (messageCollector == null) {
+ throw IllegalStateException("${if (file != null) file.path + ":" else ""}$severity: $message (no MessageCollector configured)")
+ }
+ messageCollector.report(
+ severity, message,
+ if (file == null) null else CompilerMessageLocation.create(MessageUtil.virtualFileToPath(file))
+ )
+ }
+
+ private companion object {
+ const val MULTI_RELEASE_MODULE_INFO_CLS_FILE = "META-INF/versions/9/${PsiJavaModule.MODULE_INFO_CLS_FILE}"
+ const val AUTOMATIC_MODULE_NAME = "Automatic-Module-Name"
+ const val IS_MULTI_RELEASE = "Multi-Release"
+ }
+}
diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt.as32 b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt.as32
new file mode 100644
index 00000000000..d6c8a1b03ec
--- /dev/null
+++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt.as32
@@ -0,0 +1,302 @@
+/*
+ * 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.cli.jvm.compiler
+
+import com.intellij.core.CoreJavaFileManager
+import com.intellij.openapi.diagnostic.Logger
+import com.intellij.openapi.util.text.StringUtil
+import com.intellij.openapi.vfs.VirtualFile
+import com.intellij.psi.*
+import com.intellij.psi.impl.file.PsiPackageImpl
+import com.intellij.psi.search.GlobalSearchScope
+import gnu.trove.THashMap
+import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
+import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex
+import org.jetbrains.kotlin.cli.jvm.index.SingleJavaFileRootsIndex
+import org.jetbrains.kotlin.load.java.structure.JavaClass
+import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
+import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryClassSignatureParser
+import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass
+import org.jetbrains.kotlin.load.java.structure.impl.classFiles.ClassifierResolutionContext
+import org.jetbrains.kotlin.load.java.structure.impl.classFiles.isNotTopLevelClass
+import org.jetbrains.kotlin.name.ClassId
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.resolve.jvm.KotlinCliJavaFileManager
+import org.jetbrains.kotlin.util.PerformanceCounter
+import org.jetbrains.kotlin.utils.addIfNotNull
+import java.util.*
+
+// TODO: do not inherit from CoreJavaFileManager to avoid accidental usage of its methods which do not use caches/indices
+// Currently, the only relevant usage of this class as CoreJavaFileManager is at CoreJavaDirectoryService.getPackage,
+// which is indirectly invoked from PsiPackage.getSubPackages
+class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJavaFileManager(myPsiManager), KotlinCliJavaFileManager {
+ private val perfCounter = PerformanceCounter.create("Find Java class")
+ private lateinit var index: JvmDependenciesIndex
+ private lateinit var singleJavaFileRootsIndex: SingleJavaFileRootsIndex
+ private lateinit var packagePartProviders: List
+ private val topLevelClassesCache: MutableMap = THashMap()
+ private val allScope = GlobalSearchScope.allScope(myPsiManager.project)
+ private var useFastClassFilesReading = false
+
+ fun initialize(
+ index: JvmDependenciesIndex,
+ packagePartProviders: List,
+ singleJavaFileRootsIndex: SingleJavaFileRootsIndex,
+ useFastClassFilesReading: Boolean
+ ) {
+ this.index = index
+ this.packagePartProviders = packagePartProviders
+ this.singleJavaFileRootsIndex = singleJavaFileRootsIndex
+ this.useFastClassFilesReading = useFastClassFilesReading
+ }
+
+ private fun findPsiClass(classId: ClassId, searchScope: GlobalSearchScope): PsiClass? = perfCounter.time {
+ findVirtualFileForTopLevelClass(classId, searchScope)?.findPsiClassInVirtualFile(classId.relativeClassName.asString())
+ }
+
+ private fun findVirtualFileForTopLevelClass(classId: ClassId, searchScope: GlobalSearchScope): VirtualFile? {
+ val relativeClassName = classId.relativeClassName.asString()
+ return topLevelClassesCache.getOrPut(classId.packageFqName.child(classId.relativeClassName.pathSegments().first())) {
+ index.findClass(classId) { dir, type ->
+ findVirtualFileGivenPackage(dir, relativeClassName, type)
+ }
+ ?: singleJavaFileRootsIndex.findJavaSourceClass(classId)
+ }?.takeIf { it in searchScope }
+ }
+
+ private val binaryCache: MutableMap = THashMap()
+ private val signatureParsingComponent =
+ BinaryClassSignatureParser()
+
+ override fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? {
+ val virtualFile = findVirtualFileForTopLevelClass(classId, searchScope) ?: return null
+
+ if (useFastClassFilesReading && virtualFile.extension == "class") {
+ // We return all class files' names in the directory in knownClassNamesInPackage method, so one may request an inner class
+ return binaryCache.getOrPut(classId) {
+ // Note that currently we implicitly suppose that searchScope for binary classes is constant and we do not use it
+ // as a key in cache
+ // This is a true assumption by now since there are two search scopes in compiler: one for sources and another one for binary
+ // When it become wrong because we introduce the modules into CLI, it's worth to consider
+ // having different KotlinCliJavaFileManagerImpl's for different modules
+ val classContent = virtualFile.contentsToByteArray()
+ if (virtualFile.nameWithoutExtension.contains("$") && isNotTopLevelClass(classContent)) return@getOrPut null
+ classId.outerClassId?.let { outerClassId ->
+ val outerClass = findClass(outerClassId, searchScope)
+ return@getOrPut outerClass?.findInnerClass(classId.shortClassName)
+ }
+
+ val resolver = ClassifierResolutionContext { findClass(it, allScope) }
+
+ BinaryJavaClass(
+ virtualFile,
+ classId.asSingleFqName(),
+ resolver,
+ signatureParsingComponent,
+ outerClass = null,
+ classContent = classContent
+ )
+ }
+ }
+
+ return virtualFile.findPsiClassInVirtualFile(classId.relativeClassName.asString())?.let(::JavaClassImpl)
+ }
+
+ // this method is called from IDEA to resolve dependencies in Java code
+ // which supposedly shouldn't have errors so the dependencies exist in general
+ override fun findClass(qName: String, scope: GlobalSearchScope): PsiClass? {
+ // String cannot be reliably converted to ClassId because we don't know where the package name ends and class names begin.
+ // For example, if qName is "a.b.c.d.e", we should either look for a top level class "e" in the package "a.b.c.d",
+ // or, for example, for a nested class with the relative qualified name "c.d.e" in the package "a.b".
+ // Below, we start by looking for the top level class "e" in the package "a.b.c.d" first, then for the class "d.e" in the package
+ // "a.b.c", and so on, until we find something. Most classes are top level, so most of the times the search ends quickly
+
+ forEachClassId(qName) { classId ->
+ findPsiClass(classId, scope)?.let { return it }
+ }
+
+ return null
+ }
+
+ private inline fun forEachClassId(fqName: String, block: (ClassId) -> Unit) {
+ var classId = fqName.toSafeTopLevelClassId() ?: return
+
+ while (true) {
+ block(classId)
+
+ val packageFqName = classId.packageFqName
+ if (packageFqName.isRoot) break
+
+ classId = ClassId(
+ packageFqName.parent(),
+ FqName(packageFqName.shortName().asString() + "." + classId.relativeClassName.asString()),
+ false
+ )
+ }
+ }
+
+ override fun findClasses(qName: String, scope: GlobalSearchScope): Array = perfCounter.time {
+ val result = ArrayList(1)
+ forEachClassId(qName) { classId ->
+ val relativeClassName = classId.relativeClassName.asString()
+ index.traverseDirectoriesInPackage(classId.packageFqName) { dir, rootType ->
+ val psiClass =
+ findVirtualFileGivenPackage(dir, relativeClassName, rootType)
+ ?.takeIf { it in scope }
+ ?.findPsiClassInVirtualFile(relativeClassName)
+ if (psiClass != null) {
+ result.add(psiClass)
+ }
+ // traverse all
+ true
+ }
+
+ result.addIfNotNull(
+ singleJavaFileRootsIndex.findJavaSourceClass(classId)
+ ?.takeIf { it in scope }
+ ?.findPsiClassInVirtualFile(relativeClassName)
+ )
+
+ if (result.isNotEmpty()) {
+ return@time result.toTypedArray()
+ }
+ }
+
+ PsiClass.EMPTY_ARRAY
+ }
+
+ override fun findPackage(packageName: String): PsiPackage? {
+ var found = false
+ val packageFqName = packageName.toSafeFqName() ?: return null
+ index.traverseDirectoriesInPackage(packageFqName) { _, _ ->
+ found = true
+ //abort on first found
+ false
+ }
+ if (!found) {
+ found = packagePartProviders.any { it.findPackageParts(packageName).isNotEmpty() }
+ }
+ if (!found) {
+ found = singleJavaFileRootsIndex.findJavaSourceClasses(packageFqName).isNotEmpty()
+ }
+ return if (found) PsiPackageImpl(myPsiManager, packageName) else null
+ }
+
+ private fun findVirtualFileGivenPackage(
+ packageDir: VirtualFile,
+ classNameWithInnerClasses: String,
+ rootType: JavaRoot.RootType
+ ): VirtualFile? {
+ val topLevelClassName = classNameWithInnerClasses.substringBefore('.')
+
+ val vFile = when (rootType) {
+ JavaRoot.RootType.BINARY -> packageDir.findChild("$topLevelClassName.class")
+ JavaRoot.RootType.SOURCE -> packageDir.findChild("$topLevelClassName.java")
+ } ?: return null
+
+ if (!vFile.isValid) {
+ LOG.error("Invalid child of valid parent: ${vFile.path}; ${packageDir.isValid} path=${packageDir.path}")
+ return null
+ }
+
+ return vFile
+ }
+
+ private fun VirtualFile.findPsiClassInVirtualFile(
+ classNameWithInnerClasses: String
+ ): PsiClass? {
+ val file = myPsiManager.findFile(this) as? PsiClassOwner ?: return null
+ return findClassInPsiFile(classNameWithInnerClasses, file)
+ }
+
+ override fun knownClassNamesInPackage(packageFqName: FqName): Set {
+ val result = hashSetOf()
+ index.traverseDirectoriesInPackage(packageFqName, continueSearch = {
+ dir, _ ->
+
+ for (child in dir.children) {
+ if (child.extension == "class" || child.extension == "java") {
+ result.add(child.nameWithoutExtension)
+ }
+ }
+
+ true
+ })
+
+ for (classId in singleJavaFileRootsIndex.findJavaSourceClasses(packageFqName)) {
+ assert(!classId.isNestedClass) { "ClassId of a single .java source class should not be nested: $classId" }
+ result.add(classId.shortClassName.asString())
+ }
+
+ return result
+ }
+
+/*
+ override fun findModules(moduleName: String, scope: GlobalSearchScope): Collection {
+ // TODO
+ return emptySet()
+ }
+*/
+
+ override fun getNonTrivialPackagePrefixes(): Collection = emptyList()
+
+ companion object {
+ private val LOG = Logger.getInstance(KotlinCliJavaFileManagerImpl::class.java)
+
+ private fun findClassInPsiFile(classNameWithInnerClassesDotSeparated: String, file: PsiClassOwner): PsiClass? {
+ for (topLevelClass in file.classes) {
+ val candidate = findClassByTopLevelClass(classNameWithInnerClassesDotSeparated, topLevelClass)
+ if (candidate != null) {
+ return candidate
+ }
+ }
+ return null
+ }
+
+ private fun findClassByTopLevelClass(className: String, topLevelClass: PsiClass): PsiClass? {
+ if (className.indexOf('.') < 0) {
+ return if (className == topLevelClass.name) topLevelClass else null
+ }
+
+ val segments = StringUtil.split(className, ".").iterator()
+ if (!segments.hasNext() || segments.next() != topLevelClass.name) {
+ return null
+ }
+ var curClass = topLevelClass
+ while (segments.hasNext()) {
+ val innerClassName = segments.next()
+ val innerClass = curClass.findInnerClassByName(innerClassName, false) ?: return null
+ curClass = innerClass
+ }
+ return curClass
+ }
+ }
+}
+
+// a sad workaround to avoid throwing exception when called from inside IDEA code
+private fun safely(compute: () -> T): T? = try {
+ compute()
+}
+catch (e: IllegalArgumentException) {
+ null
+}
+catch (e: AssertionError) {
+ null
+}
+
+private fun String.toSafeFqName(): FqName? = safely { FqName(this) }
+private fun String.toSafeTopLevelClassId(): ClassId? = safely { ClassId.topLevel(FqName(this)) }
diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt.as32 b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt.as32
new file mode 100644
index 00000000000..243a22cd8f6
--- /dev/null
+++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt.as32
@@ -0,0 +1,484 @@
+/*
+ * 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.cli.jvm.compiler
+
+import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.vfs.VirtualFile
+import com.intellij.psi.PsiManager
+import com.intellij.psi.impl.PsiModificationTrackerImpl
+import com.intellij.psi.search.DelegatingGlobalSearchScope
+import com.intellij.psi.search.GlobalSearchScope
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import org.jetbrains.kotlin.asJava.FilteredJvmDiagnostics
+import org.jetbrains.kotlin.backend.common.output.OutputFileCollection
+import org.jetbrains.kotlin.backend.common.output.SimpleOutputFileCollection
+import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
+import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
+import org.jetbrains.kotlin.cli.common.ExitCode
+import org.jetbrains.kotlin.cli.common.checkKotlinPackageUsage
+import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
+import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.OUTPUT
+import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.WARNING
+import org.jetbrains.kotlin.cli.common.messages.MessageCollector
+import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
+import org.jetbrains.kotlin.cli.common.output.outputUtils.writeAll
+import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
+import org.jetbrains.kotlin.cli.jvm.config.*
+import org.jetbrains.kotlin.codegen.*
+import org.jetbrains.kotlin.codegen.state.GenerationState
+import org.jetbrains.kotlin.codegen.state.GenerationStateEventCallback
+import org.jetbrains.kotlin.config.*
+import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
+import org.jetbrains.kotlin.idea.MainFunctionDetector
+import org.jetbrains.kotlin.javac.JavacWrapper
+import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager
+import org.jetbrains.kotlin.modules.Module
+import org.jetbrains.kotlin.modules.TargetId
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.script.tryConstructClassFromStringArgs
+import org.jetbrains.kotlin.util.PerformanceCounter
+import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize
+import java.io.File
+import java.lang.reflect.InvocationTargetException
+import java.net.URLClassLoader
+import java.util.concurrent.TimeUnit
+
+object KotlinToJVMBytecodeCompiler {
+
+ private fun getAbsolutePaths(buildFile: File, module: Module): List {
+ return module.getSourceFiles().map { sourceFile ->
+ val source = File(sourceFile)
+ if (!source.isAbsolute) {
+ File(buildFile.absoluteFile.parentFile, sourceFile).absolutePath
+ }
+ else {
+ source.absolutePath
+ }
+ }
+ }
+
+ private fun writeOutput(
+ configuration: CompilerConfiguration,
+ outputFiles: OutputFileCollection,
+ mainClass: FqName?
+ ) {
+ val reportOutputFiles = configuration.getBoolean(CommonConfigurationKeys.REPORT_OUTPUT_FILES)
+ val jarPath = configuration.get(JVMConfigurationKeys.OUTPUT_JAR)
+ val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)
+ if (jarPath != null) {
+ val includeRuntime = configuration.get(JVMConfigurationKeys.INCLUDE_RUNTIME, false)
+ CompileEnvironmentUtil.writeToJar(jarPath, includeRuntime, mainClass, outputFiles)
+ if (reportOutputFiles) {
+ val message = OutputMessageUtil.formatOutputMessage(outputFiles.asList().flatMap { it.sourceFiles }.distinct(), jarPath)
+ messageCollector.report(OUTPUT, message)
+ }
+ return
+ }
+
+ val outputDir = configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY) ?: File(".")
+ outputFiles.writeAll(outputDir, messageCollector, reportOutputFiles)
+ }
+
+ private fun createOutputFilesFlushingCallbackIfPossible(configuration: CompilerConfiguration): GenerationStateEventCallback {
+ if (configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY) == null) {
+ return GenerationStateEventCallback.DO_NOTHING
+ }
+ return GenerationStateEventCallback { state ->
+ val currentOutput = SimpleOutputFileCollection(state.factory.currentOutput)
+ writeOutput(configuration, currentOutput, mainClass = null)
+ if (!configuration.get(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, false)) {
+ state.factory.releaseGeneratedOutput()
+ }
+ }
+ }
+
+ internal fun compileModules(environment: KotlinCoreEnvironment, buildFile: File, chunk: List): Boolean {
+ ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
+
+ val moduleVisibilityManager = ModuleVisibilityManager.SERVICE.getInstance(environment.project)
+
+ val projectConfiguration = environment.configuration
+ for (module in chunk) {
+ moduleVisibilityManager.addModule(module)
+ }
+
+ val friendPaths = environment.configuration.getList(JVMConfigurationKeys.FRIEND_PATHS)
+ for (path in friendPaths) {
+ moduleVisibilityManager.addFriendPath(path)
+ }
+
+ val targetDescription = "in targets [" + chunk.joinToString { input -> input.getModuleName() + "-" + input.getModuleType() } + "]"
+
+ val result = repeatAnalysisIfNeeded(analyze(environment, targetDescription), environment, targetDescription)
+ if (result == null || !result.shouldGenerateCode) return false
+
+ ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
+
+ result.throwIfError()
+
+ val outputs = newLinkedHashMapWithExpectedSize(chunk.size)
+
+ for (module in chunk) {
+ ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
+ val ktFiles = CompileEnvironmentUtil.getKtFiles(
+ environment.project, getAbsolutePaths(buildFile, module), projectConfiguration
+ ) { path -> throw IllegalStateException("Should have been checked before: $path") }
+ if (!checkKotlinPackageUsage(environment, ktFiles)) return false
+
+ val moduleConfiguration = projectConfiguration.copy().apply {
+ put(JVMConfigurationKeys.OUTPUT_DIRECTORY, File(module.getOutputDirectory()))
+ }
+
+ outputs[module] = generate(environment, moduleConfiguration, result, ktFiles, module)
+ }
+
+ try {
+ for ((_, state) in outputs) {
+ ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
+ writeOutput(state.configuration, state.factory, null)
+ }
+
+ if (projectConfiguration.getBoolean(JVMConfigurationKeys.COMPILE_JAVA)) {
+ val singleModule = chunk.singleOrNull()
+ if (singleModule != null) {
+ return JavacWrapper.getInstance(environment.project).use {
+ it.compile(File(singleModule.getOutputDirectory()))
+ }
+ }
+ else {
+ projectConfiguration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).let {
+ it.report(WARNING, "A chunk contains multiple modules (${chunk.joinToString { it.getModuleName() }}). -Xuse-javac option couldn't be used to compile java files")
+ }
+ JavacWrapper.getInstance(environment.project).close()
+ }
+ }
+
+ return true
+ }
+ finally {
+ outputs.values.forEach(GenerationState::destroy)
+ }
+ }
+
+ internal fun configureSourceRoots(configuration: CompilerConfiguration, chunk: List, buildFile: File) {
+ for (module in chunk) {
+ configuration.addKotlinSourceRoots(getAbsolutePaths(buildFile, module))
+ }
+
+ for (module in chunk) {
+ for ((path, packagePrefix) in module.getJavaSourceRoots()) {
+ configuration.addJavaSourceRoot(File(path), packagePrefix)
+ }
+ }
+
+ val isJava9Module = false /*chunk.any { module ->
+ module.getJavaSourceRoots().any { (path, packagePrefix) ->
+ val file = File(path)
+ packagePrefix == null &&
+ (file.name == PsiJavaModule.MODULE_INFO_FILE ||
+ (file.isDirectory && file.listFiles().any { it.name == PsiJavaModule.MODULE_INFO_FILE }))
+ }
+ }*/
+
+ for (module in chunk) {
+ for (classpathRoot in module.getClasspathRoots()) {
+ configuration.add(
+ JVMConfigurationKeys.CONTENT_ROOTS,
+ if (isJava9Module) JvmModulePathRoot(File(classpathRoot)) else JvmClasspathRoot(File(classpathRoot))
+ )
+ }
+ }
+
+ for (module in chunk) {
+ val modularJdkRoot = module.modularJdkRoot
+ if (modularJdkRoot != null) {
+ // We use the SDK of the first module in the chunk, which is not always correct because some other module in the chunk
+ // might depend on a different SDK
+ configuration.put(JVMConfigurationKeys.JDK_HOME, File(modularJdkRoot))
+ break
+ }
+ }
+
+ configuration.addAll(JVMConfigurationKeys.MODULES, chunk)
+ }
+
+ private fun findMainClass(generationState: GenerationState, files: List): FqName? {
+ val mainFunctionDetector = MainFunctionDetector(generationState.bindingContext)
+ return files.asSequence()
+ .map { file ->
+ if (mainFunctionDetector.hasMain(file.declarations))
+ JvmFileClassUtil.getFileClassInfoNoResolve(file).facadeClassFqName
+ else
+ null
+ }
+ .singleOrNull { it != null }
+ }
+
+ fun compileBunchOfSources(environment: KotlinCoreEnvironment): Boolean {
+ val moduleVisibilityManager = ModuleVisibilityManager.SERVICE.getInstance(environment.project)
+
+ val friendPaths = environment.configuration.getList(JVMConfigurationKeys.FRIEND_PATHS)
+ for (path in friendPaths) {
+ moduleVisibilityManager.addFriendPath(path)
+ }
+
+ if (!checkKotlinPackageUsage(environment, environment.getSourceFiles())) return false
+
+ val generationState = analyzeAndGenerate(environment) ?: return false
+
+ val mainClass = findMainClass(generationState, environment.getSourceFiles())
+
+ try {
+ writeOutput(environment.configuration, generationState.factory, mainClass)
+ return true
+ }
+ finally {
+ generationState.destroy()
+ }
+ }
+
+ internal fun compileAndExecuteScript(environment: KotlinCoreEnvironment, scriptArgs: List): ExitCode {
+ val scriptClass = compileScript(environment) ?: return ExitCode.COMPILATION_ERROR
+
+ try {
+ try {
+ tryConstructClassFromStringArgs(scriptClass, scriptArgs)
+ ?: throw RuntimeException("unable to find appropriate constructor for class ${scriptClass.name} accepting arguments $scriptArgs\n")
+ }
+ finally {
+ // NB: these lines are required (see KT-9546) but aren't covered by tests
+ System.out.flush()
+ System.err.flush()
+ }
+ }
+ catch (e: Throwable) {
+ reportExceptionFromScript(e)
+ return ExitCode.SCRIPT_EXECUTION_ERROR
+ }
+
+ return ExitCode.OK
+ }
+
+ private fun repeatAnalysisIfNeeded(
+ result: AnalysisResult?,
+ environment: KotlinCoreEnvironment,
+ targetDescription: String?
+ ): AnalysisResult? {
+ if (result is AnalysisResult.RetryWithAdditionalJavaRoots) {
+ val configuration = environment.configuration
+
+ val oldReadOnlyValue = configuration.isReadOnly
+ configuration.isReadOnly = false
+ configuration.addJavaSourceRoots(result.additionalJavaRoots)
+ configuration.isReadOnly = oldReadOnlyValue
+
+ if (result.addToEnvironment) {
+ environment.updateClasspath(result.additionalJavaRoots.map { JavaSourceRoot(it, null) })
+ }
+
+ // Clear package caches (see KotlinJavaPsiFacade)
+ ApplicationManager.getApplication().runWriteAction {
+ (PsiManager.getInstance(environment.project).modificationTracker as? PsiModificationTrackerImpl)?.incCounter()
+ }
+
+ // Clear all diagnostic messages
+ configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY]?.clear()
+
+ // Repeat analysis with additional Java roots (kapt generated sources)
+ return analyze(environment, targetDescription)
+ }
+
+ return result
+ }
+
+ private fun reportExceptionFromScript(exception: Throwable) {
+ // expecting InvocationTargetException from constructor invocation with cause that describes the actual cause
+ val stream = System.err
+ val cause = exception.cause
+ if (exception !is InvocationTargetException || cause == null) {
+ exception.printStackTrace(stream)
+ return
+ }
+ stream.println(cause)
+ val fullTrace = cause.stackTrace
+ for (i in 0 until fullTrace.size - exception.stackTrace.size) {
+ stream.println("\tat " + fullTrace[i])
+ }
+ }
+
+ fun compileScript(environment: KotlinCoreEnvironment, parentClassLoader: ClassLoader? = null): Class<*>? {
+ val state = analyzeAndGenerate(environment) ?: return null
+
+ try {
+ val urls = environment.configuration.getList(JVMConfigurationKeys.CONTENT_ROOTS).mapNotNull { root ->
+ when (root) {
+ is JvmModulePathRoot -> root.file // TODO: only add required modules
+ is JvmClasspathRoot -> root.file
+ else -> null
+ }
+ }.map { it.toURI().toURL() }
+
+ val classLoader = GeneratedClassLoader(state.factory, parentClassLoader ?: URLClassLoader(urls.toTypedArray(), null))
+
+ val script = environment.getSourceFiles()[0].script ?: error("Script must be parsed")
+ return classLoader.loadClass(script.fqName.asString())
+ }
+ catch (e: Exception) {
+ throw RuntimeException("Failed to evaluate script: " + e, e)
+ }
+ }
+
+ fun analyzeAndGenerate(environment: KotlinCoreEnvironment): GenerationState? {
+ val result = repeatAnalysisIfNeeded(analyze(environment, null), environment, null) ?: return null
+
+ if (!result.shouldGenerateCode) return null
+
+ result.throwIfError()
+
+ return generate(environment, environment.configuration, result, environment.getSourceFiles(), null)
+ }
+
+ private fun analyze(environment: KotlinCoreEnvironment, targetDescription: String?): AnalysisResult? {
+ val sourceFiles = environment.getSourceFiles()
+ val collector = environment.messageCollector
+
+ val analysisStart = PerformanceCounter.currentTime()
+ val analyzerWithCompilerReport = AnalyzerWithCompilerReport(collector, environment.configuration.languageVersionSettings)
+ analyzerWithCompilerReport.analyzeAndReport(sourceFiles) {
+ val project = environment.project
+ val moduleOutputs = environment.configuration.get(JVMConfigurationKeys.MODULES)?.mapNotNullTo(hashSetOf()) { module ->
+ environment.findLocalFile(module.getOutputDirectory())
+ }.orEmpty()
+ val sourcesOnly = TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, sourceFiles)
+ // To support partial and incremental compilation, we add the scope which contains binaries from output directories
+ // of the compiled modules (.class) to the list of scopes of the source module
+ val scope = if (moduleOutputs.isEmpty()) sourcesOnly else sourcesOnly.uniteWith(DirectoriesScope(project, moduleOutputs))
+ TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
+ project,
+ sourceFiles,
+ NoScopeRecordCliBindingTrace(),
+ environment.configuration,
+ environment::createPackagePartProvider,
+ sourceModuleSearchScope = scope
+ )
+ }
+
+ val analysisNanos = PerformanceCounter.currentTime() - analysisStart
+
+ val sourceLinesOfCode = environment.countLinesOfCode(sourceFiles)
+ val time = TimeUnit.NANOSECONDS.toMillis(analysisNanos)
+ val speed = sourceLinesOfCode.toFloat() * 1000 / time
+
+ val message = "ANALYZE: ${sourceFiles.size} files ($sourceLinesOfCode lines) ${targetDescription ?: ""}" +
+ "in $time ms - ${"%.3f".format(speed)} loc/s"
+
+ K2JVMCompiler.reportPerf(environment.configuration, message)
+
+ val analysisResult = analyzerWithCompilerReport.analysisResult
+
+ return if (!analyzerWithCompilerReport.hasErrors() || analysisResult is AnalysisResult.RetryWithAdditionalJavaRoots)
+ analysisResult
+ else
+ null
+ }
+
+ class DirectoriesScope(
+ project: Project,
+ private val directories: Set
+ ) : DelegatingGlobalSearchScope(GlobalSearchScope.allScope(project)) {
+ private val fileSystems = directories.mapTo(hashSetOf(), VirtualFile::getFileSystem)
+
+ override fun contains(file: VirtualFile): Boolean {
+ if (file.fileSystem !in fileSystems) return false
+
+ var parent: VirtualFile = file
+ while (true) {
+ if (parent in directories) return true
+ parent = parent.parent ?: return false
+ }
+ }
+
+ override fun toString() = "All files under: $directories"
+ }
+
+ private fun GenerationState.Builder.withModule(module: Module?) =
+ apply {
+ targetId(module?.let { TargetId(it) })
+ moduleName(module?.getModuleName())
+ outDirectory(module?.let { File(it.getOutputDirectory()) })
+ }
+
+ private fun generate(
+ environment: KotlinCoreEnvironment,
+ configuration: CompilerConfiguration,
+ result: AnalysisResult,
+ sourceFiles: List,
+ module: Module?
+ ): GenerationState {
+ val isKapt2Enabled = environment.project.getUserData(IS_KAPT2_ENABLED_KEY) ?: false
+ val generationState = GenerationState.Builder(
+ environment.project,
+ ClassBuilderFactories.binaries(isKapt2Enabled),
+ result.moduleDescriptor,
+ result.bindingContext,
+ sourceFiles,
+ configuration
+ )
+ .codegenFactory(if (configuration.getBoolean(JVMConfigurationKeys.IR)) JvmIrCodegenFactory else DefaultCodegenFactory)
+ .withModule(module)
+ .onIndependentPartCompilationEnd(createOutputFilesFlushingCallbackIfPossible(configuration))
+ .build()
+
+ ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
+
+ val generationStart = PerformanceCounter.currentTime()
+
+ KotlinCodegenFacade.compileCorrectFiles(generationState, CompilationErrorHandler.THROW_EXCEPTION)
+
+ val generationNanos = PerformanceCounter.currentTime() - generationStart
+ val desc = if (module != null) "target " + module.getModuleName() + "-" + module.getModuleType() + " " else ""
+ val numberOfSourceFiles = sourceFiles.size
+ val numberOfLines = environment.countLinesOfCode(sourceFiles)
+ val time = TimeUnit.NANOSECONDS.toMillis(generationNanos)
+ val speed = numberOfLines.toFloat() * 1000 / time
+ val message = "GENERATE: $numberOfSourceFiles files ($numberOfLines lines) ${desc}in $time ms - ${"%.3f".format(speed)} loc/s"
+
+ K2JVMCompiler.reportPerf(environment.configuration, message)
+ ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
+
+ AnalyzerWithCompilerReport.reportDiagnostics(
+ FilteredJvmDiagnostics(
+ generationState.collectedExtraJvmDiagnostics,
+ result.bindingContext.diagnostics
+ ),
+ environment.messageCollector
+ )
+
+ AnalyzerWithCompilerReport.reportBytecodeVersionErrors(
+ generationState.extraJvmDiagnosticsTrace.bindingContext, environment.messageCollector
+ )
+
+ ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
+ return generationState
+ }
+
+ private val KotlinCoreEnvironment.messageCollector: MessageCollector
+ get() = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
+}
diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/modules/CliJavaModuleFinder.kt.as32 b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/modules/CliJavaModuleFinder.kt.as32
new file mode 100644
index 00000000000..a52e80c4ef3
--- /dev/null
+++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/modules/CliJavaModuleFinder.kt.as32
@@ -0,0 +1,48 @@
+/*
+ * 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.cli.jvm.modules
+
+import com.intellij.openapi.vfs.VirtualFile
+import org.jetbrains.kotlin.resolve.jvm.modules.JavaModule
+import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleFinder
+
+class CliJavaModuleFinder(jrtFileSystemRoot: VirtualFile?) : JavaModuleFinder {
+ private val modulesRoot = jrtFileSystemRoot?.findChild("modules")
+ private val userModules = linkedMapOf()
+
+ fun addUserModule(module: JavaModule) {
+ userModules.putIfAbsent(module.name, module)
+ }
+
+ val allObservableModules: Sequence
+ get() = systemModules + userModules.values
+
+ val systemModules: Sequence
+ get() = modulesRoot?.children.orEmpty().asSequence().mapNotNull(this::findSystemModule)
+
+ override fun findModule(name: String): JavaModule? =
+ modulesRoot?.findChild(name)?.let(this::findSystemModule) ?: userModules[name]
+
+ private fun findSystemModule(moduleRoot: VirtualFile): JavaModule.Explicit? {
+ /*
+ val file = moduleRoot.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE) ?: return null
+ val moduleInfo = JavaModuleInfo.read(file) ?: return null
+ return JavaModule.Explicit(moduleInfo, listOf(JavaModule.Root(moduleRoot, isBinary = true)), file)
+ */
+ return null
+ }
+}
diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassImpl.kt.as32 b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassImpl.kt.as32
new file mode 100644
index 00000000000..716f1c7e740
--- /dev/null
+++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassImpl.kt.as32
@@ -0,0 +1,133 @@
+/*
+ * 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.load.java.structure.impl
+
+import com.intellij.openapi.diagnostic.Logger
+import com.intellij.openapi.vfs.VirtualFile
+import com.intellij.psi.PsiClass
+import com.intellij.psi.PsiTypeParameter
+import com.intellij.psi.search.SearchScope
+import org.jetbrains.kotlin.asJava.KtLightClassMarker
+import org.jetbrains.kotlin.descriptors.Visibility
+import org.jetbrains.kotlin.load.java.structure.*
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.psi.KtPsiUtil
+import org.jetbrains.kotlin.psi.psiUtil.contains
+
+class JavaClassImpl(psiClass: PsiClass) : JavaClassifierImpl(psiClass), VirtualFileBoundJavaClass, JavaAnnotationOwnerImpl, JavaModifierListOwnerImpl {
+ init {
+ assert(psiClass !is PsiTypeParameter) { "PsiTypeParameter should be wrapped in JavaTypeParameter, not JavaClass: use JavaClassifier.create()" }
+ }
+
+ override val innerClassNames: Collection
+ get() = psi.innerClasses.mapNotNull { it.name?.takeIf(Name::isValidIdentifier)?.let(Name::identifier) }
+
+ override fun findInnerClass(name: Name): JavaClass? {
+ return psi.findInnerClassByName(name.asString(), false)?.let(::JavaClassImpl)
+ }
+
+ override val fqName: FqName?
+ get() {
+ val qualifiedName = psi.qualifiedName
+ return if (qualifiedName == null) null else FqName(qualifiedName)
+ }
+
+ override val name: Name
+ get() = KtPsiUtil.safeName(psi.name)
+
+ override val isInterface: Boolean
+ get() = psi.isInterface
+
+ override val isAnnotationType: Boolean
+ get() = psi.isAnnotationType
+
+ override val isEnum: Boolean
+ get() = psi.isEnum
+
+ override val outerClass: JavaClassImpl?
+ get() {
+ val outer = psi.containingClass
+ return if (outer == null) null else JavaClassImpl(outer)
+ }
+
+ override val typeParameters: List
+ get() = typeParameters(psi.typeParameters)
+
+ override val supertypes: Collection
+ get() = classifierTypes(psi.superTypes)
+
+ override val methods: Collection
+ get() {
+ assertNotLightClass()
+ // We apply distinct here because PsiClass#getMethods() can return duplicate PSI methods, for example in Lombok (see KT-11778)
+ // Return type seems to be null for example for the 'clone' Groovy method generated by @AutoClone (see EA-73795)
+ return methods(psi.methods.filter { method -> !method.isConstructor && method.returnType != null }).distinct()
+ }
+
+ override val fields: Collection
+ get() {
+ assertNotLightClass()
+ return fields(psi.fields.filter { field ->
+ val name = field.name
+ // ex. Android plugin generates LightFields for resources started from '.' (.DS_Store file etc)
+ name != null && Name.isValidIdentifier(name)
+ })
+ }
+
+ override val constructors: Collection
+ get() {
+ assertNotLightClass()
+ // See for example org.jetbrains.plugins.scala.lang.psi.light.ScFunctionWrapper,
+ // which is present in getConstructors(), but its isConstructor() returns false
+ return constructors(psi.constructors.filter { method -> method.isConstructor })
+ }
+
+ override val isAbstract: Boolean
+ get() = JavaElementUtil.isAbstract(this)
+
+ override val isStatic: Boolean
+ get() = JavaElementUtil.isStatic(this)
+
+ override val isFinal: Boolean
+ get() = JavaElementUtil.isFinal(this)
+
+ override val visibility: Visibility
+ get() = JavaElementUtil.getVisibility(this)
+
+ override val lightClassOriginKind: LightClassOriginKind?
+ get() = (psi as? KtLightClassMarker)?.originKind
+
+ override val virtualFile: VirtualFile?
+ get() = psi.containingFile?.virtualFile
+
+ override fun isFromSourceCodeInScope(scope: SearchScope): Boolean = psi.containingFile in scope
+
+ override fun getAnnotationOwnerPsi() = psi.modifierList
+
+ private fun assertNotLightClass() {
+ val psiClass = psi
+ if (psiClass !is KtLightClassMarker) return
+
+ val message = "Querying members of JavaClass created for $psiClass of type ${psiClass::class.java} defined in file ${psiClass.containingFile?.virtualFile?.canonicalPath}"
+ LOGGER.error(message)
+ }
+
+ companion object {
+ private val LOGGER = Logger.getInstance(JavaClassImpl::class.java)
+ }
+}
diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinBinaryClassCache.kt.as32 b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinBinaryClassCache.kt.as32
new file mode 100644
index 00000000000..3ed195c944c
--- /dev/null
+++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinBinaryClassCache.kt.as32
@@ -0,0 +1,73 @@
+/*
+ * 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.load.kotlin
+
+import com.intellij.ide.highlighter.JavaClassFileType
+import com.intellij.openapi.Disposable
+import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.components.ServiceManager
+import com.intellij.openapi.util.Computable
+import com.intellij.openapi.vfs.VirtualFile
+
+class KotlinBinaryClassCache : Disposable {
+ private class RequestCache {
+ internal var virtualFile: VirtualFile? = null
+ internal var modificationStamp: Long = 0
+ internal var virtualFileKotlinClass: VirtualFileKotlinClass? = null
+
+ fun cache(file: VirtualFile, aClass: VirtualFileKotlinClass?): VirtualFileKotlinClass? {
+ virtualFile = file
+ virtualFileKotlinClass = aClass
+ modificationStamp = file.modificationStamp
+
+ return aClass
+ }
+ }
+
+ private val cache = object : ThreadLocal() {
+ override fun initialValue(): RequestCache {
+ return RequestCache()
+ }
+ }
+
+ override fun dispose() {
+ // This is only relevant for tests. We create a new instance of Application for each test, and so a new instance of this service is
+ // also created for each test. However all tests share the same event dispatch thread, which would collect all instances of this
+ // thread-local if they're not removed properly. Each instance would transitively retain VFS resulting in OutOfMemoryError
+ cache.remove()
+ }
+
+ companion object {
+ fun getKotlinBinaryClass(file: VirtualFile, fileContent: ByteArray? = null): KotlinJvmBinaryClass? {
+ if (file.fileType !== JavaClassFileType.INSTANCE) return null
+
+ val service = ServiceManager.getService(KotlinBinaryClassCache::class.java)
+ val requestCache = service.cache.get()
+
+ if (file.modificationStamp == requestCache.modificationStamp && file == requestCache.virtualFile) {
+ return requestCache.virtualFileKotlinClass
+ }
+
+ val aClass = ApplicationManager.getApplication().runReadAction(Computable {
+ @Suppress("DEPRECATION")
+ VirtualFileKotlinClass.create(file, fileContent)
+ })
+
+ return requestCache.cache(file, aClass)
+ }
+ }
+}
diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/modules/JavaModuleInfo.kt.as32 b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/modules/JavaModuleInfo.kt.as32
new file mode 100644
index 00000000000..1bd0dfffc2d
--- /dev/null
+++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/modules/JavaModuleInfo.kt.as32
@@ -0,0 +1,89 @@
+/*
+ * 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.resolve.jvm.modules
+
+import com.intellij.openapi.vfs.VirtualFile
+//import com.intellij.psi.PsiJavaModule
+import com.intellij.psi.PsiModifier
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.utils.compact
+import org.jetbrains.org.objectweb.asm.ClassReader
+import org.jetbrains.org.objectweb.asm.ClassVisitor
+//import org.jetbrains.org.objectweb.asm.ModuleVisitor
+import org.jetbrains.org.objectweb.asm.Opcodes
+//import org.jetbrains.org.objectweb.asm.Opcodes.ACC_TRANSITIVE
+import java.io.IOException
+
+class JavaModuleInfo(
+ val moduleName: String,
+ val requires: List,
+ val exports: List
+) {
+ data class Requires(val moduleName: String, val isTransitive: Boolean)
+
+ data class Exports(val packageFqName: FqName, val toModules: List)
+
+ override fun toString(): String =
+ "Module $moduleName (${requires.size} requires, ${exports.size} exports)"
+
+ companion object {
+ /*fun create(psiJavaModule: PsiJavaModule): JavaModuleInfo {
+ return JavaModuleInfo(
+ psiJavaModule.name,
+ psiJavaModule.requires.mapNotNull { statement ->
+ statement.moduleName?.let { moduleName ->
+ JavaModuleInfo.Requires(moduleName, statement.hasModifierProperty(PsiModifier.TRANSITIVE))
+ }
+ },
+ psiJavaModule.exports.mapNotNull { statement ->
+ statement.packageName?.let { packageName ->
+ JavaModuleInfo.Exports(FqName(packageName), statement.moduleNames)
+ }
+ }
+ )
+ }*/
+
+ /*fun read(file: VirtualFile): JavaModuleInfo? {
+ val contents = try { file.contentsToByteArray() } catch (e: IOException) { return null }
+
+ var moduleName: String? = null
+ val requires = arrayListOf()
+ val exports = arrayListOf()
+
+ ClassReader(contents).accept(object : ClassVisitor(Opcodes.ASM6) {
+ override fun visitModule(name: String, access: Int, version: String?): ModuleVisitor {
+ moduleName = name
+
+ return object : ModuleVisitor(Opcodes.ASM6) {
+ override fun visitRequire(module: String, access: Int, version: String?) {
+ requires.add(Requires(module, (access and ACC_TRANSITIVE) != 0))
+ }
+
+ override fun visitExport(packageFqName: String, access: Int, modules: Array?) {
+ // For some reason, '/' is the delimiter in packageFqName here
+ exports.add(Exports(FqName(packageFqName.replace('/', '.')), modules?.toList().orEmpty()))
+ }
+ }
+ }
+ }, ClassReader.SKIP_DEBUG or ClassReader.SKIP_CODE or ClassReader.SKIP_FRAMES)
+
+ return if (moduleName != null)
+ JavaModuleInfo(moduleName!!, requires.compact(), exports.compact())
+ else null
+ }*/
+ }
+}
diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/test/KotlinTestUtils.java.as32 b/compiler/tests-common/tests/org/jetbrains/kotlin/test/KotlinTestUtils.java.as32
new file mode 100644
index 00000000000..7b30fd60c9e
--- /dev/null
+++ b/compiler/tests-common/tests/org/jetbrains/kotlin/test/KotlinTestUtils.java.as32
@@ -0,0 +1,1206 @@
+/*
+ * 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.test;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.ShutDownTracker;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.util.text.StringUtilRt;
+import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFileFactory;
+import com.intellij.psi.impl.PsiFileFactoryImpl;
+import com.intellij.rt.execution.junit.FileComparisonFailure;
+import com.intellij.testFramework.LightVirtualFile;
+import com.intellij.testFramework.TestDataFile;
+import com.intellij.util.containers.ContainerUtil;
+import junit.framework.TestCase;
+import kotlin.collections.CollectionsKt;
+import kotlin.collections.SetsKt;
+import kotlin.jvm.functions.Function1;
+import kotlin.text.StringsKt;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
+import org.jetbrains.kotlin.analyzer.AnalysisResult;
+import org.jetbrains.kotlin.builtins.DefaultBuiltIns;
+import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
+import org.jetbrains.kotlin.checkers.CompilerTestLanguageVersionSettings;
+import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys;
+import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation;
+import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity;
+import org.jetbrains.kotlin.cli.common.messages.MessageCollector;
+import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles;
+import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
+import org.jetbrains.kotlin.cli.jvm.config.JvmContentRootsKt;
+import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime;
+import org.jetbrains.kotlin.config.*;
+import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl;
+import org.jetbrains.kotlin.diagnostics.Diagnostic;
+import org.jetbrains.kotlin.diagnostics.Errors;
+import org.jetbrains.kotlin.diagnostics.Severity;
+import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages;
+import org.jetbrains.kotlin.idea.KotlinLanguage;
+import org.jetbrains.kotlin.jvm.compiler.LoadDescriptorUtil;
+import org.jetbrains.kotlin.lexer.KtTokens;
+import org.jetbrains.kotlin.name.Name;
+import org.jetbrains.kotlin.psi.KtExpression;
+import org.jetbrains.kotlin.psi.KtFile;
+import org.jetbrains.kotlin.psi.KtPsiFactoryKt;
+import org.jetbrains.kotlin.resolve.BindingContext;
+import org.jetbrains.kotlin.resolve.BindingTrace;
+import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics;
+import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil;
+import org.jetbrains.kotlin.storage.LockBasedStorageManager;
+import org.jetbrains.kotlin.test.util.JetTestUtilsKt;
+import org.jetbrains.kotlin.types.KotlinType;
+import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo;
+import org.jetbrains.kotlin.util.slicedMap.ReadOnlySlice;
+import org.jetbrains.kotlin.util.slicedMap.SlicedMap;
+import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
+import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
+import org.jetbrains.kotlin.utils.PathUtil;
+import org.junit.Assert;
+
+import javax.tools.*;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.lang.reflect.Method;
+import java.nio.charset.Charset;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static org.jetbrains.kotlin.test.InTextDirectivesUtils.isCompatibleTarget;
+import static org.jetbrains.kotlin.test.InTextDirectivesUtils.isDirectiveDefined;
+
+public class KotlinTestUtils {
+ public static String TEST_MODULE_NAME = "test-module";
+
+ public static final String TEST_GENERATOR_NAME = "org.jetbrains.kotlin.generators.tests.TestsPackage";
+ public static final String PLEASE_REGENERATE_TESTS = "Please regenerate tests (GenerateTests.kt)";
+
+ public static final boolean RUN_IGNORED_TESTS_AS_REGULAR =
+ Boolean.getBoolean("org.jetbrains.kotlin.run.ignored.tests.as.regular");
+
+ private static final List filesToDelete = new ArrayList<>();
+
+ /**
+ * Syntax:
+ *
+ * // MODULE: name(dependency1, dependency2, ...)
+ *
+ * // FILE: name
+ *
+ * Several files may follow one module
+ */
+ private static final String MODULE_DELIMITER = ",\\s*";
+
+ private static final Pattern FILE_OR_MODULE_PATTERN = Pattern.compile(
+ "(?://\\s*MODULE:\\s*([^()\\n]+)(?:\\(([^()]+(?:" + MODULE_DELIMITER + "[^()]+)*)\\))?\\s*(?:\\(([^()]+(?:" + MODULE_DELIMITER + "[^()]+)*)\\))?\\s*)?" +
+ "//\\s*FILE:\\s*(.*)$", Pattern.MULTILINE);
+ private static final Pattern DIRECTIVE_PATTERN = Pattern.compile("^//\\s*!([\\w_]+)(:\\s*(.*)$)?", Pattern.MULTILINE);
+ private static final Pattern LINE_SEPARATOR_PATTERN = Pattern.compile("\\r\\n|\\r|\\n");
+
+ public static final BindingTrace DUMMY_TRACE = new BindingTrace() {
+ @NotNull
+ @Override
+ public BindingContext getBindingContext() {
+ return new BindingContext() {
+
+ @NotNull
+ @Override
+ public Diagnostics getDiagnostics() {
+ return Diagnostics.Companion.getEMPTY();
+ }
+
+ @Override
+ public V get(ReadOnlySlice slice, K key) {
+ return DUMMY_TRACE.get(slice, key);
+ }
+
+ @NotNull
+ @Override
+ public Collection getKeys(WritableSlice slice) {
+ return DUMMY_TRACE.getKeys(slice);
+ }
+
+ @NotNull
+ @TestOnly
+ @Override
+ public ImmutableMap getSliceContents(@NotNull ReadOnlySlice slice) {
+ return ImmutableMap.of();
+ }
+
+ @Nullable
+ @Override
+ public KotlinType getType(@NotNull KtExpression expression) {
+ return DUMMY_TRACE.getType(expression);
+ }
+
+ @Override
+ public void addOwnDataTo(@NotNull BindingTrace trace, boolean commitDiagnostics) {
+ // do nothing
+ }
+ };
+ }
+
+ @Override
+ public void record(WritableSlice slice, K key, V value) {
+ }
+
+ @Override
+ public void record(WritableSlice slice, K key) {
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public V get(ReadOnlySlice slice, K key) {
+ if (slice == BindingContext.PROCESSED) return (V) Boolean.FALSE;
+ return SlicedMap.DO_NOTHING.get(slice, key);
+ }
+
+ @NotNull
+ @Override
+ public Collection getKeys(WritableSlice slice) {
+ assert slice.isCollective();
+ return Collections.emptySet();
+ }
+
+ @Nullable
+ @Override
+ public KotlinType getType(@NotNull KtExpression expression) {
+ KotlinTypeInfo typeInfo = get(BindingContext.EXPRESSION_TYPE_INFO, expression);
+ return typeInfo != null ? typeInfo.getType() : null;
+ }
+
+ @Override
+ public void recordType(@NotNull KtExpression expression, @Nullable KotlinType type) {
+ }
+
+ @Override
+ public void report(@NotNull Diagnostic diagnostic) {
+ if (Errors.UNRESOLVED_REFERENCE_DIAGNOSTICS.contains(diagnostic.getFactory())) {
+ throw new IllegalStateException("Unresolved: " + diagnostic.getPsiElement().getText());
+ }
+ }
+
+ @Override
+ public boolean wantsDiagnostics() {
+ return false;
+ }
+ };
+
+ public static BindingTrace DUMMY_EXCEPTION_ON_ERROR_TRACE = new BindingTrace() {
+ @NotNull
+ @Override
+ public BindingContext getBindingContext() {
+ return new BindingContext() {
+ @NotNull
+ @Override
+ public Diagnostics getDiagnostics() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V get(ReadOnlySlice slice, K key) {
+ return DUMMY_EXCEPTION_ON_ERROR_TRACE.get(slice, key);
+ }
+
+ @NotNull
+ @Override
+ public Collection getKeys(WritableSlice slice) {
+ return DUMMY_EXCEPTION_ON_ERROR_TRACE.getKeys(slice);
+ }
+
+ @NotNull
+ @TestOnly
+ @Override
+ public ImmutableMap getSliceContents(@NotNull ReadOnlySlice slice) {
+ return ImmutableMap.of();
+ }
+
+ @Nullable
+ @Override
+ public KotlinType getType(@NotNull KtExpression expression) {
+ return DUMMY_EXCEPTION_ON_ERROR_TRACE.getType(expression);
+ }
+
+ @Override
+ public void addOwnDataTo(@NotNull BindingTrace trace, boolean commitDiagnostics) {
+ // do nothing
+ }
+ };
+ }
+
+ @Override
+ public void record(WritableSlice slice, K key, V value) {
+ }
+
+ @Override
+ public void record(WritableSlice slice, K key) {
+ }
+
+ @Override
+ public V get(ReadOnlySlice slice, K key) {
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public Collection getKeys(WritableSlice slice) {
+ assert slice.isCollective();
+ return Collections.emptySet();
+ }
+
+ @Nullable
+ @Override
+ public KotlinType getType(@NotNull KtExpression expression) {
+ return null;
+ }
+
+ @Override
+ public void recordType(@NotNull KtExpression expression, @Nullable KotlinType type) {
+ }
+
+ @Override
+ public void report(@NotNull Diagnostic diagnostic) {
+ if (diagnostic.getSeverity() == Severity.ERROR) {
+ throw new IllegalStateException(DefaultErrorMessages.render(diagnostic));
+ }
+ }
+
+ @Override
+ public boolean wantsDiagnostics() {
+ return true;
+ }
+ };
+
+ // We suspect sequences of eight consecutive hexadecimal digits to be a package part hash code
+ private static final Pattern STRIP_PACKAGE_PART_HASH_PATTERN = Pattern.compile("\\$([0-9a-f]{8})");
+
+ private KotlinTestUtils() {
+ }
+
+ @NotNull
+ public static AnalysisResult analyzeFile(@NotNull KtFile file, @NotNull KotlinCoreEnvironment environment) {
+ return JvmResolveUtil.analyze(file, environment);
+ }
+
+ @NotNull
+ public static KotlinCoreEnvironment createEnvironmentWithMockJdkAndIdeaAnnotations(Disposable disposable) {
+ return createEnvironmentWithMockJdkAndIdeaAnnotations(disposable, ConfigurationKind.ALL);
+ }
+
+ @NotNull
+ public static KotlinCoreEnvironment createEnvironmentWithMockJdkAndIdeaAnnotations(Disposable disposable, @NotNull ConfigurationKind configurationKind) {
+ return createEnvironmentWithJdkAndNullabilityAnnotationsFromIdea(disposable, configurationKind, TestJdkKind.MOCK_JDK);
+ }
+
+ @NotNull
+ public static KotlinCoreEnvironment createEnvironmentWithJdkAndNullabilityAnnotationsFromIdea(
+ @NotNull Disposable disposable,
+ @NotNull ConfigurationKind configurationKind,
+ @NotNull TestJdkKind jdkKind
+ ) {
+ return KotlinCoreEnvironment.createForTests(
+ disposable, newConfiguration(configurationKind, jdkKind, getAnnotationsJar()), EnvironmentConfigFiles.JVM_CONFIG_FILES
+ );
+ }
+
+ @NotNull
+ public static KotlinCoreEnvironment createEnvironmentWithFullJdkAndIdeaAnnotations(Disposable disposable) {
+ return createEnvironmentWithJdkAndNullabilityAnnotationsFromIdea(disposable, ConfigurationKind.ALL, TestJdkKind.FULL_JDK);
+ }
+
+ @NotNull
+ public static String getTestDataPathBase() {
+ return getHomeDirectory() + "/compiler/testData";
+ }
+
+ private static String homeDir = computeHomeDirectory();
+
+ @NotNull
+ public static String getHomeDirectory() {
+ return homeDir;
+ }
+
+ @NotNull
+ private static String computeHomeDirectory() {
+ String userDir = System.getProperty("user.dir");
+ File dir = new File(userDir == null ? "." : userDir);
+ return FileUtil.toCanonicalPath(dir.getAbsolutePath());
+ }
+
+ public static File findMockJdkRtJar() {
+ return new File(getHomeDirectory(), "compiler/testData/mockJDK/jre/lib/rt.jar");
+ }
+
+ // Differs from common mock JDK only by one additional 'nonExistingMethod' in Collection and constructor from Double in Throwable
+ // It's needed to test the way we load additional built-ins members that neither in black nor white lists
+ public static File findMockJdkRtModified() {
+ return new File(getHomeDirectory(), "compiler/testData/mockJDKModified/rt.jar");
+ }
+
+ public static File findAndroidApiJar() {
+ String androidJarProp = System.getProperty("android.jar");
+ File androidJarFile = androidJarProp == null ? null : new File(androidJarProp);
+ if (androidJarFile == null || !androidJarFile.isFile()) {
+ throw new RuntimeException(
+ "Unable to get a valid path from 'android.jar' property (" +
+ androidJarProp +
+ "), please point it to the 'android.jar' file location");
+ }
+ return androidJarFile;
+ }
+
+ @NotNull
+ public static File findAndroidSdk() {
+ String androidSdkProp = System.getProperty("android.sdk");
+ File androidSdkDir = androidSdkProp == null ? null : new File(androidSdkProp);
+ if (androidSdkDir == null || !androidSdkDir.isDirectory()) {
+ throw new RuntimeException(
+ "Unable to get a valid path from 'android.sdk' property (" +
+ androidSdkProp +
+ "), please point it to the android SDK location");
+ }
+ return androidSdkDir;
+ }
+
+ public static String getAndroidSdkSystemIndependentPath() {
+ return com.intellij.util.PathUtil.toSystemIndependentName(findAndroidSdk().getAbsolutePath());
+ }
+
+ public static File getAnnotationsJar() {
+ return new File(getHomeDirectory(), "compiler/testData/mockJDK/jre/lib/annotations.jar");
+ }
+
+ public static void mkdirs(@NotNull File file) {
+ if (file.isDirectory()) {
+ return;
+ }
+ if (!file.mkdirs()) {
+ if (file.exists()) {
+ throw new IllegalStateException("Failed to create " + file + ": file exists and not a directory");
+ }
+ throw new IllegalStateException("Failed to create " + file);
+ }
+ }
+
+ @NotNull
+ public static File tmpDirForTest(TestCase test) throws IOException {
+ File answer = normalizeFile(FileUtil.createTempDirectory(test.getClass().getSimpleName(), test.getName()));
+ deleteOnShutdown(answer);
+ return answer;
+ }
+
+ @NotNull
+ public static File tmpDir(String name) throws IOException {
+ // We should use this form. otherwise directory will be deleted on each test.
+ File answer = normalizeFile(FileUtil.createTempDirectory(new File(System.getProperty("java.io.tmpdir")), name, ""));
+ deleteOnShutdown(answer);
+ return answer;
+ }
+
+ private static File normalizeFile(File file) throws IOException {
+ // Get canonical file to be sure that it's the same as inside the compiler,
+ // for example, on Windows, if a canonical path contains any space from FileUtil.createTempDirectory we will get
+ // a File with short names (8.3) in its path and it will break some normalization passes in tests.
+ return file.getCanonicalFile();
+ }
+
+ private static void deleteOnShutdown(File file) {
+ if (filesToDelete.isEmpty()) {
+ ShutDownTracker.getInstance().registerShutdownTask(() -> {
+ for (File victim : filesToDelete) {
+ FileUtil.delete(victim);
+ }
+ });
+ }
+
+ filesToDelete.add(file);
+ }
+
+ @NotNull
+ public static KtFile createFile(@NotNull @NonNls String name, @NotNull String text, @NotNull Project project) {
+ String shortName = name.substring(name.lastIndexOf('/') + 1);
+ shortName = shortName.substring(shortName.lastIndexOf('\\') + 1);
+ LightVirtualFile virtualFile = new LightVirtualFile(shortName, KotlinLanguage.INSTANCE, StringUtilRt.convertLineSeparators(text)) {
+ @NotNull
+ @Override
+ public String getPath() {
+ //TODO: patch LightVirtualFile
+ return "/" + name;
+ }
+ };
+
+ virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET);
+ PsiFileFactoryImpl factory = (PsiFileFactoryImpl) PsiFileFactory.getInstance(project);
+ //noinspection ConstantConditions
+ return (KtFile) factory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, true, false);
+ }
+
+ public static String doLoadFile(String myFullDataPath, String name) throws IOException {
+ String fullName = myFullDataPath + File.separatorChar + name;
+ return doLoadFile(new File(fullName));
+ }
+
+ public static String doLoadFile(@NotNull File file) throws IOException {
+ try {
+ return FileUtil.loadFile(file, CharsetToolkit.UTF8, true);
+ }
+ catch (FileNotFoundException fileNotFoundException) {
+ /*
+ * Unfortunately, the FileNotFoundException will only show the relative path in it's exception message.
+ * This clarifies the exception by showing the full path.
+ */
+ String messageWithFullPath = file.getAbsolutePath() + " (No such file or directory)";
+ throw new IOException(
+ "Ensure you have your 'Working Directory' configured correctly as the root " +
+ "Kotlin project directory in your test configuration\n\t" +
+ messageWithFullPath,
+ fileNotFoundException);
+ }
+ }
+
+ public static String getFilePath(File file) {
+ return FileUtil.toSystemIndependentName(file.getPath());
+ }
+
+ @NotNull
+ public static CompilerConfiguration newConfiguration() {
+ CompilerConfiguration configuration = new CompilerConfiguration();
+ configuration.put(CommonConfigurationKeys.MODULE_NAME, TEST_MODULE_NAME);
+
+ if ("true".equals(System.getProperty("kotlin.ni"))) {
+ // Enable new inference for tests which do not declare their own language version settings
+ CommonConfigurationKeysKt.setLanguageVersionSettings(configuration, new CompilerTestLanguageVersionSettings(
+ Collections.emptyMap(),
+ LanguageVersionSettingsImpl.DEFAULT.getApiVersion(),
+ LanguageVersionSettingsImpl.DEFAULT.getLanguageVersion(),
+ Collections.emptyMap()
+ ));
+ }
+
+ configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, new MessageCollector() {
+ @Override
+ public void clear() {
+ }
+
+ @Override
+ public void report(
+ @NotNull CompilerMessageSeverity severity, @NotNull String message, @Nullable CompilerMessageLocation location
+ ) {
+ if (severity == CompilerMessageSeverity.ERROR) {
+ String prefix = location == null
+ ? ""
+ : "(" + location.getPath() + ":" + location.getLine() + ":" + location.getColumn() + ") ";
+ throw new AssertionError(prefix + message);
+ }
+ }
+
+ @Override
+ public boolean hasErrors() {
+ return false;
+ }
+ });
+
+ return configuration;
+ }
+
+ @NotNull
+ public static CompilerConfiguration newConfiguration(
+ @NotNull ConfigurationKind configurationKind,
+ @NotNull TestJdkKind jdkKind,
+ @NotNull File... extraClasspath
+ ) {
+ return newConfiguration(configurationKind, jdkKind, Arrays.asList(extraClasspath), Collections.emptyList());
+ }
+
+ @NotNull
+ public static CompilerConfiguration newConfiguration(
+ @NotNull ConfigurationKind configurationKind,
+ @NotNull TestJdkKind jdkKind,
+ @NotNull List classpath,
+ @NotNull List javaSource
+ ) {
+ CompilerConfiguration configuration = newConfiguration();
+ JvmContentRootsKt.addJavaSourceRoots(configuration, javaSource);
+ if (jdkKind == TestJdkKind.MOCK_JDK) {
+ JvmContentRootsKt.addJvmClasspathRoot(configuration, findMockJdkRtJar());
+ configuration.put(JVMConfigurationKeys.NO_JDK, true);
+ }
+ else if (jdkKind == TestJdkKind.MODIFIED_MOCK_JDK) {
+ JvmContentRootsKt.addJvmClasspathRoot(configuration, findMockJdkRtModified());
+ configuration.put(JVMConfigurationKeys.NO_JDK, true);
+ }
+ else if (jdkKind == TestJdkKind.ANDROID_API) {
+ JvmContentRootsKt.addJvmClasspathRoot(configuration, findAndroidApiJar());
+ configuration.put(JVMConfigurationKeys.NO_JDK, true);
+ }
+ else if (jdkKind == TestJdkKind.FULL_JDK_6) {
+ String jdk6 = System.getenv("JDK_16");
+ assert jdk6 != null : "Environment variable JDK_16 is not set";
+ configuration.put(JVMConfigurationKeys.JDK_HOME, new File(jdk6));
+ }
+ else if (jdkKind == TestJdkKind.FULL_JDK_9) {
+ configuration.put(JVMConfigurationKeys.JDK_HOME, getJdk9Home());
+ }
+ else {
+ JvmContentRootsKt.addJvmClasspathRoots(configuration, PathUtil.getJdkClassesRootsFromCurrentJre());
+ }
+
+ if (configurationKind.getWithRuntime()) {
+ JvmContentRootsKt.addJvmClasspathRoot(configuration, ForTestCompileRuntime.runtimeJarForTests());
+ JvmContentRootsKt.addJvmClasspathRoot(configuration, ForTestCompileRuntime.scriptRuntimeJarForTests());
+ JvmContentRootsKt.addJvmClasspathRoot(configuration, ForTestCompileRuntime.kotlinTestJarForTests());
+ }
+ else if (configurationKind.getWithMockRuntime()) {
+ JvmContentRootsKt.addJvmClasspathRoot(configuration, ForTestCompileRuntime.minimalRuntimeJarForTests());
+ JvmContentRootsKt.addJvmClasspathRoot(configuration, ForTestCompileRuntime.scriptRuntimeJarForTests());
+ }
+ if (configurationKind.getWithReflection()) {
+ JvmContentRootsKt.addJvmClasspathRoot(configuration, ForTestCompileRuntime.reflectJarForTests());
+ }
+
+ JvmContentRootsKt.addJvmClasspathRoots(configuration, classpath);
+
+ return configuration;
+ }
+
+ @NotNull
+ public static File getJdk9Home() {
+ String jdk9 = System.getenv("JDK_9");
+ if (jdk9 == null) {
+ jdk9 = System.getenv("JDK_19");
+ if (jdk9 == null) {
+ throw new AssertionError("Environment variable JDK_9 is not set!");
+ }
+ }
+ return new File(jdk9);
+ }
+
+ public static void resolveAllKotlinFiles(KotlinCoreEnvironment environment) throws IOException {
+ List paths = ContentRootsKt.getKotlinSourceRoots(environment.getConfiguration());
+ if (paths.isEmpty()) return;
+ List ktFiles = new ArrayList<>();
+ for (String path : paths) {
+ File file = new File(path);
+ if (file.isFile()) {
+ ktFiles.add(loadJetFile(environment.getProject(), file));
+ }
+ else {
+ //noinspection ConstantConditions
+ for (File childFile : file.listFiles()) {
+ if (childFile.getName().endsWith(".kt") || childFile.getName().endsWith(".kts")) {
+ ktFiles.add(loadJetFile(environment.getProject(), childFile));
+ }
+ }
+ }
+ }
+ JvmResolveUtil.analyze(ktFiles, environment);
+ }
+
+ public static void assertEqualsToFile(@NotNull File expectedFile, @NotNull Editor editor) {
+ String actualText = editor.getDocument().getText();
+ String afterText = new StringBuilder(actualText).insert(editor.getCaretModel().getOffset(), "").toString();
+
+ assertEqualsToFile(expectedFile, afterText);
+ }
+
+ public static void assertEqualsToFile(@NotNull File expectedFile, @NotNull String actual) {
+ assertEqualsToFile(expectedFile, actual, s -> s);
+ }
+
+ public static void assertEqualsToFile(@NotNull String message, @NotNull File expectedFile, @NotNull String actual) {
+ assertEqualsToFile(message, expectedFile, actual, s -> s);
+ }
+
+ public static void assertEqualsToFile(@NotNull File expectedFile, @NotNull String actual, @NotNull Function1 sanitizer) {
+ assertEqualsToFile("Actual data differs from file content", expectedFile, actual, sanitizer);
+ }
+
+ public static void assertEqualsToFile(@NotNull String message, @NotNull File expectedFile, @NotNull String actual, @NotNull Function1 sanitizer) {
+ try {
+ String actualText = JetTestUtilsKt.trimTrailingWhitespacesAndAddNewlineAtEOF(StringUtil.convertLineSeparators(actual.trim()));
+
+ if (!expectedFile.exists()) {
+ FileUtil.writeToFile(expectedFile, actualText);
+ Assert.fail("Expected data file did not exist. Generating: " + expectedFile);
+ }
+ String expected = FileUtil.loadFile(expectedFile, CharsetToolkit.UTF8, true);
+
+ String expectedText = JetTestUtilsKt.trimTrailingWhitespacesAndAddNewlineAtEOF(StringUtil.convertLineSeparators(expected.trim()));
+
+ if (!Comparing.equal(sanitizer.invoke(expectedText), sanitizer.invoke(actualText))) {
+ throw new FileComparisonFailure(message + ": " + expectedFile.getName(),
+ expected, actual, expectedFile.getAbsolutePath());
+ }
+ }
+ catch (IOException e) {
+ throw ExceptionUtilsKt.rethrow(e);
+ }
+ }
+
+ public static boolean compileKotlinWithJava(
+ @NotNull List javaFiles,
+ @NotNull List ktFiles,
+ @NotNull File outDir,
+ @NotNull Disposable disposable,
+ @Nullable File javaErrorFile
+ ) throws IOException {
+ if (!ktFiles.isEmpty()) {
+ KotlinCoreEnvironment environment = createEnvironmentWithFullJdkAndIdeaAnnotations(disposable);
+ LoadDescriptorUtil.compileKotlinToDirAndGetModule(ktFiles, outDir, environment);
+ }
+ else {
+ boolean mkdirs = outDir.mkdirs();
+ assert mkdirs : "Not created: " + outDir;
+ }
+ if (javaFiles.isEmpty()) return true;
+
+ return compileJavaFiles(javaFiles, Arrays.asList(
+ "-classpath", outDir.getPath() + File.pathSeparator + ForTestCompileRuntime.runtimeJarForTests(),
+ "-d", outDir.getPath()
+ ), javaErrorFile);
+ }
+
+ public interface TestFileFactory {
+ F createFile(@Nullable M module, @NotNull String fileName, @NotNull String text, @NotNull Map directives);
+ M createModule(@NotNull String name, @NotNull List dependencies, @NotNull List friends);
+ }
+
+ public static abstract class TestFileFactoryNoModules implements TestFileFactory {
+ @Override
+ public final F createFile(
+ @Nullable Void module,
+ @NotNull String fileName,
+ @NotNull String text,
+ @NotNull Map directives
+ ) {
+ return create(fileName, text, directives);
+ }
+
+ @NotNull
+ public abstract F create(@NotNull String fileName, @NotNull String text, @NotNull Map directives);
+
+ @Override
+ public Void createModule(@NotNull String name, @NotNull List dependencies, @NotNull List friends) {
+ return null;
+ }
+ }
+
+ @NotNull
+ public static List createTestFiles(@Nullable String testFileName, String expectedText, TestFileFactory factory) {
+ return createTestFiles(testFileName, expectedText, factory, false);
+ }
+
+ @NotNull
+ public static List createTestFiles(String testFileName, String expectedText, TestFileFactory factory,
+ boolean preserveLocations) {
+ Map directives = parseDirectives(expectedText);
+
+ List testFiles = Lists.newArrayList();
+ Matcher matcher = FILE_OR_MODULE_PATTERN.matcher(expectedText);
+ boolean hasModules = false;
+ if (!matcher.find()) {
+ assert testFileName != null : "testFileName should not be null if no FILE directive defined";
+ // One file
+ testFiles.add(factory.createFile(null, testFileName, expectedText, directives));
+ }
+ else {
+ int processedChars = 0;
+ M module = null;
+ // Many files
+ while (true) {
+ String moduleName = matcher.group(1);
+ String moduleDependencies = matcher.group(2);
+ String moduleFriends = matcher.group(3);
+ if (moduleName != null) {
+ moduleName = moduleName.trim();
+ hasModules = true;
+ module = factory.createModule(moduleName, parseModuleList(moduleDependencies), parseModuleList(moduleFriends));
+ }
+
+ String fileName = matcher.group(4);
+ int start = processedChars;
+
+ boolean nextFileExists = matcher.find();
+ int end;
+ if (nextFileExists) {
+ end = matcher.start();
+ }
+ else {
+ end = expectedText.length();
+ }
+ String fileText = preserveLocations ?
+ substringKeepingLocations(expectedText, start, end) :
+ expectedText.substring(start,end);
+ processedChars = end;
+
+ testFiles.add(factory.createFile(module, fileName, fileText, directives));
+
+ if (!nextFileExists) break;
+ }
+ assert processedChars == expectedText.length() : "Characters skipped from " +
+ processedChars +
+ " to " +
+ (expectedText.length() - 1);
+ }
+
+ if (isDirectiveDefined(expectedText, "WITH_COROUTINES")) {
+ M supportModule = hasModules ? factory.createModule("support", Collections.emptyList(), Collections.emptyList()) : null;
+ testFiles.add(factory.createFile(supportModule,
+ "CoroutineUtil.kt",
+ "package helpers\n" +
+ "import kotlin.coroutines.experimental.*\n" +
+ "fun handleResultContinuation(x: (T) -> Unit): Continuation = object: Continuation {\n" +
+ " override val context = EmptyCoroutineContext\n" +
+ " override fun resumeWithException(exception: Throwable) {\n" +
+ " throw exception\n" +
+ " }\n" +
+ "\n" +
+ " override fun resume(data: T) = x(data)\n" +
+ "}\n" +
+ "\n" +
+ "fun handleExceptionContinuation(x: (Throwable) -> Unit): Continuation = object: Continuation {\n" +
+ " override val context = EmptyCoroutineContext\n" +
+ " override fun resumeWithException(exception: Throwable) {\n" +
+ " x(exception)\n" +
+ " }\n" +
+ "\n" +
+ " override fun resume(data: Any?) { }\n" +
+ "}\n" +
+ "\n" +
+ "open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation {\n" +
+ " companion object : EmptyContinuation()\n" +
+ " override fun resume(data: Any?) {}\n" +
+ " override fun resumeWithException(exception: Throwable) { throw exception }\n" +
+ "}",
+ directives
+ ));
+ }
+
+ return testFiles;
+ }
+
+ private static String substringKeepingLocations(String string, int start, int end) {
+ Matcher matcher = LINE_SEPARATOR_PATTERN.matcher(string);
+ StringBuilder prefix = new StringBuilder();
+ int lastLineOffset = 0;
+ while (matcher.find()) {
+ if (matcher.end() > start) {
+ break;
+ }
+
+ lastLineOffset = matcher.end();
+ prefix.append('\n');
+ }
+
+ while (lastLineOffset++ < start) {
+ prefix.append(' ');
+ }
+
+ return prefix + string.substring(start, end);
+ }
+
+ private static List parseModuleList(@Nullable String dependencies) {
+ if (dependencies == null) return Collections.emptyList();
+ return StringsKt.split(dependencies, Pattern.compile(MODULE_DELIMITER), 0);
+ }
+
+ @NotNull
+ public static Map parseDirectives(String expectedText) {
+ Map directives = Maps.newHashMap();
+ Matcher directiveMatcher = DIRECTIVE_PATTERN.matcher(expectedText);
+ int start = 0;
+ while (directiveMatcher.find()) {
+ if (directiveMatcher.start() != start) {
+ Assert.fail("Directives should only occur at the beginning of a file: " + directiveMatcher.group());
+ }
+ String name = directiveMatcher.group(1);
+ String value = directiveMatcher.group(3);
+ String oldValue = directives.put(name, value);
+ Assert.assertNull("Directive overwritten: " + name + " old value: " + oldValue + " new value: " + value, oldValue);
+ start = directiveMatcher.end() + 1;
+ }
+ return directives;
+ }
+
+ public static List loadBeforeAfterText(String filePath) {
+ String content;
+
+ try {
+ content = FileUtil.loadFile(new File(filePath), true);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ List files = createTestFiles("", content, new TestFileFactoryNoModules() {
+ @NotNull
+ @Override
+ public String create(@NotNull String fileName, @NotNull String text, @NotNull Map directives) {
+ int firstLineEnd = text.indexOf('\n');
+ return StringUtil.trimTrailing(text.substring(firstLineEnd + 1));
+ }
+ });
+
+ Assert.assertTrue("Exactly two files expected: ", files.size() == 2);
+
+ return files;
+ }
+
+ public static String getLastCommentedLines(@NotNull Document document) {
+ List resultLines = new ArrayList<>();
+ for (int i = document.getLineCount() - 1; i >= 0; i--) {
+ int lineStart = document.getLineStartOffset(i);
+ int lineEnd = document.getLineEndOffset(i);
+ if (document.getCharsSequence().subSequence(lineStart, lineEnd).toString().trim().isEmpty()) {
+ continue;
+ }
+
+ if ("//".equals(document.getCharsSequence().subSequence(lineStart, lineStart + 2).toString())) {
+ resultLines.add(document.getCharsSequence().subSequence(lineStart + 2, lineEnd));
+ }
+ else {
+ break;
+ }
+ }
+ Collections.reverse(resultLines);
+ StringBuilder result = new StringBuilder();
+ for (CharSequence line : resultLines) {
+ result.append(line).append("\n");
+ }
+ result.delete(result.length() - 1, result.length());
+ return result.toString();
+ }
+
+ public enum CommentType {
+ ALL,
+ LINE_COMMENT,
+ BLOCK_COMMENT
+ }
+
+ @NotNull
+ public static String getLastCommentInFile(@NotNull KtFile file) {
+ return CollectionsKt.first(getLastCommentsInFile(file, CommentType.ALL, true));
+ }
+
+ @NotNull
+ public static List getLastCommentsInFile(@NotNull KtFile file, CommentType commentType, boolean assertMustExist) {
+ PsiElement lastChild = file.getLastChild();
+ if (lastChild != null && lastChild.getNode().getElementType().equals(KtTokens.WHITE_SPACE)) {
+ lastChild = lastChild.getPrevSibling();
+ }
+ assert lastChild != null;
+
+ List comments = ContainerUtil.newArrayList();
+
+ while (true) {
+ if (lastChild.getNode().getElementType().equals(KtTokens.BLOCK_COMMENT)) {
+ if (commentType == CommentType.ALL || commentType == CommentType.BLOCK_COMMENT) {
+ String lastChildText = lastChild.getText();
+ comments.add(lastChildText.substring(2, lastChildText.length() - 2).trim());
+ }
+ }
+ else if (lastChild.getNode().getElementType().equals(KtTokens.EOL_COMMENT)) {
+ if (commentType == CommentType.ALL || commentType == CommentType.LINE_COMMENT) {
+ comments.add(lastChild.getText().substring(2).trim());
+ }
+ }
+ else {
+ break;
+ }
+
+ lastChild = lastChild.getPrevSibling();
+ }
+
+ if (comments.isEmpty() && assertMustExist) {
+ throw new AssertionError(String.format(
+ "Test file '%s' should end in a comment of type %s; last node was: %s", file.getName(), commentType, lastChild));
+ }
+
+ return comments;
+ }
+
+ public static boolean compileJavaFiles(@NotNull Collection files, List options) throws IOException {
+ return compileJavaFiles(files, options, null);
+ }
+
+ private static boolean compileJavaFiles(@NotNull Collection files, List options, @Nullable File javaErrorFile) throws IOException {
+ JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
+ DiagnosticCollector diagnosticCollector = new DiagnosticCollector<>();
+ try (StandardJavaFileManager fileManager =
+ javaCompiler.getStandardFileManager(diagnosticCollector, Locale.ENGLISH, Charset.forName("utf-8"))) {
+ Iterable extends JavaFileObject> javaFileObjectsFromFiles = fileManager.getJavaFileObjectsFromFiles(files);
+
+ JavaCompiler.CompilationTask task = javaCompiler.getTask(
+ new StringWriter(), // do not write to System.err
+ fileManager,
+ diagnosticCollector,
+ options,
+ null,
+ javaFileObjectsFromFiles);
+
+ Boolean success = task.call(); // do NOT inline this variable, call() should complete before errorsToString()
+ if (javaErrorFile == null || !javaErrorFile.exists()) {
+ Assert.assertTrue(errorsToString(diagnosticCollector, true), success);
+ }
+ else {
+ assertEqualsToFile(javaErrorFile, errorsToString(diagnosticCollector, false));
+ }
+ return success;
+ }
+ }
+
+ public static boolean compileJavaFilesExternallyWithJava9(@NotNull Collection files, @NotNull List options) {
+ List command = new ArrayList<>();
+ command.add(new File(getJdk9Home(), "bin/javac").getPath());
+ command.addAll(options);
+ for (File file : files) {
+ command.add(file.getPath());
+ }
+
+ try {
+ Process process = new ProcessBuilder().command(command).inheritIO().start();
+ process.waitFor();
+ return process.exitValue() == 0;
+ }
+ catch (Exception e) {
+ throw ExceptionUtilsKt.rethrow(e);
+ }
+ }
+
+ @NotNull
+ private static String errorsToString(@NotNull DiagnosticCollector diagnosticCollector, boolean humanReadable) {
+ StringBuilder builder = new StringBuilder();
+ for (javax.tools.Diagnostic extends JavaFileObject> diagnostic : diagnosticCollector.getDiagnostics()) {
+ if (diagnostic.getKind() != javax.tools.Diagnostic.Kind.ERROR) continue;
+
+ if (humanReadable) {
+ builder.append(diagnostic).append("\n");
+ }
+ else {
+ builder.append(new File(diagnostic.getSource().toUri()).getName()).append(":")
+ .append(diagnostic.getLineNumber()).append(":")
+ .append(diagnostic.getColumnNumber()).append(":")
+ .append(diagnostic.getCode()).append("\n");
+ }
+ }
+ return builder.toString();
+ }
+
+ public static String navigationMetadata(@TestDataFile String testFile) {
+ return testFile;
+ }
+
+ public static String getTestsRoot(@NotNull Class> testCaseClass) {
+ TestMetadata testClassMetadata = testCaseClass.getAnnotation(TestMetadata.class);
+ Assert.assertNotNull("No metadata for class: " + testCaseClass, testClassMetadata);
+ return testClassMetadata.value();
+ }
+
+ /**
+ * @return test data file name specified in the metadata of test method
+ */
+ @Nullable
+ public static String getTestDataFileName(@NotNull Class> testCaseClass, @NotNull String testName) {
+ try {
+ Method method = testCaseClass.getDeclaredMethod(testName);
+ return getMethodMetadata(method);
+ }
+ catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void assertAllTestsPresentByMetadata(
+ @NotNull Class> testCaseClass,
+ @NotNull File testDataDir,
+ @NotNull Pattern filenamePattern,
+ @NotNull TargetBackend targetBackend,
+ boolean recursive,
+ @NotNull String... excludeDirs
+ ) {
+ File rootFile = new File(getTestsRoot(testCaseClass));
+
+ Set filePaths = collectPathsMetadata(testCaseClass);
+ Set exclude = SetsKt.setOf(excludeDirs);
+
+ File[] files = testDataDir.listFiles();
+ if (files != null) {
+ for (File file : files) {
+ if (file.isDirectory()) {
+ if (recursive && containsTestData(file, filenamePattern) && !exclude.contains(file.getName())) {
+ assertTestClassPresentByMetadata(testCaseClass, file);
+ }
+ }
+ else if (filenamePattern.matcher(file.getName()).matches() && isCompatibleTarget(targetBackend, file)) {
+ assertFilePathPresent(file, rootFile, filePaths);
+ }
+ }
+ }
+ }
+
+ public static void assertAllTestsPresentInSingleGeneratedClass(
+ @NotNull Class> testCaseClass,
+ @NotNull File testDataDir,
+ @NotNull Pattern filenamePattern,
+ @NotNull TargetBackend targetBackend
+ ) {
+ File rootFile = new File(getTestsRoot(testCaseClass));
+
+ Set filePaths = collectPathsMetadata(testCaseClass);
+
+ FileUtil.processFilesRecursively(testDataDir, file -> {
+ if (file.isFile() && filenamePattern.matcher(file.getName()).matches() && isCompatibleTarget(targetBackend, file)) {
+ assertFilePathPresent(file, rootFile, filePaths);
+ }
+
+ return true;
+ });
+ }
+
+ private static void assertFilePathPresent(File file, File rootFile, Set filePaths) {
+ String path = FileUtil.getRelativePath(rootFile, file);
+ if (path != null) {
+ String relativePath = nameToCompare(path);
+ if (!filePaths.contains(relativePath)) {
+ Assert.fail("Test data file missing from the generated test class: " + file + "\n" + PLEASE_REGENERATE_TESTS);
+ }
+ }
+ }
+
+ private static Set collectPathsMetadata(Class> testCaseClass) {
+ return ContainerUtil.newHashSet(ContainerUtil.map(collectMethodsMetadata(testCaseClass), KotlinTestUtils::nameToCompare));
+ }
+
+ @Nullable
+ private static String getMethodMetadata(Method method) {
+ TestMetadata testMetadata = method.getAnnotation(TestMetadata.class);
+ return (testMetadata != null) ? testMetadata.value() : null;
+ }
+
+ private static Set collectMethodsMetadata(Class> testCaseClass) {
+ Set filePaths = Sets.newHashSet();
+ for (Method method : testCaseClass.getDeclaredMethods()) {
+ String path = getMethodMetadata(method);
+ if (path != null) {
+ filePaths.add(path);
+ }
+ }
+ return filePaths;
+ }
+
+ private static boolean containsTestData(File dir, Pattern filenamePattern) {
+ File[] files = dir.listFiles();
+ assert files != null;
+ for (File file : files) {
+ if (file.isDirectory()) {
+ if (containsTestData(file, filenamePattern)) {
+ return true;
+ }
+ }
+ else {
+ if (filenamePattern.matcher(file.getName()).matches()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private static void assertTestClassPresentByMetadata(@NotNull Class> outerClass, @NotNull File testDataDir) {
+ for (Class> nestedClass : outerClass.getDeclaredClasses()) {
+ TestMetadata testMetadata = nestedClass.getAnnotation(TestMetadata.class);
+ if (testMetadata != null && testMetadata.value().equals(getFilePath(testDataDir))) {
+ return;
+ }
+ }
+ Assert.fail("Test data directory missing from the generated test class: " + testDataDir + "\n" + PLEASE_REGENERATE_TESTS);
+ }
+
+ @NotNull
+ public static KtFile loadJetFile(@NotNull Project project, @NotNull File ioFile) throws IOException {
+ String text = FileUtil.loadFile(ioFile, true);
+ return KtPsiFactoryKt.KtPsiFactory(project).createPhysicalFile(ioFile.getName(), text);
+ }
+
+ @NotNull
+ public static List loadToJetFiles(@NotNull KotlinCoreEnvironment environment, @NotNull List files) throws IOException {
+ List jetFiles = Lists.newArrayList();
+ for (File file : files) {
+ jetFiles.add(loadJetFile(environment.getProject(), file));
+ }
+ return jetFiles;
+ }
+
+ @NotNull
+ public static ModuleDescriptorImpl createEmptyModule() {
+ return createEmptyModule("");
+ }
+
+ @NotNull
+ public static ModuleDescriptorImpl createEmptyModule(@NotNull String name) {
+ return createEmptyModule(name, DefaultBuiltIns.getInstance());
+ }
+
+ @NotNull
+ public static ModuleDescriptorImpl createEmptyModule(@NotNull String name, @NotNull KotlinBuiltIns builtIns) {
+ return new ModuleDescriptorImpl(Name.special(name), LockBasedStorageManager.NO_LOCKS, builtIns);
+ }
+
+ @NotNull
+ public static File replaceExtension(@NotNull File file, @Nullable String newExtension) {
+ return new File(file.getParentFile(), FileUtil.getNameWithoutExtension(file) + (newExtension == null ? "" : "." + newExtension));
+ }
+
+ @NotNull
+ public static String replaceHashWithStar(@NotNull String string) {
+ return replaceHash(string, "*");
+ }
+
+ public static String replaceHash(@NotNull String string, @NotNull String replacement) {
+ //TODO: hashes are still used in SamWrapperCodegen
+ Matcher matcher = STRIP_PACKAGE_PART_HASH_PATTERN.matcher(string);
+ if (matcher.find()) {
+ return matcher.replaceAll("\\$" + replacement);
+ }
+ return string;
+ }
+
+ public static boolean isAllFilesPresentTest(String testName) {
+ //noinspection SpellCheckingInspection
+ return testName.toLowerCase().startsWith("allfilespresentin");
+ }
+
+ public static String nameToCompare(@NotNull String name) {
+ return (SystemInfo.isFileSystemCaseSensitive ? name : name.toLowerCase()).replace('\\', '/');
+ }
+
+ public static boolean isMultiExtensionName(@NotNull String name) {
+ int firstDotIndex = name.indexOf('.');
+ if (firstDotIndex == -1) {
+ return false;
+ }
+ // Several extension if name contains another dot
+ return name.indexOf('.', firstDotIndex + 1) != -1;
+ }
+}
diff --git a/generators/build.gradle.kts.as32 b/generators/build.gradle.kts.as32
new file mode 100644
index 00000000000..bd432828ebf
--- /dev/null
+++ b/generators/build.gradle.kts.as32
@@ -0,0 +1,43 @@
+
+plugins {
+ kotlin("jvm")
+ id("jps-compatible")
+}
+
+dependencies {
+ compile(projectTests(":compiler:cli"))
+ compile(projectTests(":idea:idea-maven"))
+ compile(projectTests(":j2k"))
+ compile(projectTests(":idea:idea-android"))
+ compile(projectTests(":jps-plugin"))
+ compile(projectTests(":plugins:android-extensions-compiler"))
+ compile(projectTests(":plugins:android-extensions-ide"))
+ compile(projectTests(":plugins:android-extensions-jps"))
+ compile(projectTests(":kotlin-annotation-processing"))
+ compile(projectTests(":kotlin-allopen-compiler-plugin"))
+ compile(projectTests(":kotlin-noarg-compiler-plugin"))
+ compile(projectTests(":kotlin-sam-with-receiver-compiler-plugin"))
+ compile(projectTests(":generators:test-generator"))
+ // testCompileOnly(intellijDep("jps-build-test"))
+ testCompileOnly(project(":kotlin-reflect-api"))
+ testRuntime(intellijDep()) { includeJars("idea_rt") }
+ testRuntime(projectDist(":kotlin-reflect"))
+}
+
+sourceSets {
+ "main" { }
+ "test" { projectDefault() }
+}
+
+projectTest {
+ workingDir = rootDir
+}
+
+val generateTests by generator("org.jetbrains.kotlin.generators.tests.GenerateTestsKt")
+
+val generateProtoBuf by generator("org.jetbrains.kotlin.generators.protobuf.GenerateProtoBufKt")
+val generateProtoBufCompare by generator("org.jetbrains.kotlin.generators.protobuf.GenerateProtoBufCompare")
+
+val generateGradleOptions by generator("org.jetbrains.kotlin.generators.arguments.GenerateGradleOptionsKt")
+
+testsJar()
diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as32 b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as32
new file mode 100644
index 00000000000..5cc0e1ed1f2
--- /dev/null
+++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as32
@@ -0,0 +1,1132 @@
+/*
+ * 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.generators.tests
+
+import org.jetbrains.kotlin.AbstractDataFlowValueRenderingTest
+import org.jetbrains.kotlin.addImport.AbstractAddImportTest
+import org.jetbrains.kotlin.allopen.AbstractBytecodeListingTestForAllOpen
+import org.jetbrains.kotlin.android.*
+import org.jetbrains.kotlin.android.annotator.AbstractAndroidGutterIconTest
+import org.jetbrains.kotlin.android.configure.AbstractConfigureProjectTest
+import org.jetbrains.kotlin.android.folding.AbstractAndroidResourceFoldingTest
+import org.jetbrains.kotlin.android.intention.AbstractAndroidIntentionTest
+import org.jetbrains.kotlin.android.intention.AbstractAndroidResourceIntentionTest
+import org.jetbrains.kotlin.android.parcel.AbstractParcelBytecodeListingTest
+import org.jetbrains.kotlin.android.quickfix.AbstractAndroidLintQuickfixTest
+import org.jetbrains.kotlin.android.quickfix.AbstractAndroidQuickFixMultiFileTest
+import org.jetbrains.kotlin.android.synthetic.test.AbstractAndroidBoxTest
+import org.jetbrains.kotlin.android.synthetic.test.AbstractAndroidBytecodeShapeTest
+import org.jetbrains.kotlin.android.synthetic.test.AbstractAndroidSyntheticPropertyDescriptorTest
+import org.jetbrains.kotlin.annotation.AbstractAnnotationProcessorBoxTest
+import org.jetbrains.kotlin.checkers.AbstractJavaAgainstKotlinBinariesCheckerTest
+import org.jetbrains.kotlin.checkers.AbstractJavaAgainstKotlinSourceCheckerTest
+import org.jetbrains.kotlin.checkers.AbstractJsCheckerTest
+import org.jetbrains.kotlin.checkers.AbstractPsiCheckerTest
+import org.jetbrains.kotlin.findUsages.AbstractFindUsagesTest
+import org.jetbrains.kotlin.findUsages.AbstractKotlinFindUsagesWithLibraryTest
+import org.jetbrains.kotlin.formatter.AbstractFormatterTest
+import org.jetbrains.kotlin.formatter.AbstractTypingIndentationTestBase
+import org.jetbrains.kotlin.generators.tests.generator.TestGroup
+import org.jetbrains.kotlin.generators.tests.generator.testGroup
+import org.jetbrains.kotlin.generators.util.KT_OR_KTS
+import org.jetbrains.kotlin.generators.util.KT_OR_KTS_WITHOUT_DOTS_IN_NAME
+import org.jetbrains.kotlin.generators.util.KT_WITHOUT_DOTS_IN_NAME
+import org.jetbrains.kotlin.idea.AbstractExpressionSelectionTest
+import org.jetbrains.kotlin.idea.AbstractKotlinTypeAliasByExpansionShortNameIndexTest
+import org.jetbrains.kotlin.idea.AbstractSmartSelectionTest
+import org.jetbrains.kotlin.idea.actions.AbstractGotoTestOrCodeActionTest
+import org.jetbrains.kotlin.idea.caches.resolve.AbstractIdeCompiledLightClassTest
+import org.jetbrains.kotlin.idea.caches.resolve.AbstractIdeLightClassTest
+import org.jetbrains.kotlin.idea.caches.resolve.AbstractMultiModuleLineMarkerTest
+import org.jetbrains.kotlin.idea.codeInsight.*
+import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractCodeInsightActionTest
+import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractGenerateHashCodeAndEqualsActionTest
+import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractGenerateTestSupportMethodActionTest
+import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractGenerateToStringActionTest
+import org.jetbrains.kotlin.idea.codeInsight.moveUpDown.AbstractMoveLeftRightTest
+import org.jetbrains.kotlin.idea.codeInsight.moveUpDown.AbstractMoveStatementTest
+import org.jetbrains.kotlin.idea.codeInsight.postfix.AbstractPostfixTemplateProviderTest
+import org.jetbrains.kotlin.idea.codeInsight.surroundWith.AbstractSurroundWithTest
+import org.jetbrains.kotlin.idea.codeInsight.unwrap.AbstractUnwrapRemoveTest
+import org.jetbrains.kotlin.idea.completion.test.*
+import org.jetbrains.kotlin.idea.completion.test.handlers.AbstractBasicCompletionHandlerTest
+import org.jetbrains.kotlin.idea.completion.test.handlers.AbstractCompletionCharFilterTest
+import org.jetbrains.kotlin.idea.completion.test.handlers.AbstractKeywordCompletionHandlerTest
+import org.jetbrains.kotlin.idea.completion.test.handlers.AbstractSmartCompletionHandlerTest
+import org.jetbrains.kotlin.idea.completion.test.weighers.AbstractBasicCompletionWeigherTest
+import org.jetbrains.kotlin.idea.completion.test.weighers.AbstractSmartCompletionWeigherTest
+import org.jetbrains.kotlin.idea.configuration.AbstractGradleConfigureProjectByChangingFileTest
+import org.jetbrains.kotlin.idea.conversion.copy.AbstractJavaToKotlinCopyPasteConversionTest
+import org.jetbrains.kotlin.idea.conversion.copy.AbstractLiteralKotlinToKotlinCopyPasteTest
+import org.jetbrains.kotlin.idea.conversion.copy.AbstractLiteralTextToKotlinCopyPasteTest
+import org.jetbrains.kotlin.idea.conversion.copy.AbstractTextJavaToKotlinCopyPasteConversionTest
+import org.jetbrains.kotlin.idea.coverage.AbstractKotlinCoverageOutputFilesTest
+import org.jetbrains.kotlin.idea.debugger.AbstractBeforeExtractFunctionInsertionTest
+import org.jetbrains.kotlin.idea.debugger.AbstractKotlinSteppingTest
+import org.jetbrains.kotlin.idea.debugger.AbstractPositionManagerTest
+import org.jetbrains.kotlin.idea.debugger.AbstractSmartStepIntoTest
+import org.jetbrains.kotlin.idea.debugger.evaluate.*
+import org.jetbrains.kotlin.idea.decompiler.navigation.AbstractNavigateToDecompiledLibraryTest
+import org.jetbrains.kotlin.idea.decompiler.navigation.AbstractNavigateToLibrarySourceTest
+import org.jetbrains.kotlin.idea.decompiler.stubBuilder.AbstractClsStubBuilderTest
+import org.jetbrains.kotlin.idea.decompiler.stubBuilder.AbstractLoadJavaClsStubTest
+import org.jetbrains.kotlin.idea.decompiler.textBuilder.AbstractCommonDecompiledTextFromJsMetadataTest
+import org.jetbrains.kotlin.idea.decompiler.textBuilder.AbstractCommonDecompiledTextTest
+import org.jetbrains.kotlin.idea.decompiler.textBuilder.AbstractJsDecompiledTextFromJsMetadataTest
+import org.jetbrains.kotlin.idea.decompiler.textBuilder.AbstractJvmDecompiledTextTest
+import org.jetbrains.kotlin.idea.editor.AbstractMultiLineStringIndentTest
+import org.jetbrains.kotlin.idea.editor.backspaceHandler.AbstractBackspaceHandlerTest
+import org.jetbrains.kotlin.idea.editor.quickDoc.AbstractQuickDocProviderTest
+import org.jetbrains.kotlin.idea.filters.AbstractKotlinExceptionFilterTest
+import org.jetbrains.kotlin.idea.folding.AbstractKotlinFoldingTest
+import org.jetbrains.kotlin.idea.hierarchy.AbstractHierarchyTest
+import org.jetbrains.kotlin.idea.hierarchy.AbstractHierarchyWithLibTest
+import org.jetbrains.kotlin.idea.highlighter.*
+import org.jetbrains.kotlin.idea.imports.AbstractJsOptimizeImportsTest
+import org.jetbrains.kotlin.idea.imports.AbstractJvmOptimizeImportsTest
+import org.jetbrains.kotlin.idea.inspections.AbstractLocalInspectionTest
+import org.jetbrains.kotlin.idea.inspections.AbstractMultiFileLocalInspectionTest
+import org.jetbrains.kotlin.idea.intentions.AbstractConcatenatedStringGeneratorTest
+import org.jetbrains.kotlin.idea.intentions.AbstractIntentionTest
+import org.jetbrains.kotlin.idea.intentions.AbstractIntentionTest2
+import org.jetbrains.kotlin.idea.intentions.AbstractMultiFileIntentionTest
+import org.jetbrains.kotlin.idea.intentions.declarations.AbstractJoinLinesTest
+import org.jetbrains.kotlin.idea.internal.AbstractBytecodeToolWindowTest
+import org.jetbrains.kotlin.idea.kdoc.AbstractKDocHighlightingTest
+import org.jetbrains.kotlin.idea.kdoc.AbstractKDocTypingTest
+import org.jetbrains.kotlin.idea.navigation.*
+import org.jetbrains.kotlin.idea.parameterInfo.AbstractParameterInfoTest
+import org.jetbrains.kotlin.idea.quickfix.AbstractQuickFixMultiFileTest
+import org.jetbrains.kotlin.idea.quickfix.AbstractQuickFixMultiModuleTest
+import org.jetbrains.kotlin.idea.quickfix.AbstractQuickFixTest
+import org.jetbrains.kotlin.idea.refactoring.AbstractNameSuggestionProviderTest
+import org.jetbrains.kotlin.idea.refactoring.copy.AbstractCopyTest
+import org.jetbrains.kotlin.idea.refactoring.copy.AbstractMultiModuleCopyTest
+import org.jetbrains.kotlin.idea.refactoring.inline.AbstractInlineTest
+import org.jetbrains.kotlin.idea.refactoring.introduce.AbstractExtractionTest
+import org.jetbrains.kotlin.idea.refactoring.move.AbstractMoveTest
+import org.jetbrains.kotlin.idea.refactoring.move.AbstractMultiModuleMoveTest
+import org.jetbrains.kotlin.idea.refactoring.pullUp.AbstractPullUpTest
+import org.jetbrains.kotlin.idea.refactoring.pushDown.AbstractPushDownTest
+import org.jetbrains.kotlin.idea.refactoring.rename.AbstractMultiModuleRenameTest
+import org.jetbrains.kotlin.idea.refactoring.rename.AbstractRenameTest
+import org.jetbrains.kotlin.idea.refactoring.safeDelete.AbstractMultiModuleSafeDeleteTest
+import org.jetbrains.kotlin.idea.refactoring.safeDelete.AbstractSafeDeleteTest
+import org.jetbrains.kotlin.idea.repl.AbstractIdeReplCompletionTest
+import org.jetbrains.kotlin.idea.resolve.*
+import org.jetbrains.kotlin.idea.scratch.AbstractScratchRunActionTest
+import org.jetbrains.kotlin.idea.script.AbstractScriptConfigurationCompletionTest
+import org.jetbrains.kotlin.idea.script.AbstractScriptConfigurationHighlightingTest
+import org.jetbrains.kotlin.idea.script.AbstractScriptConfigurationNavigationTest
+import org.jetbrains.kotlin.idea.slicer.AbstractSlicerLeafGroupingTest
+import org.jetbrains.kotlin.idea.slicer.AbstractSlicerNullnessGroupingTest
+import org.jetbrains.kotlin.idea.slicer.AbstractSlicerTreeTest
+import org.jetbrains.kotlin.idea.structureView.AbstractKotlinFileStructureTest
+import org.jetbrains.kotlin.idea.stubs.AbstractMultiFileHighlightingTest
+import org.jetbrains.kotlin.idea.stubs.AbstractResolveByStubTest
+import org.jetbrains.kotlin.idea.stubs.AbstractStubBuilderTest
+import org.jetbrains.kotlin.incremental.*
+import org.jetbrains.kotlin.j2k.AbstractJavaToKotlinConverterForWebDemoTest
+import org.jetbrains.kotlin.j2k.AbstractJavaToKotlinConverterMultiFileTest
+import org.jetbrains.kotlin.j2k.AbstractJavaToKotlinConverterSingleFileTest
+//import org.jetbrains.kotlin.jps.build.*
+//import org.jetbrains.kotlin.jps.build.android.AbstractAndroidJpsTestCase
+//import org.jetbrains.kotlin.jps.incremental.AbstractJsProtoComparisonTest
+//import org.jetbrains.kotlin.jps.incremental.AbstractJvmProtoComparisonTest
+import org.jetbrains.kotlin.kapt3.test.AbstractClassFileToSourceStubConverterTest
+import org.jetbrains.kotlin.kapt3.test.AbstractKotlinKaptContextTest
+import org.jetbrains.kotlin.noarg.AbstractBlackBoxCodegenTestForNoArg
+import org.jetbrains.kotlin.noarg.AbstractBytecodeListingTestForNoArg
+import org.jetbrains.kotlin.psi.patternMatching.AbstractPsiUnifierTest
+import org.jetbrains.kotlin.samWithReceiver.AbstractSamWithReceiverScriptTest
+import org.jetbrains.kotlin.samWithReceiver.AbstractSamWithReceiverTest
+import org.jetbrains.kotlin.search.AbstractAnnotatedMembersSearchTest
+import org.jetbrains.kotlin.search.AbstractInheritorsSearchTest
+import org.jetbrains.kotlin.shortenRefs.AbstractShortenRefsTest
+import org.jetbrains.kotlin.test.TargetBackend
+
+fun main(args: Array) {
+ System.setProperty("java.awt.headless", "true")
+
+ testGroup("idea/tests", "idea/testData") {
+ testClass {
+ model("resolve/additionalLazyResolve")
+ }
+
+ testClass {
+ model("resolve/partialBodyResolve")
+ }
+
+ testClass {
+ model("checker", recursive = false)
+ model("checker/regression")
+ model("checker/recovery")
+ model("checker/rendering")
+ model("checker/scripts", extension = "kts")
+ model("checker/duplicateJvmSignature")
+ model("checker/infos", testMethod = "doTestWithInfos")
+ model("checker/diagnosticsMessage")
+ }
+
+ testClass {
+ model("kotlinAndJavaChecker/javaAgainstKotlin")
+ model("kotlinAndJavaChecker/javaWithKotlin")
+ }
+
+ testClass {
+ model("kotlinAndJavaChecker/javaAgainstKotlin")
+ }
+
+ testClass {
+ model("unifier")
+ }
+
+ testClass {
+ model("checker/codeFragments", extension = "kt", recursive = false)
+ model("checker/codeFragments/imports", testMethod = "doTestWithImport", extension = "kt")
+ }
+
+ testClass {
+ model("quickfix.special/codeFragmentAutoImport", extension = "kt", recursive = false)
+ }
+
+ testClass {
+ model("checker/js")
+ }
+
+ testClass {
+ model("quickfix", pattern = "^([\\w\\-_]+)\\.kt$", filenameStartsLowerCase = true)
+ }
+
+ testClass {
+ model("navigation/gotoSuper", extension = "test", recursive = false)
+ }
+
+ testClass {
+ model("navigation/gotoTypeDeclaration", extension = "test")
+ }
+
+ testClass {
+ model("navigation/gotoDeclaration", extension = "test")
+ }
+
+ testClass {
+ model("parameterInfo", recursive = true, excludeDirs = listOf("withLib1/sharedLib", "withLib2/sharedLib", "withLib3/sharedLib"))
+ }
+
+ testClass {
+ model("navigation/gotoClass", testMethod = "doClassTest")
+ model("navigation/gotoSymbol", testMethod = "doSymbolTest")
+ }
+
+ testClass {
+ model("decompiler/navigation/usercode")
+ model("decompiler/navigation/usercode", testClassName ="UsercodeWithJSModule", testMethod = "doWithJSModuleTest")
+ }
+
+ testClass {
+ model("decompiler/navigation/usercode")
+ }
+
+ testClass {
+ model("navigation/implementations", recursive = false)
+ }
+
+ testClass {
+ model("navigation/gotoTestOrCode", pattern = "^(.+)\\.main\\..+\$")
+ }
+
+ testClass {
+ model("search/inheritance")
+ }
+
+ testClass {
+ model("search/annotations")
+ }
+
+ testClass {
+ model("quickfix", pattern = """^(\w+)\.((before\.Main\.\w+)|(test))$""", testMethod = "doTestWithExtraFile")
+ }
+
+ testClass {
+ model("typealiasExpansionIndex")
+ }
+
+ testClass {
+ model("highlighter")
+ }
+
+ testClass {
+ model("dslHighlighter")
+ }
+
+ testClass {
+ model("usageHighlighter")
+ }
+
+ testClass {
+ model("folding/noCollapse")
+ model("folding/checkCollapse", testMethod = "doSettingsFoldingTest")
+ }
+
+ testClass {
+ model("codeInsight/surroundWith/if", testMethod = "doTestWithIfSurrounder")
+ model("codeInsight/surroundWith/ifElse", testMethod = "doTestWithIfElseSurrounder")
+ model("codeInsight/surroundWith/ifElseExpression", testMethod = "doTestWithIfElseExpressionSurrounder")
+ model("codeInsight/surroundWith/ifElseExpressionBraces", testMethod = "doTestWithIfElseExpressionBracesSurrounder")
+ model("codeInsight/surroundWith/not", testMethod = "doTestWithNotSurrounder")
+ model("codeInsight/surroundWith/parentheses", testMethod = "doTestWithParenthesesSurrounder")
+ model("codeInsight/surroundWith/stringTemplate", testMethod = "doTestWithStringTemplateSurrounder")
+ model("codeInsight/surroundWith/when", testMethod = "doTestWithWhenSurrounder")
+ model("codeInsight/surroundWith/tryCatch", testMethod = "doTestWithTryCatchSurrounder")
+ model("codeInsight/surroundWith/tryCatchExpression", testMethod = "doTestWithTryCatchExpressionSurrounder")
+ model("codeInsight/surroundWith/tryCatchFinally", testMethod = "doTestWithTryCatchFinallySurrounder")
+ model("codeInsight/surroundWith/tryCatchFinallyExpression", testMethod = "doTestWithTryCatchFinallyExpressionSurrounder")
+ model("codeInsight/surroundWith/tryFinally", testMethod = "doTestWithTryFinallySurrounder")
+ model("codeInsight/surroundWith/functionLiteral", testMethod = "doTestWithFunctionLiteralSurrounder")
+ model("codeInsight/surroundWith/withIfExpression", testMethod = "doTestWithSurroundWithIfExpression")
+ model("codeInsight/surroundWith/withIfElseExpression", testMethod = "doTestWithSurroundWithIfElseExpression")
+ }
+
+ testClass {
+ model("joinLines")
+ }
+
+ testClass {
+ model("codeInsight/breadcrumbs")
+ }
+
+ testClass {
+ model("intentions", pattern = "^([\\w\\-_]+)\\.(kt|kts)$")
+ }
+
+ testClass {
+ model("intentions/loopToCallChain", pattern = "^([\\w\\-_]+)\\.kt$")
+ }
+
+ testClass {
+ model("concatenatedStringGenerator", pattern = "^([\\w\\-_]+)\\.kt$")
+ }
+
+ testClass {
+ model("intentions", pattern = "^(inspections\\.test)$", singleClass = true)
+ model("inspections", pattern = "^(inspections\\.test)$", singleClass = true)
+ model("inspectionsLocal", pattern = "^(inspections\\.test)$", singleClass = true)
+ }
+
+ testClass {
+ model("inspectionsLocal", pattern = "^([\\w\\-_]+)\\.(kt|kts)$")
+ }
+
+ testClass {
+ model("hierarchy/class/type", extension = null, recursive = false, testMethod = "doTypeClassHierarchyTest")
+ model("hierarchy/class/super", extension = null, recursive = false, testMethod = "doSuperClassHierarchyTest")
+ model("hierarchy/class/sub", extension = null, recursive = false, testMethod = "doSubClassHierarchyTest")
+ model("hierarchy/calls/callers", extension = null, recursive = false, testMethod = "doCallerHierarchyTest")
+ model("hierarchy/calls/callersJava", extension = null, recursive = false, testMethod = "doCallerJavaHierarchyTest")
+ model("hierarchy/calls/callees", extension = null, recursive = false, testMethod = "doCalleeHierarchyTest")
+ model("hierarchy/overrides", extension = null, recursive = false, testMethod = "doOverrideHierarchyTest")
+ }
+
+ testClass {
+ model("hierarchy/withLib", extension = null, recursive = false)
+ }
+
+ testClass {
+ model("codeInsight/moveUpDown/classBodyDeclarations", pattern = KT_OR_KTS, testMethod = "doTestClassBodyDeclaration")
+ model("codeInsight/moveUpDown/closingBraces", testMethod = "doTestExpression")
+ model("codeInsight/moveUpDown/expressions", pattern = KT_OR_KTS, testMethod = "doTestExpression")
+ model("codeInsight/moveUpDown/parametersAndArguments", testMethod = "doTestExpression")
+ }
+
+ testClass {
+ model("codeInsight/moveLeftRight")
+ }
+
+ testClass {
+ model("refactoring/inline", pattern = "^(\\w+)\\.kt$")
+ }
+
+ testClass {
+ model("codeInsight/unwrapAndRemove/removeExpression", testMethod = "doTestExpressionRemover")
+ model("codeInsight/unwrapAndRemove/unwrapThen", testMethod = "doTestThenUnwrapper")
+ model("codeInsight/unwrapAndRemove/unwrapElse", testMethod = "doTestElseUnwrapper")
+ model("codeInsight/unwrapAndRemove/removeElse", testMethod = "doTestElseRemover")
+ model("codeInsight/unwrapAndRemove/unwrapLoop", testMethod = "doTestLoopUnwrapper")
+ model("codeInsight/unwrapAndRemove/unwrapTry", testMethod = "doTestTryUnwrapper")
+ model("codeInsight/unwrapAndRemove/unwrapCatch", testMethod = "doTestCatchUnwrapper")
+ model("codeInsight/unwrapAndRemove/removeCatch", testMethod = "doTestCatchRemover")
+ model("codeInsight/unwrapAndRemove/unwrapFinally", testMethod = "doTestFinallyUnwrapper")
+ model("codeInsight/unwrapAndRemove/removeFinally", testMethod = "doTestFinallyRemover")
+ model("codeInsight/unwrapAndRemove/unwrapLambda", testMethod = "doTestLambdaUnwrapper")
+ model("codeInsight/unwrapAndRemove/unwrapFunctionParameter", testMethod = "doTestFunctionParameterUnwrapper")
+ }
+
+ testClass {
+ model("codeInsight/expressionType")
+ }
+
+ testClass {
+ model("editor/backspaceHandler")
+ }
+
+ testClass {
+ model("editor/enterHandler/multilineString")
+ }
+
+ testClass {
+ model("editor/quickDoc", pattern = """^([^_]+)\.[^\.]*$""")
+ }
+
+ testClass {
+ model("refactoring/safeDelete/deleteClass/kotlinClass", testMethod = "doClassTest")
+ model("refactoring/safeDelete/deleteClass/kotlinClassWithJava", testMethod = "doClassTestWithJava")
+ model("refactoring/safeDelete/deleteClass/javaClassWithKotlin", extension = "java", testMethod = "doJavaClassTest")
+ model("refactoring/safeDelete/deleteObject/kotlinObject", testMethod = "doObjectTest")
+ model("refactoring/safeDelete/deleteFunction/kotlinFunction", testMethod = "doFunctionTest")
+ model("refactoring/safeDelete/deleteFunction/kotlinFunctionWithJava", testMethod = "doFunctionTestWithJava")
+ model("refactoring/safeDelete/deleteFunction/javaFunctionWithKotlin", testMethod = "doJavaMethodTest")
+ model("refactoring/safeDelete/deleteProperty/kotlinProperty", testMethod = "doPropertyTest")
+ model("refactoring/safeDelete/deleteProperty/kotlinPropertyWithJava", testMethod = "doPropertyTestWithJava")
+ model("refactoring/safeDelete/deleteProperty/javaPropertyWithKotlin", testMethod = "doJavaPropertyTest")
+ model("refactoring/safeDelete/deleteTypeAlias/kotlinTypeAlias", testMethod = "doTypeAliasTest")
+ model("refactoring/safeDelete/deleteTypeParameter/kotlinTypeParameter", testMethod = "doTypeParameterTest")
+ model("refactoring/safeDelete/deleteTypeParameter/kotlinTypeParameterWithJava", testMethod = "doTypeParameterTestWithJava")
+ model("refactoring/safeDelete/deleteValueParameter/kotlinValueParameter", testMethod = "doValueParameterTest")
+ model("refactoring/safeDelete/deleteValueParameter/kotlinValueParameterWithJava", testMethod = "doValueParameterTestWithJava")
+ }
+
+ testClass {
+ model("resolve/references", pattern = KT_WITHOUT_DOTS_IN_NAME)
+ }
+
+ testClass {
+ model("resolve/referenceInJava/binaryAndSource", extension = "java")
+ model("resolve/referenceInJava/sourceOnly", extension = "java")
+ }
+
+ testClass {
+ model("resolve/referenceInJava/binaryAndSource", extension = "java")
+ }
+
+ testClass {
+ model("resolve/referenceWithLib", recursive = false)
+ }
+
+ testClass {
+ model("resolve/referenceInLib", recursive = false)
+ }
+
+ testClass {
+ model("resolve/referenceToJavaWithWrongFileStructure", recursive = false)
+ }
+
+ testClass {
+ model("findUsages/kotlin", pattern = """^(.+)\.0\.(kt|kts)$""")
+ model("findUsages/java", pattern = """^(.+)\.0\.java$""")
+ model("findUsages/propertyFiles", pattern = """^(.+)\.0\.properties$""")
+ }
+
+ testClass {
+ model("findUsages/libraryUsages", pattern = """^(.+)\.0\.kt$""")
+ }
+
+ testClass {
+ model("refactoring/move", extension = "test", singleClass = true)
+ }
+
+ testClass {
+ model("refactoring/copy", extension = "test", singleClass = true)
+ }
+
+ testClass {
+ model("refactoring/moveMultiModule", extension = "test", singleClass = true)
+ }
+
+ testClass {
+ model("refactoring/copyMultiModule", extension = "test", singleClass = true)
+ }
+
+ testClass {
+ model("refactoring/safeDeleteMultiModule", extension = "test", singleClass = true)
+ }
+
+ testClass {
+ model("multiFileIntentions", extension = "test", singleClass = true, filenameStartsLowerCase = true)
+ }
+
+ testClass {
+ model("multiFileLocalInspections", extension = "test", singleClass = true, filenameStartsLowerCase = true)
+ }
+
+ testClass {
+ model("multiFileInspections", extension = "test", singleClass = true)
+ }
+
+ testClass {
+ model("formatter", pattern = """^([^\.]+)\.after\.kt.*$""")
+ model("formatter", pattern = """^([^\.]+)\.after\.inv\.kt.*$""",
+ testMethod = "doTestInverted", testClassName = "FormatterInverted")
+ }
+
+ testClass {
+ model("indentationOnNewline", pattern = """^([^\.]+)\.after\.kt.*$""", testMethod = "doNewlineTest",
+ testClassName = "DirectSettings")
+ model("indentationOnNewline", pattern = """^([^\.]+)\.after\.inv\.kt.*$""", testMethod = "doNewlineTestWithInvert",
+ testClassName = "InvertedSettings")
+ }
+
+ testClass {
+ model("diagnosticMessage", recursive = false)
+ }
+
+ testClass {
+ model("diagnosticMessage/js", recursive = false, targetBackend = TargetBackend.JS)
+ }
+
+ testClass {
+ model("refactoring/rename", extension = "test", singleClass = true)
+ }
+
+ testClass {
+ model("refactoring/renameMultiModule", extension = "test", singleClass = true)
+ }
+
+ testClass {
+ model("codeInsight/outOfBlock")
+ }
+
+ testClass {
+ model("dataFlowValueRendering")
+ }
+
+ testClass {
+ model("copyPaste/conversion", pattern = """^([^\.]+)\.java$""")
+ }
+
+ testClass {
+ model("copyPaste/plainTextConversion", pattern = """^([^\.]+)\.txt$""")
+ }
+
+ testClass {
+ model("copyPaste/plainTextLiteral", pattern = """^([^\.]+)\.txt$""")
+ }
+
+ testClass {
+ model("copyPaste/literal", pattern = """^([^\.]+)\.kt$""")
+ }
+
+ testClass {
+ model("copyPaste/imports", pattern = KT_WITHOUT_DOTS_IN_NAME, testMethod = "doTestCopy", testClassName = "Copy", recursive = false)
+ model("copyPaste/imports", pattern = KT_WITHOUT_DOTS_IN_NAME, testMethod = "doTestCut", testClassName = "Cut", recursive = false)
+ }
+
+ testClass {
+ model("copyPaste/moveDeclarations", pattern = KT_WITHOUT_DOTS_IN_NAME, testMethod = "doTest")
+ }
+
+ testClass {
+ model("exitPoints")
+ }
+
+ testClass {
+ model("codeInsight/lineMarker")
+ }
+
+ testClass {
+ model("multiModuleLineMarker", extension = null, recursive = false)
+ }
+
+ testClass {
+ model("shortenRefs", pattern = KT_WITHOUT_DOTS_IN_NAME)
+ }
+ testClass {
+ model("addImport", pattern = KT_WITHOUT_DOTS_IN_NAME)
+ }
+
+ testClass {
+ model("smartSelection", testMethod = "doTestSmartSelection", pattern = KT_WITHOUT_DOTS_IN_NAME)
+ }
+
+ testClass {
+ model("structureView/fileStructure", pattern = KT_WITHOUT_DOTS_IN_NAME)
+ }
+
+ testClass {
+ model("expressionSelection", testMethod = "doTestExpressionSelection", pattern = KT_WITHOUT_DOTS_IN_NAME)
+ }
+
+ testClass {
+ model("decompiler/decompiledText", pattern = """^([^\.]+)$""")
+ }
+
+ testClass {
+ model("decompiler/decompiledTextJvm", pattern = """^([^\.]+)$""")
+ }
+
+ testClass {
+ model("decompiler/decompiledText", pattern = """^([^\.]+)$""", targetBackend = TargetBackend.JS)
+ }
+
+ testClass {
+ model("decompiler/decompiledTextJs", pattern = """^([^\.]+)$""", targetBackend = TargetBackend.JS)
+ }
+
+ testClass {
+ model("decompiler/stubBuilder", extension = null, recursive = false)
+ }
+
+ testClass {
+ model("editor/optimizeImports/jvm", pattern = KT_WITHOUT_DOTS_IN_NAME)
+ model("editor/optimizeImports/common", pattern = KT_WITHOUT_DOTS_IN_NAME)
+ }
+ testClass {
+ model("editor/optimizeImports/js", pattern = KT_WITHOUT_DOTS_IN_NAME)
+ model("editor/optimizeImports/common", pattern = KT_WITHOUT_DOTS_IN_NAME)
+ }
+
+ testClass {
+ model("debugger/positionManager", recursive = false, extension = "kt", testClassName = "SingleFile")
+ model("debugger/positionManager", recursive = false, extension = null, testClassName = "MultiFile")
+ }
+
+ testClass {
+ model("debugger/exceptionFilter", pattern = """^([^\.]+)$""", recursive = false)
+ }
+
+ testClass {
+ model("debugger/smartStepInto")
+ }
+
+ testClass {
+ model("debugger/insertBeforeExtractFunction", extension = "kt")
+ }
+
+ testClass {
+ model("debugger/tinyApp/src/stepping/stepIntoAndSmartStepInto", pattern = KT_WITHOUT_DOTS_IN_NAME, testMethod = "doStepIntoTest", testClassName = "StepInto")
+ model("debugger/tinyApp/src/stepping/stepIntoAndSmartStepInto", pattern = KT_WITHOUT_DOTS_IN_NAME, testMethod = "doSmartStepIntoTest", testClassName = "SmartStepInto")
+ model("debugger/tinyApp/src/stepping/stepInto", pattern = KT_WITHOUT_DOTS_IN_NAME, testMethod = "doStepIntoTest", testClassName = "StepIntoOnly")
+ model("debugger/tinyApp/src/stepping/stepOut", pattern = KT_WITHOUT_DOTS_IN_NAME, testMethod = "doStepOutTest")
+ model("debugger/tinyApp/src/stepping/stepOver", pattern = KT_WITHOUT_DOTS_IN_NAME, testMethod = "doStepOverTest")
+ model("debugger/tinyApp/src/stepping/stepOverForce", pattern = KT_WITHOUT_DOTS_IN_NAME, testMethod = "doStepOverForceTest")
+ model("debugger/tinyApp/src/stepping/filters", pattern = KT_WITHOUT_DOTS_IN_NAME, testMethod = "doStepIntoTest")
+ model("debugger/tinyApp/src/stepping/custom", pattern = KT_WITHOUT_DOTS_IN_NAME, testMethod = "doCustomTest")
+ }
+
+ testClass {
+ model("debugger/tinyApp/src/evaluate/singleBreakpoint", testMethod = "doSingleBreakpointTest")
+ model("debugger/tinyApp/src/evaluate/multipleBreakpoints", testMethod = "doMultipleBreakpointsTest")
+ }
+
+ testClass {
+ model("stubs", extension = "kt")
+ }
+
+ testClass {
+ model("multiFileHighlighting", recursive = false)
+ }
+
+ testClass {
+ model("multiModuleQuickFix", recursive = false, extension = null)
+ }
+
+ testClass {
+ model("navigation/implementations/multiModule", recursive = false, extension = null)
+ }
+
+ testClass