Merge Kotlin JPS plugin

Kotlin JPS plugin existed in Kotlin repo before but was migrated to
intellij-community together with entire Kotlin plugin.
Now I return Kotlin JPS plugin back because it turned out that it's
easier to develop JPS in KT release cycle. Also I need to
unbundle Kotlin JPS plugin in scope of KTIJ-11633
This commit is contained in:
Nikita Bobko
2022-01-12 15:10:21 +01:00
642 changed files with 26551 additions and 0 deletions
+24
View File
@@ -0,0 +1,24 @@
plugins {
kotlin("jvm")
id("jps-compatible")
}
dependencies {
compile(kotlinStdlib())
compileOnly(project(":kotlin-reflect-api"))
compile(project(":compiler:util"))
compile(project(":compiler:cli-common"))
compile(project(":compiler:frontend.java"))
compile(project(":js:js.frontend"))
compile(project(":native:frontend.native"))
compileOnly(intellijDep())
compileOnly(jpsStandalone()) { includeJars("jps-model") }
}
sourceSets {
"main" { projectDefault() }
"test" {}
}
runtimeJar()
@@ -0,0 +1,22 @@
/*
* 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.config;
public class CompilerRunnerConstants {
public static final String KOTLIN_COMPILER_NAME = "Kotlin";
public static final String INTERNAL_ERROR_PREFIX = "[Internal Error] ";
}
@@ -0,0 +1,40 @@
/*
* 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.config
import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.cli.common.arguments.Freezable
class CompilerSettings : Freezable() {
var additionalArguments: String by FreezableVar(DEFAULT_ADDITIONAL_ARGUMENTS)
var scriptTemplates: String by FreezableVar("")
var scriptTemplatesClasspath: String by FreezableVar("")
var copyJsLibraryFiles: Boolean by FreezableVar(true)
var outputDirectoryForJsLibraryFiles: String by FreezableVar(DEFAULT_OUTPUT_DIRECTORY)
companion object {
val DEFAULT_ADDITIONAL_ARGUMENTS = "-version"
private val DEFAULT_OUTPUT_DIRECTORY = "lib"
}
}
val CompilerSettings.additionalArgumentsAsList: List<String>
get() = splitArgumentString(additionalArguments)
fun splitArgumentString(arguments: String) = StringUtil.splitHonorQuotes(arguments, ' ').map {
if (it.startsWith('"')) StringUtil.unescapeChar(StringUtil.unquoteString(it), '"') else it
}
@@ -0,0 +1,28 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.config
import com.intellij.openapi.application.ApplicationManager
private const val APPLICATION_MANAGER_CLASS_NAME = "com.intellij.openapi.application.ApplicationManager"
val isJps: Boolean by lazy {
/*
Normally, JPS shouldn't have an ApplicationManager class in the classpath,
but that's not true for JPS inside IDEA right now.
Though Application is not properly initialized inside JPS so we can use it as a check.
*/
return@lazy if (doesClassExist(APPLICATION_MANAGER_CLASS_NAME)) {
ApplicationManager.getApplication() == null
} else {
true
}
}
private fun doesClassExist(fqName: String): Boolean {
val classPath = fqName.replace('.', '/') + ".class"
return {}.javaClass.classLoader.getResource(classPath) != null
}
@@ -0,0 +1,26 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.config;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension;
import org.jetbrains.jps.model.serialization.module.JpsModuleSourceRootPropertiesSerializer;
import java.util.Arrays;
import java.util.List;
public class KotlinCommonJpsModelSerializerExtension extends JpsModelSerializerExtension {
@NotNull
@Override
public List<? extends JpsModuleSourceRootPropertiesSerializer<?>> getModuleSourceRootPropertiesSerializers() {
return Arrays.asList(
KotlinSourceRootPropertiesSerializer.Source.INSTANCE,
KotlinSourceRootPropertiesSerializer.TestSource.INSTANCE,
KotlinResourceRootPropertiesSerializer.Resource.INSTANCE,
KotlinResourceRootPropertiesSerializer.TestResource.INSTANCE
);
}
}
@@ -0,0 +1,293 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.config
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.cli.common.arguments.Argument
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.copyBean
import org.jetbrains.kotlin.cli.common.arguments.parseCommandLineArguments
import org.jetbrains.kotlin.platform.IdePlatformKind
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.TargetPlatformVersion
import org.jetbrains.kotlin.platform.compat.toIdePlatform
import org.jetbrains.kotlin.platform.isCommon
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.utils.DescriptionAware
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import kotlin.reflect.KProperty1
import kotlin.reflect.full.findAnnotation
@Deprecated("Use IdePlatformKind instead.", level = DeprecationLevel.ERROR)
sealed class TargetPlatformKind<out Version : TargetPlatformVersion>(
val version: Version,
val name: String
) : DescriptionAware {
override val description = "$name ${version.description}"
class Jvm(version: JvmTarget) : @Suppress("DEPRECATION_ERROR") TargetPlatformKind<JvmTarget>(version, "JVM") {
companion object {
private val JVM_PLATFORMS by lazy { JvmTarget.values().map(::Jvm) }
operator fun get(version: JvmTarget) = JVM_PLATFORMS[version.ordinal]
}
}
object JavaScript : @Suppress("DEPRECATION_ERROR") TargetPlatformKind<TargetPlatformVersion.NoVersion>(
TargetPlatformVersion.NoVersion,
"JavaScript"
)
object Common : @Suppress("DEPRECATION_ERROR") TargetPlatformKind<TargetPlatformVersion.NoVersion>(
TargetPlatformVersion.NoVersion,
"Common (experimental)"
)
}
sealed class VersionView : DescriptionAware {
abstract val version: LanguageVersion
object LatestStable : VersionView() {
override val version: LanguageVersion = RELEASED_VERSION
override val description: String
get() = "Latest stable (${version.versionString})"
}
class Specific(override val version: LanguageVersion) : VersionView() {
override val description: String
get() = version.description
override fun equals(other: Any?) = other is Specific && version == other.version
override fun hashCode() = version.hashCode()
}
companion object {
val RELEASED_VERSION = LanguageVersion.LATEST_STABLE
fun deserialize(value: String?, isAutoAdvance: Boolean): VersionView {
if (isAutoAdvance) return LatestStable
val languageVersion = LanguageVersion.fromVersionString(value)
return if (languageVersion != null) Specific(languageVersion) else LatestStable
}
}
}
var CommonCompilerArguments.languageVersionView: VersionView
get() = VersionView.deserialize(languageVersion, autoAdvanceLanguageVersion)
set(value) {
languageVersion = value.version.versionString
autoAdvanceLanguageVersion = value == VersionView.LatestStable
}
var CommonCompilerArguments.apiVersionView: VersionView
get() = VersionView.deserialize(apiVersion, autoAdvanceApiVersion)
set(value) {
apiVersion = value.version.versionString
autoAdvanceApiVersion = value == VersionView.LatestStable
}
enum class KotlinModuleKind {
DEFAULT,
SOURCE_SET_HOLDER,
COMPILATION_AND_SOURCE_SET_HOLDER;
@Deprecated("Use KotlinFacetSettings.mppVersion.isNewMpp")
val isNewMPP: Boolean
get() = this != DEFAULT
}
enum class KotlinMultiplatformVersion(val version: Int) {
M1(1), // the first implementation of MPP. Aka 1.2.0 MPP
M2(2), // the "New" MPP. Aka 1.3.0 MPP
M3(3) // the "Hierarchical" MPP.
}
val KotlinMultiplatformVersion?.isOldMpp: Boolean
get() = this == KotlinMultiplatformVersion.M1
val KotlinMultiplatformVersion?.isNewMPP: Boolean
get() = this == KotlinMultiplatformVersion.M2
val KotlinMultiplatformVersion?.isHmpp: Boolean
get() = this == KotlinMultiplatformVersion.M3
interface ExternalSystemRunTask {
val taskName: String
val externalSystemProjectId: String
val targetName: String?
}
data class ExternalSystemTestRunTask(
override val taskName: String,
override val externalSystemProjectId: String,
override val targetName: String?
) : ExternalSystemRunTask {
fun toStringRepresentation() = "$taskName|$externalSystemProjectId|$targetName"
companion object {
fun fromStringRepresentation(line: String) =
line.split("|").let { if (it.size == 3) ExternalSystemTestRunTask(it[0], it[1], it[2]) else null }
}
override fun toString() = "$taskName@$externalSystemProjectId [$targetName]"
}
data class ExternalSystemNativeMainRunTask(
override val taskName: String,
override val externalSystemProjectId: String,
override val targetName: String?,
val entryPoint: String,
val debuggable: Boolean,
) : ExternalSystemRunTask {
fun toStringRepresentation() = "$taskName|$externalSystemProjectId|$targetName|$entryPoint|$debuggable"
companion object {
fun fromStringRepresentation(line: String): ExternalSystemNativeMainRunTask? =
line.split("|").let {
if (it.size == 5) ExternalSystemNativeMainRunTask(it[0], it[1], it[2], it[3], it[4].toBoolean()) else null
}
}
}
class KotlinFacetSettings {
companion object {
// Increment this when making serialization-incompatible changes to configuration data
val CURRENT_VERSION = 4
val DEFAULT_VERSION = 0
}
var version = CURRENT_VERSION
var useProjectSettings: Boolean = true
var mergedCompilerArguments: CommonCompilerArguments? = null
private set
// TODO: Workaround for unwanted facet settings modification on code analysis
// To be replaced with proper API for settings update (see BaseKotlinCompilerSettings as an example)
fun updateMergedArguments() {
val compilerArguments = compilerArguments
val compilerSettings = compilerSettings
mergedCompilerArguments = if (compilerArguments != null) {
copyBean(compilerArguments).apply {
if (compilerSettings != null) {
parseCommandLineArguments(compilerSettings.additionalArgumentsAsList, this)
}
}
} else null
}
var compilerArguments: CommonCompilerArguments? = null
set(value) {
field = value?.unfrozen() as CommonCompilerArguments?
updateMergedArguments()
}
var compilerSettings: CompilerSettings? = null
set(value) {
field = value?.unfrozen() as CompilerSettings?
updateMergedArguments()
}
/*
This function is needed as some setting values may not be present in compilerArguments
but present in additional arguments instead, so we have to check both cases manually
*/
inline fun <reified A : CommonCompilerArguments> isCompilerSettingPresent(settingReference: KProperty1<A, Boolean>): Boolean {
val isEnabledByCompilerArgument = compilerArguments?.safeAs<A>()?.let(settingReference::get)
if (isEnabledByCompilerArgument == true) return true
val isEnabledByAdditionalSettings = run {
val stringArgumentName = settingReference.findAnnotation<Argument>()?.value ?: return@run null
compilerSettings?.additionalArguments?.contains(stringArgumentName, ignoreCase = true)
}
return isEnabledByAdditionalSettings ?: false
}
var languageLevel: LanguageVersion?
get() = compilerArguments?.languageVersion?.let { LanguageVersion.fromFullVersionString(it) }
set(value) {
compilerArguments?.apply {
languageVersion = value?.versionString
}
}
var apiLevel: LanguageVersion?
get() = compilerArguments?.apiVersion?.let { LanguageVersion.fromFullVersionString(it) }
set(value) {
compilerArguments?.apply {
apiVersion = value?.versionString
}
}
var targetPlatform: TargetPlatform? = null
get() {
// This work-around is required in order to fix importing of the proper JVM target version and works only
// for fully actualized JVM target platform
//TODO(auskov): this hack should be removed after fixing equals in SimplePlatform
val args = compilerArguments
val singleSimplePlatform = field?.componentPlatforms?.singleOrNull()
if (singleSimplePlatform == JvmPlatforms.defaultJvmPlatform.singleOrNull() && args != null) {
return IdePlatformKind.platformByCompilerArguments(args)
}
return field
}
var externalSystemRunTasks: List<ExternalSystemRunTask> = emptyList()
@Suppress("DEPRECATION_ERROR")
@Deprecated(
message = "This accessor is deprecated and will be removed soon, use API from 'org.jetbrains.kotlin.platform.*' packages instead",
replaceWith = ReplaceWith("targetPlatform"),
level = DeprecationLevel.ERROR
)
fun getPlatform(): org.jetbrains.kotlin.platform.IdePlatform<*, *>? {
return targetPlatform?.toIdePlatform()
}
var implementedModuleNames: List<String> = emptyList() // used for first implementation of MPP, aka 'old' MPP
var dependsOnModuleNames: List<String> = emptyList() // used for New MPP and later implementations
var productionOutputPath: String? = null
var testOutputPath: String? = null
var kind: KotlinModuleKind = KotlinModuleKind.DEFAULT
var sourceSetNames: List<String> = emptyList()
var isTestModule: Boolean = false
var externalProjectId: String = ""
@Deprecated(message = "Use mppVersion.isHmppEnabled")
var isHmppEnabled: Boolean = false
val mppVersion: KotlinMultiplatformVersion?
get() = when {
isHmppEnabled -> KotlinMultiplatformVersion.M3
kind.isNewMPP -> KotlinMultiplatformVersion.M2
targetPlatform.isCommon() || implementedModuleNames.isNotEmpty() -> KotlinMultiplatformVersion.M1
else -> null
}
var pureKotlinSourceFolders: List<String> = emptyList()
}
interface KotlinFacetSettingsProvider {
fun getSettings(module: Module): KotlinFacetSettings?
fun getInitializedSettings(module: Module): KotlinFacetSettings
companion object {
fun getInstance(project: Project): KotlinFacetSettingsProvider? {
if (project.isDisposed) {
return null
}
return ServiceManager.getService(project, KotlinFacetSettingsProvider::class.java)
}
}
}
@@ -0,0 +1,27 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.config
import org.jetbrains.jps.model.ex.JpsElementTypeBase
import org.jetbrains.jps.model.java.JavaResourceRootProperties
import org.jetbrains.jps.model.java.JavaResourceRootType
import org.jetbrains.jps.model.java.JpsJavaExtensionService
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
sealed class KotlinResourceRootType() : JpsElementTypeBase<JavaResourceRootProperties>(),
JpsModuleSourceRootType<JavaResourceRootProperties> {
override fun createDefaultProperties() =
JpsJavaExtensionService.getInstance().createResourceRootProperties("", false)
}
object ResourceKotlinRootType : KotlinResourceRootType()
object TestResourceKotlinRootType : KotlinResourceRootType() {
override fun isForTests() = true
}
val ALL_KOTLIN_RESOURCE_ROOT_TYPES = setOf(ResourceKotlinRootType, TestResourceKotlinRootType)
@@ -0,0 +1,26 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.config
import org.jetbrains.jps.model.ex.JpsElementTypeBase
import org.jetbrains.jps.model.java.JavaSourceRootProperties
import org.jetbrains.jps.model.java.JavaSourceRootType
import org.jetbrains.jps.model.java.JpsJavaExtensionService
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
sealed class KotlinSourceRootType() : JpsElementTypeBase<JavaSourceRootProperties>(), JpsModuleSourceRootType<JavaSourceRootProperties> {
override fun createDefaultProperties() = JpsJavaExtensionService.getInstance().createSourceRootProperties("")
}
object SourceKotlinRootType : KotlinSourceRootType()
object TestSourceKotlinRootType : KotlinSourceRootType() {
override fun isForTests() = true
}
val ALL_KOTLIN_SOURCE_ROOT_TYPES = setOf(SourceKotlinRootType, TestSourceKotlinRootType)
@@ -0,0 +1,28 @@
/*
* 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.config;
public class SettingConstants {
private SettingConstants() {}
public static final String KOTLIN_COMMON_COMPILER_ARGUMENTS_SECTION = "KotlinCommonCompilerArguments";
public static final String KOTLIN_TO_JS_COMPILER_ARGUMENTS_SECTION = "Kotlin2JsCompilerArguments";
public static final String KOTLIN_TO_JVM_COMPILER_ARGUMENTS_SECTION = "Kotlin2JvmCompilerArguments";
public static final String KOTLIN_COMPILER_SETTINGS_SECTION = "KotlinCompilerSettings";
public static final String KOTLIN_COMPILER_SETTINGS_FILE = "kotlinc.xml";
}
@@ -0,0 +1,457 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.config
import com.intellij.util.PathUtil
import com.intellij.util.xmlb.SerializationFilter
import com.intellij.util.xmlb.SkipDefaultsSerializationFilter
import com.intellij.util.xmlb.XmlSerializer
import org.jdom.DataConversionException
import org.jdom.Element
import org.jdom.Text
import org.jetbrains.kotlin.cli.common.arguments.*
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.platform.*
import org.jetbrains.kotlin.platform.impl.FakeK2NativeCompilerArguments
import org.jetbrains.kotlin.platform.impl.JvmIdePlatformKind
import org.jetbrains.kotlin.platform.js.isJs
import org.jetbrains.kotlin.platform.jvm.JdkPlatform
import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlin.platform.konan.*
import java.lang.reflect.Modifier
import kotlin.reflect.KClass
import kotlin.reflect.full.superclasses
fun Element.getOption(name: String) = getChildren("option").firstOrNull { it.getAttribute("name").value == name }
private fun Element.getOptionValue(name: String) = getOption(name)?.getAttribute("value")?.value
private fun Element.getOptionBody(name: String) = getOption(name)?.children?.firstOrNull()
fun TargetPlatform.createArguments(init: (CommonCompilerArguments).() -> Unit = {}): CommonCompilerArguments {
return when {
isCommon() -> K2MetadataCompilerArguments().apply { init() }
isJvm() -> K2JVMCompilerArguments().apply {
init()
// TODO(dsavvinov): review this
jvmTarget = (single() as? JdkPlatform)?.targetVersion?.description ?: JvmTarget.DEFAULT.description
}
isJs() -> K2JSCompilerArguments().apply { init() }
isNative() -> FakeK2NativeCompilerArguments().apply { init() }
else -> error("Unknown platform $this")
}
}
private fun readV1Config(element: Element): KotlinFacetSettings {
return KotlinFacetSettings().apply {
val useProjectSettings = element.getOptionValue("useProjectSettings")?.toBoolean()
val versionInfoElement = element.getOptionBody("versionInfo")
val targetPlatformName = versionInfoElement?.getOptionValue("targetPlatformName")
val languageLevel = versionInfoElement?.getOptionValue("languageLevel")
val apiLevel = versionInfoElement?.getOptionValue("apiLevel")
val targetPlatform = CommonPlatforms.allSimplePlatforms.union(setOf(CommonPlatforms.defaultCommonPlatform))
.firstOrNull { it.oldFashionedDescription == targetPlatformName }
?: JvmIdePlatformKind.defaultPlatform // FIXME(dsavvinov): choose proper default
val compilerInfoElement = element.getOptionBody("compilerInfo")
val compilerSettings = CompilerSettings().apply {
compilerInfoElement?.getOptionBody("compilerSettings")?.let { compilerSettingsElement ->
XmlSerializer.deserializeInto(this, compilerSettingsElement)
}
}
val commonArgumentsElement = compilerInfoElement?.getOptionBody("_commonCompilerArguments")
val jvmArgumentsElement = compilerInfoElement?.getOptionBody("k2jvmCompilerArguments")
val jsArgumentsElement = compilerInfoElement?.getOptionBody("k2jsCompilerArguments")
val compilerArguments = targetPlatform.createArguments { freeArgs = arrayListOf() }
commonArgumentsElement?.let { XmlSerializer.deserializeInto(compilerArguments, it) }
when (compilerArguments) {
is K2JVMCompilerArguments -> jvmArgumentsElement?.let { XmlSerializer.deserializeInto(compilerArguments, it) }
is K2JSCompilerArguments -> jsArgumentsElement?.let { XmlSerializer.deserializeInto(compilerArguments, it) }
}
if (languageLevel != null) {
compilerArguments.languageVersion = languageLevel
}
if (apiLevel != null) {
compilerArguments.apiVersion = apiLevel
}
compilerArguments.detectVersionAutoAdvance()
if (useProjectSettings != null) {
this.useProjectSettings = useProjectSettings
} else {
// Migration problem workaround for pre-1.1-beta releases (mainly 1.0.6) -> 1.1-rc+
// Problematic cases: 1.1-beta/1.1-beta2 -> 1.1-rc+ (useProjectSettings gets reset to false)
// This heuristic detects old enough configurations:
if (jvmArgumentsElement == null) {
this.useProjectSettings = false
}
}
this.compilerSettings = compilerSettings
this.compilerArguments = compilerArguments
this.targetPlatform = IdePlatformKind.platformByCompilerArguments(compilerArguments)
}
}
// TODO: Introduce new version of facet serialization. See https://youtrack.jetbrains.com/issue/KT-38235
// This is necessary to avoid having too much custom logic for platform serialization.
fun Element.getFacetPlatformByConfigurationElement(): TargetPlatform {
val targetPlatform = getAttributeValue("allPlatforms").deserializeTargetPlatformByComponentPlatforms()
if (targetPlatform != null) return targetPlatform
// failed to read list of all platforms. Fallback to legacy algorithm
val platformName = getAttributeValue("platform") ?: return DefaultIdeTargetPlatformKindProvider.defaultPlatform
return CommonPlatforms.allSimplePlatforms.firstOrNull {
// first, look for exact match through all simple platforms
it.oldFashionedDescription == platformName
} ?: CommonPlatforms.defaultCommonPlatform.takeIf {
// then, check exact match for the default common platform
it.oldFashionedDescription == platformName
} ?: NativePlatforms.unspecifiedNativePlatform.takeIf {
// if none of the above succeeded, check if it's an old-style record about native platform (without suffix with target name)
it.oldFashionedDescription.startsWith(platformName)
}.orDefault() // finally, fallback to the default platform
}
private fun readV2AndLaterConfig(element: Element): KotlinFacetSettings {
return KotlinFacetSettings().apply {
element.getAttributeValue("useProjectSettings")?.let { useProjectSettings = it.toBoolean() }
val targetPlatform = element.getFacetPlatformByConfigurationElement()
this.targetPlatform = targetPlatform
readElementsList(element, "implements", "implement")?.let { implementedModuleNames = it }
readElementsList(element, "dependsOnModuleNames", "dependsOn")?.let { dependsOnModuleNames = it }
element.getChild("externalSystemTestTasks")?.let {
val testRunTasks = it.getChildren("externalSystemTestTask")
.mapNotNull { (it.content.firstOrNull() as? Text)?.textTrim }
.mapNotNull { ExternalSystemTestRunTask.fromStringRepresentation(it) }
val nativeMainRunTasks = it.getChildren("externalSystemNativeMainRunTask")
.mapNotNull { (it.content.firstOrNull() as? Text)?.textTrim }
.mapNotNull { ExternalSystemNativeMainRunTask.fromStringRepresentation(it) }
externalSystemRunTasks = testRunTasks + nativeMainRunTasks
}
element.getChild("sourceSets")?.let {
val items = it.getChildren("sourceSet")
sourceSetNames = items.mapNotNull { (it.content.firstOrNull() as? Text)?.textTrim }
}
kind = element.getChild("newMppModelJpsModuleKind")?.let {
val kindName = (it.content.firstOrNull() as? Text)?.textTrim
if (kindName != null) {
try {
KotlinModuleKind.valueOf(kindName)
} catch (e: Exception) {
null
}
} else null
} ?: KotlinModuleKind.DEFAULT
isTestModule = element.getAttributeValue("isTestModule")?.toBoolean() ?: false
externalProjectId = element.getAttributeValue("externalProjectId") ?: ""
isHmppEnabled = element.getAttribute("isHmppProject")?.booleanValue ?: false
pureKotlinSourceFolders = element.getAttributeValue("pureKotlinSourceFolders")?.split(";")?.toList() ?: emptyList()
element.getChild("compilerSettings")?.let {
compilerSettings = CompilerSettings()
XmlSerializer.deserializeInto(compilerSettings!!, it)
}
element.getChild("compilerArguments")?.let {
compilerArguments = targetPlatform.createArguments {
freeArgs = mutableListOf()
internalArguments = mutableListOf()
}
XmlSerializer.deserializeInto(compilerArguments!!, it)
compilerArguments!!.detectVersionAutoAdvance()
}
productionOutputPath = element.getChild("productionOutputPath")?.let {
PathUtil.toSystemDependentName((it.content.firstOrNull() as? Text)?.textTrim)
} ?: (compilerArguments as? K2JSCompilerArguments)?.outputFile
testOutputPath = element.getChild("testOutputPath")?.let {
PathUtil.toSystemDependentName((it.content.firstOrNull() as? Text)?.textTrim)
} ?: (compilerArguments as? K2JSCompilerArguments)?.outputFile
}
}
private fun readElementsList(element: Element, rootElementName: String, elementName: String): List<String>? {
element.getChild(rootElementName)?.let {
val items = it.getChildren(elementName)
return if (items.isNotEmpty()) {
items.mapNotNull { (it.content.firstOrNull() as? Text)?.textTrim }
} else {
listOfNotNull((it.content.firstOrNull() as? Text)?.textTrim)
}
}
return null
}
private fun readV3Config(element: Element): KotlinFacetSettings {
return readV2AndLaterConfig(element)
}
private fun readV2Config(element: Element): KotlinFacetSettings {
return readV2AndLaterConfig(element)
}
private fun readLatestConfig(element: Element): KotlinFacetSettings {
return readV2AndLaterConfig(element)
}
fun deserializeFacetSettings(element: Element): KotlinFacetSettings {
val version = try {
element.getAttribute("version")?.intValue
} catch (e: DataConversionException) {
null
} ?: KotlinFacetSettings.DEFAULT_VERSION
return when (version) {
1 -> readV1Config(element)
2 -> readV2Config(element)
3 -> readV3Config(element)
KotlinFacetSettings.CURRENT_VERSION -> readLatestConfig(element)
else -> return KotlinFacetSettings() // Reset facet configuration if versions don't match
}.apply { this.version = version }
}
fun CommonCompilerArguments.convertPathsToSystemIndependent() {
pluginClasspaths?.forEachIndexed { index, s -> pluginClasspaths!![index] = PathUtil.toSystemIndependentName(s) }
when (this) {
is K2JVMCompilerArguments -> {
destination = PathUtil.toSystemIndependentName(destination)
classpath = PathUtil.toSystemIndependentName(classpath)
jdkHome = PathUtil.toSystemIndependentName(jdkHome)
kotlinHome = PathUtil.toSystemIndependentName(kotlinHome)
friendPaths?.forEachIndexed { index, s -> friendPaths!![index] = PathUtil.toSystemIndependentName(s) }
declarationsOutputPath = PathUtil.toSystemIndependentName(declarationsOutputPath)
}
is K2JSCompilerArguments -> {
outputFile = PathUtil.toSystemIndependentName(outputFile)
libraries = PathUtil.toSystemIndependentName(libraries)
}
is K2MetadataCompilerArguments -> {
destination = PathUtil.toSystemIndependentName(destination)
classpath = PathUtil.toSystemIndependentName(classpath)
}
}
}
fun CompilerSettings.convertPathsToSystemIndependent() {
scriptTemplatesClasspath = PathUtil.toSystemIndependentName(scriptTemplatesClasspath)
outputDirectoryForJsLibraryFiles = PathUtil.toSystemIndependentName(outputDirectoryForJsLibraryFiles)
}
private fun KClass<*>.superClass() = superclasses.firstOrNull { !it.java.isInterface }
private fun Class<*>.computeNormalPropertyOrdering(): Map<String, Int> {
val result = LinkedHashMap<String, Int>()
var count = 0
generateSequence(this) { it.superclass }.forEach { clazz ->
for (field in clazz.declaredFields) {
if (field.modifiers and Modifier.STATIC != 0) continue
var propertyName = field.name
if (propertyName.endsWith(JvmAbi.DELEGATED_PROPERTY_NAME_SUFFIX)) {
propertyName = propertyName.dropLast(JvmAbi.DELEGATED_PROPERTY_NAME_SUFFIX.length)
}
result[propertyName] = count++
}
}
return result
}
private val allNormalOrderings = HashMap<Class<*>, Map<String, Int>>()
private val Class<*>.normalOrdering
get() = synchronized(allNormalOrderings) { allNormalOrderings.getOrPut(this) { computeNormalPropertyOrdering() } }
// Replacing fields with delegated properties leads to unexpected reordering of entries in facet configuration XML
// It happens due to XmlSerializer using different orderings for field- and method-based accessors
// This code restores the original ordering
private fun Element.restoreNormalOrdering(bean: Any) {
val normalOrdering = bean.javaClass.normalOrdering
val elementsToReorder = this.getContent<Element> { it is Element && it.getAttribute("name")?.value in normalOrdering }
elementsToReorder.sortedBy { normalOrdering[it.getAttribute("name")?.value!!] }
.forEachIndexed { index, element -> elementsToReorder[index] = element.clone() }
}
private fun buildChildElement(element: Element, tag: String, bean: Any, filter: SerializationFilter): Element {
return Element(tag).apply {
XmlSerializer.serializeInto(bean, this, filter)
restoreNormalOrdering(bean)
element.addContent(this)
}
}
private fun KotlinFacetSettings.writeLatestConfig(element: Element) {
val filter = SkipDefaultsSerializationFilter()
// TODO: Introduce new version of facet serialization. See https://youtrack.jetbrains.com/issue/KT-38235
// This is necessary to avoid having too much custom logic for platform serialization.
targetPlatform?.let { targetPlatform ->
element.setAttribute("platform", targetPlatform.oldFashionedDescription)
element.setAttribute("allPlatforms", targetPlatform.serializeComponentPlatforms())
}
if (!useProjectSettings) {
element.setAttribute("useProjectSettings", useProjectSettings.toString())
}
saveElementsList(element, implementedModuleNames, "implements", "implement")
saveElementsList(element, dependsOnModuleNames, "dependsOnModuleNames", "dependsOn")
if (sourceSetNames.isNotEmpty()) {
element.addContent(
Element("sourceSets").apply {
sourceSetNames.map { addContent(Element("sourceSet").apply { addContent(it) }) }
}
)
}
if (kind != KotlinModuleKind.DEFAULT) {
element.addContent(Element("newMppModelJpsModuleKind").apply { addContent(kind.name) })
element.setAttribute("isTestModule", isTestModule.toString())
}
if (externalProjectId.isNotEmpty()) {
element.setAttribute("externalProjectId", externalProjectId)
}
if (isHmppEnabled) {
element.setAttribute("isHmppProject", mppVersion.isHmpp.toString())
}
if (externalSystemRunTasks.isNotEmpty()) {
element.addContent(
Element("externalSystemTestTasks").apply {
externalSystemRunTasks.forEach { task ->
when(task) {
is ExternalSystemTestRunTask -> {
addContent(
Element("externalSystemTestTask").apply { addContent(task.toStringRepresentation()) }
)
}
is ExternalSystemNativeMainRunTask -> {
addContent(
Element("externalSystemNativeMainRunTask").apply { addContent(task.toStringRepresentation()) }
)
}
}
}
}
)
}
if (pureKotlinSourceFolders.isNotEmpty()) {
element.setAttribute("pureKotlinSourceFolders", pureKotlinSourceFolders.joinToString(";"))
}
productionOutputPath?.let {
if (it != (compilerArguments as? K2JSCompilerArguments)?.outputFile) {
element.addContent(Element("productionOutputPath").apply { addContent(PathUtil.toSystemIndependentName(it)) })
}
}
testOutputPath?.let {
if (it != (compilerArguments as? K2JSCompilerArguments)?.outputFile) {
element.addContent(Element("testOutputPath").apply { addContent(PathUtil.toSystemIndependentName(it)) })
}
}
compilerSettings?.let { copyBean(it) }?.let {
it.convertPathsToSystemIndependent()
buildChildElement(element, "compilerSettings", it, filter)
}
compilerArguments?.let { copyBean(it) }?.let {
it.convertPathsToSystemIndependent()
val compilerArgumentsXml = buildChildElement(element, "compilerArguments", it, filter)
compilerArgumentsXml.dropVersionsIfNecessary(it)
}
}
private fun saveElementsList(element: Element, elementsList: List<String>, rootElementName: String, elementName: String) {
if (elementsList.isNotEmpty()) {
element.addContent(
Element(rootElementName).apply {
val singleModule = elementsList.singleOrNull()
if (singleModule != null) {
addContent(singleModule)
} else {
elementsList.map { addContent(Element(elementName).apply { addContent(it) }) }
}
}
)
}
}
fun CommonCompilerArguments.detectVersionAutoAdvance() {
autoAdvanceLanguageVersion = languageVersion == null
autoAdvanceApiVersion = apiVersion == null
}
fun Element.dropVersionsIfNecessary(settings: CommonCompilerArguments) {
// Do not serialize language/api version if they correspond to the default language version
if (settings.autoAdvanceLanguageVersion) {
getOption("languageVersion")?.detach()
}
if (settings.autoAdvanceApiVersion) {
getOption("apiVersion")?.detach()
}
}
fun KotlinFacetSettings.serializeFacetSettings(element: Element) {
val versionToWrite = when (version) {
2, 3 -> version
else -> KotlinFacetSettings.CURRENT_VERSION
}
element.setAttribute("version", versionToWrite.toString())
writeLatestConfig(element)
}
private fun TargetPlatform.serializeComponentPlatforms(): String {
val componentPlatforms = componentPlatforms
val componentPlatformNames = componentPlatforms.mapTo(ArrayList()) { it.serializeToString() }
// workaround for old Kotlin IDE plugins, KT-38634
if (componentPlatforms.any { it is NativePlatform })
componentPlatformNames.add(NativePlatformUnspecifiedTarget.legacySerializeToString())
return componentPlatformNames.sorted().joinToString("/")
}
private fun String?.deserializeTargetPlatformByComponentPlatforms(): TargetPlatform? {
val componentPlatformNames = this?.split('/')?.toSet()
if (componentPlatformNames == null || componentPlatformNames.isEmpty())
return null
val knownComponentPlatforms = HashMap<String, SimplePlatform>() // "serialization presentation" to "simple platform name"
// first, collect serialization presentations for every known simple platform
CommonPlatforms.allSimplePlatforms
.flatMap { it.componentPlatforms }
.forEach { knownComponentPlatforms[it.serializeToString()] = it }
// next, add legacy aliases for some of the simple platforms; ex: unspecifiedNativePlatform
NativePlatformUnspecifiedTarget.let { knownComponentPlatforms[it.legacySerializeToString()] = it }
val componentPlatforms = componentPlatformNames.mapNotNull(knownComponentPlatforms::get).toSet()
return when (componentPlatforms.size) {
0 -> {
// empty set of component platforms is not allowed, in such case fallback to legacy algorithm
null
}
1 -> TargetPlatform(componentPlatforms)
else -> {
// workaround for old Kotlin IDE plugins, KT-38634
if (componentPlatforms.any { it is NativePlatformUnspecifiedTarget }
&& componentPlatforms.any { it is NativePlatformWithTarget }
) {
TargetPlatform(componentPlatforms - NativePlatformUnspecifiedTarget)
} else {
TargetPlatform(componentPlatforms)
}
}
}
}
@@ -0,0 +1,86 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.config
import org.jdom.Element
import org.jetbrains.jps.model.java.JavaResourceRootProperties
import org.jetbrains.jps.model.java.JavaSourceRootProperties
import org.jetbrains.jps.model.java.JpsJavaExtensionService
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
import org.jetbrains.jps.model.serialization.module.JpsModuleRootModelSerializer
import org.jetbrains.jps.model.serialization.module.JpsModuleSourceRootPropertiesSerializer
private const val IS_GENERATED_ATTRIBUTE = "generated"
private const val RELATIVE_OUTPUT_PATH_ATTRIBUTE = "relativeOutputPath"
const val KOTLIN_SOURCE_ROOT_TYPE_ID = "kotlin-source"
const val KOTLIN_TEST_ROOT_TYPE_ID = "kotlin-test"
const val KOTLIN_RESOURCE_ROOT_TYPE_ID = "kotlin-resource"
const val KOTLIN_TEST_RESOURCE_ROOT_TYPE_ID = "kotlin-test-resource"
// Based on org.jetbrains.jps.model.serialization.java.JpsJavaModelSerializerExtension.JavaSourceRootPropertiesSerializer class
sealed class KotlinSourceRootPropertiesSerializer(
type: JpsModuleSourceRootType<JavaSourceRootProperties>,
typeId: String
) : JpsModuleSourceRootPropertiesSerializer<JavaSourceRootProperties>(type, typeId) {
object Source : KotlinSourceRootPropertiesSerializer(
SourceKotlinRootType,
KOTLIN_SOURCE_ROOT_TYPE_ID
)
object TestSource : KotlinSourceRootPropertiesSerializer(
TestSourceKotlinRootType,
KOTLIN_TEST_ROOT_TYPE_ID
)
override fun loadProperties(sourceRootTag: Element): JavaSourceRootProperties {
val packagePrefix = sourceRootTag.getAttributeValue(JpsModuleRootModelSerializer.PACKAGE_PREFIX_ATTRIBUTE) ?: ""
val isGenerated = sourceRootTag.getAttributeValue(IS_GENERATED_ATTRIBUTE)?.toBoolean() ?: false
return JpsJavaExtensionService.getInstance().createSourceRootProperties(packagePrefix, isGenerated)
}
override fun saveProperties(properties: JavaSourceRootProperties, sourceRootTag: Element) {
val packagePrefix = properties.packagePrefix
if (packagePrefix.isNotEmpty()) {
sourceRootTag.setAttribute(JpsModuleRootModelSerializer.PACKAGE_PREFIX_ATTRIBUTE, packagePrefix)
}
if (properties.isForGeneratedSources) {
sourceRootTag.setAttribute(IS_GENERATED_ATTRIBUTE, "true")
}
}
}
// Based on org.jetbrains.jps.model.serialization.java.JpsJavaModelSerializerExtension.JavaResourceRootPropertiesSerializer
sealed class KotlinResourceRootPropertiesSerializer(
type: JpsModuleSourceRootType<JavaResourceRootProperties>,
typeId: String
) : JpsModuleSourceRootPropertiesSerializer<JavaResourceRootProperties>(type, typeId) {
object Resource : KotlinResourceRootPropertiesSerializer(
ResourceKotlinRootType,
KOTLIN_RESOURCE_ROOT_TYPE_ID
)
object TestResource : KotlinResourceRootPropertiesSerializer(
TestResourceKotlinRootType,
KOTLIN_TEST_RESOURCE_ROOT_TYPE_ID
)
override fun loadProperties(sourceRootTag: Element): JavaResourceRootProperties {
val relativeOutputPath = sourceRootTag.getAttributeValue(RELATIVE_OUTPUT_PATH_ATTRIBUTE) ?: ""
val isGenerated = sourceRootTag.getAttributeValue(IS_GENERATED_ATTRIBUTE)?.toBoolean() ?: false
return JpsJavaExtensionService.getInstance().createResourceRootProperties(relativeOutputPath, isGenerated)
}
override fun saveProperties(properties: JavaResourceRootProperties, sourceRootTag: Element) {
val relativeOutputPath = properties.relativeOutputPath
if (relativeOutputPath.isNotEmpty()) {
sourceRootTag.setAttribute(RELATIVE_OUTPUT_PATH_ATTRIBUTE, relativeOutputPath)
}
if (properties.isForGeneratedSources) {
sourceRootTag.setAttribute(IS_GENERATED_ATTRIBUTE, "true")
}
}
}
@@ -0,0 +1,35 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.platform
import com.intellij.openapi.components.ServiceManager
import org.jetbrains.kotlin.config.isJps
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.platform.TargetPlatform
interface DefaultIdeTargetPlatformKindProvider {
val defaultPlatform: TargetPlatform
companion object {
val defaultPlatform: TargetPlatform
get() {
if (isJps) {
// TODO support passing custom platforms in JPS
return JvmPlatforms.defaultJvmPlatform
}
return ServiceManager.getService(DefaultIdeTargetPlatformKindProvider::class.java).defaultPlatform
}
}
}
fun TargetPlatform?.orDefault(): TargetPlatform {
return this ?: DefaultIdeTargetPlatformKindProvider.defaultPlatform
}
fun IdePlatformKind<*>?.orDefault(): IdePlatformKind<*> {
return this ?: DefaultIdeTargetPlatformKindProvider.defaultPlatform.idePlatformKind
}
@@ -0,0 +1,27 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.platform
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.utils.DescriptionAware
@Suppress("DEPRECATION_ERROR")
@Deprecated(
message = "This interface is deprecated and will be removed soon, use API from 'org.jetbrains.kotlin.platform.*' packages instead",
replaceWith = ReplaceWith("TargetPlatform", "org.jetbrains.kotlin.platform.TargetPlatform"),
level = DeprecationLevel.ERROR
)
abstract class IdePlatform<Kind : IdePlatformKind<Kind>, out Arguments : CommonCompilerArguments> : DescriptionAware {
abstract val kind: Kind
abstract val version: TargetPlatformVersion
abstract fun createArguments(init: Arguments.() -> Unit = {}): Arguments
override val description
get() = kind.name + " " + version.description
override fun toString() = description
}
@@ -0,0 +1,83 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:JvmName("IdePlatformKindUtil")
package org.jetbrains.kotlin.platform
import com.intellij.openapi.diagnostic.Logger
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.config.isJps
import org.jetbrains.kotlin.extensions.ApplicationExtensionDescriptor
import org.jetbrains.kotlin.platform.impl.CommonIdePlatformKind
import org.jetbrains.kotlin.platform.impl.JsIdePlatformKind
import org.jetbrains.kotlin.platform.impl.JvmIdePlatformKind
import org.jetbrains.kotlin.platform.impl.NativeIdePlatformKind
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
abstract class IdePlatformKind<Kind : IdePlatformKind<Kind>> {
abstract fun supportsTargetPlatform(platform: TargetPlatform): Boolean
abstract val defaultPlatform: TargetPlatform
@Suppress("DEPRECATION_ERROR", "DeprecatedCallableAddReplaceWith")
@Deprecated(
message = "IdePlatform is deprecated and will be removed soon, please, migrate to org.jetbrains.kotlin.platform.TargetPlatform",
level = DeprecationLevel.ERROR
)
abstract fun getDefaultPlatform(): IdePlatform<*, *>
abstract fun platformByCompilerArguments(arguments: CommonCompilerArguments): TargetPlatform?
abstract val argumentsClass: Class<out CommonCompilerArguments>
abstract val name: String
abstract fun createArguments(): CommonCompilerArguments
override fun equals(other: Any?): Boolean = javaClass == other?.javaClass
override fun hashCode(): Int = javaClass.hashCode()
override fun toString() = name
companion object {
// We can't use the ApplicationExtensionDescriptor class directly because it's missing in the JPS process
private val extension = run {
if (isJps) return@run null
ApplicationExtensionDescriptor("org.jetbrains.kotlin.idePlatformKind", IdePlatformKind::class.java)
}
// For using only in JPS
private val JPS_KINDS
get() = listOf(
JvmIdePlatformKind,
JsIdePlatformKind,
CommonIdePlatformKind,
NativeIdePlatformKind
)
val ALL_KINDS by lazy {
val kinds = extension?.getInstances() ?: return@lazy JPS_KINDS
require(kinds.isNotEmpty()) { "Platform kind list is empty" }
kinds
}
fun <Args : CommonCompilerArguments> platformByCompilerArguments(arguments: Args): TargetPlatform? =
ALL_KINDS.firstNotNullResult { it.platformByCompilerArguments(arguments) }
}
}
val TargetPlatform.idePlatformKind: IdePlatformKind<*>
get() = IdePlatformKind.ALL_KINDS.filter { it.supportsTargetPlatform(this) }.let { list ->
when {
list.size == 1 -> list.first()
list.size > 1 -> list.first().also {
Logger.getInstance(IdePlatformKind.javaClass).warn("Found more than one IdePlatformKind [$list] for target [$this].")
}
else -> error("Unknown platform $this")
}
}
@@ -0,0 +1,65 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("DEPRECATION_ERROR", "TYPEALIAS_EXPANSION_DEPRECATION_ERROR")
package org.jetbrains.kotlin.platform.compat
import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.platform.CommonPlatforms
import org.jetbrains.kotlin.platform.IdePlatform
import org.jetbrains.kotlin.platform.impl.CommonIdePlatformKind
import org.jetbrains.kotlin.platform.impl.JsIdePlatformKind
import org.jetbrains.kotlin.platform.impl.JvmIdePlatformKind
import org.jetbrains.kotlin.platform.impl.NativeIdePlatformKind
import org.jetbrains.kotlin.platform.js.JsPlatform
import org.jetbrains.kotlin.platform.js.JsPlatforms
import org.jetbrains.kotlin.platform.jvm.JdkPlatform
import org.jetbrains.kotlin.platform.jvm.JvmPlatform
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.platform.konan.NativePlatforms
import org.jetbrains.kotlin.platform.konan.NativePlatform
typealias OldPlatform = org.jetbrains.kotlin.resolve.TargetPlatform
typealias NewPlatform = org.jetbrains.kotlin.platform.TargetPlatform
fun NewPlatform.toOldPlatform(): OldPlatform = when (val single = singleOrNull()) {
null -> CommonPlatforms.CompatCommonPlatform
is JvmPlatform -> JvmPlatforms.CompatJvmPlatform
is JsPlatform -> JsPlatforms.CompatJsPlatform
is NativePlatform -> NativePlatforms.CompatNativePlatform
else -> error("Unknown platform $single")
}
fun OldPlatform.toNewPlatform(): NewPlatform = when (this) {
is CommonPlatforms.CompatCommonPlatform -> this
is JvmPlatforms.CompatJvmPlatform -> this
is JsPlatforms.CompatJsPlatform -> this
is NativePlatforms.CompatNativePlatform -> this
else -> error(
"Can't convert org.jetbrains.kotlin.resolve.TargetPlatform to org.jetbrains.kotlin.platform.TargetPlatform: " +
"non-Compat instance passed\n" +
"toString: $this\n" +
"class: ${this::class}\n" +
"hashCode: ${this.hashCode().toString(16)}"
)
}
fun IdePlatform<*, *>.toNewPlatform(): NewPlatform = when (this) {
is CommonIdePlatformKind.Platform -> CommonPlatforms.defaultCommonPlatform
is JvmIdePlatformKind.Platform -> JvmPlatforms.jvmPlatformByTargetVersion(this.version)
is JsIdePlatformKind.Platform -> JsPlatforms.defaultJsPlatform
is NativeIdePlatformKind.Platform -> NativePlatforms.unspecifiedNativePlatform
else -> error("Unknown platform $this")
}
fun NewPlatform.toIdePlatform(): IdePlatform<*, *> = when (val single = singleOrNull()) {
null -> CommonIdePlatformKind.Platform
is JdkPlatform -> JvmIdePlatformKind.Platform(single.targetVersion)
is JvmPlatform -> JvmIdePlatformKind.Platform(JvmTarget.DEFAULT)
is JsPlatform -> JsIdePlatformKind.Platform
is NativePlatform -> NativeIdePlatformKind.Platform
else -> error("Unknown platform $single")
}
@@ -0,0 +1,60 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:JvmName("CommonIdePlatformUtil")
@file:Suppress("DEPRECATION_ERROR", "DeprecatedCallableAddReplaceWith")
package org.jetbrains.kotlin.platform.impl
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2MetadataCompilerArguments
import org.jetbrains.kotlin.platform.*
object CommonIdePlatformKind : IdePlatformKind<CommonIdePlatformKind>() {
override fun supportsTargetPlatform(platform: TargetPlatform) = platform.isCommon()
override fun platformByCompilerArguments(arguments: CommonCompilerArguments): TargetPlatform? {
return if (arguments is K2MetadataCompilerArguments)
CommonPlatforms.defaultCommonPlatform
else
null
}
@Deprecated(
message = "IdePlatform is deprecated and will be removed soon, please, migrate to org.jetbrains.kotlin.platform.TargetPlatform",
level = DeprecationLevel.ERROR
)
override fun getDefaultPlatform(): IdePlatform<*, *> = Platform
override fun createArguments(): CommonCompilerArguments {
return K2MetadataCompilerArguments() // TODO(dsavvinov): review that, as now MPP !== K2Metadata
}
override val defaultPlatform get() = CommonPlatforms.defaultCommonPlatform
override val argumentsClass get() = K2MetadataCompilerArguments::class.java
override val name get() = "Common (experimental)"
@Deprecated(
message = "IdePlatform is deprecated and will be removed soon, please, migrate to org.jetbrains.kotlin.platform.TargetPlatform",
level = DeprecationLevel.ERROR
)
object Platform : IdePlatform<CommonIdePlatformKind, CommonCompilerArguments>() {
override val kind get() = CommonIdePlatformKind
override val version get() = TargetPlatformVersion.NoVersion
override fun createArguments(init: CommonCompilerArguments.() -> Unit) = K2MetadataCompilerArguments().apply(init)
}
}
val IdePlatformKind<*>?.isCommon
get() = this is CommonIdePlatformKind
@Deprecated(
message = "IdePlatform is deprecated and will be removed soon, please, migrate to org.jetbrains.kotlin.platform.TargetPlatform",
level = DeprecationLevel.ERROR
)
val IdePlatform<*, *>.isCommon: Boolean
get() = this is CommonIdePlatformKind.Platform
@@ -0,0 +1,12 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.platform.impl
import org.jetbrains.kotlin.platform.DefaultIdeTargetPlatformKindProvider
class IdeaDefaultIdeTargetPlatformKindProvider private constructor() : DefaultIdeTargetPlatformKindProvider {
override val defaultPlatform = JvmIdePlatformKind.defaultPlatform
}
@@ -0,0 +1,66 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:JvmName("JsIdePlatformUtil")
@file:Suppress("DEPRECATION_ERROR", "DeprecatedCallableAddReplaceWith")
package org.jetbrains.kotlin.platform.impl
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
import org.jetbrains.kotlin.platform.IdePlatform
import org.jetbrains.kotlin.platform.IdePlatformKind
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.TargetPlatformVersion
import org.jetbrains.kotlin.platform.js.JsPlatforms
import org.jetbrains.kotlin.platform.js.isJs
object JsIdePlatformKind : IdePlatformKind<JsIdePlatformKind>() {
override fun supportsTargetPlatform(platform: TargetPlatform): Boolean = platform.isJs()
override fun platformByCompilerArguments(arguments: CommonCompilerArguments): TargetPlatform? {
return if (arguments is K2JSCompilerArguments)
JsPlatforms.defaultJsPlatform
else
null
}
val platforms get() = listOf(JsPlatforms.defaultJsPlatform)
override val defaultPlatform get() = JsPlatforms.defaultJsPlatform
@Deprecated(
message = "IdePlatform is deprecated and will be removed soon, please, migrate to org.jetbrains.kotlin.platform.TargetPlatform",
level = DeprecationLevel.ERROR
)
override fun getDefaultPlatform(): IdePlatform<*, *> = Platform
override fun createArguments(): CommonCompilerArguments {
return K2JSCompilerArguments()
}
override val argumentsClass get() = K2JSCompilerArguments::class.java
override val name get() = "JavaScript"
@Deprecated(
message = "IdePlatform is deprecated and will be removed soon, please, migrate to org.jetbrains.kotlin.platform.TargetPlatform",
level = DeprecationLevel.ERROR
)
object Platform : IdePlatform<JsIdePlatformKind, K2JSCompilerArguments>() {
override val kind get() = JsIdePlatformKind
override val version get() = TargetPlatformVersion.NoVersion
override fun createArguments(init: K2JSCompilerArguments.() -> Unit) = K2JSCompilerArguments().apply(init)
}
}
val IdePlatformKind<*>?.isJavaScript
get() = this is JsIdePlatformKind
@Deprecated(
message = "IdePlatform is deprecated and will be removed soon, please, migrate to org.jetbrains.kotlin.platform.TargetPlatform",
level = DeprecationLevel.ERROR
)
val IdePlatform<*, *>?.isJavaScript
get() = this is JsIdePlatformKind.Platform
@@ -0,0 +1,77 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:JvmName("JvmIdePlatformUtil")
@file:Suppress("DEPRECATION_ERROR", "DeprecatedCallableAddReplaceWith")
package org.jetbrains.kotlin.platform.impl
import com.intellij.util.text.VersionComparatorUtil
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.platform.IdePlatform
import org.jetbrains.kotlin.platform.IdePlatformKind
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.platform.jvm.isJvm
object JvmIdePlatformKind : IdePlatformKind<JvmIdePlatformKind>() {
override fun supportsTargetPlatform(platform: TargetPlatform): Boolean = platform.isJvm()
override fun platformByCompilerArguments(arguments: CommonCompilerArguments): TargetPlatform? {
if (arguments !is K2JVMCompilerArguments) return null
val jvmTargetDescription = arguments.jvmTarget
?: return JvmPlatforms.defaultJvmPlatform
val jvmTarget = JvmTarget.values()
.firstOrNull { VersionComparatorUtil.COMPARATOR.compare(it.description, jvmTargetDescription) >= 0 }
?: return JvmPlatforms.defaultJvmPlatform
return JvmPlatforms.jvmPlatformByTargetVersion(jvmTarget)
}
@Deprecated(
message = "IdePlatform is deprecated and will be removed soon, please, migrate to org.jetbrains.kotlin.platform.TargetPlatform",
level = DeprecationLevel.ERROR
)
override fun getDefaultPlatform(): Platform = Platform(JvmTarget.DEFAULT)
override fun createArguments(): CommonCompilerArguments {
return K2JVMCompilerArguments()
}
val platforms: List<TargetPlatform> = JvmTarget.values()
.map { ver -> JvmPlatforms.jvmPlatformByTargetVersion(ver) } + listOf(JvmPlatforms.unspecifiedJvmPlatform)
override val defaultPlatform get() = JvmPlatforms.defaultJvmPlatform
override val argumentsClass get() = K2JVMCompilerArguments::class.java
override val name get() = "JVM"
@Deprecated(
message = "IdePlatform is deprecated and will be removed soon, please, migrate to org.jetbrains.kotlin.platform.TargetPlatform",
level = DeprecationLevel.ERROR
)
data class Platform(override val version: JvmTarget) : IdePlatform<JvmIdePlatformKind, K2JVMCompilerArguments>() {
override val kind get() = JvmIdePlatformKind
override fun createArguments(init: K2JVMCompilerArguments.() -> Unit) = K2JVMCompilerArguments()
.apply(init)
.apply { jvmTarget = this@Platform.version.description }
}
}
val IdePlatformKind<*>?.isJvm
get() = this is JvmIdePlatformKind
@Deprecated(
message = "IdePlatform is deprecated and will be removed soon, please, migrate to org.jetbrains.kotlin.platform.TargetPlatform",
level = DeprecationLevel.ERROR
)
val IdePlatform<*, *>.isJvm: Boolean
get() = this is JvmIdePlatformKind.Platform
@@ -0,0 +1,70 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:JvmName("NativeIdePlatformUtil")
@file:Suppress("DEPRECATION_ERROR", "DeprecatedCallableAddReplaceWith")
package org.jetbrains.kotlin.platform.impl
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.platform.IdePlatform
import org.jetbrains.kotlin.platform.IdePlatformKind
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.TargetPlatformVersion
import org.jetbrains.kotlin.platform.konan.NativePlatforms
import org.jetbrains.kotlin.platform.konan.isNative
object NativeIdePlatformKind : IdePlatformKind<NativeIdePlatformKind>() {
override fun supportsTargetPlatform(platform: TargetPlatform): Boolean = platform.isNative()
override fun platformByCompilerArguments(arguments: CommonCompilerArguments): TargetPlatform? {
return if (arguments is FakeK2NativeCompilerArguments)
NativePlatforms.unspecifiedNativePlatform
else
null
}
override fun createArguments(): CommonCompilerArguments {
return FakeK2NativeCompilerArguments()
}
override val defaultPlatform: TargetPlatform
get() = NativePlatforms.unspecifiedNativePlatform
@Deprecated(
message = "IdePlatform is deprecated and will be removed soon, please, migrate to org.jetbrains.kotlin.platform.TargetPlatform",
level = DeprecationLevel.ERROR
)
override fun getDefaultPlatform(): IdePlatform<*, *> = Platform
override val argumentsClass
get() = FakeK2NativeCompilerArguments::class.java
override val name
get() = "Native"
@Deprecated(
message = "IdePlatform is deprecated and will be removed soon, please, migrate to org.jetbrains.kotlin.platform.TargetPlatform",
level = DeprecationLevel.ERROR
)
object Platform : IdePlatform<NativeIdePlatformKind, FakeK2NativeCompilerArguments>() {
override val kind get() = NativeIdePlatformKind
override val version get() = TargetPlatformVersion.NoVersion
override fun createArguments(init: FakeK2NativeCompilerArguments.() -> Unit) = FakeK2NativeCompilerArguments().apply(init)
}
}
// These are fake compiler arguments for Kotlin/Native - only for usage within IDEA plugin:
class FakeK2NativeCompilerArguments : CommonCompilerArguments()
val IdePlatformKind<*>?.isKotlinNative
get() = this is NativeIdePlatformKind
@Deprecated(
message = "IdePlatform is deprecated and will be removed soon, please, migrate to org.jetbrains.kotlin.platform.TargetPlatform",
level = DeprecationLevel.ERROR
)
val IdePlatform<*, *>?.isKotlinNative
get() = this is NativeIdePlatformKind.Platform
+71
View File
@@ -0,0 +1,71 @@
plugins {
kotlin("jvm")
id("jps-compatible")
}
val compilerModules: Array<String> by rootProject.extra
dependencies {
compile(project(":kotlin-build-common"))
compile(project(":core:descriptors"))
compile(project(":core:descriptors.jvm"))
compile(project(":kotlin-compiler-runner"))
compile(project(":daemon-common"))
compile(project(":daemon-common-new"))
compile(projectRuntimeJar(":kotlin-daemon-client"))
compile(projectRuntimeJar(":kotlin-daemon"))
compile(project(":compiler:frontend.java"))
compile(project(":js:js.frontend"))
compile(projectRuntimeJar(":kotlin-preloader"))
compile(project(":idea:idea-jps-common"))
Platform[193].orLower {
compileOnly(intellijDep()) { includeJars("openapi", rootProject = rootProject) }
}
compileOnly(intellijDep()) {
includeJars("jdom", "trove4j", "jps-model", "platform-api", "util", "asm-all", rootProject = rootProject)
}
compileOnly(jpsStandalone()) { includeJars("jps-builders", "jps-builders-6") }
testCompileOnly(project(":kotlin-reflect-api"))
testCompile(project(":compiler:incremental-compilation-impl"))
testCompile(projectTests(":compiler:tests-common"))
testCompile(projectTests(":compiler:incremental-compilation-impl"))
testCompile(commonDep("junit:junit"))
testCompile(project(":kotlin-test:kotlin-test-jvm"))
testCompile(projectTests(":kotlin-build-common"))
testCompileOnly(jpsStandalone()) { includeJars("jps-builders", "jps-builders-6") }
Ide.IJ {
testCompile(intellijDep("devkit"))
}
testCompile(intellijDep())
testCompile(jpsBuildTest())
compilerModules.forEach {
testRuntime(project(it))
}
testRuntimeOnly(intellijPluginDep("java"))
testRuntimeOnly(toolsJar())
testRuntime(project(":kotlin-reflect"))
testRuntime(project(":kotlin-script-runtime"))
}
sourceSets {
"main" { projectDefault() }
"test" {
Ide.IJ {
java.srcDirs("jps-tests/test")
}
}
}
projectTest(parallel = true) {
// do not replace with compile/runtime dependency,
// because it forces Intellij reindexing after each compiler change
dependsOn(":kotlin-compiler:dist")
dependsOn(":kotlin-stdlib-js-ir:packFullRuntimeKLib")
workingDir = rootDir
}
testsJar {}
@@ -0,0 +1,31 @@
/*
* 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.jps.build
import org.jetbrains.kotlin.incremental.testingUtils.BuildLogFinder
import org.jetbrains.kotlin.jps.targets.KotlinModuleBuildTarget
/**
* @see [jps-plugin/testData/incremental/cacheVersionChanged/README.md]
*/
abstract class AbstractDataContainerVersionChangedTest : AbstractIncrementalCacheVersionChangedTest() {
override val buildLogFinder: BuildLogFinder
get() = BuildLogFinder(isDataContainerBuildLogEnabled = true)
override fun getVersionManagersToTest(target: KotlinModuleBuildTarget<*>) =
listOf(kotlinCompileContext.lookupsCacheAttributesManager.versionManagerForTesting)
}
@@ -0,0 +1,52 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.jps.build
import org.jetbrains.kotlin.incremental.testingUtils.Modification
import org.jetbrains.kotlin.incremental.testingUtils.ModifyContent
import org.jetbrains.kotlin.jps.incremental.CacheVersionManager
import org.jetbrains.kotlin.jps.targets.KotlinModuleBuildTarget
/**
* @see [jps-plugin/testData/incremental/cacheVersionChanged/README.md]
*/
abstract class AbstractIncrementalCacheVersionChangedTest : AbstractIncrementalJvmJpsTest(allowNoFilesWithSuffixInTestData = true) {
override fun performAdditionalModifications(modifications: List<Modification>) {
val modifiedFiles = modifications.filterIsInstance<ModifyContent>().map { it.path }
val targets = projectDescriptor.allModuleTargets
val hasKotlin = HasKotlinMarker(projectDescriptor.dataManager)
if (modifiedFiles.any { it.endsWith("clear-has-kotlin") }) {
targets.forEach { hasKotlin.clean(it) }
}
if (modifiedFiles.none { it.endsWith("do-not-change-cache-versions") }) {
val versions = targets.flatMap {
getVersionManagersToTest(kotlinCompileContext.targetsBinding[it]!!)
}
versions.forEach {
if (it.versionFileForTesting.exists()) {
it.versionFileForTesting.writeText("777")
}
}
}
}
protected open fun getVersionManagersToTest(target: KotlinModuleBuildTarget<*>): List<CacheVersionManager> =
listOf(target.localCacheVersionManager)
}
@@ -0,0 +1,683 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.jps.build
import com.intellij.openapi.Disposable
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.io.FileUtilRt
import com.intellij.testFramework.TestLoggerFactory
import com.intellij.testFramework.UsefulTestCase
import junit.framework.TestCase
import org.apache.log4j.ConsoleAppender
import org.apache.log4j.Level
import org.apache.log4j.Logger
import org.apache.log4j.PatternLayout
import org.jetbrains.jps.ModuleChunk
import org.jetbrains.jps.api.CanceledStatus
import org.jetbrains.jps.builders.BuildResult
import org.jetbrains.jps.builders.CompileScopeTestBuilder
import org.jetbrains.jps.builders.impl.BuildDataPathsImpl
import org.jetbrains.jps.builders.impl.logging.ProjectBuilderLoggerBase
import org.jetbrains.jps.builders.java.dependencyView.Callbacks
import org.jetbrains.jps.builders.logging.BuildLoggingManager
import org.jetbrains.jps.cmdline.ProjectDescriptor
import org.jetbrains.jps.incremental.*
import org.jetbrains.jps.incremental.messages.BuildMessage
import org.jetbrains.jps.model.JpsDummyElement
import org.jetbrains.jps.model.JpsModuleRootModificationUtil
import org.jetbrains.jps.model.java.JpsJavaExtensionService
import org.jetbrains.jps.model.library.sdk.JpsSdk
import org.jetbrains.jps.util.JpsPathUtil
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2MetadataCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.parseCommandLineArguments
import org.jetbrains.kotlin.incremental.LookupSymbol
import org.jetbrains.kotlin.incremental.testingUtils.*
import org.jetbrains.kotlin.jps.build.dependeciestxt.ModulesTxt
import org.jetbrains.kotlin.jps.build.dependeciestxt.ModulesTxtBuilder
import org.jetbrains.kotlin.jps.build.fixtures.EnableICFixture
import org.jetbrains.kotlin.jps.incremental.CacheAttributesDiff
import org.jetbrains.kotlin.jps.incremental.CacheVersionManager
import org.jetbrains.kotlin.jps.incremental.CompositeLookupsCacheAttributesManager
import org.jetbrains.kotlin.jps.incremental.getKotlinCache
import org.jetbrains.kotlin.jps.model.JpsKotlinFacetModuleExtension
import org.jetbrains.kotlin.jps.model.kotlinCommonCompilerArguments
import org.jetbrains.kotlin.jps.model.kotlinFacet
import org.jetbrains.kotlin.jps.targets.KotlinModuleBuildTarget
import org.jetbrains.kotlin.platform.idePlatformKind
import org.jetbrains.kotlin.platform.impl.isJavaScript
import org.jetbrains.kotlin.platform.impl.isJvm
import org.jetbrains.kotlin.platform.orDefault
import org.jetbrains.kotlin.utils.Printer
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.PrintStream
import java.util.*
import kotlin.reflect.jvm.javaField
abstract class AbstractIncrementalJpsTest(
private val allowNoFilesWithSuffixInTestData: Boolean = false,
private val checkDumpsCaseInsensitively: Boolean = false
) : BaseKotlinJpsBuildTestCase() {
companion object {
private val COMPILATION_FAILED = "COMPILATION FAILED"
// change to "/tmp" or anything when default is too long (for easier debugging)
private val TEMP_DIRECTORY_TO_USE = File(FileUtilRt.getTempDirectory())
private val DEBUG_LOGGING_ENABLED = System.getProperty("debug.logging.enabled") == "true"
private const val ARGUMENTS_FILE_NAME = "args.txt"
private fun parseAdditionalArgs(testDir: File): List<String> {
return File(testDir, ARGUMENTS_FILE_NAME)
.takeIf { it.exists() }
?.readText()
?.split(" ", "\n")
?.filter { it.isNotBlank() }
?: emptyList()
}
}
protected lateinit var testDataDir: File
protected lateinit var workDir: File
protected lateinit var projectDescriptor: ProjectDescriptor
protected lateinit var additionalCommandLineArguments: List<String>
// is used to compare lookup dumps in a human readable way (lookup symbols are hashed in an actual lookup storage)
protected lateinit var lookupsDuringTest: MutableSet<LookupSymbol>
private var isJvmICEnabledBackup: Boolean = false
private var isJsICEnabledBackup: Boolean = false
protected var mapWorkingToOriginalFile: MutableMap<File, File> = hashMapOf()
lateinit var kotlinCompileContext: KotlinCompileContext
protected open val buildLogFinder: BuildLogFinder
get() = BuildLogFinder()
private fun enableDebugLogging() {
com.intellij.openapi.diagnostic.Logger.setFactory(TestLoggerFactory::class.java)
TestLoggerFactory.dumpLogToStdout("")
TestLoggerFactory.enableDebugLogging(testRootDisposable, "#org")
val console = ConsoleAppender()
console.layout = PatternLayout("%d [%p|%c|%C{1}] %m%n")
console.threshold = Level.ALL
console.activateOptions()
Logger.getRootLogger().addAppender(console)
}
private var systemPropertiesBackup = run {
val props = System.getProperties()
val output = ByteArrayOutputStream()
props.store(output, "System properties backup")
output.toByteArray()
}
private fun restoreSystemProperties() {
val input = ByteArrayInputStream(systemPropertiesBackup)
val props = Properties()
props.load(input)
System.setProperties(props)
}
private val enableICFixture = EnableICFixture()
override fun setUp() {
super.setUp()
enableICFixture.setUp()
lookupsDuringTest = hashSetOf()
if (DEBUG_LOGGING_ENABLED) {
enableDebugLogging()
}
}
override fun tearDown() {
restoreSystemProperties()
(AbstractIncrementalJpsTest::myProject).javaField!![this] = null
(AbstractIncrementalJpsTest::projectDescriptor).javaField!![this] = null
(AbstractIncrementalJpsTest::systemPropertiesBackup).javaField!![this] = null
lookupsDuringTest.clear()
enableICFixture.tearDown()
super.tearDown()
}
// JPS forces rebuild of all files when JVM constant has been changed and Callbacks.ConstantAffectionResolver
// is not provided, so ConstantAffectionResolver is mocked with empty implementation
// Usages in Kotlin files are expected to be found by KotlinLookupConstantSearch
protected open val mockConstantSearch: Callbacks.ConstantAffectionResolver?
get() = MockJavaConstantSearch(workDir)
private fun build(
name: String?,
scope: CompileScopeTestBuilder = CompileScopeTestBuilder.make().allModules()
): MakeResult {
val workDirPath = FileUtil.toSystemIndependentName(workDir.absolutePath)
val logger = MyLogger(workDirPath)
projectDescriptor = createProjectDescriptor(BuildLoggingManager(logger))
val lookupTracker = TestLookupTracker()
val testingContext = TestingContext(lookupTracker, logger)
projectDescriptor.project.setTestingContext(testingContext)
try {
val builder = IncProjectBuilder(
projectDescriptor,
BuilderRegistry.getInstance(),
myBuildParams,
CanceledStatus.NULL,
true
)
val buildResult = BuildResult()
builder.addMessageHandler(buildResult)
val finalScope = scope.build()
projectDescriptor.project.kotlinCommonCompilerArguments = projectDescriptor.project.kotlinCommonCompilerArguments.apply {
updateCommandLineArguments(this)
}
builder.build(finalScope, false)
// testingContext.kotlinCompileContext is initialized in KotlinBuilder.initializeKotlinContext
kotlinCompileContext = testingContext.kotlinCompileContext!!
lookupTracker.lookups.mapTo(lookupsDuringTest) { LookupSymbol(it.name, it.scopeFqName) }
if (!buildResult.isSuccessful) {
val errorMessages =
buildResult
.getMessages(BuildMessage.Kind.ERROR)
.map { it.messageText }
.map { it.replace("^.+:\\d+:\\s+".toRegex(), "").trim() }
.joinToString("\n")
return MakeResult(
log = logger.log + "$COMPILATION_FAILED\n" + errorMessages + "\n",
makeFailed = true,
mappingsDump = null,
name = name
)
} else {
return MakeResult(
log = logger.log,
makeFailed = false,
mappingsDump = createMappingsDump(projectDescriptor, kotlinCompileContext, lookupsDuringTest),
name = name
)
}
} finally {
projectDescriptor.dataManager.flush(false)
projectDescriptor.release()
}
}
private fun initialMake(): MakeResult {
val makeResult = build(null)
val initBuildLogFile = File(testDataDir, "init-build.log")
if (initBuildLogFile.exists()) {
UsefulTestCase.assertSameLinesWithFile(initBuildLogFile.absolutePath, makeResult.log)
} else {
assertFalse("Initial make failed:\n$makeResult", makeResult.makeFailed)
}
return makeResult
}
private fun make(name: String?): MakeResult {
return build(name)
}
private fun rebuild(): MakeResult {
return build(null, CompileScopeTestBuilder.rebuild().allModules())
}
private fun updateCommandLineArguments(arguments: CommonCompilerArguments) {
parseCommandLineArguments(additionalCommandLineArguments, arguments)
}
private fun rebuildAndCheckOutput(makeOverallResult: MakeResult) {
val outDir = File(getAbsolutePath("out"))
val outAfterMake = File(getAbsolutePath("out-after-make"))
if (outDir.exists()) {
FileUtil.copyDir(outDir, outAfterMake)
}
val rebuildResult = rebuild()
assertEquals(
"Rebuild failed: ${rebuildResult.makeFailed}, last make failed: ${makeOverallResult.makeFailed}. Rebuild result: $rebuildResult",
rebuildResult.makeFailed, makeOverallResult.makeFailed
)
if (!outAfterMake.exists()) {
assertFalse(outDir.exists())
} else {
assertEqualDirectories(outDir, outAfterMake, makeOverallResult.makeFailed)
}
if (!makeOverallResult.makeFailed) {
if (checkDumpsCaseInsensitively && rebuildResult.mappingsDump?.toLowerCase() == makeOverallResult.mappingsDump?.toLowerCase()) {
// do nothing
} else {
TestCase.assertEquals(rebuildResult.mappingsDump, makeOverallResult.mappingsDump)
}
}
FileUtil.delete(outAfterMake)
}
private fun clearCachesRebuildAndCheckOutput(makeOverallResult: MakeResult) {
FileUtil.delete(BuildDataPathsImpl(myDataStorageRoot).dataStorageRoot!!)
rebuildAndCheckOutput(makeOverallResult)
}
open val modulesTxtFile
get() = File(testDataDir, "dependencies.txt")
private fun readModulesTxt(): ModulesTxt? {
var actualModulesTxtFile = modulesTxtFile
if (!actualModulesTxtFile.exists()) {
// also try `"_${fileName}.txt"`. Useful for sorting files in IDE.
actualModulesTxtFile = modulesTxtFile.parentFile.resolve("_" + modulesTxtFile.name)
if (!actualModulesTxtFile.exists()) return null
}
return ModulesTxtBuilder().readFile(actualModulesTxtFile)
}
protected open fun createBuildLog(incrementalMakeResults: List<AbstractIncrementalJpsTest.MakeResult>): String =
buildString {
incrementalMakeResults.forEachIndexed { i, makeResult ->
if (i > 0) append("\n")
if (makeResult.name != null) {
append("================ Step #${i + 1} ${makeResult.name} =================\n\n")
} else {
append("================ Step #${i + 1} =================\n\n")
}
append(makeResult.log)
}
}
protected open fun doTest(testDataPath: String) {
testDataDir = File(testDataPath)
workDir = FileUtilRt.createTempDirectory(TEMP_DIRECTORY_TO_USE, "aijt-jps-build", null)
additionalCommandLineArguments = parseAdditionalArgs(File(testDataPath))
val buildLogFile = buildLogFinder.findBuildLog(testDataDir)
Disposer.register(testRootDisposable, Disposable { FileUtilRt.delete(workDir) })
val modulesTxt = configureModules()
if (modulesTxt?.muted == true) return
initialMake()
val otherMakeResults = performModificationsAndMake(
modulesTxt?.modules?.map { it.name },
hasBuildLog = buildLogFile != null
)
buildLogFile?.let {
val logs = createBuildLog(otherMakeResults)
UsefulTestCase.assertSameLinesWithFile(buildLogFile.absolutePath, logs)
val lastMakeResult = otherMakeResults.last()
clearCachesRebuildAndCheckOutput(lastMakeResult)
}
}
protected data class MakeResult(
val log: String,
val makeFailed: Boolean,
val mappingsDump: String?,
val name: String? = null
)
open val testDataSrc: File
get() = testDataDir
private fun performModificationsAndMake(
moduleNames: Collection<String>?,
hasBuildLog: Boolean
): List<MakeResult> {
val results = arrayListOf<MakeResult>()
val modifications = getModificationsToPerform(
testDataSrc,
moduleNames,
allowNoFilesWithSuffixInTestData = allowNoFilesWithSuffixInTestData || !hasBuildLog,
touchPolicy = TouchPolicy.TIMESTAMP
)
if (!hasBuildLog) {
check(modifications.size == 1 && modifications.single().isEmpty()) {
"Bad test data: build steps are provided, but there is no `build.log` file"
}
return results
}
val stepsTxt = File(testDataSrc, "_steps.txt")
val modificationNames = if (stepsTxt.exists()) stepsTxt.readLines() else null
modifications.forEachIndexed { index, step ->
step.forEach { it.perform(workDir, mapWorkingToOriginalFile) }
performAdditionalModifications(step)
if (moduleNames == null) {
preProcessSources(File(workDir, "src"))
} else {
moduleNames.forEach { preProcessSources(File(workDir, "$it/src")) }
}
val name = modificationNames?.getOrNull(index)
val makeResult = make(name)
results.add(makeResult)
}
return results
}
protected open fun performAdditionalModifications(modifications: List<Modification>) {
}
protected open fun generateModuleSources(modulesTxt: ModulesTxt) = Unit
// null means one module
private fun configureModules(): ModulesTxt? {
JpsJavaExtensionService.getInstance().getOrCreateProjectExtension(myProject).outputUrl =
JpsPathUtil.pathToUrl(getAbsolutePath("out"))
val jdk = addJdk("my jdk")
val modulesTxt = readModulesTxt()
mapWorkingToOriginalFile = hashMapOf()
if (modulesTxt == null) configureSingleModuleProject(jdk)
else configureMultiModuleProject(modulesTxt, jdk)
overrideModuleSettings()
configureRequiredLibraries()
return modulesTxt
}
open fun overrideModuleSettings() {
}
private fun configureSingleModuleProject(jdk: JpsSdk<JpsDummyElement>?) {
addModule("module", arrayOf(getAbsolutePath("src")), null, null, jdk)
val sourceDestinationDir = File(workDir, "src")
val sourcesMapping = copyTestSources(testDataDir, File(workDir, "src"), "")
mapWorkingToOriginalFile.putAll(sourcesMapping)
preProcessSources(sourceDestinationDir)
}
protected open val ModulesTxt.Module.sourceFilePrefix: String
get() = "${name}_"
private fun configureMultiModuleProject(
modulesTxt: ModulesTxt,
jdk: JpsSdk<JpsDummyElement>?
) {
modulesTxt.modules.forEach { module ->
module.jpsModule = addModule(
module.name,
arrayOf(getAbsolutePath("${module.name}/src")),
null,
null,
jdk
)!!
val kotlinFacetSettings = module.kotlinFacetSettings
if (kotlinFacetSettings != null) {
val compilerArguments = kotlinFacetSettings.compilerArguments
if (compilerArguments is K2MetadataCompilerArguments) {
val out = getAbsolutePath("${module.name}/out")
File(out).mkdirs()
compilerArguments.destination = out
} else if (compilerArguments is K2JVMCompilerArguments) {
compilerArguments.disableDefaultScriptingPlugin = true
}
module.jpsModule.container.setChild(
JpsKotlinFacetModuleExtension.KIND,
JpsKotlinFacetModuleExtension(kotlinFacetSettings)
)
}
}
modulesTxt.dependencies.forEach {
JpsModuleRootModificationUtil.addDependency(
it.from.jpsModule, it.to.jpsModule,
it.scope, it.exported
)
}
// configure module contents
generateModuleSources(modulesTxt)
modulesTxt.modules.forEach { module ->
val sourceDirName = "${module.name}/src"
val sourceDestinationDir = File(workDir, sourceDirName)
val sourcesMapping = copyTestSources(testDataSrc, sourceDestinationDir, module.sourceFilePrefix)
mapWorkingToOriginalFile.putAll(sourcesMapping)
preProcessSources(sourceDestinationDir)
}
}
private fun configureRequiredLibraries() {
myProject.modules.forEach { module ->
val platformKind = module.kotlinFacet?.settings?.targetPlatform?.idePlatformKind.orDefault()
when {
platformKind.isJvm -> {
JpsModuleRootModificationUtil.addDependency(module, requireLibrary(KotlinJpsLibrary.JvmStdLib))
JpsModuleRootModificationUtil.addDependency(module, requireLibrary(KotlinJpsLibrary.JvmTest))
}
platformKind.isJavaScript -> {
JpsModuleRootModificationUtil.addDependency(module, requireLibrary(KotlinJpsLibrary.JsStdLib))
JpsModuleRootModificationUtil.addDependency(module, requireLibrary(KotlinJpsLibrary.JsTest))
}
}
}
}
protected open fun preProcessSources(srcDir: File) {
}
override fun doGetProjectDir(): File? = workDir
internal class MyLogger(val rootPath: String) : ProjectBuilderLoggerBase(), TestingBuildLogger {
private val markedDirtyBeforeRound = ArrayList<File>()
private val markedDirtyAfterRound = ArrayList<File>()
private val customMessages = mutableListOf<String>()
override fun invalidOrUnusedCache(
chunk: KotlinChunk?,
target: KotlinModuleBuildTarget<*>?,
attributesDiff: CacheAttributesDiff<*>
) {
val cacheManager = attributesDiff.manager
val cacheTitle = when (cacheManager) {
is CacheVersionManager -> "Local cache for ${chunk ?: target}"
is CompositeLookupsCacheAttributesManager -> "Lookups cache"
else -> error("Unknown cache manager $cacheManager")
}
logLine("$cacheTitle are ${attributesDiff.status}")
}
override fun markedAsDirtyBeforeRound(files: Iterable<File>) {
markedDirtyBeforeRound.addAll(files)
}
override fun markedAsDirtyAfterRound(files: Iterable<File>) {
markedDirtyAfterRound.addAll(files)
}
override fun chunkBuildStarted(context: CompileContext, chunk: ModuleChunk) {
logDirtyFiles(markedDirtyBeforeRound) // files can be marked as dirty during build start (KotlinCompileContext initialization)
if (!chunk.isDummy(context) && context.projectDescriptor.project.modules.size > 1) {
logLine("Building ${chunk.modules.sortedBy { it.name }.joinToString { it.name }}")
}
}
override fun afterChunkBuildStarted(context: CompileContext, chunk: ModuleChunk) {
logDirtyFiles(markedDirtyBeforeRound)
}
override fun addCustomMessage(message: String) {
customMessages.add(message)
}
override fun buildFinished(exitCode: ModuleLevelBuilder.ExitCode) {
customMessages.forEach {
logLine(it)
}
customMessages.clear()
logDirtyFiles(markedDirtyAfterRound)
logLine("Exit code: $exitCode")
logLine("------------------------------------------")
}
private fun logDirtyFiles(files: MutableList<File>) {
if (files.isEmpty()) return
logLine("Marked as dirty by Kotlin:")
files.apply {
map { FileUtil.toSystemIndependentName(it.path) }
.sorted()
.forEach { logLine(it) }
clear()
}
}
private val logBuf = StringBuilder()
val log: String
get() = logBuf.toString()
val compiledFiles = hashSetOf<File>()
override fun isEnabled(): Boolean = true
override fun logCompiledFiles(files: MutableCollection<File>?, builderName: String?, description: String?) {
super.logCompiledFiles(files, builderName, description)
if (builderName == KotlinBuilder.KOTLIN_BUILDER_NAME) {
compiledFiles.addAll(files!!)
}
}
override fun logLine(message: String?) {
logBuf.append(message!!.replace("^$rootPath/".toRegex(), " ")).append('\n')
}
}
}
private fun createMappingsDump(
project: ProjectDescriptor,
kotlinContext: KotlinCompileContext,
lookupsDuringTest: Set<LookupSymbol>
) = createKotlinCachesDump(project, kotlinContext, lookupsDuringTest) + "\n\n\n" +
createCommonMappingsDump(project) + "\n\n\n" +
createJavaMappingsDump(project)
internal fun createKotlinCachesDump(
project: ProjectDescriptor,
kotlinContext: KotlinCompileContext,
lookupsDuringTest: Set<LookupSymbol>
) = createKotlinIncrementalCacheDump(project, kotlinContext) + "\n\n\n" +
createLookupCacheDump(kotlinContext, lookupsDuringTest)
private fun createKotlinIncrementalCacheDump(
project: ProjectDescriptor,
kotlinContext: KotlinCompileContext
): String {
return buildString {
for (target in project.allModuleTargets.sortedBy { it.presentableName }) {
val kotlinCache = project.dataManager.getKotlinCache(kotlinContext.targetsBinding[target])
if (kotlinCache != null) {
append("<target $target>\n")
append(kotlinCache.dump())
append("</target $target>\n\n\n")
}
}
}
}
private fun createLookupCacheDump(kotlinContext: KotlinCompileContext, lookupsDuringTest: Set<LookupSymbol>): String {
val sb = StringBuilder()
val p = Printer(sb)
p.println("Begin of Lookup Maps")
p.println()
kotlinContext.lookupStorageManager.withLookupStorage { lookupStorage ->
lookupStorage.forceGC()
p.print(lookupStorage.dump(lookupsDuringTest))
}
p.println()
p.println("End of Lookup Maps")
return sb.toString()
}
private fun createCommonMappingsDump(project: ProjectDescriptor): String {
val resultBuf = StringBuilder()
val result = Printer(resultBuf)
result.println("Begin of SourceToOutputMap")
result.pushIndent()
for (target in project.allModuleTargets) {
result.println(target)
result.pushIndent()
val mapping = project.dataManager.getSourceToOutputMap(target)
mapping.sources.sorted().forEach {
val outputs = mapping.getOutputs(it)!!.sorted()
if (outputs.isNotEmpty()) {
result.println("source $it -> $outputs")
}
}
result.popIndent()
}
result.popIndent()
result.println("End of SourceToOutputMap")
return resultBuf.toString()
}
private fun createJavaMappingsDump(project: ProjectDescriptor): String {
val byteArrayOutputStream = ByteArrayOutputStream()
PrintStream(byteArrayOutputStream).use {
project.dataManager.mappings.toStream(it)
}
return byteArrayOutputStream.toString()
}
internal val ProjectDescriptor.allModuleTargets: Collection<ModuleBuildTarget>
get() = buildTargetIndex.allTargets.filterIsInstance<ModuleBuildTarget>()
private val EXPORTED_SUFFIX = "[exported]"
@@ -0,0 +1,681 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.jps.build
import com.intellij.openapi.Disposable
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.io.FileUtilRt
import com.intellij.testFramework.TestLoggerFactory
import com.intellij.testFramework.UsefulTestCase
import junit.framework.TestCase
import org.apache.log4j.ConsoleAppender
import org.apache.log4j.Level
import org.apache.log4j.Logger
import org.apache.log4j.PatternLayout
import org.jetbrains.jps.ModuleChunk
import org.jetbrains.jps.api.CanceledStatus
import org.jetbrains.jps.builders.BuildResult
import org.jetbrains.jps.builders.CompileScopeTestBuilder
import org.jetbrains.jps.builders.impl.BuildDataPathsImpl
import org.jetbrains.jps.builders.impl.logging.ProjectBuilderLoggerBase
import org.jetbrains.jps.builders.java.dependencyView.Callbacks
import org.jetbrains.jps.builders.logging.BuildLoggingManager
import org.jetbrains.jps.cmdline.ProjectDescriptor
import org.jetbrains.jps.incremental.*
import org.jetbrains.jps.incremental.messages.BuildMessage
import org.jetbrains.jps.model.JpsDummyElement
import org.jetbrains.jps.model.JpsModuleRootModificationUtil
import org.jetbrains.jps.model.java.JpsJavaExtensionService
import org.jetbrains.jps.model.library.sdk.JpsSdk
import org.jetbrains.jps.util.JpsPathUtil
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2MetadataCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.parseCommandLineArguments
import org.jetbrains.kotlin.incremental.LookupSymbol
import org.jetbrains.kotlin.incremental.testingUtils.*
import org.jetbrains.kotlin.jps.build.dependeciestxt.ModulesTxt
import org.jetbrains.kotlin.jps.build.dependeciestxt.ModulesTxtBuilder
import org.jetbrains.kotlin.jps.build.fixtures.EnableICFixture
import org.jetbrains.kotlin.jps.incremental.*
import org.jetbrains.kotlin.jps.model.JpsKotlinFacetModuleExtension
import org.jetbrains.kotlin.jps.model.kotlinCommonCompilerArguments
import org.jetbrains.kotlin.jps.model.kotlinFacet
import org.jetbrains.kotlin.jps.targets.KotlinModuleBuildTarget
import org.jetbrains.kotlin.platform.idePlatformKind
import org.jetbrains.kotlin.platform.impl.isJavaScript
import org.jetbrains.kotlin.platform.impl.isJvm
import org.jetbrains.kotlin.platform.orDefault
import org.jetbrains.kotlin.utils.Printer
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.PrintStream
import java.util.*
import kotlin.reflect.jvm.javaField
abstract class AbstractIncrementalJpsTest(
private val allowNoFilesWithSuffixInTestData: Boolean = false,
private val checkDumpsCaseInsensitively: Boolean = false
) : BaseKotlinJpsBuildTestCase() {
companion object {
private val COMPILATION_FAILED = "COMPILATION FAILED"
// change to "/tmp" or anything when default is too long (for easier debugging)
private val TEMP_DIRECTORY_TO_USE = File(FileUtilRt.getTempDirectory())
private val DEBUG_LOGGING_ENABLED = System.getProperty("debug.logging.enabled") == "true"
private const val ARGUMENTS_FILE_NAME = "args.txt"
private fun parseAdditionalArgs(testDir: File): List<String> {
return File(testDir, ARGUMENTS_FILE_NAME)
.takeIf { it.exists() }
?.readText()
?.split(" ", "\n")
?.filter { it.isNotBlank() }
?: emptyList()
}
}
protected lateinit var testDataDir: File
protected lateinit var workDir: File
protected lateinit var projectDescriptor: ProjectDescriptor
protected lateinit var additionalCommandLineArguments: List<String>
// is used to compare lookup dumps in a human readable way (lookup symbols are hashed in an actual lookup storage)
protected lateinit var lookupsDuringTest: MutableSet<LookupSymbol>
private var isJvmICEnabledBackup: Boolean = false
private var isJsICEnabledBackup: Boolean = false
protected var mapWorkingToOriginalFile: MutableMap<File, File> = hashMapOf()
lateinit var kotlinCompileContext: KotlinCompileContext
protected open val buildLogFinder: BuildLogFinder
get() = BuildLogFinder()
private fun enableDebugLogging() {
com.intellij.openapi.diagnostic.Logger.setFactory(TestLoggerFactory::class.java)
TestLoggerFactory.dumpLogToStdout("")
TestLoggerFactory.enableDebugLogging(testRootDisposable, "#org")
val console = ConsoleAppender()
console.layout = PatternLayout("%d [%p|%c|%C{1}] %m%n")
console.threshold = Level.ALL
console.activateOptions()
Logger.getRootLogger().addAppender(console)
}
private var systemPropertiesBackup = run {
val props = System.getProperties()
val output = ByteArrayOutputStream()
props.store(output, "System properties backup")
output.toByteArray()
}
private fun restoreSystemProperties() {
val input = ByteArrayInputStream(systemPropertiesBackup)
val props = Properties()
props.load(input)
System.setProperties(props)
}
private val enableICFixture = EnableICFixture()
override fun setUp() {
super.setUp()
enableICFixture.setUp()
lookupsDuringTest = hashSetOf()
if (DEBUG_LOGGING_ENABLED) {
enableDebugLogging()
}
}
override fun tearDown() {
restoreSystemProperties()
(AbstractIncrementalJpsTest::myProject).javaField!![this] = null
(AbstractIncrementalJpsTest::projectDescriptor).javaField!![this] = null
(AbstractIncrementalJpsTest::systemPropertiesBackup).javaField!![this] = null
lookupsDuringTest.clear()
enableICFixture.tearDown()
super.tearDown()
}
// JPS forces rebuild of all files when JVM constant has been changed and Callbacks.ConstantAffectionResolver
// is not provided, so ConstantAffectionResolver is mocked with empty implementation
// Usages in Kotlin files are expected to be found by KotlinLookupConstantSearch
protected open val mockConstantSearch: Callbacks.ConstantAffectionResolver?
get() = MockJavaConstantSearch(workDir)
private fun build(
name: String?,
scope: CompileScopeTestBuilder = CompileScopeTestBuilder.make().allModules()
): MakeResult {
val workDirPath = FileUtil.toSystemIndependentName(workDir.absolutePath)
val logger = MyLogger(workDirPath)
projectDescriptor = createProjectDescriptor(BuildLoggingManager(logger))
val lookupTracker = TestLookupTracker()
val testingContext = TestingContext(lookupTracker, logger)
projectDescriptor.project.setTestingContext(testingContext)
try {
val builder = IncProjectBuilder(
projectDescriptor,
BuilderRegistry.getInstance(),
myBuildParams,
CanceledStatus.NULL,
mockConstantSearch,
true
)
val buildResult = BuildResult()
builder.addMessageHandler(buildResult)
val finalScope = scope.build()
projectDescriptor.project.kotlinCommonCompilerArguments = projectDescriptor.project.kotlinCommonCompilerArguments.apply {
updateCommandLineArguments(this)
}
builder.build(finalScope, false)
// testingContext.kotlinCompileContext is initialized in KotlinBuilder.initializeKotlinContext
kotlinCompileContext = testingContext.kotlinCompileContext!!
lookupTracker.lookups.mapTo(lookupsDuringTest) { LookupSymbol(it.name, it.scopeFqName) }
if (!buildResult.isSuccessful) {
val errorMessages =
buildResult
.getMessages(BuildMessage.Kind.ERROR)
.map { it.messageText }
.map { it.replace("^.+:\\d+:\\s+".toRegex(), "").trim() }
.joinToString("\n")
return MakeResult(
log = logger.log + "$COMPILATION_FAILED\n" + errorMessages + "\n",
makeFailed = true,
mappingsDump = null,
name = name
)
} else {
return MakeResult(
log = logger.log,
makeFailed = false,
mappingsDump = createMappingsDump(projectDescriptor, kotlinCompileContext, lookupsDuringTest),
name = name
)
}
} finally {
projectDescriptor.dataManager.flush(false)
projectDescriptor.release()
}
}
private fun initialMake(): MakeResult {
val makeResult = build(null)
val initBuildLogFile = File(testDataDir, "init-build.log")
if (initBuildLogFile.exists()) {
UsefulTestCase.assertSameLinesWithFile(initBuildLogFile.absolutePath, makeResult.log)
} else {
assertFalse("Initial make failed:\n$makeResult", makeResult.makeFailed)
}
return makeResult
}
private fun make(name: String?): MakeResult {
return build(name)
}
private fun rebuild(): MakeResult {
return build(null, CompileScopeTestBuilder.rebuild().allModules())
}
private fun updateCommandLineArguments(arguments: CommonCompilerArguments) {
parseCommandLineArguments(additionalCommandLineArguments, arguments)
}
private fun rebuildAndCheckOutput(makeOverallResult: MakeResult) {
val outDir = File(getAbsolutePath("out"))
val outAfterMake = File(getAbsolutePath("out-after-make"))
if (outDir.exists()) {
FileUtil.copyDir(outDir, outAfterMake)
}
val rebuildResult = rebuild()
assertEquals(
"Rebuild failed: ${rebuildResult.makeFailed}, last make failed: ${makeOverallResult.makeFailed}. Rebuild result: $rebuildResult",
rebuildResult.makeFailed, makeOverallResult.makeFailed
)
if (!outAfterMake.exists()) {
assertFalse(outDir.exists())
} else {
assertEqualDirectories(outDir, outAfterMake, makeOverallResult.makeFailed)
}
if (!makeOverallResult.makeFailed) {
if (checkDumpsCaseInsensitively && rebuildResult.mappingsDump?.toLowerCase() == makeOverallResult.mappingsDump?.toLowerCase()) {
// do nothing
} else {
TestCase.assertEquals(rebuildResult.mappingsDump, makeOverallResult.mappingsDump)
}
}
FileUtil.delete(outAfterMake)
}
private fun clearCachesRebuildAndCheckOutput(makeOverallResult: MakeResult) {
FileUtil.delete(BuildDataPathsImpl(myDataStorageRoot).dataStorageRoot!!)
rebuildAndCheckOutput(makeOverallResult)
}
open val modulesTxtFile
get() = File(testDataDir, "dependencies.txt")
private fun readModulesTxt(): ModulesTxt? {
var actualModulesTxtFile = modulesTxtFile
if (!actualModulesTxtFile.exists()) {
// also try `"_${fileName}.txt"`. Useful for sorting files in IDE.
actualModulesTxtFile = modulesTxtFile.parentFile.resolve("_" + modulesTxtFile.name)
if (!actualModulesTxtFile.exists()) return null
}
return ModulesTxtBuilder().readFile(actualModulesTxtFile)
}
protected open fun createBuildLog(incrementalMakeResults: List<AbstractIncrementalJpsTest.MakeResult>): String =
buildString {
incrementalMakeResults.forEachIndexed { i, makeResult ->
if (i > 0) append("\n")
if (makeResult.name != null) {
append("================ Step #${i + 1} ${makeResult.name} =================\n\n")
} else {
append("================ Step #${i + 1} =================\n\n")
}
append(makeResult.log)
}
}
protected open fun doTest(testDataPath: String) {
testDataDir = File(testDataPath)
workDir = FileUtilRt.createTempDirectory(TEMP_DIRECTORY_TO_USE, "aijt-jps-build", null)
additionalCommandLineArguments = parseAdditionalArgs(File(testDataPath))
val buildLogFile = buildLogFinder.findBuildLog(testDataDir)
Disposer.register(testRootDisposable, Disposable { FileUtilRt.delete(workDir) })
val modulesTxt = configureModules()
if (modulesTxt?.muted == true) return
initialMake()
val otherMakeResults = performModificationsAndMake(
modulesTxt?.modules?.map { it.name },
hasBuildLog = buildLogFile != null
)
buildLogFile?.let {
val logs = createBuildLog(otherMakeResults)
UsefulTestCase.assertSameLinesWithFile(buildLogFile.absolutePath, logs)
val lastMakeResult = otherMakeResults.last()
clearCachesRebuildAndCheckOutput(lastMakeResult)
}
}
protected data class MakeResult(
val log: String,
val makeFailed: Boolean,
val mappingsDump: String?,
val name: String? = null
)
open val testDataSrc: File
get() = testDataDir
private fun performModificationsAndMake(
moduleNames: Collection<String>?,
hasBuildLog: Boolean
): List<MakeResult> {
val results = arrayListOf<MakeResult>()
val modifications = getModificationsToPerform(
testDataSrc,
moduleNames,
allowNoFilesWithSuffixInTestData = allowNoFilesWithSuffixInTestData || !hasBuildLog,
touchPolicy = TouchPolicy.TIMESTAMP
)
if (!hasBuildLog) {
check(modifications.size == 1 && modifications.single().isEmpty()) {
"Bad test data: build steps are provided, but there is no `build.log` file"
}
return results
}
val stepsTxt = File(testDataSrc, "_steps.txt")
val modificationNames = if (stepsTxt.exists()) stepsTxt.readLines() else null
modifications.forEachIndexed { index, step ->
step.forEach { it.perform(workDir, mapWorkingToOriginalFile) }
performAdditionalModifications(step)
if (moduleNames == null) {
preProcessSources(File(workDir, "src"))
} else {
moduleNames.forEach { preProcessSources(File(workDir, "$it/src")) }
}
val name = modificationNames?.getOrNull(index)
val makeResult = make(name)
results.add(makeResult)
}
return results
}
protected open fun performAdditionalModifications(modifications: List<Modification>) {
}
protected open fun generateModuleSources(modulesTxt: ModulesTxt) = Unit
// null means one module
private fun configureModules(): ModulesTxt? {
JpsJavaExtensionService.getInstance().getOrCreateProjectExtension(myProject).outputUrl =
JpsPathUtil.pathToUrl(getAbsolutePath("out"))
val jdk = addJdk("my jdk")
val modulesTxt = readModulesTxt()
mapWorkingToOriginalFile = hashMapOf()
if (modulesTxt == null) configureSingleModuleProject(jdk)
else configureMultiModuleProject(modulesTxt, jdk)
overrideModuleSettings()
configureRequiredLibraries()
return modulesTxt
}
open fun overrideModuleSettings() {
}
private fun configureSingleModuleProject(jdk: JpsSdk<JpsDummyElement>?) {
addModule("module", arrayOf(getAbsolutePath("src")), null, null, jdk)
val sourceDestinationDir = File(workDir, "src")
val sourcesMapping = copyTestSources(testDataDir, File(workDir, "src"), "")
mapWorkingToOriginalFile.putAll(sourcesMapping)
preProcessSources(sourceDestinationDir)
}
protected open val ModulesTxt.Module.sourceFilePrefix: String
get() = "${name}_"
private fun configureMultiModuleProject(
modulesTxt: ModulesTxt,
jdk: JpsSdk<JpsDummyElement>?
) {
modulesTxt.modules.forEach { module ->
module.jpsModule = addModule(
module.name,
arrayOf(getAbsolutePath("${module.name}/src")),
null,
null,
jdk
)!!
val kotlinFacetSettings = module.kotlinFacetSettings
if (kotlinFacetSettings != null) {
val compilerArguments = kotlinFacetSettings.compilerArguments
if (compilerArguments is K2MetadataCompilerArguments) {
val out = getAbsolutePath("${module.name}/out")
File(out).mkdirs()
compilerArguments.destination = out
} else if (compilerArguments is K2JVMCompilerArguments) {
compilerArguments.disableDefaultScriptingPlugin = true
}
module.jpsModule.container.setChild(
JpsKotlinFacetModuleExtension.KIND,
JpsKotlinFacetModuleExtension(kotlinFacetSettings)
)
}
}
modulesTxt.dependencies.forEach {
JpsModuleRootModificationUtil.addDependency(
it.from.jpsModule, it.to.jpsModule,
it.scope, it.exported
)
}
// configure module contents
generateModuleSources(modulesTxt)
modulesTxt.modules.forEach { module ->
val sourceDirName = "${module.name}/src"
val sourceDestinationDir = File(workDir, sourceDirName)
val sourcesMapping = copyTestSources(testDataSrc, sourceDestinationDir, module.sourceFilePrefix)
mapWorkingToOriginalFile.putAll(sourcesMapping)
preProcessSources(sourceDestinationDir)
}
}
private fun configureRequiredLibraries() {
myProject.modules.forEach { module ->
val platformKind = module.kotlinFacet?.settings?.targetPlatform?.idePlatformKind.orDefault()
when {
platformKind.isJvm -> {
JpsModuleRootModificationUtil.addDependency(module, requireLibrary(KotlinJpsLibrary.JvmStdLib))
JpsModuleRootModificationUtil.addDependency(module, requireLibrary(KotlinJpsLibrary.JvmTest))
}
platformKind.isJavaScript -> {
JpsModuleRootModificationUtil.addDependency(module, requireLibrary(KotlinJpsLibrary.JsStdLib))
JpsModuleRootModificationUtil.addDependency(module, requireLibrary(KotlinJpsLibrary.JsTest))
}
}
}
}
protected open fun preProcessSources(srcDir: File) {
}
override fun doGetProjectDir(): File? = workDir
internal class MyLogger(val rootPath: String) : ProjectBuilderLoggerBase(), TestingBuildLogger {
private val markedDirtyBeforeRound = ArrayList<File>()
private val markedDirtyAfterRound = ArrayList<File>()
private val customMessages = mutableListOf<String>()
override fun invalidOrUnusedCache(
chunk: KotlinChunk?,
target: KotlinModuleBuildTarget<*>?,
attributesDiff: CacheAttributesDiff<*>
) {
val cacheManager = attributesDiff.manager
val cacheTitle = when (cacheManager) {
is CacheVersionManager -> "Local cache for ${chunk ?: target}"
is CompositeLookupsCacheAttributesManager -> "Lookups cache"
else -> error("Unknown cache manager $cacheManager")
}
logLine("$cacheTitle are ${attributesDiff.status}")
}
override fun markedAsDirtyBeforeRound(files: Iterable<File>) {
markedDirtyBeforeRound.addAll(files)
}
override fun markedAsDirtyAfterRound(files: Iterable<File>) {
markedDirtyAfterRound.addAll(files)
}
override fun chunkBuildStarted(context: CompileContext, chunk: ModuleChunk) {
logDirtyFiles(markedDirtyBeforeRound) // files can be marked as dirty during build start (KotlinCompileContext initialization)
if (!chunk.isDummy(context) && context.projectDescriptor.project.modules.size > 1) {
logLine("Building ${chunk.modules.sortedBy { it.name }.joinToString { it.name }}")
}
}
override fun afterChunkBuildStarted(context: CompileContext, chunk: ModuleChunk) {
logDirtyFiles(markedDirtyBeforeRound)
}
override fun addCustomMessage(message: String) {
customMessages.add(message)
}
override fun buildFinished(exitCode: ModuleLevelBuilder.ExitCode) {
customMessages.forEach {
logLine(it)
}
customMessages.clear()
logDirtyFiles(markedDirtyAfterRound)
logLine("Exit code: $exitCode")
logLine("------------------------------------------")
}
private fun logDirtyFiles(files: MutableList<File>) {
if (files.isEmpty()) return
logLine("Marked as dirty by Kotlin:")
files.apply {
map { FileUtil.toSystemIndependentName(it.path) }
.sorted()
.forEach { logLine(it) }
clear()
}
}
private val logBuf = StringBuilder()
val log: String
get() = logBuf.toString()
val compiledFiles = hashSetOf<File>()
override fun isEnabled(): Boolean = true
override fun logCompiledFiles(files: MutableCollection<File>?, builderName: String?, description: String?) {
super.logCompiledFiles(files, builderName, description)
if (builderName == KotlinBuilder.KOTLIN_BUILDER_NAME) {
compiledFiles.addAll(files!!)
}
}
override fun logLine(message: String?) {
logBuf.append(message!!.replace("^$rootPath/".toRegex(), " ")).append('\n')
}
}
}
private fun createMappingsDump(
project: ProjectDescriptor,
kotlinContext: KotlinCompileContext,
lookupsDuringTest: Set<LookupSymbol>
) = createKotlinCachesDump(project, kotlinContext, lookupsDuringTest) + "\n\n\n" +
createCommonMappingsDump(project) + "\n\n\n" +
createJavaMappingsDump(project)
internal fun createKotlinCachesDump(
project: ProjectDescriptor,
kotlinContext: KotlinCompileContext,
lookupsDuringTest: Set<LookupSymbol>
) = createKotlinIncrementalCacheDump(project, kotlinContext) + "\n\n\n" +
createLookupCacheDump(kotlinContext, lookupsDuringTest)
private fun createKotlinIncrementalCacheDump(
project: ProjectDescriptor,
kotlinContext: KotlinCompileContext
): String {
return buildString {
for (target in project.allModuleTargets.sortedBy { it.presentableName }) {
val kotlinCache = project.dataManager.getKotlinCache(kotlinContext.targetsBinding[target])
if (kotlinCache != null) {
append("<target $target>\n")
append(kotlinCache.dump())
append("</target $target>\n\n\n")
}
}
}
}
private fun createLookupCacheDump(kotlinContext: KotlinCompileContext, lookupsDuringTest: Set<LookupSymbol>): String {
val sb = StringBuilder()
val p = Printer(sb)
p.println("Begin of Lookup Maps")
p.println()
kotlinContext.lookupStorageManager.withLookupStorage { lookupStorage ->
lookupStorage.forceGC()
p.print(lookupStorage.dump(lookupsDuringTest))
}
p.println()
p.println("End of Lookup Maps")
return sb.toString()
}
private fun createCommonMappingsDump(project: ProjectDescriptor): String {
val resultBuf = StringBuilder()
val result = Printer(resultBuf)
result.println("Begin of SourceToOutputMap")
result.pushIndent()
for (target in project.allModuleTargets) {
result.println(target)
result.pushIndent()
val mapping = project.dataManager.getSourceToOutputMap(target)
mapping.sources.sorted().forEach {
val outputs = mapping.getOutputs(it)!!.sorted()
if (outputs.isNotEmpty()) {
result.println("source $it -> $outputs")
}
}
result.popIndent()
}
result.popIndent()
result.println("End of SourceToOutputMap")
return resultBuf.toString()
}
private fun createJavaMappingsDump(project: ProjectDescriptor): String {
val byteArrayOutputStream = ByteArrayOutputStream()
PrintStream(byteArrayOutputStream).use {
project.dataManager.mappings.toStream(it)
}
return byteArrayOutputStream.toString()
}
internal val ProjectDescriptor.allModuleTargets: Collection<ModuleBuildTarget>
get() = buildTargetIndex.allTargets.filterIsInstance<ModuleBuildTarget>()
private val EXPORTED_SUFFIX = "[exported]"
@@ -0,0 +1,40 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
import org.jetbrains.kotlin.config.KotlinFacetSettings
import org.jetbrains.kotlin.incremental.testingUtils.BuildLogFinder
import org.jetbrains.kotlin.incremental.testingUtils.BuildLogFinder.Companion.JS_JPS_LOG
import org.jetbrains.kotlin.jps.model.JpsKotlinFacetModuleExtension
import org.jetbrains.kotlin.platform.js.JsPlatforms
import java.io.File
abstract class AbstractIncrementalJsJpsTest : AbstractIncrementalJpsTest() {
override val buildLogFinder: BuildLogFinder
get() = super.buildLogFinder.copy(isJsEnabled = true)
override fun doTest(testDataPath: String) {
val buildLogFile = File(testDataPath).resolve(JS_JPS_LOG)
if (!buildLogFile.exists()) {
buildLogFile.writeText("JPS JS LOG PLACEHOLDER")
}
super.doTest(testDataPath)
}
override fun overrideModuleSettings() {
myProject.modules.forEach {
val facet = KotlinFacetSettings()
facet.compilerArguments = K2JSCompilerArguments()
facet.targetPlatform = JsPlatforms.defaultJsPlatform
it.container.setChild(
JpsKotlinFacetModuleExtension.KIND,
JpsKotlinFacetModuleExtension(facet)
)
}
}
}
@@ -0,0 +1,19 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.jps.model.k2JvmCompilerArguments
abstract class AbstractIncrementalJvmJpsTest(
allowNoFilesWithSuffixInTestData: Boolean = false
) : AbstractIncrementalJpsTest(allowNoFilesWithSuffixInTestData = allowNoFilesWithSuffixInTestData) {
override fun overrideModuleSettings() {
myProject.k2JvmCompilerArguments = K2JVMCompilerArguments().also {
it.disableDefaultScriptingPlugin = true
}
}
}
@@ -0,0 +1,151 @@
/*
* 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.jps.build
import com.intellij.testFramework.UsefulTestCase
import org.jetbrains.jps.builders.BuildTarget
import org.jetbrains.jps.builders.storage.BuildDataPaths
import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.incremental.KOTLIN_CACHE_DIRECTORY_NAME
import org.jetbrains.kotlin.incremental.storage.BasicMapsOwner
import org.jetbrains.kotlin.incremental.testingUtils.Modification
import org.jetbrains.kotlin.incremental.testingUtils.ModifyContent
import org.jetbrains.kotlin.jps.build.fixtures.EnableICFixture
import org.jetbrains.kotlin.jps.incremental.KotlinDataContainerTarget
import org.jetbrains.kotlin.jps.targets.KotlinModuleBuildTarget
import org.jetbrains.kotlin.utils.Printer
import java.io.File
abstract class AbstractIncrementalLazyCachesTest : AbstractIncrementalJpsTest() {
private val expectedCachesFileName: String
get() = "expected-kotlin-caches.txt"
private val enableICFixture = EnableICFixture()
override fun setUp() {
super.setUp()
enableICFixture.setUp()
}
override fun tearDown() {
enableICFixture.tearDown()
super.tearDown()
}
override fun doTest(testDataPath: String) {
super.doTest(testDataPath)
val actual = dumpKotlinCachesFileNames()
val expectedFile = File(testDataPath, expectedCachesFileName)
UsefulTestCase.assertSameLinesWithFile(expectedFile.canonicalPath, actual)
}
override fun performAdditionalModifications(modifications: List<Modification>) {
super.performAdditionalModifications(modifications)
for (modification in modifications) {
if (modification !is ModifyContent) continue
val name = File(modification.path).name
when {
name.endsWith("incremental-compilation") -> {
IncrementalCompilation.setIsEnabledForJvm(modification.dataFile.readAsBool())
}
}
}
}
fun File.readAsBool(): Boolean {
val content = this.readText()
return when (content.trim()) {
"on" -> true
"off" -> false
else -> throw IllegalStateException("$this content is expected to be 'on' or 'off'")
}
}
private fun dumpKotlinCachesFileNames(): String {
val sb = StringBuilder()
val printer = Printer(sb)
val chunks = kotlinCompileContext.targetsIndex.chunks
val dataManager = projectDescriptor.dataManager
val paths = dataManager.dataPaths
dumpCachesForTarget(
printer,
paths,
KotlinDataContainerTarget,
kotlinCompileContext.lookupsCacheAttributesManager.versionManagerForTesting.versionFileForTesting
)
data class TargetInChunk(val chunk: KotlinChunk, val target: KotlinModuleBuildTarget<*>)
val allTargets = chunks.flatMap { chunk ->
chunk.targets.map { target ->
TargetInChunk(chunk, target)
}
}.sortedBy { it.target.jpsModuleBuildTarget.presentableName }
allTargets.forEach { (chunk, target) ->
val metaBuildInfo = chunk.buildMetaInfoFile(target.jpsModuleBuildTarget)
dumpCachesForTarget(
printer, paths, target.jpsModuleBuildTarget,
target.localCacheVersionManager.versionFileForTesting,
metaBuildInfo,
subdirectory = KOTLIN_CACHE_DIRECTORY_NAME
)
}
return sb.toString()
}
private fun dumpCachesForTarget(
p: Printer,
paths: BuildDataPaths,
target: BuildTarget<*>,
vararg cacheVersionsFiles: File,
subdirectory: String? = null
) {
p.println(target)
p.pushIndent()
val dataRoot = paths.getTargetDataRoot(target).let { if (subdirectory != null) File(it, subdirectory) else it }
cacheVersionsFiles
.filter(File::exists)
.sortedBy { it.name }
.forEach { p.println(it.name) }
kotlinCacheNames(dataRoot).sorted().forEach { p.println(it) }
p.popIndent()
}
private fun kotlinCacheNames(dir: File): List<String> {
val result = arrayListOf<String>()
for (file in dir.walk()) {
if (file.isFile && file.extension == BasicMapsOwner.CACHE_EXTENSION) {
result.add(file.name)
}
}
return result
}
}
@@ -0,0 +1,116 @@
/*
* 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.jps.build
import com.intellij.openapi.util.io.FileUtil
import org.jetbrains.jps.model.JpsDummyElement
import org.jetbrains.jps.model.JpsModuleRootModificationUtil
import org.jetbrains.jps.model.JpsProject
import org.jetbrains.jps.model.java.JpsJavaDependencyScope
import org.jetbrains.jps.model.java.JpsJavaLibraryType
import org.jetbrains.jps.model.java.JpsJavaSdkType
import org.jetbrains.jps.model.library.JpsLibrary
import org.jetbrains.jps.model.library.JpsOrderRootType
import org.jetbrains.jps.model.library.sdk.JpsSdk
import org.jetbrains.jps.model.module.JpsModule
import org.jetbrains.jps.util.JpsPathUtil
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
import org.jetbrains.kotlin.utils.PathUtil
import java.io.File
import java.io.IOException
abstract class AbstractKotlinJpsBuildTestCase : BaseKotlinJpsBuildTestCase() {
protected lateinit var workDir: File
@Throws(IOException::class)
override fun doGetProjectDir(): File? {
return workDir
}
override fun addJdk(name: String, path: String?): JpsSdk<JpsDummyElement> {
val homePath = System.getProperty("java.home")
val versionString = System.getProperty("java.version")
val jdk = myModel.global.addSdk(name, homePath, versionString, JpsJavaSdkType.INSTANCE)
jdk.addRoot(JpsPathUtil.pathToUrl(path), JpsOrderRootType.COMPILED)
return jdk.properties
}
protected fun addKotlinMockRuntimeDependency(): JpsLibrary {
return addDependency(KotlinJpsLibrary.MockRuntime)
}
protected fun addKotlinStdlibDependency(): JpsLibrary {
return addDependency(KotlinJpsLibrary.JvmStdLib)
}
protected fun addKotlinJavaScriptStdlibDependency(): JpsLibrary {
return addDependency(KotlinJpsLibrary.JsStdLib)
}
private fun addDependency(library: KotlinJpsLibrary): JpsLibrary {
return addDependency(myProject, library)
}
protected fun addDependency(libraryName: String, libraryFile: File): JpsLibrary {
return addDependency(myProject, libraryName, libraryFile)
}
companion object {
val TEST_DATA_PATH = "jps-plugin/testData/"
@JvmStatic
protected fun addKotlinStdlibDependency(modules: Collection<JpsModule>, exported: Boolean = false): JpsLibrary {
return addDependency(modules, KotlinJpsLibrary.JvmStdLib, exported)
}
@JvmStatic
private fun addDependency(project: JpsProject, library: KotlinJpsLibrary, exported: Boolean = false): JpsLibrary {
return addDependency(JpsJavaDependencyScope.COMPILE, project.modules, exported, library.id, *library.roots)
}
@JvmStatic
private fun addDependency(modules: Collection<JpsModule>, library: KotlinJpsLibrary, exported: Boolean = false): JpsLibrary {
return addDependency(JpsJavaDependencyScope.COMPILE, modules, exported, library.id, *library.roots)
}
@JvmStatic
private fun addDependency(project: JpsProject, libraryName: String, libraryFile: File): JpsLibrary {
return addDependency(JpsJavaDependencyScope.COMPILE, project.modules, false, libraryName, libraryFile)
}
@JvmStatic
protected fun addDependency(
type: JpsJavaDependencyScope,
modules: Collection<JpsModule>,
exported: Boolean,
libraryName: String,
vararg file: File
): JpsLibrary {
val library = modules.iterator().next().project.addLibrary(libraryName, JpsJavaLibraryType.INSTANCE)
for (fileRoot in file) {
library.addRoot(fileRoot, JpsOrderRootType.COMPILED)
}
for (module in modules) {
JpsModuleRootModificationUtil.addDependency(module, library, type, exported)
}
return library
}
}
}
@@ -0,0 +1,368 @@
/*
* 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.jps.build
import com.intellij.testFramework.UsefulTestCase
import com.intellij.util.containers.StringInterner
import org.jetbrains.kotlin.TestWithWorkingDir
import org.jetbrains.kotlin.build.JvmSourceRoot
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
import org.jetbrains.kotlin.compilerRunner.*
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.incremental.components.LookupInfo
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.components.Position
import org.jetbrains.kotlin.incremental.components.ScopeKind
import org.jetbrains.kotlin.incremental.isKotlinFile
import org.jetbrains.kotlin.incremental.js.*
import org.jetbrains.kotlin.incremental.makeModuleFile
import org.jetbrains.kotlin.incremental.testingUtils.TouchPolicy
import org.jetbrains.kotlin.incremental.testingUtils.copyTestSources
import org.jetbrains.kotlin.incremental.testingUtils.getModificationsToPerform
import org.jetbrains.kotlin.incremental.utils.TestMessageCollector
import org.jetbrains.kotlin.jps.build.fixtures.EnableICFixture
import org.jetbrains.kotlin.jps.incremental.createTestingCompilerEnvironment
import org.jetbrains.kotlin.jps.incremental.runJSCompiler
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.utils.JsMetadataVersion
import org.jetbrains.kotlin.utils.PathUtil
import java.io.*
import java.util.*
abstract class AbstractJvmLookupTrackerTest : AbstractLookupTrackerTest() {
private val sourceToOutputMapping = hashMapOf<File, MutableSet<File>>()
override fun setUp() {
super.setUp()
sourceToOutputMapping.clear()
}
override fun markDirty(removedAndModifiedSources: Iterable<File>) {
for (sourceFile in removedAndModifiedSources) {
val outputs = sourceToOutputMapping.remove(sourceFile) ?: continue
for (output in outputs) {
output.delete()
}
}
}
override fun processCompilationResults(outputItemsCollector: OutputItemsCollectorImpl, services: Services) {
for ((sourceFiles, outputFile) in outputItemsCollector.outputs) {
if (outputFile.extension == "kotlin_module") continue
for (sourceFile in sourceFiles) {
val outputsForSource = sourceToOutputMapping.getOrPut(sourceFile) { hashSetOf() }
outputsForSource.add(outputFile)
}
}
}
override fun runCompiler(filesToCompile: Iterable<File>, env: JpsCompilerEnvironment): Any? {
val moduleFile = makeModuleFile(
name = "test",
isTest = true,
outputDir = outDir,
sourcesToCompile = filesToCompile.toList(),
commonSources = emptyList(),
javaSourceRoots = listOf(JvmSourceRoot(srcDir, null)),
classpath = listOf(outDir, ForTestCompileRuntime.runtimeJarForTests()).filter { it.exists() },
friendDirs = emptyList()
)
val args = K2JVMCompilerArguments().apply {
disableDefaultScriptingPlugin = true
buildFile = moduleFile.canonicalPath
reportOutputFiles = true
}
val argsArray = ArgumentUtils.convertArgumentsToStringList(args).toTypedArray()
try {
val stream = ByteArrayOutputStream()
val out = PrintStream(stream)
val exitCode = CompilerRunnerUtil.invokeExecMethod(K2JVMCompiler::class.java.name, argsArray, env, out)
val reader = BufferedReader(StringReader(stream.toString()))
CompilerOutputParser.parseCompilerMessagesFromReader(env.messageCollector, reader, env.outputItemsCollector)
return exitCode
}
finally {
moduleFile.delete()
}
}
}
abstract class AbstractJsKlibLookupTrackerTest : AbstractJsLookupTrackerTest() {
override val jsStdlibFile: File
get() = File("build/js-ir-runtime/full-runtime.klib")
override fun configureAdditionalArgs(args: K2JSCompilerArguments) {
args.irProduceKlibDir = true
args.irOnly = true
args.outputFile = outDir.resolve("out.klib").absolutePath
}
}
abstract class AbstractJsLookupTrackerTest : AbstractLookupTrackerTest() {
private var header: ByteArray? = null
private val packageParts: MutableMap<File, TranslationResultValue> = hashMapOf()
private val serializedIrFiles: MutableMap<File, IrTranslationResultValue> = hashMapOf()
override fun setUp() {
super.setUp()
header = null
packageParts.clear()
serializedIrFiles.clear()
}
override fun Services.Builder.registerAdditionalServices() {
if (header != null) {
register(
IncrementalDataProvider::class.java,
IncrementalDataProviderImpl(
headerMetadata = header!!,
compiledPackageParts = packageParts,
metadataVersion = JsMetadataVersion.INSTANCE.toArray(),
packageMetadata = emptyMap(), // TODO pass correct metadata
serializedIrFiles = serializedIrFiles
)
)
}
register(IncrementalResultsConsumer::class.java, IncrementalResultsConsumerImpl())
}
override fun markDirty(removedAndModifiedSources: Iterable<File>) {
removedAndModifiedSources.forEach {
packageParts.remove(it)
serializedIrFiles.remove(it)
}
}
override fun processCompilationResults(outputItemsCollector: OutputItemsCollectorImpl, services: Services) {
val incrementalResults = services.get(IncrementalResultsConsumer::class.java) as IncrementalResultsConsumerImpl
header = incrementalResults.headerMetadata
packageParts.putAll(incrementalResults.packageParts)
serializedIrFiles.putAll(incrementalResults.irFileData)
}
protected open val jsStdlibFile: File
get() = PathUtil.kotlinPathsForDistDirectory.jsStdLibJarPath
protected open fun configureAdditionalArgs(args: K2JSCompilerArguments) {
args.outputFile = File(outDir, "out.js").canonicalPath
}
override fun runCompiler(filesToCompile: Iterable<File>, env: JpsCompilerEnvironment): Any? {
val args = K2JSCompilerArguments().apply {
val libPaths = arrayListOf(jsStdlibFile.absolutePath) + (libraries ?: "").split(File.pathSeparator)
libraries = libPaths.joinToString(File.pathSeparator)
reportOutputFiles = true
freeArgs = filesToCompile.map { it.canonicalPath }
}
configureAdditionalArgs(args)
return runJSCompiler(args, env)
}
}
abstract class AbstractLookupTrackerTest : TestWithWorkingDir() {
private val DECLARATION_KEYWORDS = listOf("interface", "class", "enum class", "object", "fun", "operator fun", "val", "var")
private val DECLARATION_STARTS_WITH = DECLARATION_KEYWORDS.map { it + " " }
// ignore KDoc like comments which starts with `/**`, example: /** text */
private val COMMENT_WITH_LOOKUP_INFO = "/\\*[^*]+\\*/".toRegex()
protected lateinit var srcDir: File
protected lateinit var outDir: File
private val enableICFixture = EnableICFixture()
override fun setUp() {
super.setUp()
srcDir = File(workingDir, "src").apply { mkdirs() }
outDir = File(workingDir, "out")
enableICFixture.setUp()
}
override fun tearDown() {
enableICFixture.tearDown()
super.tearDown()
}
protected abstract fun markDirty(removedAndModifiedSources: Iterable<File>)
protected abstract fun processCompilationResults(outputItemsCollector: OutputItemsCollectorImpl, services: Services)
protected abstract fun runCompiler(filesToCompile: Iterable<File>, env: JpsCompilerEnvironment): Any?
fun doTest(path: String) {
val sb = StringBuilder()
fun StringBuilder.indentln(string: String) {
appendLine(" $string")
}
fun CompilerOutput.logOutput(stepName: String) {
sb.appendLine("==== $stepName ====")
sb.appendLine("Compiling files:")
for (compiledFile in compiledFiles.sortedBy { it.canonicalPath }) {
val lookupsFromFile = lookups[compiledFile]
val lookupStatus = when {
lookupsFromFile == null -> "(unknown)"
lookupsFromFile.isEmpty() -> "(no lookups)"
else -> ""
}
val relativePath = compiledFile.toRelativeString(workingDir).replace("\\", "/")
sb.indentln("$relativePath$lookupStatus")
}
sb.appendLine("Exit code: $exitCode")
errors.forEach(sb::indentln)
sb.appendLine()
}
val testDir = File(path)
val workToOriginalFileMap = HashMap(copyTestSources(testDir, srcDir, filePrefix = ""))
var dirtyFiles = srcDir.walk().filterTo(HashSet()) { it.isKotlinFile(listOf("kt", "kts")) }
val steps = getModificationsToPerform(testDir, moduleNames = null, allowNoFilesWithSuffixInTestData = true, touchPolicy = TouchPolicy.CHECKSUM)
.filter { it.isNotEmpty() }
val filesToLookups = arrayListOf<Map<File, List<LookupInfo>>>()
fun CompilerOutput.originalFilesToLookups() =
compiledFiles.associateBy({ workToOriginalFileMap[it]!! }, { lookups[it] ?: emptyList() })
make(dirtyFiles).apply {
logOutput("INITIAL BUILD")
filesToLookups.add(originalFilesToLookups())
}
for ((i, modifications) in steps.withIndex()) {
dirtyFiles = modifications.mapNotNullTo(HashSet()) { it.perform(workingDir, workToOriginalFileMap) }
make(dirtyFiles).apply {
logOutput("STEP ${i + 1}")
filesToLookups.add(originalFilesToLookups())
}
}
val expectedBuildLog = File(testDir, "build.log")
UsefulTestCase.assertSameLinesWithFile(expectedBuildLog.canonicalPath, sb.toString())
assertEquals(steps.size + 1, filesToLookups.size)
for ((i, lookupsAtStepI) in filesToLookups.withIndex()) {
val step = if (i == 0) "INITIAL BUILD" else "STEP $i"
for ((file, lookups) in lookupsAtStepI) {
checkLookupsInFile(step, file, lookups)
}
}
}
private class CompilerOutput(
val exitCode: String,
val errors: List<String>,
val compiledFiles: Iterable<File>,
val lookups: Map<File, List<LookupInfo>>
)
private fun make(filesToCompile: Iterable<File>): CompilerOutput {
filesToCompile.forEach {
it.writeText(it.readText().replace(COMMENT_WITH_LOOKUP_INFO, ""))
}
markDirty(filesToCompile)
val lookupTracker = TestLookupTracker()
val messageCollector = TestMessageCollector()
val outputItemsCollector = OutputItemsCollectorImpl()
val services = Services.Builder().run {
register(LookupTracker::class.java, lookupTracker)
registerAdditionalServices()
build()
}
val environment = createTestingCompilerEnvironment(messageCollector, outputItemsCollector, services)
val exitCode = runCompiler(filesToCompile, environment) as? ExitCode
if (exitCode == ExitCode.OK) {
processCompilationResults(outputItemsCollector, environment.services)
}
val lookups = lookupTracker.lookups.groupBy { File(it.filePath) }
val lookupsFromCompiledFiles = filesToCompile.associate { it to (lookups[it] ?: emptyList()) }
return CompilerOutput(exitCode.toString(), messageCollector.errors, filesToCompile, lookupsFromCompiledFiles)
}
protected open fun Services.Builder.registerAdditionalServices() {}
private fun checkLookupsInFile(step: String, expectedFile: File, lookupsFromFile: List<LookupInfo>) {
val text = expectedFile.readText().replace(COMMENT_WITH_LOOKUP_INFO, "")
val lines = text.lines().toMutableList()
for ((line, lookupsFromLine) in lookupsFromFile.groupBy { it.position.line }) {
val columnToLookups = lookupsFromLine.groupBy { it.position.column }.toList().sortedBy { it.first }
val lineContent = lines[line - 1]
val parts = ArrayList<CharSequence>(columnToLookups.size * 2)
var start = 0
for ((column, lookupsFromColumn) in columnToLookups) {
val end = column - 1
parts.add(lineContent.subSequence(start, end))
val lookups = lookupsFromColumn.mapTo(sortedSetOf()) {
val rest = lineContent.substring(end)
val name =
when {
rest.startsWith(it.name) || // same name
rest.startsWith("$" + it.name) || // backing field
DECLARATION_STARTS_WITH.any { rest.startsWith(it) } // it's declaration
-> ""
else -> "(" + it.name + ")"
}
it.scopeKind.toString()[0].toLowerCase()
.toString() + ":" + it.scopeFqName.let { if (it.isNotEmpty()) it else "<root>" } + name
}.joinToString(separator = " ", prefix = "/*", postfix = "*/")
parts.add(lookups)
start = end
}
lines[line - 1] = parts.joinToString("") + lineContent.subSequence(start, lineContent.length)
}
val actual = lines.joinToString("\n")
KotlinTestUtils.assertEqualsToFile("Lookups do not match after $step", expectedFile, actual)
}
}
class TestLookupTracker : LookupTracker {
val lookups = arrayListOf<LookupInfo>()
private val interner = StringInterner()
override val requiresPosition: Boolean
get() = true
override fun record(filePath: String, position: Position, scopeFqName: String, scopeKind: ScopeKind, name: String) {
val internedFilePath = interner.intern(filePath)
val internedScopeFqName = interner.intern(scopeFqName)
val internedName = interner.intern(name)
lookups.add(LookupInfo(internedFilePath, position, internedScopeFqName, scopeKind, internedName))
}
}
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build
import org.jetbrains.kotlin.jps.build.dependeciestxt.ModulesTxt
import org.jetbrains.kotlin.jps.build.dependeciestxt.MppJpsIncTestsGenerator
import java.io.File
abstract class AbstractMultiplatformJpsTestWithGeneratedContent : AbstractIncrementalJpsTest() {
override val modulesTxtFile: File
get() = File(testDataDir.parent, "dependencies.txt").also {
check(it.exists()) {
"`dependencies.txt` should be in parent dir. " +
"See `jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/README.md` for details"
}
}
override val testDataSrc: File
get() = File(workDir, "generatedTestDataSources")
override fun generateModuleSources(modulesTxt: ModulesTxt) {
testDataSrc.mkdirs()
val testCaseName = testDataDir.name
val generator = MppJpsIncTestsGenerator(modulesTxt) { testDataSrc }
val testCase = generator.testCases.find { it.name == testCaseName }
?: error("Test case `$testCaseName` is not configured in ${modulesTxt.fileName}")
testCase.generate()
}
override val ModulesTxt.Module.sourceFilePrefix: String
get() = "${indexedName}_"
}
@@ -0,0 +1,53 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.jps.build
import org.jetbrains.jps.builders.JpsBuildTestCase
import org.jetbrains.jps.model.library.JpsLibrary
import org.jetbrains.kotlin.compilerRunner.JpsKotlinCompilerRunner
import org.jetbrains.kotlin.test.WithMutedInDatabaseRunTest
import org.jetbrains.kotlin.test.runTest
@WithMutedInDatabaseRunTest
abstract class BaseKotlinJpsBuildTestCase : JpsBuildTestCase() {
@Throws(Exception::class)
override fun setUp() {
super.setUp()
System.setProperty("kotlin.jps.tests", "true")
}
@Throws(Exception::class)
override fun tearDown() {
System.clearProperty("kotlin.jps.tests")
myModel = null
myBuildParams.clear()
JpsKotlinCompilerRunner.releaseCompileServiceSession()
super.tearDown()
}
private val libraries = mutableMapOf<String, JpsLibrary>()
protected fun requireLibrary(library: KotlinJpsLibrary) = libraries.getOrPut(library.id) {
library.create(myProject)
}
override fun runTest() {
runTest {
super.runTest()
}
}
}
@@ -0,0 +1,229 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class DataContainerVersionChangedTestGenerated extends AbstractDataContainerVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInCacheVersionChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("clearedHasKotlin")
public void testClearedHasKotlin() throws Exception {
runTest("jps-plugin/testData/incremental/cacheVersionChanged/clearedHasKotlin/");
}
@TestMetadata("exportedModule")
public void testExportedModule() throws Exception {
runTest("jps-plugin/testData/incremental/cacheVersionChanged/exportedModule/");
}
@TestMetadata("javaOnlyModulesAreNotAffected")
public void testJavaOnlyModulesAreNotAffected() throws Exception {
runTest("jps-plugin/testData/incremental/cacheVersionChanged/javaOnlyModulesAreNotAffected/");
}
@TestMetadata("module1Modified")
public void testModule1Modified() throws Exception {
runTest("jps-plugin/testData/incremental/cacheVersionChanged/module1Modified/");
}
@TestMetadata("module2Modified")
public void testModule2Modified() throws Exception {
runTest("jps-plugin/testData/incremental/cacheVersionChanged/module2Modified/");
}
@TestMetadata("moduleWithConstantModified")
public void testModuleWithConstantModified() throws Exception {
runTest("jps-plugin/testData/incremental/cacheVersionChanged/moduleWithConstantModified/");
}
@TestMetadata("moduleWithInlineModified")
public void testModuleWithInlineModified() throws Exception {
runTest("jps-plugin/testData/incremental/cacheVersionChanged/moduleWithInlineModified/");
}
@TestMetadata("touchedFile")
public void testTouchedFile() throws Exception {
runTest("jps-plugin/testData/incremental/cacheVersionChanged/touchedFile/");
}
@TestMetadata("touchedOnlyJavaFile")
public void testTouchedOnlyJavaFile() throws Exception {
runTest("jps-plugin/testData/incremental/cacheVersionChanged/touchedOnlyJavaFile/");
}
@TestMetadata("untouchedFiles")
public void testUntouchedFiles() throws Exception {
runTest("jps-plugin/testData/incremental/cacheVersionChanged/untouchedFiles/");
}
@TestMetadata("withError")
public void testWithError() throws Exception {
runTest("jps-plugin/testData/incremental/cacheVersionChanged/withError/");
}
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged/clearedHasKotlin")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClearedHasKotlin extends AbstractDataContainerVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClearedHasKotlin() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged/clearedHasKotlin"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged/exportedModule")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ExportedModule extends AbstractDataContainerVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInExportedModule() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged/exportedModule"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged/javaOnlyModulesAreNotAffected")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class JavaOnlyModulesAreNotAffected extends AbstractDataContainerVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInJavaOnlyModulesAreNotAffected() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged/javaOnlyModulesAreNotAffected"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged/module1Modified")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Module1Modified extends AbstractDataContainerVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInModule1Modified() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged/module1Modified"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged/module2Modified")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Module2Modified extends AbstractDataContainerVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInModule2Modified() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged/module2Modified"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged/moduleWithConstantModified")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ModuleWithConstantModified extends AbstractDataContainerVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInModuleWithConstantModified() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged/moduleWithConstantModified"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged/moduleWithInlineModified")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ModuleWithInlineModified extends AbstractDataContainerVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInModuleWithInlineModified() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged/moduleWithInlineModified"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged/touchedFile")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class TouchedFile extends AbstractDataContainerVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInTouchedFile() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged/touchedFile"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged/touchedOnlyJavaFile")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class TouchedOnlyJavaFile extends AbstractDataContainerVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInTouchedOnlyJavaFile() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged/touchedOnlyJavaFile"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged/untouchedFiles")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class UntouchedFiles extends AbstractDataContainerVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInUntouchedFiles() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged/untouchedFiles"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged/withError")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class WithError extends AbstractDataContainerVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInWithError() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged/withError"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
}
@@ -0,0 +1,229 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class IncrementalCacheVersionChangedTestGenerated extends AbstractIncrementalCacheVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInCacheVersionChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("clearedHasKotlin")
public void testClearedHasKotlin() throws Exception {
runTest("jps-plugin/testData/incremental/cacheVersionChanged/clearedHasKotlin/");
}
@TestMetadata("exportedModule")
public void testExportedModule() throws Exception {
runTest("jps-plugin/testData/incremental/cacheVersionChanged/exportedModule/");
}
@TestMetadata("javaOnlyModulesAreNotAffected")
public void testJavaOnlyModulesAreNotAffected() throws Exception {
runTest("jps-plugin/testData/incremental/cacheVersionChanged/javaOnlyModulesAreNotAffected/");
}
@TestMetadata("module1Modified")
public void testModule1Modified() throws Exception {
runTest("jps-plugin/testData/incremental/cacheVersionChanged/module1Modified/");
}
@TestMetadata("module2Modified")
public void testModule2Modified() throws Exception {
runTest("jps-plugin/testData/incremental/cacheVersionChanged/module2Modified/");
}
@TestMetadata("moduleWithConstantModified")
public void testModuleWithConstantModified() throws Exception {
runTest("jps-plugin/testData/incremental/cacheVersionChanged/moduleWithConstantModified/");
}
@TestMetadata("moduleWithInlineModified")
public void testModuleWithInlineModified() throws Exception {
runTest("jps-plugin/testData/incremental/cacheVersionChanged/moduleWithInlineModified/");
}
@TestMetadata("touchedFile")
public void testTouchedFile() throws Exception {
runTest("jps-plugin/testData/incremental/cacheVersionChanged/touchedFile/");
}
@TestMetadata("touchedOnlyJavaFile")
public void testTouchedOnlyJavaFile() throws Exception {
runTest("jps-plugin/testData/incremental/cacheVersionChanged/touchedOnlyJavaFile/");
}
@TestMetadata("untouchedFiles")
public void testUntouchedFiles() throws Exception {
runTest("jps-plugin/testData/incremental/cacheVersionChanged/untouchedFiles/");
}
@TestMetadata("withError")
public void testWithError() throws Exception {
runTest("jps-plugin/testData/incremental/cacheVersionChanged/withError/");
}
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged/clearedHasKotlin")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClearedHasKotlin extends AbstractIncrementalCacheVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClearedHasKotlin() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged/clearedHasKotlin"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged/exportedModule")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ExportedModule extends AbstractIncrementalCacheVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInExportedModule() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged/exportedModule"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged/javaOnlyModulesAreNotAffected")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class JavaOnlyModulesAreNotAffected extends AbstractIncrementalCacheVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInJavaOnlyModulesAreNotAffected() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged/javaOnlyModulesAreNotAffected"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged/module1Modified")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Module1Modified extends AbstractIncrementalCacheVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInModule1Modified() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged/module1Modified"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged/module2Modified")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Module2Modified extends AbstractIncrementalCacheVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInModule2Modified() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged/module2Modified"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged/moduleWithConstantModified")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ModuleWithConstantModified extends AbstractIncrementalCacheVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInModuleWithConstantModified() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged/moduleWithConstantModified"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged/moduleWithInlineModified")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ModuleWithInlineModified extends AbstractIncrementalCacheVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInModuleWithInlineModified() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged/moduleWithInlineModified"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged/touchedFile")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class TouchedFile extends AbstractIncrementalCacheVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInTouchedFile() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged/touchedFile"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged/touchedOnlyJavaFile")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class TouchedOnlyJavaFile extends AbstractIncrementalCacheVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInTouchedOnlyJavaFile() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged/touchedOnlyJavaFile"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged/untouchedFiles")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class UntouchedFiles extends AbstractIncrementalCacheVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInUntouchedFiles() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged/untouchedFiles"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/cacheVersionChanged/withError")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class WithError extends AbstractIncrementalCacheVersionChangedTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInWithError() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged/withError"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
}
@@ -0,0 +1,43 @@
/*
* 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.jps.build
class IncrementalConstantSearchTest : AbstractIncrementalJpsTest() {
fun testJavaConstantChangedUsedInKotlin() {
doTest("jps-plugin/testData/incremental/custom/javaConstantChangedUsedInKotlin/")
}
fun testJavaConstantUnchangedUsedInKotlin() {
doTest("jps-plugin/testData/incremental/custom/javaConstantUnchangedUsedInKotlin/")
}
fun testKotlinConstantChangedUsedInJava() {
doTest("jps-plugin/testData/incremental/custom/kotlinConstantChangedUsedInJava/")
}
fun testKotlinJvmFieldChangedUsedInJava() {
doTest("jps-plugin/testData/incremental/custom/kotlinJvmFieldChangedUsedInJava/")
}
fun testKotlinConstantUnchangedUsedInJava() {
doTest("jps-plugin/testData/incremental/custom/kotlinConstantUnchangedUsedInJava/")
}
fun testKotlinJvmFieldUnchangedUsedInJava() {
doTest("jps-plugin/testData/incremental/custom/kotlinJvmFieldUnchangedUsedInJava/")
}
}
@@ -0,0 +1,463 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("jps-plugin/testData/incremental/multiModule/common")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class IncrementalJsJpsTestGenerated extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInCommon() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("classAdded")
public void testClassAdded() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/classAdded/");
}
@TestMetadata("classRemoved")
public void testClassRemoved() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/classRemoved/");
}
@TestMetadata("constantValueChanged")
public void testConstantValueChanged() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/constantValueChanged/");
}
@TestMetadata("copyFileToAnotherModule")
public void testCopyFileToAnotherModule() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/copyFileToAnotherModule/");
}
@TestMetadata("defaultArgumentInConstructorRemoved")
public void testDefaultArgumentInConstructorRemoved() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/defaultArgumentInConstructorRemoved/");
}
@TestMetadata("defaultParameterAdded")
public void testDefaultParameterAdded() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/defaultParameterAdded/");
}
@TestMetadata("defaultParameterAddedForTopLevelFun")
public void testDefaultParameterAddedForTopLevelFun() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/defaultParameterAddedForTopLevelFun/");
}
@TestMetadata("defaultParameterRemoved")
public void testDefaultParameterRemoved() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/defaultParameterRemoved/");
}
@TestMetadata("defaultParameterRemovedForTopLevelFun")
public void testDefaultParameterRemovedForTopLevelFun() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/defaultParameterRemovedForTopLevelFun/");
}
@TestMetadata("defaultValueInConstructorRemoved")
public void testDefaultValueInConstructorRemoved() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/defaultValueInConstructorRemoved/");
}
@TestMetadata("duplicatedClass")
public void testDuplicatedClass() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/duplicatedClass/");
}
@TestMetadata("exportedDependency")
public void testExportedDependency() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/exportedDependency/");
}
@TestMetadata("functionFromDifferentPackageChanged")
public void testFunctionFromDifferentPackageChanged() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/functionFromDifferentPackageChanged/");
}
@TestMetadata("inlineFunctionInlined")
public void testInlineFunctionInlined() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/inlineFunctionInlined/");
}
@TestMetadata("inlineFunctionTwoPackageParts")
public void testInlineFunctionTwoPackageParts() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/inlineFunctionTwoPackageParts/");
}
@TestMetadata("moveFileToAnotherModule")
public void testMoveFileToAnotherModule() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/moveFileToAnotherModule/");
}
@TestMetadata("simple")
public void testSimple() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/simple/");
}
@TestMetadata("simpleDependency")
public void testSimpleDependency() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/simpleDependency/");
}
@TestMetadata("simpleDependencyErrorOnAccessToInternal1")
public void testSimpleDependencyErrorOnAccessToInternal1() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/simpleDependencyErrorOnAccessToInternal1/");
}
@TestMetadata("simpleDependencyErrorOnAccessToInternal2")
public void testSimpleDependencyErrorOnAccessToInternal2() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/simpleDependencyErrorOnAccessToInternal2/");
}
@TestMetadata("simpleDependencyUnchanged")
public void testSimpleDependencyUnchanged() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/simpleDependencyUnchanged/");
}
@TestMetadata("transitiveDependency")
public void testTransitiveDependency() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/transitiveDependency/");
}
@TestMetadata("transitiveInlining")
public void testTransitiveInlining() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/transitiveInlining/");
}
@TestMetadata("twoDependants")
public void testTwoDependants() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/common/twoDependants/");
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/classAdded")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassAdded extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassAdded() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/classAdded"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/classRemoved")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassRemoved extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassRemoved() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/classRemoved"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/constantValueChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ConstantValueChanged extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInConstantValueChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/constantValueChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/copyFileToAnotherModule")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class CopyFileToAnotherModule extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInCopyFileToAnotherModule() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/copyFileToAnotherModule"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/defaultArgumentInConstructorRemoved")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class DefaultArgumentInConstructorRemoved extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInDefaultArgumentInConstructorRemoved() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/defaultArgumentInConstructorRemoved"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/defaultParameterAdded")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class DefaultParameterAdded extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInDefaultParameterAdded() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/defaultParameterAdded"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/defaultParameterAddedForTopLevelFun")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class DefaultParameterAddedForTopLevelFun extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInDefaultParameterAddedForTopLevelFun() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/defaultParameterAddedForTopLevelFun"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/defaultParameterRemoved")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class DefaultParameterRemoved extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInDefaultParameterRemoved() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/defaultParameterRemoved"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/defaultParameterRemovedForTopLevelFun")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class DefaultParameterRemovedForTopLevelFun extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInDefaultParameterRemovedForTopLevelFun() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/defaultParameterRemovedForTopLevelFun"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/defaultValueInConstructorRemoved")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class DefaultValueInConstructorRemoved extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInDefaultValueInConstructorRemoved() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/defaultValueInConstructorRemoved"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/duplicatedClass")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class DuplicatedClass extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInDuplicatedClass() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/duplicatedClass"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/exportedDependency")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ExportedDependency extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInExportedDependency() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/exportedDependency"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/functionFromDifferentPackageChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class FunctionFromDifferentPackageChanged extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInFunctionFromDifferentPackageChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/functionFromDifferentPackageChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/inlineFunctionInlined")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class InlineFunctionInlined extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInInlineFunctionInlined() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/inlineFunctionInlined"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/inlineFunctionTwoPackageParts")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class InlineFunctionTwoPackageParts extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInInlineFunctionTwoPackageParts() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/inlineFunctionTwoPackageParts"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/moveFileToAnotherModule")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class MoveFileToAnotherModule extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInMoveFileToAnotherModule() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/moveFileToAnotherModule"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/simple")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Simple extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSimple() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/simple"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/simpleDependency")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SimpleDependency extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSimpleDependency() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/simpleDependency"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/simpleDependencyErrorOnAccessToInternal1")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SimpleDependencyErrorOnAccessToInternal1 extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSimpleDependencyErrorOnAccessToInternal1() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/simpleDependencyErrorOnAccessToInternal1"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/simpleDependencyErrorOnAccessToInternal2")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SimpleDependencyErrorOnAccessToInternal2 extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSimpleDependencyErrorOnAccessToInternal2() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/simpleDependencyErrorOnAccessToInternal2"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/simpleDependencyUnchanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SimpleDependencyUnchanged extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSimpleDependencyUnchanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/simpleDependencyUnchanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/transitiveDependency")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class TransitiveDependency extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInTransitiveDependency() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/transitiveDependency"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/transitiveInlining")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class TransitiveInlining extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInTransitiveInlining() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/transitiveInlining"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/common/twoDependants")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class TwoDependants extends AbstractIncrementalJsJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInTwoDependants() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/common/twoDependants"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
}
@@ -0,0 +1,263 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@RunWith(JUnit3RunnerWithInners.class)
public class IncrementalLazyCachesTestGenerated extends AbstractIncrementalLazyCachesTest {
@TestMetadata("jps-plugin/testData/incremental/lazyKotlinCaches")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class LazyKotlinCaches extends AbstractIncrementalLazyCachesTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInLazyKotlinCaches() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/lazyKotlinCaches"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("class")
public void testClass() throws Exception {
runTest("jps-plugin/testData/incremental/lazyKotlinCaches/class/");
}
@TestMetadata("classInheritance")
public void testClassInheritance() throws Exception {
runTest("jps-plugin/testData/incremental/lazyKotlinCaches/classInheritance/");
}
@TestMetadata("constant")
public void testConstant() throws Exception {
runTest("jps-plugin/testData/incremental/lazyKotlinCaches/constant/");
}
@TestMetadata("function")
public void testFunction() throws Exception {
runTest("jps-plugin/testData/incremental/lazyKotlinCaches/function/");
}
@TestMetadata("inlineFunctionWithUsage")
public void testInlineFunctionWithUsage() throws Exception {
runTest("jps-plugin/testData/incremental/lazyKotlinCaches/inlineFunctionWithUsage/");
}
@TestMetadata("inlineFunctionWithoutUsage")
public void testInlineFunctionWithoutUsage() throws Exception {
runTest("jps-plugin/testData/incremental/lazyKotlinCaches/inlineFunctionWithoutUsage/");
}
@TestMetadata("noKotlin")
public void testNoKotlin() throws Exception {
runTest("jps-plugin/testData/incremental/lazyKotlinCaches/noKotlin/");
}
@TestMetadata("topLevelPropertyAccess")
public void testTopLevelPropertyAccess() throws Exception {
runTest("jps-plugin/testData/incremental/lazyKotlinCaches/topLevelPropertyAccess/");
}
@TestMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/class")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Class extends AbstractIncrementalLazyCachesTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClass() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/lazyKotlinCaches/class"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/classInheritance")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassInheritance extends AbstractIncrementalLazyCachesTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassInheritance() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/lazyKotlinCaches/classInheritance"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/constant")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Constant extends AbstractIncrementalLazyCachesTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInConstant() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/lazyKotlinCaches/constant"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/function")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Function extends AbstractIncrementalLazyCachesTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInFunction() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/lazyKotlinCaches/function"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/inlineFunctionWithUsage")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class InlineFunctionWithUsage extends AbstractIncrementalLazyCachesTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInInlineFunctionWithUsage() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/lazyKotlinCaches/inlineFunctionWithUsage"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/inlineFunctionWithoutUsage")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class InlineFunctionWithoutUsage extends AbstractIncrementalLazyCachesTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInInlineFunctionWithoutUsage() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/lazyKotlinCaches/inlineFunctionWithoutUsage"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/noKotlin")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class NoKotlin extends AbstractIncrementalLazyCachesTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInNoKotlin() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/lazyKotlinCaches/noKotlin"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/lazyKotlinCaches/topLevelPropertyAccess")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class TopLevelPropertyAccess extends AbstractIncrementalLazyCachesTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInTopLevelPropertyAccess() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/lazyKotlinCaches/topLevelPropertyAccess"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
}
@TestMetadata("jps-plugin/testData/incremental/changeIncrementalOption")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ChangeIncrementalOption extends AbstractIncrementalLazyCachesTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInChangeIncrementalOption() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/changeIncrementalOption"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("incrementalOff")
public void testIncrementalOff() throws Exception {
runTest("jps-plugin/testData/incremental/changeIncrementalOption/incrementalOff/");
}
@TestMetadata("incrementalOffOn")
public void testIncrementalOffOn() throws Exception {
runTest("jps-plugin/testData/incremental/changeIncrementalOption/incrementalOffOn/");
}
@TestMetadata("incrementalOffOnJavaChanged")
public void testIncrementalOffOnJavaChanged() throws Exception {
runTest("jps-plugin/testData/incremental/changeIncrementalOption/incrementalOffOnJavaChanged/");
}
@TestMetadata("incrementalOffOnJavaOnly")
public void testIncrementalOffOnJavaOnly() throws Exception {
runTest("jps-plugin/testData/incremental/changeIncrementalOption/incrementalOffOnJavaOnly/");
}
@TestMetadata("jps-plugin/testData/incremental/changeIncrementalOption/incrementalOff")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class IncrementalOff extends AbstractIncrementalLazyCachesTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInIncrementalOff() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/changeIncrementalOption/incrementalOff"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/changeIncrementalOption/incrementalOffOn")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class IncrementalOffOn extends AbstractIncrementalLazyCachesTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInIncrementalOffOn() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/changeIncrementalOption/incrementalOffOn"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/changeIncrementalOption/incrementalOffOnJavaChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class IncrementalOffOnJavaChanged extends AbstractIncrementalLazyCachesTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInIncrementalOffOnJavaChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/changeIncrementalOption/incrementalOffOnJavaChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/changeIncrementalOption/incrementalOffOnJavaOnly")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class IncrementalOffOnJavaOnly extends AbstractIncrementalLazyCachesTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInIncrementalOffOnJavaOnly() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/changeIncrementalOption/incrementalOffOnJavaOnly"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
}
}
@@ -0,0 +1,48 @@
/*
* 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.jps.build
import com.intellij.openapi.util.SystemInfoRt
import org.jetbrains.jps.model.java.JavaSourceRootType
import org.jetbrains.kotlin.incremental.testingUtils.Modification
class IncrementalProjectPathCaseChangedTest : AbstractIncrementalJpsTest(checkDumpsCaseInsensitively = true) {
fun testProjectPathCaseChanged() {
doTest("jps-plugin/testData/incremental/custom/projectPathCaseChanged/")
}
fun testProjectPathCaseChangedMultiFile() {
doTest("jps-plugin/testData/incremental/custom/projectPathCaseChangedMultiFile/")
}
override fun doTest(testDataPath: String) {
if (SystemInfoRt.isFileSystemCaseSensitive) {
return
}
super.doTest(testDataPath)
}
override fun performAdditionalModifications(modifications: List<Modification>) {
val module = myProject.modules[0]
val sourceRoot = module.sourceRoots[0].url
assert(sourceRoot.endsWith("/src"))
val newSourceRoot = sourceRoot.replace("/src", "/SRC")
module.removeSourceRoot(sourceRoot, JavaSourceRootType.SOURCE)
module.addSourceRoot(newSourceRoot, JavaSourceRootType.SOURCE)
}
}
@@ -0,0 +1,59 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build
import junit.framework.TestCase
class JoinToReadableStringTest : TestCase() {
fun test0() {
assertEquals(
"",
listOf<String>().joinToReadableString()
)
}
fun test1() {
assertEquals(
"a",
listOf("a").joinToReadableString()
)
}
fun test2() {
assertEquals(
"a and b",
listOf("a", "b").joinToReadableString()
)
}
fun test3() {
assertEquals(
"a, b and c",
listOf("a", "b", "c").joinToReadableString()
)
}
fun test4() {
assertEquals(
"a, b, c and d",
listOf("a", "b", "c", "d").joinToReadableString()
)
}
fun test5() {
assertEquals(
"a, b, c, d and e",
listOf("a", "b", "c", "d", "e").joinToReadableString()
)
}
fun test6() {
assertEquals(
"a, b, c, d, e and 1 more",
listOf("a", "b", "c", "d", "e", "f").joinToReadableString()
)
}
}
@@ -0,0 +1,61 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("jps-plugin/testData/incremental/lookupTracker/jsKlib")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class JsKlibLookupTrackerTestGenerated extends AbstractJsKlibLookupTrackerTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInJsKlib() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/lookupTracker/jsKlib"), Pattern.compile("^([^\\.]+)$"), null, false);
}
@TestMetadata("classifierMembers")
public void testClassifierMembers() throws Exception {
runTest("jps-plugin/testData/incremental/lookupTracker/jsKlib/classifierMembers/");
}
@TestMetadata("conventions")
public void testConventions() throws Exception {
runTest("jps-plugin/testData/incremental/lookupTracker/jsKlib/conventions/");
}
@TestMetadata("expressionType")
public void testExpressionType() throws Exception {
runTest("jps-plugin/testData/incremental/lookupTracker/jsKlib/expressionType/");
}
@TestMetadata("localDeclarations")
public void testLocalDeclarations() throws Exception {
runTest("jps-plugin/testData/incremental/lookupTracker/jsKlib/localDeclarations/");
}
@TestMetadata("packageDeclarations")
public void testPackageDeclarations() throws Exception {
runTest("jps-plugin/testData/incremental/lookupTracker/jsKlib/packageDeclarations/");
}
@TestMetadata("simple")
public void testSimple() throws Exception {
runTest("jps-plugin/testData/incremental/lookupTracker/jsKlib/simple/");
}
}
@@ -0,0 +1,61 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("jps-plugin/testData/incremental/lookupTracker/js")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class JsLookupTrackerTestGenerated extends AbstractJsLookupTrackerTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInJs() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/lookupTracker/js"), Pattern.compile("^([^\\.]+)$"), null, false);
}
@TestMetadata("classifierMembers")
public void testClassifierMembers() throws Exception {
runTest("jps-plugin/testData/incremental/lookupTracker/js/classifierMembers/");
}
@TestMetadata("conventions")
public void testConventions() throws Exception {
runTest("jps-plugin/testData/incremental/lookupTracker/js/conventions/");
}
@TestMetadata("expressionType")
public void testExpressionType() throws Exception {
runTest("jps-plugin/testData/incremental/lookupTracker/js/expressionType/");
}
@TestMetadata("localDeclarations")
public void testLocalDeclarations() throws Exception {
runTest("jps-plugin/testData/incremental/lookupTracker/js/localDeclarations/");
}
@TestMetadata("packageDeclarations")
public void testPackageDeclarations() throws Exception {
runTest("jps-plugin/testData/incremental/lookupTracker/js/packageDeclarations/");
}
@TestMetadata("simple")
public void testSimple() throws Exception {
runTest("jps-plugin/testData/incremental/lookupTracker/js/simple/");
}
}
@@ -0,0 +1,76 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("jps-plugin/testData/incremental/lookupTracker/jvm")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class JvmLookupTrackerTestGenerated extends AbstractJvmLookupTrackerTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInJvm() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/lookupTracker/jvm"), Pattern.compile("^([^\\.]+)$"), null, false);
}
@TestMetadata("classifierMembers")
public void testClassifierMembers() throws Exception {
runTest("jps-plugin/testData/incremental/lookupTracker/jvm/classifierMembers/");
}
@TestMetadata("conventions")
public void testConventions() throws Exception {
runTest("jps-plugin/testData/incremental/lookupTracker/jvm/conventions/");
}
@TestMetadata("expressionType")
public void testExpressionType() throws Exception {
runTest("jps-plugin/testData/incremental/lookupTracker/jvm/expressionType/");
}
@TestMetadata("java")
public void testJava() throws Exception {
runTest("jps-plugin/testData/incremental/lookupTracker/jvm/java/");
}
@TestMetadata("localDeclarations")
public void testLocalDeclarations() throws Exception {
runTest("jps-plugin/testData/incremental/lookupTracker/jvm/localDeclarations/");
}
@TestMetadata("packageDeclarations")
public void testPackageDeclarations() throws Exception {
runTest("jps-plugin/testData/incremental/lookupTracker/jvm/packageDeclarations/");
}
@TestMetadata("SAM")
public void testSAM() throws Exception {
runTest("jps-plugin/testData/incremental/lookupTracker/jvm/SAM/");
}
@TestMetadata("simple")
public void testSimple() throws Exception {
runTest("jps-plugin/testData/incremental/lookupTracker/jvm/simple/");
}
@TestMetadata("syntheticProperties")
public void testSyntheticProperties() throws Exception {
runTest("jps-plugin/testData/incremental/lookupTracker/jvm/syntheticProperties/");
}
}
@@ -0,0 +1,111 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build
import com.intellij.openapi.util.io.FileUtil
import org.jetbrains.jps.model.java.JpsJavaExtensionService
import org.jetbrains.jps.model.module.JpsModule
import org.jetbrains.jps.util.JpsPathUtil
import java.io.File
import java.nio.file.Paths
abstract class KotlinJpsBuildTestBase : AbstractKotlinJpsBuildTestCase() {
protected lateinit var originalProjectDir: File
protected val expectedOutputFile: File
get() = File(originalProjectDir, "expected-output.txt")
override fun setUp() {
super.setUp()
val currentTestMethod = this::class.members.firstOrNull { it.name == "test" + getTestName(false) }
val workingDirFromAnnotation = currentTestMethod?.annotations?.filterIsInstance<WorkingDir>()?.firstOrNull()?.name
val projDirPath = Paths.get(
TEST_DATA_PATH,
"general",
workingDirFromAnnotation ?: getTestName(false)
)
originalProjectDir = projDirPath.toFile()
workDir = copyTestDataToTmpDir(originalProjectDir)
orCreateProjectDir
}
protected open fun copyTestDataToTmpDir(testDataDir: File): File {
assert(testDataDir.exists()) { "Cannot find source folder " + testDataDir.absolutePath }
val tmpDir = FileUtil.createTempDirectory("kjbtb-jps-build", null)
FileUtil.copyDir(testDataDir, tmpDir)
return tmpDir
}
override fun tearDown() {
workDir.deleteRecursively()
super.tearDown()
}
override fun doGetProjectDir(): File = workDir
annotation class WorkingDir(val name: String)
enum class LibraryDependency {
NONE,
JVM_MOCK_RUNTIME,
JVM_FULL_RUNTIME,
JS_STDLIB,
}
protected fun initProject(libraryDependency: LibraryDependency = LibraryDependency.NONE) {
addJdk(JDK_NAME)
loadProject(workDir.absolutePath + File.separator + PROJECT_NAME + ".ipr")
when (libraryDependency) {
LibraryDependency.NONE -> {}
LibraryDependency.JVM_MOCK_RUNTIME -> addKotlinMockRuntimeDependency()
LibraryDependency.JVM_FULL_RUNTIME -> addKotlinStdlibDependency()
LibraryDependency.JS_STDLIB -> addKotlinJavaScriptStdlibDependency()
}
}
companion object {
const val JDK_NAME = "IDEA_JDK"
const val PROJECT_NAME = "kotlinProject"
@JvmStatic
protected fun assertFilesExistInOutput(module: JpsModule, vararg relativePaths: String) {
for (path in relativePaths) {
val outputFile = findFileInOutputDir(module, path)
assertTrue("Output not written: " + outputFile.absolutePath + "\n Directory contents: \n" + dirContents(
outputFile.parentFile
), outputFile.exists())
}
}
@JvmStatic
protected fun findFileInOutputDir(module: JpsModule, relativePath: String): File {
val outputUrl = JpsJavaExtensionService.getInstance().getOutputUrl(module, false)
assertNotNull(outputUrl)
val outputDir = File(JpsPathUtil.urlToPath(outputUrl))
return File(outputDir, relativePath)
}
@JvmStatic
protected fun assertFilesNotExistInOutput(module: JpsModule, vararg relativePaths: String) {
val outputUrl = JpsJavaExtensionService.getInstance().getOutputUrl(module, false)
assertNotNull(outputUrl)
val outputDir = File(JpsPathUtil.urlToPath(outputUrl))
for (path in relativePaths) {
val outputFile = File(outputDir, path)
assertFalse("Output directory \"" + outputFile.absolutePath + "\" contains \"" + path + "\"", outputFile.exists())
}
}
private fun dirContents(dir: File): String {
val files = dir.listFiles() ?: return "<not found>"
val builder = StringBuilder()
for (file in files) {
builder.append(" * ").append(file.name).append("\n")
}
return builder.toString()
}
}
}
@@ -0,0 +1,159 @@
/*
* 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.jps.build
import org.jetbrains.jps.builders.JpsBuildTestCase
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.compilerRunner.JpsKotlinCompilerRunner
import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.daemon.common.isDaemonEnabled
import org.jetbrains.kotlin.jps.build.fixtures.EnableICFixture
import org.jetbrains.kotlin.jps.model.kotlinCommonCompilerArguments
import org.jetbrains.kotlin.jps.model.kotlinCompilerArguments
import java.io.File
import kotlin.reflect.KMutableProperty1
class KotlinJpsBuildTestIncremental : KotlinJpsBuildTest() {
private val enableICFixture = EnableICFixture()
override fun setUp() {
super.setUp()
enableICFixture.setUp()
}
override fun tearDown() {
enableICFixture.tearDown()
super.tearDown()
}
fun testKotlinJavaScriptChangePackage() {
initProject(LibraryDependency.JS_STDLIB)
buildAllModules().assertSuccessful()
val class2Kt = File(workDir, "src/Class2.kt")
val newClass2KtContent = class2Kt.readText().replace("package2", "package1")
JpsBuildTestCase.change(class2Kt.path, newClass2KtContent)
buildAllModules().assertSuccessful()
checkOutputFilesList(File(workDir, "out/production"))
}
fun testJpsDaemonIC() {
fun testImpl() {
assertTrue("Daemon was not enabled!", isDaemonEnabled())
doTest()
val module = myProject.modules.get(0)
val mainKtClassFile = findFileInOutputDir(module, "MainKt.class")
assertTrue("$mainKtClassFile does not exist!", mainKtClassFile.exists())
val fooKt = File(workDir, "src/Foo.kt")
JpsBuildTestCase.change(fooKt.path, null)
buildAllModules().assertSuccessful()
assertCompiled(KotlinBuilder.KOTLIN_BUILDER_NAME, "src/Foo.kt")
JpsBuildTestCase.change(fooKt.path, "class Foo(val x: Int = 0)")
buildAllModules().assertSuccessful()
assertCompiled(KotlinBuilder.KOTLIN_BUILDER_NAME, "src/main.kt", "src/Foo.kt")
}
withDaemon {
withSystemProperty(JpsKotlinCompilerRunner.FAIL_ON_FALLBACK_PROPERTY, "true") {
testImpl()
}
}
}
fun testManyFiles() {
doTest()
val module = myProject.modules.get(0)
assertFilesExistInOutput(module, "foo/MainKt.class", "boo/BooKt.class", "foo/Bar.class")
checkWhen(touch("src/main.kt"), null, packageClasses("kotlinProject", "src/main.kt", "foo.MainKt"))
checkWhen(touch("src/boo.kt"), null, packageClasses("kotlinProject", "src/boo.kt", "boo.BooKt"))
checkWhen(touch("src/Bar.kt"), arrayOf("src/Bar.kt"), arrayOf(module("kotlinProject"), klass("kotlinProject", "foo.Bar")))
checkWhen(del("src/main.kt"),
pathsToCompile = null,
pathsToDelete = packageClasses("kotlinProject", "src/main.kt", "foo.MainKt"))
assertFilesExistInOutput(module, "boo/BooKt.class", "foo/Bar.class")
assertFilesNotExistInOutput(module, "foo/MainKt.class")
checkWhen(touch("src/boo.kt"), null, packageClasses("kotlinProject", "src/boo.kt", "boo.BooKt"))
checkWhen(touch("src/Bar.kt"), null, arrayOf(module("kotlinProject"), klass("kotlinProject", "foo.Bar")))
}
fun testManyFilesForPackage() {
doTest()
val module = myProject.modules.get(0)
assertFilesExistInOutput(module, "foo/MainKt.class", "boo/BooKt.class", "foo/Bar.class")
checkWhen(touch("src/main.kt"), null, packageClasses("kotlinProject", "src/main.kt", "foo.MainKt"))
checkWhen(touch("src/boo.kt"), null, packageClasses("kotlinProject", "src/boo.kt", "boo.BooKt"))
checkWhen(touch("src/Bar.kt"),
arrayOf("src/Bar.kt"),
arrayOf(klass("kotlinProject", "foo.Bar"),
packagePartClass("kotlinProject", "src/Bar.kt", "foo.MainKt"),
module("kotlinProject")))
checkWhen(del("src/main.kt"),
pathsToCompile = null,
pathsToDelete = packageClasses("kotlinProject", "src/main.kt", "foo.MainKt"))
assertFilesExistInOutput(module, "boo/BooKt.class", "foo/Bar.class")
checkWhen(touch("src/boo.kt"), null, packageClasses("kotlinProject", "src/boo.kt", "boo.BooKt"))
checkWhen(touch("src/Bar.kt"), null,
arrayOf(klass("kotlinProject", "foo.Bar"),
packagePartClass("kotlinProject", "src/Bar.kt", "foo.MainKt"),
module("kotlinProject")))
}
@WorkingDir("LanguageOrApiVersionChanged")
fun testLanguageVersionChanged() {
languageOrApiVersionChanged(CommonCompilerArguments::languageVersion)
}
@WorkingDir("LanguageOrApiVersionChanged")
fun testApiVersionChanged() {
languageOrApiVersionChanged(CommonCompilerArguments::apiVersion)
}
private fun languageOrApiVersionChanged(versionProperty: KMutableProperty1<CommonCompilerArguments, String?>) {
initProject(LibraryDependency.JVM_MOCK_RUNTIME)
assertEquals(1, myProject.modules.size)
val module = myProject.modules.first()
val args = module.kotlinCompilerArguments
fun setVersion(newVersion: String) {
versionProperty.set(args, newVersion)
myProject.kotlinCommonCompilerArguments = args
}
assertNull(args.apiVersion)
buildAllModules().assertSuccessful()
setVersion(LanguageVersion.LATEST_STABLE.versionString)
buildAllModules().assertSuccessful()
assertCompiled(KotlinBuilder.KOTLIN_BUILDER_NAME)
setVersion(LanguageVersion.KOTLIN_1_3.versionString)
buildAllModules().assertSuccessful()
assertCompiled(KotlinBuilder.KOTLIN_BUILDER_NAME, "src/Bar.kt", "src/Foo.kt")
}
}
@@ -0,0 +1,50 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build
import org.jetbrains.jps.model.JpsProject
import org.jetbrains.jps.model.java.JpsJavaLibraryType
import org.jetbrains.jps.model.library.JpsLibrary
import org.jetbrains.jps.model.library.JpsOrderRootType
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
import org.jetbrains.kotlin.utils.PathUtil
import java.io.File
enum class KotlinJpsLibrary(val id: String, vararg val roots: File) {
MockRuntime(
"kotlin-mock-runtime",
ForTestCompileRuntime.minimalRuntimeJarForTests()
),
JvmStdLib(
"kotlin-stdlib",
PathUtil.kotlinPathsForDistDirectory.stdlibPath,
File(PathUtil.kotlinPathsForDistDirectory.libPath, "annotations-13.0.jar")
),
JvmTest(
"kotlin-test",
PathUtil.kotlinPathsForDistDirectory.kotlinTestPath
),
JsStdLib(
"KotlinJavaScript",
PathUtil.kotlinPathsForDistDirectory.jsStdLibJarPath
),
JsTest(
"KotlinJavaScriptTest",
PathUtil.kotlinPathsForDistDirectory.jsKotlinTestJarPath
);
fun create(project: JpsProject): JpsLibrary {
val library = project.addLibrary(id, JpsJavaLibraryType.INSTANCE)
for (fileRoot in roots) {
library.addRoot(fileRoot, JpsOrderRootType.COMPILED)
}
return library
}
}
@@ -0,0 +1,49 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build
import com.intellij.util.concurrency.FixedFuture
import org.jetbrains.jps.builders.java.dependencyView.Callbacks
import org.jetbrains.kotlin.incremental.isJavaFile
import java.io.File
import java.util.concurrent.Future
/**
* Mocks Intellij Java constant search.
* When JPS is run from Intellij, it sends find usages request to IDE (it only searches for references inside Java files).
*
* We rely on heuristics instead of precise usages search.
* A Java file is considered affected if:
* 1. It contains changed field name as a content substring.
* 2. Its simple file name is not equal to a field's owner class simple name (to avoid recompiling field's declaration again)
*/
class MockJavaConstantSearch(private val workDir: File) :
Callbacks.ConstantAffectionResolver {
override fun request(
ownerClassName: String,
fieldName: String,
accessFlags: Int,
fieldRemoved: Boolean,
accessChanged: Boolean
): Future<Callbacks.ConstantAffection> {
fun File.isAffected(): Boolean {
if (!isJavaFile()) return false
if (nameWithoutExtension == ownerClassName.substringAfterLast(".")) return false
val code = readText()
return code.contains(fieldName)
}
val affectedJavaFiles = workDir.walk().filter(File::isAffected).toList()
return FixedFuture(
Callbacks.ConstantAffection(
affectedJavaFiles
)
)
}
}
@@ -0,0 +1,456 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class MultiplatformJpsTestWithGeneratedContentGenerated extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInMultiplatformMultiModule() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ignoreAndWarnAboutNative")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class IgnoreAndWarnAboutNative extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInIgnoreAndWarnAboutNative() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ignoreAndWarnAboutNative"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("editingCKotlin")
public void testEditingCKotlin() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ignoreAndWarnAboutNative/editingCKotlin/");
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ignoreAndWarnAboutNative/editingCKotlin")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingCKotlin extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInEditingCKotlin() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ignoreAndWarnAboutNative/editingCKotlin"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simple")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Simple extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSimple() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simple"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("editingCKotlin")
public void testEditingCKotlin() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simple/editingCKotlin/");
}
@TestMetadata("editingPJsKotlin")
public void testEditingPJsKotlin() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simple/editingPJsKotlin/");
}
@TestMetadata("editingPJvmJava")
public void testEditingPJvmJava() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simple/editingPJvmJava/");
}
@TestMetadata("editingPJvmKotlin")
public void testEditingPJvmKotlin() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simple/editingPJvmKotlin/");
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simple/editingCKotlin")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingCKotlin extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInEditingCKotlin() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simple/editingCKotlin"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simple/editingPJsKotlin")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingPJsKotlin extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInEditingPJsKotlin() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simple/editingPJsKotlin"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simple/editingPJvmJava")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingPJvmJava extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInEditingPJvmJava() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simple/editingPJvmJava"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simple/editingPJvmKotlin")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingPJvmKotlin extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInEditingPJvmKotlin() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simple/editingPJvmKotlin"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simpleJsJvmProjectWithTests")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SimpleJsJvmProjectWithTests extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSimpleJsJvmProjectWithTests() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simpleJsJvmProjectWithTests"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("editingCMainExpectActual")
public void testEditingCMainExpectActual() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simpleJsJvmProjectWithTests/editingCMainExpectActual/");
}
@TestMetadata("editingCTestsExpectActual")
public void testEditingCTestsExpectActual() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simpleJsJvmProjectWithTests/editingCTestsExpectActual/");
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simpleJsJvmProjectWithTests/editingCMainExpectActual")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingCMainExpectActual extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInEditingCMainExpectActual() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simpleJsJvmProjectWithTests/editingCMainExpectActual"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simpleJsJvmProjectWithTests/editingCTestsExpectActual")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingCTestsExpectActual extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInEditingCTestsExpectActual() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simpleJsJvmProjectWithTests/editingCTestsExpectActual"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simpleNewMpp")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SimpleNewMpp extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSimpleNewMpp() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simpleNewMpp"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("editingCKotlin")
public void testEditingCKotlin() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simpleNewMpp/editingCKotlin/");
}
@TestMetadata("editingPJsKotlin")
public void testEditingPJsKotlin() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simpleNewMpp/editingPJsKotlin/");
}
@TestMetadata("editingPJvmJava")
public void testEditingPJvmJava() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simpleNewMpp/editingPJvmJava/");
}
@TestMetadata("editingPJvmKotlin")
public void testEditingPJvmKotlin() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simpleNewMpp/editingPJvmKotlin/");
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simpleNewMpp/editingCKotlin")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingCKotlin extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInEditingCKotlin() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simpleNewMpp/editingCKotlin"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simpleNewMpp/editingPJsKotlin")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingPJsKotlin extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInEditingPJsKotlin() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simpleNewMpp/editingPJsKotlin"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simpleNewMpp/editingPJvmJava")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingPJvmJava extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInEditingPJvmJava() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simpleNewMpp/editingPJvmJava"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simpleNewMpp/editingPJvmKotlin")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingPJvmKotlin extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInEditingPJvmKotlin() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/simpleNewMpp/editingPJvmKotlin"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Ultimate extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInUltimate() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("editingACommonExpectActual")
public void testEditingACommonExpectActual() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingACommonExpectActual/");
}
@TestMetadata("editingAJsClientKotlin")
public void testEditingAJsClientKotlin() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingAJsClientKotlin/");
}
@TestMetadata("editingAJvmClientJava")
public void testEditingAJvmClientJava() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingAJvmClientJava/");
}
@TestMetadata("editingAJvmClientKotlin")
public void testEditingAJvmClientKotlin() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingAJvmClientKotlin/");
}
@TestMetadata("editingBCommonExpectActual")
public void testEditingBCommonExpectActual() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingBCommonExpectActual/");
}
@TestMetadata("editingRJsKotlin")
public void testEditingRJsKotlin() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingRJsKotlin/");
}
@TestMetadata("editingRJvmKotlin")
public void testEditingRJvmKotlin() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingRJvmKotlin/");
}
@TestMetadata("editingRaJsKotlin")
public void testEditingRaJsKotlin() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingRaJsKotlin/");
}
@TestMetadata("editingRaJvmKotlin")
public void testEditingRaJvmKotlin() throws Exception {
runTest("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingRaJvmKotlin/");
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingACommonExpectActual")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingACommonExpectActual extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInEditingACommonExpectActual() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingACommonExpectActual"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingAJsClientKotlin")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingAJsClientKotlin extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInEditingAJsClientKotlin() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingAJsClientKotlin"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingAJvmClientJava")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingAJvmClientJava extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInEditingAJvmClientJava() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingAJvmClientJava"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingAJvmClientKotlin")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingAJvmClientKotlin extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInEditingAJvmClientKotlin() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingAJvmClientKotlin"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingBCommonExpectActual")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingBCommonExpectActual extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInEditingBCommonExpectActual() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingBCommonExpectActual"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingRJsKotlin")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingRJsKotlin extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInEditingRJsKotlin() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingRJsKotlin"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingRJvmKotlin")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingRJvmKotlin extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInEditingRJvmKotlin() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingRJvmKotlin"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingRaJsKotlin")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingRaJsKotlin extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInEditingRaJsKotlin() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingRaJsKotlin"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingRaJvmKotlin")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingRaJvmKotlin extends AbstractMultiplatformJpsTestWithGeneratedContent {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInEditingRaJvmKotlin() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/multiModule/multiplatform/withGeneratedContent/ultimate/editingRaJvmKotlin"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
}
}
@@ -0,0 +1,152 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build
import org.jetbrains.jps.builders.*
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor
import org.jetbrains.jps.cmdline.ProjectDescriptor
import org.jetbrains.jps.incremental.ModuleBuildTarget
import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot
import org.jetbrains.kotlin.incremental.KOTLIN_CACHE_DIRECTORY_NAME
import org.jetbrains.kotlin.incremental.testingUtils.assertEqualDirectories
import org.jetbrains.kotlin.jps.build.fixtures.EnableICFixture
import org.jetbrains.kotlin.jps.incremental.KotlinDataContainerTarget
import java.io.File
import kotlin.io.path.ExperimentalPathApi
import kotlin.io.path.createTempDirectory
import kotlin.reflect.KFunction1
class RelocatableJpsCachesTest : BaseKotlinJpsBuildTestCase() {
private val enableICFixture = EnableICFixture()
private lateinit var workingDir: File
@OptIn(ExperimentalPathApi::class)
override fun setUp() {
super.setUp()
enableICFixture.setUp()
workingDir = createTempDirectory("RelocatableJpsCachesTest-" + getTestName(false)).toFile()
}
override fun tearDown() {
workingDir.deleteRecursively()
enableICFixture.tearDown()
super.tearDown()
}
fun testRelocatableCaches() {
buildTwiceAndCompare(RelocatableCacheTestCase::testRelocatableCaches)
}
private fun buildTwiceAndCompare(testMethod: KFunction1<RelocatableCacheTestCase, Unit>) {
val test1WorkingDir = workingDir.resolve("test1")
val test1KotlinCachesDir = workingDir.resolve("test1KotlinCaches")
val test2WorkingDir = workingDir.resolve("test2")
val test2KotlinCachesDir = workingDir.resolve("test2KotlinCaches")
runTestAndCopyKotlinCaches(test1WorkingDir, test1KotlinCachesDir, testMethod)
runTestAndCopyKotlinCaches(test2WorkingDir, test2KotlinCachesDir, testMethod)
assertEqualDirectories(test1KotlinCachesDir, test2KotlinCachesDir, forgiveExtraFiles = false)
}
private fun runTestAndCopyKotlinCaches(
projectWorkingDir: File,
dirToCopyKotlinCaches: File,
testMethod: KFunction1<RelocatableCacheTestCase, Unit>
) {
val testCase = object : RelocatableCacheTestCase(
projectWorkingDir = projectWorkingDir,
dirToCopyKotlinCaches = dirToCopyKotlinCaches
) {
override fun getName(): String = testMethod.name
}
testCase.exposedPrivateApi.setUp()
try {
testMethod.call(testCase)
} finally {
testCase.exposedPrivateApi.tearDown()
}
}
}
// the class should not be executed directly (hence it's abstract)
abstract class RelocatableCacheTestCase(
private val projectWorkingDir: File,
private val dirToCopyKotlinCaches: File
) : KotlinJpsBuildTestBase() {
val exposedPrivateApi = ExposedPrivateApi()
fun testRelocatableCaches() {
initProject(LibraryDependency.JVM_FULL_RUNTIME)
buildAllModules().assertSuccessful()
assertFilesExistInOutput(
myProject.modules.single(),
"MainKt.class", "Foo.class", "FooChild.class", "utils/Utils.class"
)
}
override fun copyTestDataToTmpDir(testDataDir: File): File {
testDataDir.copyRecursively(projectWorkingDir)
return projectWorkingDir
}
override fun doBuild(descriptor: ProjectDescriptor, scopeBuilder: CompileScopeTestBuilder?): BuildResult =
super.doBuild(descriptor, scopeBuilder).also {
copyKotlinCaches(descriptor)
}
private fun copyKotlinCaches(descriptor: ProjectDescriptor) {
val kotlinDataPaths = HashSet<File>()
val dataPaths = descriptor.dataManager.dataPaths
kotlinDataPaths.add(dataPaths.getTargetDataRoot(KotlinDataContainerTarget))
for (target in descriptor.buildTargetIndex.allTargets) {
if (!target.isKotlinTarget(descriptor)) continue
val targetDataRoot = descriptor.dataManager.dataPaths.getTargetDataRoot(target)
val kotlinDataRoot = targetDataRoot.resolve(KOTLIN_CACHE_DIRECTORY_NAME)
assert(kotlinDataRoot.isDirectory) { "Kotlin data root '$kotlinDataRoot' is not a directory" }
kotlinDataPaths.add(kotlinDataRoot)
}
dirToCopyKotlinCaches.deleteRecursively()
val originalStorageRoot = descriptor.dataManager.dataPaths.dataStorageRoot
for (kotlinCacheRoot in kotlinDataPaths) {
val relativePath = kotlinCacheRoot.relativeTo(originalStorageRoot).path
val targetDir = dirToCopyKotlinCaches.resolve(relativePath)
targetDir.parentFile.mkdirs()
kotlinCacheRoot.copyRecursively(targetDir)
}
}
private fun BuildTarget<*>.isKotlinTarget(descriptor: ProjectDescriptor): Boolean {
fun JavaSourceRootDescriptor.containsKotlinSources() = root.walk().any { it.isKotlinSourceFile }
if (this !is ModuleBuildTarget) return false
val rootDescriptors = computeRootDescriptors(
descriptor.model,
descriptor.moduleExcludeIndex,
descriptor.ignoredFileIndex,
descriptor.dataManager.dataPaths
)
return rootDescriptors.any { it is JavaSourceRootDescriptor && it.containsKotlinSources() }
}
// the famous Public Morozov pattern
inner class ExposedPrivateApi {
fun setUp() {
this@RelocatableCacheTestCase.setUp()
}
fun tearDown() {
this@RelocatableCacheTestCase.tearDown()
}
}
}
@@ -0,0 +1,89 @@
/*
* 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.jps.build
import com.intellij.util.PathUtil
import org.jetbrains.jps.model.java.JpsJavaExtensionService
import org.jetbrains.kotlin.cli.common.CompilerSystemProperties
import org.jetbrains.kotlin.compilerRunner.JpsKotlinCompilerRunner
import org.jetbrains.kotlin.daemon.common.OSKind
import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File
class SimpleKotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() {
override fun setUp() {
super.setUp()
workDir = KotlinTestUtils.tmpDirForTest(this)
}
fun testLoadingKotlinFromDifferentModules() {
val aFile = createFile("m1/K.kt",
"""
package m1;
interface K {
}
""")
createFile("m1/J.java",
"""
package m1;
public interface J {
K bar();
}
""")
val a = addModule("m1", PathUtil.getParentPath(aFile))
val bFile = createFile("m2/m2.kt",
"""
import m1.J;
import m1.K;
interface M2: J {
override fun bar(): K
}
""")
val b = addModule("b", PathUtil.getParentPath(bFile))
JpsJavaExtensionService.getInstance().getOrCreateDependencyExtension(
b.dependenciesList.addModuleDependency(a)
).isExported = false
addKotlinStdlibDependency()
rebuildAllModules()
}
// TODO: add JS tests
fun testDaemon() {
withDaemon {
withSystemProperty(CompilerSystemProperties.COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY.property, "true") {
withSystemProperty(JpsKotlinCompilerRunner.FAIL_ON_FALLBACK_PROPERTY, "true") {
testLoadingKotlinFromDifferentModules()
}
}
}
}
}
// copied from CompilerDaemonTest.kt
// TODO: find shared place for this function
// java.util.Logger used in the daemon silently forgets to log into a file specified in the config on Windows,
// if file path is given in windows form (using backslash as a separator); the reason is unknown
// this function makes a path with forward slashed, that works on windows too
internal val File.loggerCompatiblePath: String
get() =
if (OSKind.current == OSKind.Windows) absolutePath.replace('\\', '/')
else absolutePath
@@ -0,0 +1,329 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build.dependeciestxt
import org.jetbrains.jps.model.java.JpsJavaDependencyScope
import org.jetbrains.jps.model.module.JpsModule
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2MetadataCompilerArguments
import org.jetbrains.kotlin.config.CompilerSettings
import org.jetbrains.kotlin.config.KotlinFacetSettings
import org.jetbrains.kotlin.config.KotlinModuleKind.COMPILATION_AND_SOURCE_SET_HOLDER
import org.jetbrains.kotlin.config.KotlinModuleKind.SOURCE_SET_HOLDER
import org.jetbrains.kotlin.jps.build.dependeciestxt.ModulesTxt.Dependency.Kind.*
import org.jetbrains.kotlin.platform.CommonPlatforms
import org.jetbrains.kotlin.platform.impl.FakeK2NativeCompilerArguments
import org.jetbrains.kotlin.platform.isCommon
import org.jetbrains.kotlin.platform.js.JsPlatforms
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlin.platform.konan.NativePlatforms
import java.io.File
import kotlin.reflect.KMutableProperty1
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.full.memberProperties
/**
* Modules description file.
* See [README.md] for more details.
*/
data class ModulesTxt(
val muted: Boolean,
val file: File,
val fileName: String,
val modules: List<Module>,
val dependencies: List<Dependency>
) {
override fun toString() = fileName
data class Module(val name: String) {
var index: Int = -1
val indexedName
get() = "${index.toString().padStart(2, '0')}_$name"
/**
* Facet should not be created for old tests
*/
var kotlinFacetSettings: KotlinFacetSettings? = null
val dependencies = mutableListOf<Dependency>()
val usages = mutableListOf<Dependency>()
val isCommonModule
get() =
kotlinFacetSettings?.targetPlatform.isCommon() ||
kotlinFacetSettings?.kind == SOURCE_SET_HOLDER
val isJvmModule
get() = kotlinFacetSettings?.targetPlatform.isJvm()
val expectedBy
get() = dependencies.filter {
it.kind == EXPECTED_BY ||
it.kind == INCLUDE
}
@Flag
var edit: Boolean = false
@Flag
var editJvm: Boolean = false
@Flag
var editExpectActual: Boolean = false
lateinit var jpsModule: JpsModule
companion object {
val flags: Map<String, KMutableProperty1<Module, Boolean>> = Module::class.memberProperties
.filter { it.findAnnotation<Flag>() != null }
.filterIsInstance<KMutableProperty1<Module, Boolean>>()
.associateBy { it.name }
}
}
annotation class Flag
data class Dependency(
val from: Module,
val to: Module,
val scope: JpsJavaDependencyScope,
val kind: Kind,
val exported: Boolean
) {
val effectivelyExported
get() = kind == EXPECTED_BY || exported
init {
from.dependencies.add(this)
to.usages.add(this)
}
enum class Kind {
DEPENDENCY,
EXPECTED_BY,
INCLUDE
}
}
}
class ModulesTxtBuilder {
var muted = false
val modules = mutableMapOf<String, ModuleRef>()
private val dependencies = mutableListOf<DependencyBuilder>()
/**
* Reference to module which can be defined later
*/
class ModuleRef(name: String) {
var defined: Boolean = false
var actual: ModulesTxt.Module = ModulesTxt.Module(name)
override fun toString() = actual.name
fun build(index: Int): ModulesTxt.Module {
val result = actual
result.index = index
val kotlinFacetSettings = result.kotlinFacetSettings
if (kotlinFacetSettings != null) {
kotlinFacetSettings.implementedModuleNames =
result.dependencies.asSequence()
.filter { it.kind == EXPECTED_BY }
.map { it.to.name }
.toList()
kotlinFacetSettings.sourceSetNames =
result.dependencies.asSequence()
.filter { it.kind == INCLUDE }
.map { it.to.name }
.toList()
}
return result
}
}
/**
* Temporary object for resolving references to modules.
*/
data class DependencyBuilder(
val from: ModuleRef,
val to: ModuleRef,
val scope: JpsJavaDependencyScope,
val kind: ModulesTxt.Dependency.Kind,
val exported: Boolean
) {
fun build(): ModulesTxt.Dependency {
when (kind) {
DEPENDENCY -> Unit
EXPECTED_BY -> check(to.actual.isCommonModule) {
"$this: ${to.actual} is not common module"
}
INCLUDE -> check(to.actual.kotlinFacetSettings?.kind == SOURCE_SET_HOLDER) {
"$this: ${to.actual} is not source set holder"
}
}
return ModulesTxt.Dependency(from.actual, to.actual, scope, kind, exported)
}
}
fun readFile(file: File, fileTitle: String = file.toString()): ModulesTxt {
try {
file.forEachLine { line ->
parseDeclaration(line)
}
// dependencies need to be build first: module.build() requires it
val dependencies = dependencies.map { it.build() }
val modules = modules.values.mapIndexed { index, moduleRef -> moduleRef.build(index) }
return ModulesTxt(muted, file, fileTitle, modules, dependencies)
} catch (t: Throwable) {
throw Error("Error while reading $file: ${t.message}", t)
}
}
private fun parseDeclaration(line: String) = doParseDeclaration(removeComments(line))
private fun removeComments(line: String) = line.split("//", limit = 2)[0].trim()
private fun doParseDeclaration(line: String) {
when {
line.isEmpty() -> Unit // skip empty lines
line == "MUTED" -> {
muted = true
}
line.contains("->") -> {
val (from, rest) = line.split("->", limit = 2)
if (rest.isBlank()) {
// `name -> ` - module
newModule(ValueWithFlags(from))
} else {
val (to, flags) = parseValueWithFlags(rest.trim())
newDependency(from.trim(), to.trim(), flags) // `from -> to [flag1, flag2, ...]` - dependency
}
}
else -> newModule(parseValueWithFlags(line)) // `name [flag1, flag2, ...]` - module
}
}
/**
* `value [flag1, flag2, ...]`
*/
private fun parseValueWithFlags(str: String): ValueWithFlags {
val parts = str.split("[", limit = 2)
return if (parts.size > 1) {
val (value, flags) = parts
ValueWithFlags(
value = value.trim(),
flags = flags.trim()
.removeSuffix("]")
.split(",")
.map { it.trim() }
.filter { it.isNotEmpty() }
.toSet()
)
} else ValueWithFlags(str)
}
data class ValueWithFlags(val value: String, val flags: Set<String> = setOf())
private fun moduleRef(name: String) =
modules.getOrPut(name) { ModuleRef(name) }
private fun newModule(def: ValueWithFlags): ModulesTxt.Module {
val name = def.value.trim()
val module = ModulesTxt.Module(name)
val settings = KotlinFacetSettings()
module.kotlinFacetSettings = settings
settings.useProjectSettings = false
settings.compilerSettings = CompilerSettings().also {
it.additionalArguments = "-version -Xmulti-platform"
}
val moduleRef = moduleRef(name)
check(!moduleRef.defined) { "Module `$name` already defined" }
moduleRef.defined = true
moduleRef.actual = module
def.flags.forEach { flag ->
when (flag) {
"sourceSetHolder" -> settings.kind = SOURCE_SET_HOLDER
"compilationAndSourceSetHolder" -> settings.kind = COMPILATION_AND_SOURCE_SET_HOLDER
"common" -> settings.compilerArguments =
K2MetadataCompilerArguments().also { settings.targetPlatform = CommonPlatforms.defaultCommonPlatform }
"jvm" -> settings.compilerArguments =
K2JVMCompilerArguments().also { settings.targetPlatform = JvmPlatforms.defaultJvmPlatform }
"js" -> settings.compilerArguments =
K2JSCompilerArguments().also { settings.targetPlatform = JsPlatforms.defaultJsPlatform }
"native" -> settings.compilerArguments =
FakeK2NativeCompilerArguments().also { settings.targetPlatform = NativePlatforms.unspecifiedNativePlatform }
else -> {
val flagProperty = ModulesTxt.Module.flags[flag]
if (flagProperty != null) flagProperty.set(module, true)
else error("Unknown module flag `$flag`")
}
}
}
return module
}
private fun newDependency(from: String, to: String, flags: Set<String>): DependencyBuilder? {
if (to.isEmpty()) {
// `x -> ` should just create undefined module `x`
moduleRef(from)
check(flags.isEmpty()) {
"`name -> [flag1, flag2, ...]` - not allowed due to the ambiguity of belonging to modules/dependencies. " +
"Please use `x [attrs...]` syntax for module attributes."
}
return null
} else {
var exported = false
var scope: JpsJavaDependencyScope? = null
var kind: ModulesTxt.Dependency.Kind = DEPENDENCY
fun setScope(newScope: JpsJavaDependencyScope) {
check(scope == null) { "`$this: $from -> $to` dependency is already flagged as $scope" }
scope = newScope
}
fun setKind(newKind: ModulesTxt.Dependency.Kind) {
check(kind == DEPENDENCY) { "`$this: $from -> $to` dependency is already flagged as $kind" }
kind = newKind
}
flags.forEach { flag ->
when (flag) {
"exported" -> exported = true
"compile" -> setScope(JpsJavaDependencyScope.COMPILE)
"test" -> setScope(JpsJavaDependencyScope.TEST)
"runtime" -> setScope(JpsJavaDependencyScope.RUNTIME)
"provided" -> setScope(JpsJavaDependencyScope.PROVIDED)
"expectedBy" -> setKind(EXPECTED_BY)
"include" -> setKind(INCLUDE)
else -> error("Unknown dependency flag `$flag`")
}
}
return DependencyBuilder(
from = moduleRef(from),
to = moduleRef(to),
scope = scope ?: JpsJavaDependencyScope.COMPILE,
kind = kind,
exported = exported
).also {
dependencies.add(it)
}
}
}
}
@@ -0,0 +1,441 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build.dependeciestxt
import java.io.File
/**
* Utility for generating common/platform module stub contents based on it's dependencies.
*/
fun actualizeMppJpsIncTestCaseDirs(rootDir: String, dir: String) {
val rootDirFile = File("$rootDir/$dir")
check(rootDirFile.isDirectory) { "`$rootDirFile` is not a directory" }
rootDirFile.listFiles { it: File -> it.isDirectory }.forEach { dirFile ->
val dependenciesTxtFile = File(dirFile, "dependencies.txt")
if (dependenciesTxtFile.exists()) {
val fileTitle = "$dir/${dirFile.name}/dependencies.txt"
val dependenciesTxt = ModulesTxtBuilder().readFile(dependenciesTxtFile, fileTitle)
MppJpsIncTestsGenerator(dependenciesTxt) { File(dirFile, it.name) }
.actualizeTestCasesDirs(dirFile)
}
}
return
}
class MppJpsIncTestsGenerator(val txt: ModulesTxt, val testCaseDirProvider: (TestCase) -> File) {
val ModulesTxt.Module.capitalName get() = name.capitalize()
val testCases: List<TestCase>
init {
val testCases = mutableListOf<TestCase>()
txt.modules.forEach {
if (it.edit)
testCases.add(EditingTestCase(it, changeJavaClass = false))
if (it.editJvm && it.isJvmModule)
testCases.add(EditingTestCase(it, changeJavaClass = true))
if (it.editExpectActual && it.isCommonModule)
testCases.add(EditingExpectActualTestCase(it))
}
this.testCases = testCases
}
fun actualizeTestCasesDirs(rootDir: File) {
val requiredDirs = mutableSetOf<File>()
testCases.forEach {
val dir = it.dir
check(requiredDirs.add(dir)) { "TestCase dir clash $dir" }
if (!dir.exists()) {
File(dir, "build.log").setFileContent("")
}
}
rootDir.listFiles().forEach {
if (it.isDirectory && it !in requiredDirs) {
it.deleteRecursively()
}
}
}
/**
* Set required content for [this] [File].
*/
fun File.setFileContent(content: String) {
check(!exists()) {
"File `$this` already exists," +
"\n\n============= contents ============\n" +
readText() +
"\n===================================\n" +
"\n============ new content ==========\n" +
content +
"\n===================================\n"
}
parentFile.mkdirs()
writeText(content)
}
data class ModuleContentSettings(
val module: ModulesTxt.Module,
val serviceNameSuffix: String = "",
val generateActualDeclarationsFor: List<ModulesTxt.Module> = module.expectedBy.map { it.to },
val generatePlatformDependent: Boolean = true,
var generateKtFile: Boolean = true,
var generateJavaFile: Boolean = true
)
inner class EditingTestCase(val module: ModulesTxt.Module, val changeJavaClass: Boolean) : TestCase() {
override val name: String =
if (changeJavaClass) "editing${module.capitalName}Java"
else "editing${module.capitalName}Kotlin"
override val dir: File = testCaseDirProvider(this)
override fun generate() {
generateBaseContent()
// create new file with service implementation
// don't create expect/actual functions (generatePlatformDependent = false)
module.contentsSettings = ModuleContentSettings(
module,
serviceNameSuffix = "New",
generatePlatformDependent = false,
generateKtFile = !changeJavaClass,
generateJavaFile = changeJavaClass
)
when {
module.isCommonModule -> {
step("create new service") {
generateCommonFile(
module,
fileNameSuffix = ".new.$step"
)
}
step("edit new service") {
generateCommonFile(
module,
fileNameSuffix = ".touch.$step"
)
}
step("delete new service") {
serviceKtFile(
module,
fileNameSuffix = ".delete.$step"
).setFileContent("")
}
}
else -> {
step("create new service") {
// generateKtFile event if changeJavaClass requested (for test calling java from kotlin)
val prevModuleContentsSettings = module.contentsSettings
module.contentsSettings = module.contentsSettings.copy(generateKtFile = true)
generatePlatformFile(
module,
fileNameSuffix = ".new.$step"
)
module.contentsSettings = prevModuleContentsSettings
}
step("edit new service") {
generatePlatformFile(
module,
fileNameSuffix = ".touch.$step"
)
}
step("delete new service") {
if (changeJavaClass) serviceJavaFile(module, fileNameSuffix = ".delete.$step").setFileContent("")
// kotlin file also created for testing java class
serviceKtFile(module, fileNameSuffix = ".delete.$step").setFileContent("")
}
}
}
generateStepsTxt()
}
}
inner class EditingExpectActualTestCase(val commonModule: ModulesTxt.Module) : TestCase() {
override val name: String = "editing${commonModule.capitalName}ExpectActual"
override val dir: File = testCaseDirProvider(this)
override fun generate() {
generateBaseContent()
check(commonModule.isCommonModule)
val implModules = commonModule.usages
.asSequence()
.filter {
it.kind == ModulesTxt.Dependency.Kind.EXPECTED_BY ||
it.kind == ModulesTxt.Dependency.Kind.INCLUDE
}
.map { it.from }
commonModule.contentsSettings = ModuleContentSettings(commonModule, serviceNameSuffix = "New")
implModules.forEach { implModule ->
implModule.contentsSettings = ModuleContentSettings(
implModule,
serviceNameSuffix = "New",
generateActualDeclarationsFor = listOf(commonModule)
)
}
step("create new service in ${commonModule.name}") {
generateCommonFile(commonModule, fileNameSuffix = ".new.$step")
}
implModules.forEach { implModule ->
step("create new service in ${implModule.name}") {
generatePlatformFile(implModule, fileNameSuffix = ".new.$step")
}
}
step("change new service in ${commonModule.name}") {
generateCommonFile(commonModule, fileNameSuffix = ".touch.$step")
}
implModules.forEach { implModule ->
if (implModule.isJvmModule) {
implModule.contentsSettings.generateKtFile = false
implModule.contentsSettings.generateJavaFile = true
step("change new service in ${implModule.name}: java") {
generatePlatformFile(implModule, fileNameSuffix = ".touch.$step")
}
implModule.contentsSettings.generateKtFile = true
implModule.contentsSettings.generateJavaFile = false
step("change new service in ${implModule.name}: kotlin") {
generatePlatformFile(implModule, fileNameSuffix = ".touch.$step")
}
} else {
step("change new service in ${implModule.name}") {
generatePlatformFile(implModule, fileNameSuffix = ".touch.$step")
}
}
}
implModules.forEach { implModule ->
step("delete new service in ${implModule.name}") {
serviceKtFile(implModule, fileNameSuffix = ".delete.$step").setFileContent("")
}
}
step("delete new service in ${commonModule.name}") {
serviceKtFile(commonModule, fileNameSuffix = ".delete.$step").setFileContent("")
}
generateStepsTxt()
}
}
abstract inner class TestCase() {
abstract val name: String
abstract fun generate()
abstract val dir: File
private val modules = mutableMapOf<ModulesTxt.Module, ModuleContentSettings>()
var step = 1
val steps = mutableListOf<String>()
protected inline fun step(name: String, body: () -> Unit) {
body()
steps.add(name)
step++
}
var ModulesTxt.Module.contentsSettings: ModuleContentSettings
get() = modules.getOrPut(this) { ModuleContentSettings(this) }
set(value) {
modules[this] = value
}
protected fun generateStepsTxt() {
File(dir, "_steps.txt").setFileContent(steps.joinToString("\n"))
}
fun generateBaseContent() {
dir.mkdir()
txt.modules.forEach {
generateModuleContents(it)
}
}
private fun generateModuleContents(module: ModulesTxt.Module) {
when {
module.isCommonModule -> {
// common module
generateCommonFile(module)
}
module.expectedBy.isEmpty() -> {
// regular module
generatePlatformFile(module)
}
else -> {
// common module platform implementation
generatePlatformFile(module)
}
}
}
private val ModulesTxt.Module.serviceName
get() = "$capitalName${contentsSettings.serviceNameSuffix}"
private val ModulesTxt.Module.javaClassName
get() = "${serviceName}JavaClass"
protected fun serviceKtFile(module: ModulesTxt.Module, fileNameSuffix: String = ""): File {
val suffix =
if (module.isCommonModule) "${module.serviceName}Header"
else "${module.name.capitalize()}${module.contentsSettings.serviceNameSuffix}Impl"
return File(dir, "${module.indexedName}_service$suffix.kt$fileNameSuffix")
}
fun serviceJavaFile(module: ModulesTxt.Module, fileNameSuffix: String = ""): File {
return File(dir, "${module.indexedName}_${module.javaClassName}.java$fileNameSuffix")
}
private val ModulesTxt.Module.platformDependentFunName: String
get() {
check(isCommonModule)
return "${name}_platformDependent$serviceName"
}
private val ModulesTxt.Module.platformIndependentFunName: String
get() {
check(isCommonModule)
return "${name}_platformIndependent$serviceName"
}
private val ModulesTxt.Module.platformOnlyFunName: String
get() {
// platformOnly fun names already unique, so no module name prefix required
return "${name}_platformOnly${contentsSettings.serviceNameSuffix}"
}
protected fun generateCommonFile(
module: ModulesTxt.Module,
fileNameSuffix: String = ""
) {
val settings = module.contentsSettings
serviceKtFile(module, fileNameSuffix).setFileContent(buildString {
if (settings.generatePlatformDependent)
appendLine("expect fun ${module.platformDependentFunName}(): String")
appendLine("fun ${module.platformIndependentFunName}() = \"common$fileNameSuffix\"")
appendTestFun(module, settings)
})
}
protected fun generatePlatformFile(
module: ModulesTxt.Module,
fileNameSuffix: String = ""
) {
val isJvm = module.isJvmModule
val settings = module.contentsSettings
val javaClassName = module.javaClassName
if (settings.generateKtFile) {
serviceKtFile(module, fileNameSuffix).setFileContent(buildString {
if (settings.generatePlatformDependent) {
for (expectedBy in settings.generateActualDeclarationsFor) {
appendLine(
"actual fun ${expectedBy.platformDependentFunName}(): String" +
" = \"${module.name}$fileNameSuffix\""
)
}
}
appendLine(
"fun ${module.platformOnlyFunName}()" +
" = \"${module.name}$fileNameSuffix\""
)
appendTestFun(module, settings)
})
}
if (isJvm && settings.generateJavaFile) {
serviceJavaFile(module, fileNameSuffix).setFileContent(
"""
|public class $javaClassName {
| public String doStuff() {
| return "${module.name}$fileNameSuffix";
| }
|}
""".trimMargin()
)
}
}
// call all functions declared in this module and all of its dependencies recursively
private fun StringBuilder.appendTestFun(
module: ModulesTxt.Module,
settings: ModuleContentSettings
) {
appendLine()
appendLine("fun Test${module.serviceName}() {")
val thisAndDependencies = mutableSetOf(module)
module.collectDependenciesRecursivelyTo(thisAndDependencies)
thisAndDependencies.forEach { thisOrDependent ->
if (thisOrDependent.isCommonModule) {
appendLine(" ${thisOrDependent.platformIndependentFunName}()")
if (settings.generatePlatformDependent) {
appendLine(" ${thisOrDependent.platformDependentFunName}()")
}
} else {
// platform module
appendLine(" ${thisOrDependent.platformOnlyFunName}()")
if (thisOrDependent.isJvmModule && thisOrDependent.contentsSettings.generateJavaFile) {
appendLine(" ${thisOrDependent.javaClassName}().doStuff()")
}
}
}
appendLine("}")
}
private fun ModulesTxt.Module.collectDependenciesRecursivelyTo(
collection: MutableCollection<ModulesTxt.Module>,
exportedOnly: Boolean = false
) {
dependencies.forEach {
if (!exportedOnly || it.effectivelyExported) {
val dependentModule = it.to
collection.add(dependentModule)
dependentModule.collectDependenciesRecursivelyTo(collection, exportedOnly = true)
}
}
}
override fun toString() = name
}
}
@@ -0,0 +1,38 @@
Useful micro-language for concise description of project structure.
Mostly like the [DOT language](https://www.graphviz.org/doc/info/attrs.html).
## Example
```
c [common]
p1 [jvm]
p2 [jvm]
p1 -> c [expectedBy]
p2 -> c [expectedBy]
```
## Format
File contains declarations of modules and dependencies:
- Module: `module_name [flag1, key1=value1, ...]`
- Dependency: `source_module_name -> target_module_name [flag1, key1=value1, ...]`
Referring to undefined module is allowed (`jvm` module will be created at this case).
This modules can be defined after reference. Several declarations for same module is not allowed.
Supported module flags:
- `common` (old MPP)
- `sourceSetHolder`, `compilationAndSourceSetHolder` (new MPP)
- `jvm` (default)
- `js`
- `edit`, `editJvm`, `editExcpetActual` - see jps-plugin/testData/incremental/multiplatform/multiModule/README.md
Supported dependency flags:
- `compile` (default)
- `test`
- `runtime`
- `provided`
- `expectedBy` (old MPP)
- `included` (new MPP)
- `exproted`
@@ -0,0 +1,29 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build.fixtures
import org.jetbrains.kotlin.config.IncrementalCompilation
class EnableICFixture(
private val enableJvmIC: Boolean = true,
private val enableJsIC: Boolean = true
) {
private var isICEnabledBackup: Boolean = false
private var isICEnabledForJsBackup: Boolean = false
fun setUp() {
isICEnabledBackup = IncrementalCompilation.isEnabledForJvm()
IncrementalCompilation.setIsEnabledForJvm(enableJvmIC)
isICEnabledForJsBackup = IncrementalCompilation.isEnabledForJs()
IncrementalCompilation.setIsEnabledForJs(enableJsIC)
}
fun tearDown() {
IncrementalCompilation.setIsEnabledForJvm(isICEnabledBackup)
IncrementalCompilation.setIsEnabledForJs(isICEnabledForJsBackup)
}
}
@@ -0,0 +1,29 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.jps.build
import org.jetbrains.kotlin.incremental.testingUtils.Modification
class IncrementalRenameModuleTest : AbstractIncrementalJpsTest() {
fun testRenameModule() {
doTest("jps-plugin/testData/incremental/custom/renameModule/")
}
override fun performAdditionalModifications(modifications: List<Modification>) {
projectDescriptor.project.modules.forEach { it.name += "Renamed" }
}
}
@@ -0,0 +1,73 @@
/*
* 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.jps.build
import com.intellij.openapi.util.io.FileUtil
import org.jetbrains.kotlin.cli.common.CompilerSystemProperties
import org.jetbrains.kotlin.compilerRunner.JpsKotlinCompilerRunner
inline fun withSystemProperty(property: String, newValue: String?, fn: ()->Unit) {
val backup = System.getProperty(property)
setOrClearSysProperty(property, newValue)
try {
fn()
}
finally {
setOrClearSysProperty(property, backup)
}
}
@Suppress("NOTHING_TO_INLINE")
inline fun setOrClearSysProperty(property: String, newValue: String?) {
if (newValue != null) {
System.setProperty(property, newValue)
}
else {
System.clearProperty(property)
}
}
fun withDaemon(fn: () -> Unit) {
val daemonHome = FileUtil.createTempDirectory("daemon-home", "testJpsDaemonIC")
withSystemProperty(CompilerSystemProperties.COMPILE_DAEMON_CUSTOM_RUN_FILES_PATH_FOR_TESTS.property, daemonHome.absolutePath) {
withSystemProperty(CompilerSystemProperties.COMPILE_DAEMON_ENABLED_PROPERTY.property, "true") {
try {
fn()
} finally {
JpsKotlinCompilerRunner.shutdownDaemon()
// Try to force directory deletion to prevent test failure later in tearDown().
// Working Daemon can prevent folder deletion on Windows, because Daemon shutdown
// is asynchronous.
var attempts = 0
daemonHome.deleteRecursively()
while (daemonHome.exists() && attempts < 100) {
daemonHome.deleteRecursively()
attempts++
Thread.sleep(50)
}
if (daemonHome.exists()) {
error("Couldn't delete Daemon home directory")
}
}
}
}
}
@@ -0,0 +1,72 @@
/*
* 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.jps.incremental
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.incremental.ProtoData
import org.jetbrains.kotlin.incremental.getProtoData
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumer
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumerImpl
import org.jetbrains.kotlin.incremental.utils.TestMessageCollector
import org.jetbrains.kotlin.name.ClassId
import org.junit.Assert
import java.io.File
abstract class AbstractJsProtoComparisonTest : AbstractProtoComparisonTest<ProtoData>() {
override fun expectedOutputFile(testDir: File): File =
File(testDir, "result-js.out")
.takeIf { it.exists() }
?: super.expectedOutputFile(testDir)
override fun compileAndGetClasses(sourceDir: File, outputDir: File): Map<ClassId, ProtoData> {
val incrementalResults = IncrementalResultsConsumerImpl()
val services = Services.Builder().run {
register(IncrementalResultsConsumer::class.java, incrementalResults)
build()
}
val ktFiles = sourceDir.walkMatching { it.name.endsWith(".kt") }.map { it.canonicalPath }.toList()
val messageCollector = TestMessageCollector()
val outputItemsCollector = OutputItemsCollectorImpl()
val args = K2JSCompilerArguments().apply {
outputFile = File(outputDir, "out.js").canonicalPath
metaInfo = true
main = K2JsArgumentConstants.NO_CALL
freeArgs = ktFiles
}
val env = createTestingCompilerEnvironment(messageCollector, outputItemsCollector, services)
runJSCompiler(args, env).let { exitCode ->
val expectedOutput = "OK"
val actualOutput = (listOf(exitCode?.name) + messageCollector.errors).joinToString("\n")
Assert.assertEquals(expectedOutput, actualOutput)
}
val classes = hashMapOf<ClassId, ProtoData>()
for ((sourceFile, translationResult) in incrementalResults.packageParts) {
classes.putAll(getProtoData(sourceFile, translationResult.metadata))
}
return classes
}
override fun ProtoData.toProtoData(): ProtoData? = this
}
@@ -0,0 +1,58 @@
/*
* 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.jps.incremental
import org.jetbrains.kotlin.incremental.LocalFileKotlinClass
import org.jetbrains.kotlin.incremental.ProtoData
import org.jetbrains.kotlin.incremental.storage.ProtoMapValue
import org.jetbrains.kotlin.incremental.toProtoData
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.metadata.jvm.deserialization.BitEncoding
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.test.MockLibraryUtil
import java.io.File
abstract class AbstractJvmProtoComparisonTest : AbstractProtoComparisonTest<LocalFileKotlinClass>() {
override fun compileAndGetClasses(sourceDir: File, outputDir: File): Map<ClassId, LocalFileKotlinClass> {
MockLibraryUtil.compileKotlin(sourceDir.path, outputDir, extraOptions = listOf("-Xdisable-default-scripting-plugin"))
val classFiles = outputDir.walkMatching { it.name.endsWith(".class") }
val localClassFiles = classFiles.map { LocalFileKotlinClass.create(it)!! }
return localClassFiles.associateBy { it.classId }
}
override fun LocalFileKotlinClass.toProtoData(): ProtoData? {
assert(classHeader.metadataVersion.isCompatible()) { "Incompatible class ($classHeader): $location" }
val bytes by lazy { BitEncoding.decodeBytes(classHeader.data!!) }
val strings by lazy { classHeader.strings!! }
val packageFqName = classId.packageFqName
return when (classHeader.kind) {
KotlinClassHeader.Kind.CLASS -> {
ProtoMapValue(false, bytes, strings).toProtoData(packageFqName)
}
KotlinClassHeader.Kind.FILE_FACADE,
KotlinClassHeader.Kind.MULTIFILE_CLASS_PART -> {
ProtoMapValue(true, bytes, strings).toProtoData(packageFqName)
}
else -> {
null
}
}
}
}
@@ -0,0 +1,123 @@
/*
* 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.jps.incremental
import org.jetbrains.kotlin.TestWithWorkingDir
import org.jetbrains.kotlin.incremental.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.utils.Printer
import java.io.File
abstract class AbstractProtoComparisonTest<PROTO_DATA> : TestWithWorkingDir() {
protected abstract fun compileAndGetClasses(sourceDir: File, outputDir: File): Map<ClassId, PROTO_DATA>
protected abstract fun PROTO_DATA.toProtoData(): ProtoData?
protected open fun expectedOutputFile(testDir: File): File =
File(testDir, "result.out")
fun doTest(testDataPath: String) {
val testDir = File(testDataPath)
val oldClassMap = classesForPrefixedSources(testDir, workingDir, "old")
val newClassMap = classesForPrefixedSources(testDir, workingDir, "new")
val sb = StringBuilder()
val p = Printer(sb)
(oldClassMap.keys - newClassMap.keys).sortedBy { it.toString() }.forEach { classId ->
p.println("REMOVED $classId")
}
(newClassMap.keys - oldClassMap.keys).sortedBy { it.toString() }.forEach { classId ->
p.println("ADDED $classId")
}
(oldClassMap.keys.intersect(newClassMap.keys)).sortedBy { it.toString() }.forEach { classId ->
val oldData = oldClassMap[classId]!!.toProtoData()
val newData = newClassMap[classId]!!.toProtoData()
if (oldData == null || newData == null) {
p.println("SKIPPED $classId")
return@forEach
}
val rawProtoDifference = when {
oldData is ClassProtoData && newData is ClassProtoData -> {
ProtoCompareGenerated(
oldNameResolver = oldData.nameResolver,
newNameResolver = newData.nameResolver,
oldTypeTable = oldData.proto.typeTableOrNull,
newTypeTable = newData.proto.typeTableOrNull
).difference(oldData.proto, newData.proto)
}
oldData is PackagePartProtoData && newData is PackagePartProtoData -> {
ProtoCompareGenerated(
oldNameResolver = oldData.nameResolver,
newNameResolver = newData.nameResolver,
oldTypeTable = oldData.proto.typeTableOrNull,
newTypeTable = newData.proto.typeTableOrNull
).difference(oldData.proto, newData.proto)
}
else -> null
}
rawProtoDifference?.let {
if (it.isNotEmpty()) {
p.println("PROTO DIFFERENCE in $classId: ${it.sortedBy { it.name }.joinToString()}")
}
}
val changesInfo = ChangesCollector().apply { collectProtoChanges(oldData, newData) }.changes()
if (changesInfo.isEmpty()) {
return@forEach
}
val changes = changesInfo.map {
when (it) {
is ChangeInfo.SignatureChanged -> "CLASS_SIGNATURE"
is ChangeInfo.MembersChanged -> "MEMBERS\n ${it.names.sorted()}"
is ChangeInfo.ParentsChanged -> "PARENTS\n ${it.parentsChanged.map { it.asString()}.sorted()}"
}
}.sorted()
p.println("CHANGES in $classId: ${changes.joinToString()}")
}
KotlinTestUtils.assertEqualsToFile(expectedOutputFile(testDir), sb.toString())
}
private fun classesForPrefixedSources(testDir: File, workingDir: File, prefix: String): Map<ClassId, PROTO_DATA> {
val srcDir = workingDir.createSubDirectory("$prefix/src")
val outDir = workingDir.createSubDirectory("$prefix/out")
copySourceFiles(testDir, srcDir, prefix)
return compileAndGetClasses(srcDir, outDir)
}
private fun copySourceFiles(sourceDir: File, targetDir: File, prefix: String) {
for (srcFile in sourceDir.walkMatching { it.name.startsWith(prefix) }) {
val targetFile = File(targetDir, srcFile.name.replaceFirst(prefix, "main"))
srcFile.copyTo(targetFile)
}
}
protected fun File.createSubDirectory(relativePath: String): File =
File(this, relativePath).apply { mkdirs() }
protected fun File.walkMatching(predicate: (File)->Boolean): Sequence<File> =
walk().filter { predicate(it) }
}
@@ -0,0 +1,57 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.incremental
import org.jetbrains.kotlin.load.kotlin.JvmBytecodeBinaryVersion
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
import org.junit.Assert.assertEquals
import org.junit.Test
class CacheVersionTest {
@Test
fun testConstruct() {
assertEquals(
3011001,
CacheVersion(
3,
JvmBytecodeBinaryVersion(1, 0, 3),
JvmMetadataVersion(1, 1, 13)
).intValue
)
}
@Test
fun testDeconstruct() {
assertEquals(
"CacheVersion(caches: 3, bytecode: 1.0, metadata: 1.1)",
CacheVersion(3011001).toString()
)
}
@Test
fun testConstructDeconstruct() {
val version = CacheVersion(
1,
JvmBytecodeBinaryVersion(2, 3),
JvmMetadataVersion(4, 5)
)
assertEquals(1024305, version.intValue)
assertEquals("CacheVersion(caches: 1, bytecode: 2.3, metadata: 4.5)", version.toString())
}
@Test
fun testMaxValues() {
assertEquals(
"CacheVersion(caches: 2146, bytecode: 9.9, metadata: 9.99)",
CacheVersion(
2146,
JvmBytecodeBinaryVersion(9, 9),
JvmMetadataVersion(9, 99)
).toString()
)
}
}
@@ -0,0 +1,82 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.incremental
import org.jetbrains.kotlin.jps.incremental.CacheStatus
import org.jetbrains.kotlin.jps.incremental.loadDiff
import org.junit.Test
import java.io.File
import kotlin.test.assertEquals
class CompositeLookupsCacheAttributesManagerTest {
val manager = CompositeLookupsCacheAttributesManager(File("not-used"), setOf())
@Test
fun testNothingToJava() {
assertEquals(
CacheStatus.INVALID,
manager.loadDiff(
actual = null,
expected = CompositeLookupsCacheAttributes(1, setOf("jvm"))
).status
)
}
@Test
fun testNothingToJavaAndJs() {
assertEquals(
CacheStatus.INVALID,
manager.loadDiff(
actual = null,
expected = CompositeLookupsCacheAttributes(1, setOf("jvm", "js"))
).status
)
}
@Test
fun testJsToJava() {
assertEquals(
CacheStatus.INVALID,
manager.loadDiff(
actual = CompositeLookupsCacheAttributes(1, setOf("jvm")),
expected = CompositeLookupsCacheAttributes(1, setOf("js"))
).status
)
}
@Test
fun testJsAndJavaToJava() {
assertEquals(
CacheStatus.VALID,
manager.loadDiff(
actual = CompositeLookupsCacheAttributes(1, setOf("jvm", "js")),
expected = CompositeLookupsCacheAttributes(1, setOf("jvm"))
).status
)
}
@Test
fun testJsAndJavaToJavaWithOtherVersion() {
assertEquals(
CacheStatus.INVALID,
manager.loadDiff(
actual = CompositeLookupsCacheAttributes(1, setOf("jvm", "js")),
expected = CompositeLookupsCacheAttributes(2, setOf("jvm"))
).status
)
}
@Test
fun testJavaToJsAndJava() {
assertEquals(
CacheStatus.INVALID,
manager.loadDiff(
actual = CompositeLookupsCacheAttributes(1, setOf("jvm")),
expected = CompositeLookupsCacheAttributes(1, setOf("jvm", "js"))
).status
)
}
}
@@ -0,0 +1,711 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.incremental;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@RunWith(JUnit3RunnerWithInners.class)
public class JsProtoComparisonTestGenerated extends AbstractJsProtoComparisonTest {
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassSignatureChange extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassSignatureChange() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("classAnnotationListChanged")
public void testClassAnnotationListChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classSignatureChange/classAnnotationListChanged/");
}
@TestMetadata("classFlagsAndMembersChanged")
public void testClassFlagsAndMembersChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classSignatureChange/classFlagsAndMembersChanged/");
}
@TestMetadata("classFlagsChanged")
public void testClassFlagsChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classSignatureChange/classFlagsChanged/");
}
@TestMetadata("classTypeParameterListChanged")
public void testClassTypeParameterListChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classSignatureChange/classTypeParameterListChanged/");
}
@TestMetadata("classWithSuperTypeListChanged")
public void testClassWithSuperTypeListChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classSignatureChange/classWithSuperTypeListChanged/");
}
@TestMetadata("nestedClassSignatureChanged")
public void testNestedClassSignatureChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classSignatureChange/nestedClassSignatureChanged/");
}
@TestMetadata("sealedClassImplAdded")
public void testSealedClassImplAdded() throws Exception {
runTest("jps-plugin/testData/comparison/classSignatureChange/sealedClassImplAdded/");
}
@TestMetadata("sealedClassImplRemoved")
public void testSealedClassImplRemoved() throws Exception {
runTest("jps-plugin/testData/comparison/classSignatureChange/sealedClassImplRemoved/");
}
@TestMetadata("sealedClassNestedImplAdded")
public void testSealedClassNestedImplAdded() throws Exception {
runTest("jps-plugin/testData/comparison/classSignatureChange/sealedClassNestedImplAdded/");
}
@TestMetadata("sealedClassNestedImplAddedDeep")
public void testSealedClassNestedImplAddedDeep() throws Exception {
runTest("jps-plugin/testData/comparison/classSignatureChange/sealedClassNestedImplAddedDeep/");
}
@TestMetadata("sealedClassNestedImplRemoved")
public void testSealedClassNestedImplRemoved() throws Exception {
runTest("jps-plugin/testData/comparison/classSignatureChange/sealedClassNestedImplRemoved/");
}
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange/classAnnotationListChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassAnnotationListChanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassAnnotationListChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange/classAnnotationListChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange/classFlagsAndMembersChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassFlagsAndMembersChanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassFlagsAndMembersChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange/classFlagsAndMembersChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange/classFlagsChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassFlagsChanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassFlagsChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange/classFlagsChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange/classTypeParameterListChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassTypeParameterListChanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassTypeParameterListChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange/classTypeParameterListChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange/classWithSuperTypeListChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassWithSuperTypeListChanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassWithSuperTypeListChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange/classWithSuperTypeListChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange/nestedClassSignatureChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class NestedClassSignatureChanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInNestedClassSignatureChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange/nestedClassSignatureChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange/sealedClassImplAdded")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SealedClassImplAdded extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSealedClassImplAdded() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange/sealedClassImplAdded"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange/sealedClassImplRemoved")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SealedClassImplRemoved extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSealedClassImplRemoved() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange/sealedClassImplRemoved"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange/sealedClassNestedImplAdded")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SealedClassNestedImplAdded extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSealedClassNestedImplAdded() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange/sealedClassNestedImplAdded"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange/sealedClassNestedImplAddedDeep")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SealedClassNestedImplAddedDeep extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSealedClassNestedImplAddedDeep() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange/sealedClassNestedImplAddedDeep"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange/sealedClassNestedImplRemoved")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SealedClassNestedImplRemoved extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSealedClassNestedImplRemoved() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange/sealedClassNestedImplRemoved"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
}
@TestMetadata("jps-plugin/testData/comparison/classPrivateOnlyChange")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassPrivateOnlyChange extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassPrivateOnlyChange() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classPrivateOnlyChange"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("classWithPrivateFunChanged")
public void testClassWithPrivateFunChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateFunChanged/");
}
@TestMetadata("classWithPrivatePrimaryConstructorChanged")
public void testClassWithPrivatePrimaryConstructorChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivatePrimaryConstructorChanged/");
}
@TestMetadata("classWithPrivateSecondaryConstructorChanged")
public void testClassWithPrivateSecondaryConstructorChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateSecondaryConstructorChanged/");
}
@TestMetadata("classWithPrivateValChanged")
public void testClassWithPrivateValChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateValChanged/");
}
@TestMetadata("classWithPrivateVarChanged")
public void testClassWithPrivateVarChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateVarChanged/");
}
@TestMetadata("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateFunChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassWithPrivateFunChanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassWithPrivateFunChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateFunChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivatePrimaryConstructorChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassWithPrivatePrimaryConstructorChanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassWithPrivatePrimaryConstructorChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivatePrimaryConstructorChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateSecondaryConstructorChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassWithPrivateSecondaryConstructorChanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassWithPrivateSecondaryConstructorChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateSecondaryConstructorChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateValChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassWithPrivateValChanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassWithPrivateValChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateValChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateVarChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassWithPrivateVarChanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassWithPrivateVarChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateVarChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassMembersOnlyChanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassMembersOnlyChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("classWithCompanionObjectChanged")
public void testClassWithCompanionObjectChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithCompanionObjectChanged/");
}
@TestMetadata("classWithConstructorChanged")
public void testClassWithConstructorChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithConstructorChanged/");
}
@TestMetadata("classWithFunAndValChanged")
public void testClassWithFunAndValChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithFunAndValChanged/");
}
@TestMetadata("classWithNestedClassesChanged")
public void testClassWithNestedClassesChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithNestedClassesChanged/");
}
@TestMetadata("classWitnEnumChanged")
public void testClassWitnEnumChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classMembersOnlyChanged/classWitnEnumChanged/");
}
@TestMetadata("defaultValues")
public void testDefaultValues() throws Exception {
runTest("jps-plugin/testData/comparison/classMembersOnlyChanged/defaultValues/");
}
@TestMetadata("membersAnnotationListChanged")
public void testMembersAnnotationListChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classMembersOnlyChanged/membersAnnotationListChanged/");
}
@TestMetadata("membersFlagsChanged")
public void testMembersFlagsChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classMembersOnlyChanged/membersFlagsChanged/");
}
@TestMetadata("nestedClassMembersChanged")
public void testNestedClassMembersChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classMembersOnlyChanged/nestedClassMembersChanged/");
}
@TestMetadata("sealedClassImplAdded")
public void testSealedClassImplAdded() throws Exception {
runTest("jps-plugin/testData/comparison/classMembersOnlyChanged/sealedClassImplAdded/");
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithCompanionObjectChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassWithCompanionObjectChanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassWithCompanionObjectChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithCompanionObjectChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithConstructorChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassWithConstructorChanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassWithConstructorChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithConstructorChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithFunAndValChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassWithFunAndValChanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassWithFunAndValChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithFunAndValChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithNestedClassesChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassWithNestedClassesChanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassWithNestedClassesChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithNestedClassesChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/classWitnEnumChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassWitnEnumChanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassWitnEnumChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged/classWitnEnumChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/defaultValues")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class DefaultValues extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInDefaultValues() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged/defaultValues"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/membersAnnotationListChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class MembersAnnotationListChanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInMembersAnnotationListChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged/membersAnnotationListChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/membersFlagsChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class MembersFlagsChanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInMembersFlagsChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged/membersFlagsChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/nestedClassMembersChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class NestedClassMembersChanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInNestedClassMembersChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged/nestedClassMembersChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/sealedClassImplAdded")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SealedClassImplAdded extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSealedClassImplAdded() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged/sealedClassImplAdded"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
}
@TestMetadata("jps-plugin/testData/comparison/packageMembers")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PackageMembers extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInPackageMembers() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/packageMembers"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("defaultValues")
public void testDefaultValues() throws Exception {
runTest("jps-plugin/testData/comparison/packageMembers/defaultValues/");
}
@TestMetadata("membersAnnotationListChanged")
public void testMembersAnnotationListChanged() throws Exception {
runTest("jps-plugin/testData/comparison/packageMembers/membersAnnotationListChanged/");
}
@TestMetadata("membersFlagsChanged")
public void testMembersFlagsChanged() throws Exception {
runTest("jps-plugin/testData/comparison/packageMembers/membersFlagsChanged/");
}
@TestMetadata("packageFacadePrivateOnlyChanges")
public void testPackageFacadePrivateOnlyChanges() throws Exception {
runTest("jps-plugin/testData/comparison/packageMembers/packageFacadePrivateOnlyChanges/");
}
@TestMetadata("packageFacadePublicChanges")
public void testPackageFacadePublicChanges() throws Exception {
runTest("jps-plugin/testData/comparison/packageMembers/packageFacadePublicChanges/");
}
@TestMetadata("jps-plugin/testData/comparison/packageMembers/defaultValues")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class DefaultValues extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInDefaultValues() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/packageMembers/defaultValues"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/packageMembers/membersAnnotationListChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class MembersAnnotationListChanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInMembersAnnotationListChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/packageMembers/membersAnnotationListChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/packageMembers/membersFlagsChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class MembersFlagsChanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInMembersFlagsChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/packageMembers/membersFlagsChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/packageMembers/packageFacadePrivateOnlyChanges")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PackageFacadePrivateOnlyChanges extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInPackageFacadePrivateOnlyChanges() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/packageMembers/packageFacadePrivateOnlyChanges"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/packageMembers/packageFacadePublicChanges")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PackageFacadePublicChanges extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInPackageFacadePublicChanges() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/packageMembers/packageFacadePublicChanges"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
}
@TestMetadata("jps-plugin/testData/comparison/unchanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Unchanged extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInUnchanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/unchanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("unchangedClass")
public void testUnchangedClass() throws Exception {
runTest("jps-plugin/testData/comparison/unchanged/unchangedClass/");
}
@TestMetadata("unchangedPackageFacade")
public void testUnchangedPackageFacade() throws Exception {
runTest("jps-plugin/testData/comparison/unchanged/unchangedPackageFacade/");
}
@TestMetadata("jps-plugin/testData/comparison/unchanged/unchangedClass")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class UnchangedClass extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInUnchangedClass() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/unchanged/unchangedClass"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/unchanged/unchangedPackageFacade")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class UnchangedPackageFacade extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInUnchangedPackageFacade() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/unchanged/unchangedPackageFacade"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
}
@TestMetadata("jps-plugin/testData/comparison/jsOnly")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class JsOnly extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInJsOnly() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/jsOnly"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("externals")
public void testExternals() throws Exception {
runTest("jps-plugin/testData/comparison/jsOnly/externals/");
}
@TestMetadata("jps-plugin/testData/comparison/jsOnly/externals")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Externals extends AbstractJsProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInExternals() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/jsOnly/externals"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
}
}
@@ -0,0 +1,765 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.incremental;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@RunWith(JUnit3RunnerWithInners.class)
public class JvmProtoComparisonTestGenerated extends AbstractJvmProtoComparisonTest {
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassSignatureChange extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassSignatureChange() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("classAnnotationListChanged")
public void testClassAnnotationListChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classSignatureChange/classAnnotationListChanged/");
}
@TestMetadata("classFlagsAndMembersChanged")
public void testClassFlagsAndMembersChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classSignatureChange/classFlagsAndMembersChanged/");
}
@TestMetadata("classFlagsChanged")
public void testClassFlagsChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classSignatureChange/classFlagsChanged/");
}
@TestMetadata("classTypeParameterListChanged")
public void testClassTypeParameterListChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classSignatureChange/classTypeParameterListChanged/");
}
@TestMetadata("classWithSuperTypeListChanged")
public void testClassWithSuperTypeListChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classSignatureChange/classWithSuperTypeListChanged/");
}
@TestMetadata("nestedClassSignatureChanged")
public void testNestedClassSignatureChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classSignatureChange/nestedClassSignatureChanged/");
}
@TestMetadata("sealedClassImplAdded")
public void testSealedClassImplAdded() throws Exception {
runTest("jps-plugin/testData/comparison/classSignatureChange/sealedClassImplAdded/");
}
@TestMetadata("sealedClassImplRemoved")
public void testSealedClassImplRemoved() throws Exception {
runTest("jps-plugin/testData/comparison/classSignatureChange/sealedClassImplRemoved/");
}
@TestMetadata("sealedClassNestedImplAdded")
public void testSealedClassNestedImplAdded() throws Exception {
runTest("jps-plugin/testData/comparison/classSignatureChange/sealedClassNestedImplAdded/");
}
@TestMetadata("sealedClassNestedImplAddedDeep")
public void testSealedClassNestedImplAddedDeep() throws Exception {
runTest("jps-plugin/testData/comparison/classSignatureChange/sealedClassNestedImplAddedDeep/");
}
@TestMetadata("sealedClassNestedImplRemoved")
public void testSealedClassNestedImplRemoved() throws Exception {
runTest("jps-plugin/testData/comparison/classSignatureChange/sealedClassNestedImplRemoved/");
}
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange/classAnnotationListChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassAnnotationListChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassAnnotationListChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange/classAnnotationListChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange/classFlagsAndMembersChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassFlagsAndMembersChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassFlagsAndMembersChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange/classFlagsAndMembersChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange/classFlagsChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassFlagsChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassFlagsChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange/classFlagsChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange/classTypeParameterListChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassTypeParameterListChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassTypeParameterListChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange/classTypeParameterListChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange/classWithSuperTypeListChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassWithSuperTypeListChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassWithSuperTypeListChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange/classWithSuperTypeListChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange/nestedClassSignatureChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class NestedClassSignatureChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInNestedClassSignatureChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange/nestedClassSignatureChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange/sealedClassImplAdded")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SealedClassImplAdded extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSealedClassImplAdded() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange/sealedClassImplAdded"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange/sealedClassImplRemoved")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SealedClassImplRemoved extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSealedClassImplRemoved() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange/sealedClassImplRemoved"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange/sealedClassNestedImplAdded")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SealedClassNestedImplAdded extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSealedClassNestedImplAdded() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange/sealedClassNestedImplAdded"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange/sealedClassNestedImplAddedDeep")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SealedClassNestedImplAddedDeep extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSealedClassNestedImplAddedDeep() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange/sealedClassNestedImplAddedDeep"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classSignatureChange/sealedClassNestedImplRemoved")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SealedClassNestedImplRemoved extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSealedClassNestedImplRemoved() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classSignatureChange/sealedClassNestedImplRemoved"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
}
@TestMetadata("jps-plugin/testData/comparison/classPrivateOnlyChange")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassPrivateOnlyChange extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassPrivateOnlyChange() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classPrivateOnlyChange"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("classWithPrivateFunChanged")
public void testClassWithPrivateFunChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateFunChanged/");
}
@TestMetadata("classWithPrivatePrimaryConstructorChanged")
public void testClassWithPrivatePrimaryConstructorChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivatePrimaryConstructorChanged/");
}
@TestMetadata("classWithPrivateSecondaryConstructorChanged")
public void testClassWithPrivateSecondaryConstructorChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateSecondaryConstructorChanged/");
}
@TestMetadata("classWithPrivateValChanged")
public void testClassWithPrivateValChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateValChanged/");
}
@TestMetadata("classWithPrivateVarChanged")
public void testClassWithPrivateVarChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateVarChanged/");
}
@TestMetadata("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateFunChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassWithPrivateFunChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassWithPrivateFunChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateFunChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivatePrimaryConstructorChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassWithPrivatePrimaryConstructorChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassWithPrivatePrimaryConstructorChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivatePrimaryConstructorChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateSecondaryConstructorChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassWithPrivateSecondaryConstructorChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassWithPrivateSecondaryConstructorChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateSecondaryConstructorChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateValChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassWithPrivateValChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassWithPrivateValChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateValChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateVarChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassWithPrivateVarChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassWithPrivateVarChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classPrivateOnlyChange/classWithPrivateVarChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassMembersOnlyChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassMembersOnlyChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("classWithCompanionObjectChanged")
public void testClassWithCompanionObjectChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithCompanionObjectChanged/");
}
@TestMetadata("classWithConstructorChanged")
public void testClassWithConstructorChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithConstructorChanged/");
}
@TestMetadata("classWithFunAndValChanged")
public void testClassWithFunAndValChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithFunAndValChanged/");
}
@TestMetadata("classWithNestedClassesChanged")
public void testClassWithNestedClassesChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithNestedClassesChanged/");
}
@TestMetadata("classWitnEnumChanged")
public void testClassWitnEnumChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classMembersOnlyChanged/classWitnEnumChanged/");
}
@TestMetadata("defaultValues")
public void testDefaultValues() throws Exception {
runTest("jps-plugin/testData/comparison/classMembersOnlyChanged/defaultValues/");
}
@TestMetadata("membersAnnotationListChanged")
public void testMembersAnnotationListChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classMembersOnlyChanged/membersAnnotationListChanged/");
}
@TestMetadata("membersFlagsChanged")
public void testMembersFlagsChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classMembersOnlyChanged/membersFlagsChanged/");
}
@TestMetadata("nestedClassMembersChanged")
public void testNestedClassMembersChanged() throws Exception {
runTest("jps-plugin/testData/comparison/classMembersOnlyChanged/nestedClassMembersChanged/");
}
@TestMetadata("sealedClassImplAdded")
public void testSealedClassImplAdded() throws Exception {
runTest("jps-plugin/testData/comparison/classMembersOnlyChanged/sealedClassImplAdded/");
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithCompanionObjectChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassWithCompanionObjectChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassWithCompanionObjectChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithCompanionObjectChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithConstructorChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassWithConstructorChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassWithConstructorChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithConstructorChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithFunAndValChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassWithFunAndValChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassWithFunAndValChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithFunAndValChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithNestedClassesChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassWithNestedClassesChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassWithNestedClassesChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged/classWithNestedClassesChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/classWitnEnumChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassWitnEnumChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassWitnEnumChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged/classWitnEnumChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/defaultValues")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class DefaultValues extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInDefaultValues() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged/defaultValues"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/membersAnnotationListChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class MembersAnnotationListChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInMembersAnnotationListChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged/membersAnnotationListChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/membersFlagsChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class MembersFlagsChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInMembersFlagsChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged/membersFlagsChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/nestedClassMembersChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class NestedClassMembersChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInNestedClassMembersChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged/nestedClassMembersChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/sealedClassImplAdded")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SealedClassImplAdded extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSealedClassImplAdded() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/classMembersOnlyChanged/sealedClassImplAdded"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
}
@TestMetadata("jps-plugin/testData/comparison/packageMembers")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PackageMembers extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInPackageMembers() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/packageMembers"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("defaultValues")
public void testDefaultValues() throws Exception {
runTest("jps-plugin/testData/comparison/packageMembers/defaultValues/");
}
@TestMetadata("membersAnnotationListChanged")
public void testMembersAnnotationListChanged() throws Exception {
runTest("jps-plugin/testData/comparison/packageMembers/membersAnnotationListChanged/");
}
@TestMetadata("membersFlagsChanged")
public void testMembersFlagsChanged() throws Exception {
runTest("jps-plugin/testData/comparison/packageMembers/membersFlagsChanged/");
}
@TestMetadata("packageFacadePrivateOnlyChanges")
public void testPackageFacadePrivateOnlyChanges() throws Exception {
runTest("jps-plugin/testData/comparison/packageMembers/packageFacadePrivateOnlyChanges/");
}
@TestMetadata("packageFacadePublicChanges")
public void testPackageFacadePublicChanges() throws Exception {
runTest("jps-plugin/testData/comparison/packageMembers/packageFacadePublicChanges/");
}
@TestMetadata("jps-plugin/testData/comparison/packageMembers/defaultValues")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class DefaultValues extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInDefaultValues() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/packageMembers/defaultValues"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/packageMembers/membersAnnotationListChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class MembersAnnotationListChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInMembersAnnotationListChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/packageMembers/membersAnnotationListChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/packageMembers/membersFlagsChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class MembersFlagsChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInMembersFlagsChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/packageMembers/membersFlagsChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/packageMembers/packageFacadePrivateOnlyChanges")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PackageFacadePrivateOnlyChanges extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInPackageFacadePrivateOnlyChanges() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/packageMembers/packageFacadePrivateOnlyChanges"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/packageMembers/packageFacadePublicChanges")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PackageFacadePublicChanges extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInPackageFacadePublicChanges() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/packageMembers/packageFacadePublicChanges"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
}
@TestMetadata("jps-plugin/testData/comparison/unchanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Unchanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInUnchanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/unchanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("unchangedClass")
public void testUnchangedClass() throws Exception {
runTest("jps-plugin/testData/comparison/unchanged/unchangedClass/");
}
@TestMetadata("unchangedPackageFacade")
public void testUnchangedPackageFacade() throws Exception {
runTest("jps-plugin/testData/comparison/unchanged/unchangedPackageFacade/");
}
@TestMetadata("jps-plugin/testData/comparison/unchanged/unchangedClass")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class UnchangedClass extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInUnchangedClass() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/unchanged/unchangedClass"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/unchanged/unchangedPackageFacade")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class UnchangedPackageFacade extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInUnchangedPackageFacade() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/unchanged/unchangedPackageFacade"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
}
@TestMetadata("jps-plugin/testData/comparison/jvmOnly")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class JvmOnly extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInJvmOnly() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/jvmOnly"), Pattern.compile("^([^\\.]+)$"), null, true);
}
@TestMetadata("classToFileFacade")
public void testClassToFileFacade() throws Exception {
runTest("jps-plugin/testData/comparison/jvmOnly/classToFileFacade/");
}
@TestMetadata("membersFlagsChanged")
public void testMembersFlagsChanged() throws Exception {
runTest("jps-plugin/testData/comparison/jvmOnly/membersFlagsChanged/");
}
@TestMetadata("packageFacadeMultifileClassChanged")
public void testPackageFacadeMultifileClassChanged() throws Exception {
runTest("jps-plugin/testData/comparison/jvmOnly/packageFacadeMultifileClassChanged/");
}
@TestMetadata("packageFacadeToClass")
public void testPackageFacadeToClass() throws Exception {
runTest("jps-plugin/testData/comparison/jvmOnly/packageFacadeToClass/");
}
@TestMetadata("jps-plugin/testData/comparison/jvmOnly/classToFileFacade")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassToFileFacade extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassToFileFacade() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/jvmOnly/classToFileFacade"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/jvmOnly/membersFlagsChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class MembersFlagsChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInMembersFlagsChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/jvmOnly/membersFlagsChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/jvmOnly/packageFacadeMultifileClassChanged")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PackageFacadeMultifileClassChanged extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInPackageFacadeMultifileClassChanged() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/jvmOnly/packageFacadeMultifileClassChanged"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
@TestMetadata("jps-plugin/testData/comparison/jvmOnly/packageFacadeToClass")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PackageFacadeToClass extends AbstractJvmProtoComparisonTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInPackageFacadeToClass() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/comparison/jvmOnly/packageFacadeToClass"), Pattern.compile("^([^\\.]+)$"), null, true);
}
}
}
}
@@ -0,0 +1,67 @@
/*
* 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.jps.incremental
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.js.K2JSCompiler
import org.jetbrains.kotlin.compilerRunner.*
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.jps.build.KotlinBuilder
import org.jetbrains.kotlin.utils.PathUtil
import java.io.*
fun createTestingCompilerEnvironment(
messageCollector: MessageCollector,
outputItemsCollector: OutputItemsCollectorImpl,
services: Services
): JpsCompilerEnvironment {
val paths = PathUtil.kotlinPathsForDistDirectory
val wrappedMessageCollector = MessageCollectorToOutputItemsCollectorAdapter(messageCollector, outputItemsCollector)
return JpsCompilerEnvironment(
paths,
services,
KotlinBuilder.classesToLoadByParent,
wrappedMessageCollector,
outputItemsCollector,
MockProgressReporter
)
}
fun runJSCompiler(args: K2JSCompilerArguments, env: JpsCompilerEnvironment): ExitCode? {
val argsArray = ArgumentUtils.convertArgumentsToStringList(args).toTypedArray()
val stream = ByteArrayOutputStream()
val out = PrintStream(stream)
val exitCode = CompilerRunnerUtil.invokeExecMethod(K2JSCompiler::class.java.name, argsArray, env, out)
val reader = BufferedReader(StringReader(stream.toString()))
CompilerOutputParser.parseCompilerMessagesFromReader(env.messageCollector, reader, env.outputItemsCollector)
return exitCode as? ExitCode
}
private object MockProgressReporter : ProgressReporter {
override fun progress(message: String) {
}
override fun compilationStarted() {
}
override fun clearProgress() {
}
}
@@ -0,0 +1,62 @@
/*
* 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.jvm.compiler
import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType
import org.jetbrains.kotlin.build.JvmSourceRoot
import org.jetbrains.kotlin.modules.KotlinModuleXmlBuilder
import org.jetbrains.kotlin.test.MockLibraryUtil
import org.jetbrains.kotlin.test.TestCaseWithTmpdir
import org.jetbrains.kotlin.test.util.KtTestUtil
import org.jetbrains.kotlin.utils.PathUtil
import java.io.File
/**
* This test checks that Java classes from sources have higher priority in Kotlin resolution process than classes from binaries.
* To test this, we compile a Kotlin+Java module (in two modes: CLI and module-based) where a runtime Java class was replaced
* with a "newer" version in sources, and check that this class resolves to the one from sources by calling a method absent in the runtime
*/
class ClasspathOrderTest : TestCaseWithTmpdir() {
companion object {
private val sourceDir = File(KtTestUtil.getTestDataPathBase() + "/classpathOrder").absoluteFile
}
fun testClasspathOrderForCLI() {
MockLibraryUtil.compileKotlin(sourceDir.path, tmpdir)
}
fun testClasspathOrderForModuleScriptBuild() {
val xmlContent = KotlinModuleXmlBuilder().addModule(
"name",
File(tmpdir, "output").absolutePath,
listOf(sourceDir),
listOf(JvmSourceRoot(sourceDir)),
listOf(PathUtil.kotlinPathsForDistDirectory.stdlibPath),
emptyList(),
null,
JavaModuleBuildTargetType.PRODUCTION.typeId,
JavaModuleBuildTargetType.PRODUCTION.isTests,
setOf(),
emptyList()
).asText().toString()
val xml = File(tmpdir, "module.xml")
xml.writeText(xmlContent)
MockLibraryUtil.compileKotlinModule(xml.absolutePath)
}
}
@@ -0,0 +1,111 @@
/*
* 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.modules;
import junit.framework.TestCase;
import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
import org.jetbrains.kotlin.build.JvmSourceRoot;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
public class KotlinModuleXmlGeneratorTest extends TestCase {
public void testBasic() throws Exception {
String actual = new KotlinModuleXmlBuilder().addModule(
"name",
"output",
Arrays.asList(new File("s1"), new File("s2")),
Collections.singletonList(new JvmSourceRoot(new File("java"), null)),
Arrays.asList(new File("cp1"), new File("cp2")),
Collections.emptyList(),
null,
JavaModuleBuildTargetType.PRODUCTION.getTypeId(),
JavaModuleBuildTargetType.PRODUCTION.isTests(),
Collections.emptySet(),
Collections.emptyList()
).asText().toString();
KotlinTestUtils.assertEqualsToFile(new File("idea/testData/modules.xml/basic.xml"), actual);
}
public void testFiltered() throws Exception {
String actual = new KotlinModuleXmlBuilder().addModule(
"name",
"output",
Arrays.asList(new File("s1"), new File("s2")),
Collections.emptyList(),
Arrays.asList(new File("cp1"), new File("cp2")),
Collections.emptyList(),
null,
JavaModuleBuildTargetType.PRODUCTION.getTypeId(),
JavaModuleBuildTargetType.PRODUCTION.isTests(),
Collections.singleton(new File("cp1")),
Collections.emptyList()
).asText().toString();
KotlinTestUtils.assertEqualsToFile(new File("idea/testData/modules.xml/filtered.xml"), actual);
}
public void testMultiple() throws Exception {
KotlinModuleXmlBuilder builder = new KotlinModuleXmlBuilder();
builder.addModule(
"name",
"output",
Arrays.asList(new File("s1"), new File("s2")),
Collections.emptyList(),
Arrays.asList(new File("cp1"), new File("cp2")),
Collections.emptyList(),
null,
JavaModuleBuildTargetType.PRODUCTION.getTypeId(),
JavaModuleBuildTargetType.PRODUCTION.isTests(),
Collections.singleton(new File("cp1")),
Collections.emptyList()
);
builder.addModule(
"name2",
"output2",
Arrays.asList(new File("s12"), new File("s22")),
Collections.emptyList(),
Arrays.asList(new File("cp12"), new File("cp22")),
Collections.emptyList(),
null,
JavaModuleBuildTargetType.TEST.getTypeId(),
JavaModuleBuildTargetType.TEST.isTests(),
Collections.singleton(new File("cp12")),
Collections.emptyList()
);
String actual = builder.asText().toString();
KotlinTestUtils.assertEqualsToFile(new File("idea/testData/modules.xml/multiple.xml"), actual);
}
public void testModularJdkRoot() throws Exception {
String actual = new KotlinModuleXmlBuilder().addModule(
"name",
"output",
Collections.emptyList(),
Collections.emptyList(),
Collections.emptyList(),
Collections.emptyList(),
new File("/path/to/modular/jdk"),
JavaModuleBuildTargetType.PRODUCTION.getTypeId(),
JavaModuleBuildTargetType.PRODUCTION.isTests(),
Collections.emptySet(),
Collections.emptyList()
).asText().toString();
KotlinTestUtils.assertEqualsToFile(new File("idea/testData/modules.xml/modularJdkRoot.xml"), actual);
}
}
@@ -0,0 +1,115 @@
/*
* 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.jps.build.kannotator;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.BuildResult;
import org.jetbrains.jps.model.module.JpsModule;
import org.jetbrains.jps.model.module.JpsModuleSourceRoot;
import org.jetbrains.kotlin.incremental.testingUtils.ClassFilesComparisonKt;
import org.jetbrains.kotlin.jps.build.AbstractKotlinJpsBuildTestCase;
import java.io.File;
import java.io.IOException;
public class KannotatorJpsTest extends AbstractKotlinJpsBuildTestCase {
private static final String JDK_NAME = "1.6";
@Override
public void setUp() throws Exception {
super.setUp();
File sourceFilesRoot = new File(TEST_DATA_PATH + File.separator + "kannotator");
workDir = copyTestDataToTmpDir(sourceFilesRoot);
}
public void testMakeKannotator() throws IOException {
initProject();
rebuildAllModules();
FileUtil.copyDir(getOutDir(), getOutDirAfterRebuild());
for (JpsModule module : myProject.getModules()) {
for (JpsModuleSourceRoot sourceRoot : module.getSourceRoots()) {
processFile(sourceRoot.getFile());
}
}
}
@NotNull
private File getOutDir() {
return new File(workDir, "out");
}
@NotNull
private File getOutDirAfterRebuild() {
return new File(workDir, "out-after-rebuild");
}
private void processFile(File root) {
if (root.isDirectory()) {
File[] files = root.listFiles();
if (files == null) return;
for (File file : files) {
processFile(file);
}
}
else if (root.getName().endsWith(".kt")) {
System.out.println("Test started. File: " + root.getName());
String path = root.getAbsolutePath();
System.out.println("Change file: " + path);
change(path);
buildAllModules().assertSuccessful();
System.out.println("Make successful");
System.out.println("Checking output directories after make and rebuild");
ClassFilesComparisonKt
.assertEqualDirectories(new File(getOutDirAfterRebuild(), "production"), new File(getOutDir(), "production"), false);
ClassFilesComparisonKt.assertEqualDirectories(new File(getOutDirAfterRebuild(), "test"), new File(getOutDir(), "test"), false);
System.out.println("Test successfully finished. File: " + root.getName());
System.out.println("-----");
}
}
@Override
protected void rebuildAllModules() {
System.out.println("'Rebuild all' started");
super.rebuildAllModules();
System.out.println("'Rebuild all' finished");
}
@NotNull
@Override
protected BuildResult buildAllModules() {
System.out.println("'Make all' started");
BuildResult result = super.buildAllModules();
System.out.println("'Make all' finished");
return result;
}
private void initProject() {
addJdk(JDK_NAME);
loadProject(workDir.getAbsolutePath());
addKotlinStdlibDependency();
}
@Override
public void tearDown() throws Exception {
FileUtil.delete(workDir);
super.tearDown();
}
}
@@ -0,0 +1,2 @@
org.jetbrains.kotlin.jps.build.KotlinSourceRootProvider
org.jetbrains.kotlin.jps.build.KotlinResourcesRootProvider
@@ -0,0 +1 @@
org.jetbrains.kotlin.jps.build.KotlinJavaBuilderExtension
@@ -0,0 +1 @@
org.jetbrains.jps.builders.java.dependencyView.NullabilityAnnotationsTracker
@@ -0,0 +1 @@
org.jetbrains.kotlin.jps.build.KotlinBuilderService
@@ -0,0 +1 @@
org.jetbrains.kotlin.jps.model.KotlinModelSerializerService
@@ -0,0 +1,79 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jps.builders.java.dependencyView
import gnu.trove.TIntHashSet
import org.jetbrains.jps.builders.java.dependencyView.TypeRepr.ClassType
import org.jetbrains.kotlin.fileClasses.internalNameWithoutInnerClasses
import org.jetbrains.kotlin.load.java.JAVAX_NONNULL_ANNOTATION
import org.jetbrains.kotlin.load.java.NOT_NULL_ANNOTATIONS
import org.jetbrains.kotlin.load.java.NULLABLE_ANNOTATIONS
import java.util.*
internal class NullabilityAnnotationsTracker : AnnotationsChangeTracker() {
private val annotations =
(NULLABLE_ANNOTATIONS + JAVAX_NONNULL_ANNOTATION + NOT_NULL_ANNOTATIONS).mapTo(HashSet()) { it.internalNameWithoutInnerClasses }
.toTypedArray()
override fun methodAnnotationsChanged(
context: DependencyContext,
method: MethodRepr,
annotationsDiff: Difference.Specifier<ClassType, Difference>,
paramAnnotationsDiff: Difference.Specifier<ParamAnnotation, Difference>
): Set<Recompile> {
val changedAnnotations = annotationsDiff.addedOrRemoved() +
paramAnnotationsDiff.addedOrRemoved().map { it.type }
return handleNullAnnotationsChanges(context, method, changedAnnotations)
}
override fun fieldAnnotationsChanged(
context: NamingContext,
field: FieldRepr,
annotationsDiff: Difference.Specifier<ClassType, Difference>
): Set<Recompile> {
return handleNullAnnotationsChanges(context, field, annotationsDiff.addedOrRemoved())
}
private fun handleNullAnnotationsChanges(
context: NamingContext,
protoMember: ProtoMember,
annotations: Sequence<TypeRepr.ClassType>
): Set<Recompile> {
val nullabilityAnnotations = TIntHashSet(this.annotations.toIntArray { context.get(it) })
val changedNullAnnotation = annotations.firstOrNull { nullabilityAnnotations.contains(it.className) }
val result = EnumSet.noneOf(Recompile::class.java)
if (changedNullAnnotation != null) {
result.add(Recompile.USAGES)
if (protoMember is MethodRepr && !protoMember.isFinal) {
// methods can be overridden, whereas fields cannot be
result.add(Recompile.SUBCLASSES)
}
}
return result
}
private fun <T> Difference.Specifier<T, Difference>.addedOrRemoved(): Sequence<T> =
added().asSequence() + removed().asSequence()
private inline fun <T> Array<T>.toIntArray(fn: (T) -> Int): IntArray =
IntArray(size) { i -> fn(get(i)) }
}
@@ -0,0 +1,123 @@
/*
* 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.compilerRunner
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.preloading.ClassPreloadingUtils
import org.jetbrains.kotlin.preloading.Preloader
import org.jetbrains.kotlin.utils.KotlinPaths
import org.jetbrains.kotlin.utils.KotlinPathsFromBaseDirectory
import java.io.File
import java.io.PrintStream
import java.lang.ref.SoftReference
object CompilerRunnerUtil {
private var ourClassLoaderRef = SoftReference<ClassLoader>(null)
internal val jdkToolsJar: File?
get() {
val javaHomePath = System.getProperty("java.home")
if (javaHomePath == null || javaHomePath.isEmpty()) {
return null
}
val javaHome = File(javaHomePath)
var toolsJar = File(javaHome, "lib/tools.jar")
if (toolsJar.exists()) {
return toolsJar.canonicalFile
}
// We might be inside jre.
if (javaHome.name == "jre") {
toolsJar = File(javaHome.parent, "lib/tools.jar")
if (toolsJar.exists()) {
return toolsJar.canonicalFile
}
}
return null
}
@Synchronized
private fun getOrCreateClassLoader(
environment: JpsCompilerEnvironment,
paths: List<File>
): ClassLoader {
var classLoader = ourClassLoaderRef.get()
if (classLoader == null) {
classLoader = ClassPreloadingUtils.preloadClasses(
paths,
Preloader.DEFAULT_CLASS_NUMBER_ESTIMATE,
CompilerRunnerUtil::class.java.classLoader,
environment.classesToLoadByParent
)
ourClassLoaderRef = SoftReference(classLoader)
}
return classLoader!!
}
fun getLibPath(paths: KotlinPaths, messageCollector: MessageCollector): File? {
val libs = paths.libPath
if (libs.exists() && !libs.isFile) return libs
messageCollector.report(
ERROR,
"Broken compiler at '" + libs.absolutePath + "'. Make sure plugin is properly installed", null
)
return null
}
fun invokeExecMethod(
compilerClassName: String,
arguments: Array<String>,
environment: JpsCompilerEnvironment,
out: PrintStream
): Any? = withCompilerClassloader(environment) { classLoader ->
val compiler = Class.forName(compilerClassName, true, classLoader)
val exec = compiler.getMethod(
"execAndOutputXml",
PrintStream::class.java,
Class.forName("org.jetbrains.kotlin.config.Services", true, classLoader),
Array<String>::class.java
)
exec.invoke(compiler.newInstance(), out, environment.services, arguments)
}
fun invokeClassesFqNames(
environment: JpsCompilerEnvironment,
files: Set<File>
): Set<String> = withCompilerClassloader(environment) { classLoader ->
val klass = Class.forName("org.jetbrains.kotlin.incremental.parsing.ParseFileUtilsKt", true, classLoader)
val method = klass.getMethod("classesFqNames", Set::class.java)
@Suppress("UNCHECKED_CAST")
method.invoke(klass, files) as? Set<String>
} ?: emptySet()
private fun <T> withCompilerClassloader(
environment: JpsCompilerEnvironment,
fn: (ClassLoader) -> T
): T? {
val libPath = getLibPath(environment.kotlinPaths, environment.messageCollector) ?: return null
val kotlinPaths = KotlinPathsFromBaseDirectory(libPath)
val paths = kotlinPaths.classPath(KotlinPaths.ClassPaths.CompilerWithScripting).toMutableList()
jdkToolsJar?.let { paths.add(it) }
val classLoader = getOrCreateClassLoader(environment, paths)
return fn(classLoader)
}
}
@@ -0,0 +1,34 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.compilerRunner
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.preloading.ClassCondition
import org.jetbrains.kotlin.utils.KotlinPaths
class JpsCompilerEnvironment(
val kotlinPaths: KotlinPaths,
services: Services,
val classesToLoadByParent: ClassCondition,
messageCollector: MessageCollector,
outputItemsCollector: OutputItemsCollectorImpl,
val progressReporter: ProgressReporter
) : CompilerEnvironment(services, messageCollector, outputItemsCollector) {
override val outputItemsCollector: OutputItemsCollectorImpl
get() = super.outputItemsCollector as OutputItemsCollectorImpl
}
@@ -0,0 +1,50 @@
/*
* 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.compilerRunner
import org.jetbrains.kotlin.daemon.client.CompilerCallbackServicesFacadeServer
import org.jetbrains.kotlin.daemon.client.reportFromDaemon
import org.jetbrains.kotlin.daemon.common.JpsCompilerServicesFacade
import org.jetbrains.kotlin.daemon.common.SOCKET_ANY_FREE_PORT
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumer
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
import java.io.Serializable
internal class JpsCompilerServicesFacadeImpl(
private val env: JpsCompilerEnvironment,
port: Int = SOCKET_ANY_FREE_PORT
) : CompilerCallbackServicesFacadeServer(
env.services[IncrementalCompilationComponents::class.java],
env.services[LookupTracker::class.java],
env.services[CompilationCanceledStatus::class.java],
env.services[ExpectActualTracker::class.java],
env.services[IncrementalResultsConsumer::class.java],
env.services[IncrementalDataProvider::class.java],
port
), JpsCompilerServicesFacade {
override fun report(category: Int, severity: Int, message: String?, attachment: Serializable?) {
env.messageCollector.reportFromDaemon(
{ outFile, srcFiles -> env.outputItemsCollector.add(srcFiles, outFile) },
category, severity, message, attachment
)
}
}
@@ -0,0 +1,375 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.compilerRunner
import com.intellij.util.xmlb.XmlSerializerUtil
import org.jetbrains.annotations.TestOnly
import org.jetbrains.jps.api.GlobalOptions
import org.jetbrains.kotlin.cli.common.CompilerSystemProperties
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.arguments.*
import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil
import org.jetbrains.kotlin.config.CompilerSettings
import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.config.additionalArgumentsAsList
import org.jetbrains.kotlin.daemon.client.CompileServiceSession
import org.jetbrains.kotlin.daemon.client.KotlinCompilerClient
import org.jetbrains.kotlin.daemon.common.*
import org.jetbrains.kotlin.jps.build.KotlinBuilder
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.PrintStream
class JpsKotlinCompilerRunner {
private val log: KotlinLogger = JpsKotlinLogger(KotlinBuilder.LOG)
private var compilerSettings: CompilerSettings? = null
private inline fun withCompilerSettings(settings: CompilerSettings, fn: () -> Unit) {
val old = compilerSettings
try {
compilerSettings = settings
fn()
} finally {
compilerSettings = old
}
}
companion object {
@Volatile
private var _jpsCompileServiceSession: CompileServiceSession? = null
@TestOnly
fun shutdownDaemon() {
_jpsCompileServiceSession?.let {
try {
it.compileService.shutdown()
} catch (_: Throwable) {
}
}
_jpsCompileServiceSession = null
}
fun releaseCompileServiceSession() {
_jpsCompileServiceSession?.let {
try {
it.compileService.releaseCompileSession(it.sessionId)
} catch (_: Throwable) {
}
}
_jpsCompileServiceSession = null
}
@Synchronized
private fun getOrCreateDaemonConnection(newConnection: () -> CompileServiceSession?): CompileServiceSession? {
// TODO: consider adding state "ping" to the daemon interface
if (_jpsCompileServiceSession == null || _jpsCompileServiceSession!!.compileService.getDaemonOptions() !is CompileService.CallResult.Good<DaemonOptions>) {
releaseCompileServiceSession()
_jpsCompileServiceSession = newConnection()
}
return _jpsCompileServiceSession
}
const val FAIL_ON_FALLBACK_PROPERTY = "test.kotlin.jps.compiler.runner.fail.on.fallback"
}
fun classesFqNamesByFiles(
environment: JpsCompilerEnvironment,
files: Set<File>
): Set<String> = withDaemonOrFallback(
withDaemon = {
doWithDaemon(environment) { sessionId, daemon ->
daemon.classesFqNamesByFiles(
sessionId,
files.toSet() // convert to standard HashSet to avoid serialization issues
)
}
},
fallback = {
CompilerRunnerUtil.invokeClassesFqNames(environment, files)
}
)
fun runK2MetadataCompiler(
commonArguments: CommonCompilerArguments,
k2MetadataArguments: K2MetadataCompilerArguments,
compilerSettings: CompilerSettings,
environment: JpsCompilerEnvironment,
destination: String,
classpath: Collection<String>,
sourceFiles: Collection<File>
) {
val arguments = mergeBeans(commonArguments, XmlSerializerUtil.createCopy(k2MetadataArguments))
val classpathSet = arguments.classpath?.split(File.pathSeparator)?.toMutableSet() ?: mutableSetOf()
classpathSet.addAll(classpath)
arguments.classpath = classpath.joinToString(File.pathSeparator)
arguments.freeArgs = sourceFiles.map { it.absolutePath }
arguments.destination = arguments.destination ?: destination
withCompilerSettings(compilerSettings) {
runCompiler(KotlinCompilerClass.METADATA, arguments, environment)
}
}
fun runK2JvmCompiler(
commonArguments: CommonCompilerArguments,
k2jvmArguments: K2JVMCompilerArguments,
compilerSettings: CompilerSettings,
environment: JpsCompilerEnvironment,
moduleFile: File
) {
val arguments = mergeBeans(commonArguments, XmlSerializerUtil.createCopy(k2jvmArguments))
setupK2JvmArguments(moduleFile, arguments)
withCompilerSettings(compilerSettings) {
runCompiler(KotlinCompilerClass.JVM, arguments, environment)
}
}
fun runK2JsCompiler(
commonArguments: CommonCompilerArguments,
k2jsArguments: K2JSCompilerArguments,
compilerSettings: CompilerSettings,
environment: JpsCompilerEnvironment,
allSourceFiles: Collection<File>,
commonSources: Collection<File>,
sourceMapRoots: Collection<File>,
libraries: List<String>,
friendModules: List<String>,
outputFile: File
) {
log.debug("K2JS: common arguments: " + ArgumentUtils.convertArgumentsToStringList(commonArguments))
log.debug("K2JS: JS arguments: " + ArgumentUtils.convertArgumentsToStringList(k2jsArguments))
val arguments = mergeBeans(commonArguments, XmlSerializerUtil.createCopy(k2jsArguments))
log.debug("K2JS: merged arguments: " + ArgumentUtils.convertArgumentsToStringList(arguments))
setupK2JsArguments(outputFile, allSourceFiles, commonSources, libraries, friendModules, arguments)
if (arguments.sourceMap) {
arguments.sourceMapBaseDirs = sourceMapRoots.joinToString(File.pathSeparator) { it.path }
}
log.debug("K2JS: arguments after setup" + ArgumentUtils.convertArgumentsToStringList(arguments))
withCompilerSettings(compilerSettings) {
runCompiler(KotlinCompilerClass.JS, arguments, environment)
}
}
private fun compileWithDaemonOrFallback(
compilerClassName: String,
compilerArgs: CommonCompilerArguments,
environment: JpsCompilerEnvironment
) {
log.debug("Using kotlin-home = " + environment.kotlinPaths.homePath)
withDaemonOrFallback(
withDaemon = { compileWithDaemon(compilerClassName, compilerArgs, environment) },
fallback = { fallbackCompileStrategy(compilerArgs, compilerClassName, environment) }
)
}
private fun runCompiler(compilerClassName: String, compilerArgs: CommonCompilerArguments, environment: JpsCompilerEnvironment) {
try {
compileWithDaemonOrFallback(compilerClassName, compilerArgs, environment)
} catch (e: Throwable) {
MessageCollectorUtil.reportException(environment.messageCollector, e)
reportInternalCompilerError(environment.messageCollector)
}
}
private fun compileWithDaemon(
compilerClassName: String,
compilerArgs: CommonCompilerArguments,
environment: JpsCompilerEnvironment
): Int? {
val targetPlatform = when (compilerClassName) {
KotlinCompilerClass.JVM -> CompileService.TargetPlatform.JVM
KotlinCompilerClass.JS -> CompileService.TargetPlatform.JS
KotlinCompilerClass.METADATA -> CompileService.TargetPlatform.METADATA
else -> throw IllegalArgumentException("Unknown compiler type $compilerClassName")
}
val compilerMode = CompilerMode.JPS_COMPILER
val verbose = compilerArgs.verbose
val options = CompilationOptions(
compilerMode,
targetPlatform,
reportCategories(verbose),
reportSeverity(verbose),
requestedCompilationResults = emptyArray()
)
return doWithDaemon(environment) { sessionId, daemon ->
environment.withProgressReporter { progress ->
progress.compilationStarted()
daemon.compile(
sessionId,
withAdditionalCompilerArgs(compilerArgs),
options,
JpsCompilerServicesFacadeImpl(environment),
null
)
}
}
}
private fun <T> withDaemonOrFallback(withDaemon: () -> T?, fallback: () -> T): T =
if (isDaemonEnabled()) {
withDaemon() ?: fallback()
} else {
fallback()
}
private fun <T> doWithDaemon(
environment: JpsCompilerEnvironment,
fn: (sessionId: Int, daemon: CompileService) -> CompileService.CallResult<T>
): T? {
log.debug("Try to connect to daemon")
val connection = getDaemonConnection(environment)
if (connection == null) {
log.info("Could not connect to daemon")
return null
}
val (daemon, sessionId) = connection
val res = fn(sessionId, daemon)
// TODO: consider implementing connection retry, instead of fallback here
return res.takeUnless { it is CompileService.CallResult.Dying }?.get()
}
private fun withAdditionalCompilerArgs(compilerArgs: CommonCompilerArguments): Array<String> {
val allArgs = ArgumentUtils.convertArgumentsToStringList(compilerArgs) +
(compilerSettings?.additionalArgumentsAsList ?: emptyList())
return allArgs.toTypedArray()
}
private fun reportCategories(verbose: Boolean): Array<Int> {
val categories =
if (!verbose) {
arrayOf(ReportCategory.COMPILER_MESSAGE, ReportCategory.EXCEPTION)
} else {
ReportCategory.values()
}
return categories.map { it.code }.toTypedArray()
}
private fun reportSeverity(verbose: Boolean): Int =
if (!verbose) {
ReportSeverity.INFO.code
} else {
ReportSeverity.DEBUG.code
}
private fun fallbackCompileStrategy(
compilerArgs: CommonCompilerArguments,
compilerClassName: String,
environment: JpsCompilerEnvironment
) {
if ("true" == System.getProperty("kotlin.jps.tests") && "true" == System.getProperty(FAIL_ON_FALLBACK_PROPERTY)) {
error("Cannot compile with Daemon, see logs bellow. Fallback strategy is disabled in tests")
}
// otherwise fallback to in-process
log.info("Compile in-process")
val stream = ByteArrayOutputStream()
val out = PrintStream(stream)
// the property should be set at least for parallel builds to avoid parallel building problems (racing between destroying and using environment)
// unfortunately it cannot be currently set by default globally, because it breaks many tests
// since there is no reliable way so far to detect running under tests, switching it on only for parallel builds
if (System.getProperty(GlobalOptions.COMPILE_PARALLEL_OPTION, "false").toBoolean())
CompilerSystemProperties.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY.value = "true"
val rc = environment.withProgressReporter { progress ->
progress.compilationStarted()
CompilerRunnerUtil.invokeExecMethod(compilerClassName, withAdditionalCompilerArgs(compilerArgs), environment, out)
}
// exec() returns an ExitCode object, class of which is loaded with a different class loader,
// so we take it's contents through reflection
val exitCode = ExitCode.valueOf(getReturnCodeFromObject(rc))
processCompilerOutput(environment.messageCollector, environment.outputItemsCollector, stream, exitCode)
}
private fun setupK2JvmArguments(moduleFile: File, settings: K2JVMCompilerArguments) {
with(settings) {
buildFile = moduleFile.absolutePath
destination = null
noStdlib = true
noReflect = true
noJdk = true
}
}
private fun setupK2JsArguments(
_outputFile: File,
allSourceFiles: Collection<File>,
_commonSources: Collection<File>,
_libraries: List<String>,
_friendModules: List<String>,
settings: K2JSCompilerArguments
) {
with(settings) {
noStdlib = true
freeArgs = allSourceFiles.map { it.path }.toMutableList()
commonSources = _commonSources.map { it.path }.toTypedArray()
outputFile = _outputFile.path
metaInfo = true
libraries = _libraries.joinToString(File.pathSeparator)
friendModules = _friendModules.joinToString(File.pathSeparator)
}
}
private fun getReturnCodeFromObject(rc: Any?): String = when {
rc == null -> ExitCode.INTERNAL_ERROR.toString()
ExitCode::class.java.name == rc::class.java.name -> rc.toString()
else -> throw IllegalStateException("Unexpected return: " + rc)
}
private fun getDaemonConnection(environment: JpsCompilerEnvironment): CompileServiceSession? =
getOrCreateDaemonConnection {
environment.progressReporter.progress("connecting to daemon")
val libPath = CompilerRunnerUtil.getLibPath(environment.kotlinPaths, environment.messageCollector)
val compilerPath = File(libPath, "kotlin-compiler.jar")
val daemonJarPath = File(libPath, "kotlin-daemon.jar")
val toolsJarPath = CompilerRunnerUtil.jdkToolsJar
val compilerId = CompilerId.makeCompilerId(listOfNotNull(compilerPath, toolsJarPath, daemonJarPath))
val daemonOptions = configureDaemonOptions()
val additionalJvmParams = mutableListOf<String>()
IncrementalCompilation.toJvmArgs(additionalJvmParams)
val clientFlagFile = KotlinCompilerClient.getOrCreateClientFlagFile(daemonOptions)
val sessionFlagFile = makeAutodeletingFlagFile("compiler-jps-session-", File(daemonOptions.runFilesPathOrDefault))
environment.withProgressReporter { progress ->
progress.progress("connecting to daemon")
KotlinCompilerRunnerUtils.newDaemonConnection(
compilerId,
clientFlagFile,
sessionFlagFile,
environment.messageCollector,
log.isDebugEnabled,
daemonOptions,
additionalJvmParams.toTypedArray()
)
}
}
}
@@ -0,0 +1,40 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.compilerRunner
import com.intellij.openapi.diagnostic.Logger
internal class JpsKotlinLogger(private val log: Logger) : KotlinLogger {
override fun error(msg: String) {
log.error(msg)
}
override fun warn(msg: String) {
log.warn(msg)
}
override fun info(msg: String) {
log.info(msg)
}
override fun debug(msg: String) {
log.debug(msg)
}
override val isDebugEnabled: Boolean
get() = log.isDebugEnabled
}
@@ -0,0 +1,38 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.compilerRunner
import org.jetbrains.jps.ModuleChunk
import org.jetbrains.jps.incremental.CompileContext
import org.jetbrains.jps.incremental.messages.ProgressMessage
interface ProgressReporter {
fun progress(message: String)
fun compilationStarted()
fun clearProgress()
}
class ProgressReporterImpl(private val context: CompileContext, private val chunk: ModuleChunk) : ProgressReporter {
override fun progress(message: String) {
context.processMessage(ProgressMessage("Kotlin: $message"))
}
override fun compilationStarted() {
progress("compiling [${chunk.presentableShortName}]")
}
override fun clearProgress() {
context.processMessage(ProgressMessage(""))
}
}
inline fun <T> JpsCompilerEnvironment.withProgressReporter(fn: (ProgressReporter) -> T): T =
try {
fn(progressReporter)
} finally {
progressReporter.clearProgress()
}
@@ -0,0 +1,168 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.jps.build
import com.intellij.openapi.diagnostic.Logger
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.jps.ModuleChunk
import org.jetbrains.jps.builders.BuildRootDescriptor
import org.jetbrains.jps.builders.BuildTarget
import org.jetbrains.jps.builders.FileProcessor
import org.jetbrains.jps.builders.impl.DirtyFilesHolderBase
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor
import org.jetbrains.jps.builders.java.dependencyView.Mappings
import org.jetbrains.jps.incremental.BuildOperations
import org.jetbrains.jps.incremental.CompileContext
import org.jetbrains.jps.incremental.FSOperations
import org.jetbrains.jps.incremental.ModuleBuildTarget
import org.jetbrains.jps.incremental.fs.CompilationRound
import java.io.File
import java.util.HashMap
import kotlin.collections.*
/**
* Entry point for safely marking files as dirty.
*/
class FSOperationsHelper(
private val compileContext: CompileContext,
private val chunk: ModuleChunk,
private val dirtyFilesHolder: KotlinDirtySourceFilesHolder,
private val log: Logger
) {
private val moduleBasedFilter = ModulesBasedFileFilter(compileContext, chunk)
internal var hasMarkedDirty = false
private set
private val buildLogger = compileContext.testingContext?.buildLogger
fun markChunk(recursively: Boolean, kotlinOnly: Boolean, excludeFiles: Set<File> = setOf()) {
fun shouldMark(file: File): Boolean {
if (kotlinOnly && !file.isKotlinSourceFile) return false
if (file in excludeFiles) return false
hasMarkedDirty = true
return true
}
if (recursively) {
FSOperations.markDirtyRecursively(compileContext, CompilationRound.NEXT, chunk, ::shouldMark)
} else {
FSOperations.markDirty(compileContext, CompilationRound.NEXT, chunk, ::shouldMark)
}
}
internal fun markFilesForCurrentRound(files: Iterable<File>) {
files.forEach {
val root = compileContext.projectDescriptor.buildRootIndex.findJavaRootDescriptor(compileContext, it)
if (root != null) dirtyFilesHolder.byTarget[root.target]?._markDirty(it, root)
}
markFilesImpl(files, currentRound = true) { it.exists() && moduleBasedFilter.accept(it) }
}
/**
* Marks given [files] as dirty for current round and given [target] of [chunk].
*/
fun markFilesForCurrentRound(target: ModuleBuildTarget, files: Collection<File>) {
require(target in chunk.targets)
val targetDirtyFiles = dirtyFilesHolder.byTarget.getValue(target)
val dirtyFileToRoot = HashMap<File, JavaSourceRootDescriptor>()
files.forEach { file ->
val root = compileContext.projectDescriptor.buildRootIndex
.findAllParentDescriptors<BuildRootDescriptor>(file, compileContext)
.single { sourceRoot -> sourceRoot.target == target }
targetDirtyFiles._markDirty(file, root as JavaSourceRootDescriptor)
dirtyFileToRoot[file] = root
}
markFilesImpl(files, currentRound = true) { it.exists() }
cleanOutputsForNewDirtyFilesInCurrentRound(target, dirtyFileToRoot)
}
private fun cleanOutputsForNewDirtyFilesInCurrentRound(target: ModuleBuildTarget, dirtyFiles: Map<File, JavaSourceRootDescriptor>) {
val dirtyFilesHolder = object : DirtyFilesHolderBase<JavaSourceRootDescriptor, ModuleBuildTarget>(compileContext) {
override fun processDirtyFiles(processor: FileProcessor<JavaSourceRootDescriptor, ModuleBuildTarget>) {
dirtyFiles.forEach { (file, root) -> processor.apply(target, file, root) }
}
override fun hasDirtyFiles(): Boolean = dirtyFiles.isNotEmpty()
}
BuildOperations.cleanOutputsCorrespondingToChangedFiles(compileContext, dirtyFilesHolder)
}
fun markFiles(files: Iterable<File>) {
markFilesImpl(files, currentRound = false) { it.exists() }
}
fun markInChunkOrDependents(files: Iterable<File>, excludeFiles: Set<File>) {
markFilesImpl(files, currentRound = false) {
it !in excludeFiles && it.exists() && moduleBasedFilter.accept(it)
}
}
private inline fun markFilesImpl(
files: Iterable<File>,
currentRound: Boolean,
shouldMark: (File) -> Boolean
) {
val filesToMark = files.filterTo(HashSet(), shouldMark)
if (filesToMark.isEmpty()) return
val compilationRound = if (currentRound) {
buildLogger?.markedAsDirtyBeforeRound(filesToMark)
CompilationRound.CURRENT
} else {
buildLogger?.markedAsDirtyAfterRound(filesToMark)
hasMarkedDirty = true
CompilationRound.NEXT
}
for (fileToMark in filesToMark) {
FSOperations.markDirty(compileContext, compilationRound, fileToMark)
}
log.debug("Mark dirty: $filesToMark ($compilationRound)")
}
// Based on `JavaBuilderUtil#ModulesBasedFileFilter` from Intellij
private class ModulesBasedFileFilter(
private val context: CompileContext,
chunk: ModuleChunk
) : Mappings.DependentFilesFilter {
private val chunkTargets = chunk.targets
private val buildRootIndex = context.projectDescriptor.buildRootIndex
private val buildTargetIndex = context.projectDescriptor.buildTargetIndex
private val cache = HashMap<BuildTarget<*>, Set<BuildTarget<*>>>()
override fun accept(file: File): Boolean {
val rd = buildRootIndex.findJavaRootDescriptor(context, file) ?: return true
val target = rd.target
if (target in chunkTargets) return true
val targetOfFileWithDependencies = cache.getOrPut(target) { buildTargetIndex.getDependenciesRecursively(target, context) }
return ContainerUtil.intersects(targetOfFileWithDependencies, chunkTargets)
}
override fun belongsToCurrentTargetChunk(file: File): Boolean {
val rd = buildRootIndex.findJavaRootDescriptor(context, file)
return rd != null && chunkTargets.contains(rd.target)
}
}
}
@@ -0,0 +1,14 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build
import org.jetbrains.jps.model.JpsProject
import org.jetbrains.jps.model.serialization.JpsModelSerializationDataService
import org.jetbrains.kotlin.incremental.storage.RelativeFileToPathConverter
internal class JpsFileToPathConverter(
jpsProject: JpsProject
) : RelativeFileToPathConverter(JpsModelSerializationDataService.getBaseDirectory(jpsProject))
@@ -0,0 +1,772 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.jps.build
import com.intellij.openapi.diagnostic.Logger
import org.jetbrains.jps.ModuleChunk
import org.jetbrains.jps.builders.DirtyFilesHolder
import org.jetbrains.jps.builders.FileProcessor
import org.jetbrains.jps.builders.impl.DirtyFilesHolderBase
import org.jetbrains.jps.builders.java.JavaBuilderUtil
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor
import org.jetbrains.jps.builders.storage.BuildDataCorruptedException
import org.jetbrains.jps.incremental.*
import org.jetbrains.jps.incremental.ModuleLevelBuilder.ExitCode.*
import org.jetbrains.jps.incremental.java.JavaBuilder
import org.jetbrains.jps.model.JpsProject
import org.jetbrains.kotlin.build.GeneratedFile
import org.jetbrains.kotlin.build.GeneratedJvmClass
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil
import org.jetbrains.kotlin.compilerRunner.*
import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.config.KotlinModuleKind
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.daemon.common.isDaemonEnabled
import org.jetbrains.kotlin.incremental.*
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.build.report.ICReporterBase
import org.jetbrains.kotlin.jps.incremental.JpsIncrementalCache
import org.jetbrains.kotlin.jps.incremental.JpsLookupStorageManager
import org.jetbrains.kotlin.jps.model.kotlinKind
import org.jetbrains.kotlin.jps.targets.KotlinJvmModuleBuildTarget
import org.jetbrains.kotlin.jps.targets.KotlinModuleBuildTarget
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.preloading.ClassCondition
import org.jetbrains.kotlin.utils.KotlinPaths
import org.jetbrains.kotlin.utils.KotlinPathsFromHomeDir
import org.jetbrains.kotlin.utils.PathUtil
import java.io.File
import java.util.*
import kotlin.collections.HashSet
import kotlin.system.measureTimeMillis
class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
companion object {
const val KOTLIN_BUILDER_NAME: String = "Kotlin Builder"
val LOG = Logger.getInstance("#org.jetbrains.kotlin.jps.build.KotlinBuilder")
const val SKIP_CACHE_VERSION_CHECK_PROPERTY = "kotlin.jps.skip.cache.version.check"
const val JPS_KOTLIN_HOME_PROPERTY = "jps.kotlin.home"
val classesToLoadByParent: ClassCondition
get() = ClassCondition { className ->
className.startsWith("org.jetbrains.kotlin.load.kotlin.incremental.components.")
|| className.startsWith("org.jetbrains.kotlin.incremental.components.")
|| className.startsWith("org.jetbrains.kotlin.incremental.js")
|| className == "org.jetbrains.kotlin.config.Services"
|| className.startsWith("org.apache.log4j.") // For logging from compiler
|| className == "org.jetbrains.kotlin.progress.CompilationCanceledStatus"
|| className == "org.jetbrains.kotlin.progress.CompilationCanceledException"
|| className == "org.jetbrains.kotlin.modules.TargetId"
|| className == "org.jetbrains.kotlin.cli.common.ExitCode"
}
}
private val statisticsLogger = TeamcityStatisticsLogger()
override fun getPresentableName() = KOTLIN_BUILDER_NAME
override fun getCompilableFileExtensions() = arrayListOf("kt", "kts")
override fun buildStarted(context: CompileContext) {
logSettings(context)
}
private fun logSettings(context: CompileContext) {
LOG.debug("==========================================")
LOG.info("is Kotlin incremental compilation enabled for JVM: ${IncrementalCompilation.isEnabledForJvm()}")
LOG.info("is Kotlin incremental compilation enabled for JS: ${IncrementalCompilation.isEnabledForJs()}")
LOG.info("is Kotlin compiler daemon enabled: ${isDaemonEnabled()}")
val historyLabel = context.getBuilderParameter("history label")
if (historyLabel != null) {
LOG.info("Label in local history: $historyLabel")
}
}
/**
* Ensure Kotlin Context initialized.
* Kotlin Context should be initialized only when required (before first kotlin chunk build).
*/
private fun ensureKotlinContextInitialized(context: CompileContext): KotlinCompileContext {
val kotlinCompileContext = context.getUserData(kotlinCompileContextKey)
if (kotlinCompileContext != null) return kotlinCompileContext
// don't synchronize on context, since it is chunk local only
synchronized(kotlinCompileContextKey) {
val actualKotlinCompileContext = context.getUserData(kotlinCompileContextKey)
if (actualKotlinCompileContext != null) return actualKotlinCompileContext
try {
return initializeKotlinContext(context)
} catch (t: Throwable) {
jpsReportInternalBuilderError(context, Error("Cannot initialize Kotlin context: ${t.message}", t))
throw t
}
}
}
private fun initializeKotlinContext(context: CompileContext): KotlinCompileContext {
val kotlinContext: KotlinCompileContext
val time = measureTimeMillis {
kotlinContext = KotlinCompileContext(context)
context.putUserData(kotlinCompileContextKey, kotlinContext)
context.testingContext?.kotlinCompileContext = kotlinContext
if (kotlinContext.shouldCheckCacheVersions && kotlinContext.hasKotlin()) {
kotlinContext.checkCacheVersions()
}
kotlinContext.cleanupCaches()
kotlinContext.reportUnsupportedTargets()
}
LOG.info("Total Kotlin global compile context initialization time: $time ms")
return kotlinContext
}
override fun buildFinished(context: CompileContext) {
ensureKotlinContextDisposed(context)
}
private fun ensureKotlinContextDisposed(context: CompileContext) {
if (context.getUserData(kotlinCompileContextKey) != null) {
// don't synchronize on context, since it chunk local only
synchronized(kotlinCompileContextKey) {
val kotlinCompileContext = context.getUserData(kotlinCompileContextKey)
if (kotlinCompileContext != null) {
kotlinCompileContext.dispose()
context.putUserData(kotlinCompileContextKey, null)
statisticsLogger.reportTotal()
}
}
}
}
override fun chunkBuildStarted(context: CompileContext, chunk: ModuleChunk) {
super.chunkBuildStarted(context, chunk)
if (chunk.isDummy(context)) return
val kotlinContext = ensureKotlinContextInitialized(context)
val buildLogger = context.testingContext?.buildLogger
buildLogger?.chunkBuildStarted(context, chunk)
if (JavaBuilderUtil.isForcedRecompilationAllJavaModules(context)) return
val targets = chunk.targets
if (targets.none { kotlinContext.hasKotlinMarker[it] == true }) return
val kotlinChunk = kotlinContext.getChunk(chunk) ?: return
kotlinContext.checkChunkCacheVersion(kotlinChunk)
if (!kotlinContext.rebuildingAllKotlin && kotlinChunk.isEnabled) {
markAdditionalFilesForInitialRound(kotlinChunk, chunk, kotlinContext)
}
buildLogger?.afterChunkBuildStarted(context, chunk)
}
/**
* Invalidate usages of removed classes.
* See KT-13677 for more details.
*
* todo(1.2.80): move to KotlinChunk
* todo(1.2.80): got rid of jpsGlobalContext usages (replace with KotlinCompileContext)
*/
private fun markAdditionalFilesForInitialRound(
kotlinChunk: KotlinChunk,
chunk: ModuleChunk,
kotlinContext: KotlinCompileContext
) {
val context = kotlinContext.jpsContext
val dirtyFilesHolder = KotlinDirtySourceFilesHolder(
chunk,
context,
object : DirtyFilesHolderBase<JavaSourceRootDescriptor, ModuleBuildTarget>(context) {
override fun processDirtyFiles(processor: FileProcessor<JavaSourceRootDescriptor, ModuleBuildTarget>) {
FSOperations.processFilesToRecompile(context, chunk, processor)
}
}
)
val fsOperations = FSOperationsHelper(context, chunk, dirtyFilesHolder, LOG)
val representativeTarget = kotlinContext.targetsBinding[chunk.representativeTarget()] ?: return
// dependent caches are not required, since we are not going to update caches
val incrementalCaches = kotlinChunk.loadCaches(loadDependent = false)
val messageCollector = MessageCollectorAdapter(context, representativeTarget)
val environment = createCompileEnvironment(
kotlinContext.jpsContext,
representativeTarget,
incrementalCaches,
LookupTracker.DO_NOTHING,
ExpectActualTracker.DoNothing,
chunk,
messageCollector
) ?: return
val removedClasses = HashSet<String>()
for (target in kotlinChunk.targets) {
val cache = incrementalCaches[target] ?: continue
val dirtyFiles = dirtyFilesHolder.getDirtyFiles(target.jpsModuleBuildTarget).keys
val removedFiles = dirtyFilesHolder.getRemovedFiles(target.jpsModuleBuildTarget)
val existingClasses = JpsKotlinCompilerRunner().classesFqNamesByFiles(environment, dirtyFiles)
val previousClasses = cache.classesFqNamesBySources(dirtyFiles + removedFiles)
for (jvmClassName in previousClasses) {
val fqName = jvmClassName.asString()
if (fqName !in existingClasses) {
removedClasses.add(fqName)
}
}
}
val changesCollector = ChangesCollector()
removedClasses.forEach { changesCollector.collectSignature(FqName(it), areSubclassesAffected = true) }
val affectedByRemovedClasses = changesCollector.getDirtyFiles(incrementalCaches.values, kotlinContext.lookupStorageManager)
fsOperations.markFilesForCurrentRound(affectedByRemovedClasses.dirtyFiles + affectedByRemovedClasses.forceRecompileTogether)
}
override fun chunkBuildFinished(context: CompileContext, chunk: ModuleChunk) {
super.chunkBuildFinished(context, chunk)
if (chunk.isDummy(context)) return
// Temporary workaround for KT-33808
val kotlinContext = ensureKotlinContextInitialized(context)
for (target in chunk.targets) {
if (kotlinContext.hasKotlinMarker[target] != true) continue
val outputRoots = target.getOutputRoots(context)
if (outputRoots.size > 1) {
outputRoots.forEach { it.mkdirs() }
}
}
LOG.debug("------------------------------------------")
}
override fun build(
context: CompileContext,
chunk: ModuleChunk,
dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>,
outputConsumer: ModuleLevelBuilder.OutputConsumer
): ModuleLevelBuilder.ExitCode {
if (chunk.isDummy(context))
return NOTHING_DONE
val kotlinTarget = context.kotlinBuildTargets[chunk.representativeTarget()] ?: return OK
val messageCollector = MessageCollectorAdapter(context, kotlinTarget)
// New mpp project model: modules which is imported from sources sets of the compilations shouldn't be compiled for now.
// It should be compiled only as one of source root of target compilation, which is added in [KotlinSourceRootProvider].
if (chunk.modules.any { it.kotlinKind == KotlinModuleKind.SOURCE_SET_HOLDER }) {
if (chunk.modules.size > 1) {
messageCollector.report(
CompilerMessageSeverity.ERROR,
"Cyclically dependent modules are not supported in multiplatform projects"
)
return ABORT
}
return NOTHING_DONE
}
val kotlinDirtyFilesHolder = KotlinDirtySourceFilesHolder(chunk, context, dirtyFilesHolder)
val fsOperations = FSOperationsHelper(context, chunk, kotlinDirtyFilesHolder, LOG)
try {
val proposedExitCode =
doBuild(chunk, kotlinTarget, context, kotlinDirtyFilesHolder, messageCollector, outputConsumer, fsOperations)
val actualExitCode = if (proposedExitCode == OK && fsOperations.hasMarkedDirty) ADDITIONAL_PASS_REQUIRED else proposedExitCode
LOG.debug("Build result: $actualExitCode")
context.testingContext?.buildLogger?.buildFinished(actualExitCode)
return actualExitCode
} catch (e: StopBuildException) {
LOG.info("Caught exception: $e")
throw e
} catch (e: BuildDataCorruptedException) {
LOG.info("Caught exception: $e")
throw e
} catch (e: Throwable) {
LOG.info("Caught exception: $e")
MessageCollectorUtil.reportException(messageCollector, e)
return ABORT
}
}
private fun doBuild(
chunk: ModuleChunk,
representativeTarget: KotlinModuleBuildTarget<*>,
context: CompileContext,
kotlinDirtyFilesHolder: KotlinDirtySourceFilesHolder,
messageCollector: MessageCollectorAdapter,
outputConsumer: OutputConsumer,
fsOperations: FSOperationsHelper
): ModuleLevelBuilder.ExitCode {
// Workaround for Android Studio
if (representativeTarget is KotlinJvmModuleBuildTarget && !JavaBuilder.IS_ENABLED[context, true]) {
messageCollector.report(INFO, "Kotlin JPS plugin is disabled")
return NOTHING_DONE
}
val kotlinContext = context.kotlin
val kotlinChunk = chunk.toKotlinChunk(context)!!
if (!kotlinChunk.haveSameCompiler) {
messageCollector.report(
ERROR,
"Cyclically dependent modules ${kotlinChunk.presentableModulesToCompilersList} should have same compiler."
)
return ABORT
}
if (!kotlinChunk.isEnabled) {
return NOTHING_DONE
}
val projectDescriptor = context.projectDescriptor
val dataManager = projectDescriptor.dataManager
val targets = chunk.targets
val isChunkRebuilding = JavaBuilderUtil.isForcedRecompilationAllJavaModules(context)
|| targets.any { kotlinContext.rebuildAfterCacheVersionChanged[it] == true }
if (!kotlinDirtyFilesHolder.hasDirtyOrRemovedFiles) {
if (isChunkRebuilding) {
targets.forEach {
kotlinContext.hasKotlinMarker[it] = false
}
}
targets.forEach { kotlinContext.rebuildAfterCacheVersionChanged.clean(it) }
return NOTHING_DONE
}
// Request CHUNK_REBUILD when IC is off and there are dirty Kotlin files
// Otherwise unexpected compile error might happen, when there are Groovy files,
// but they are not dirty, so Groovy builder does not generate source stubs,
// and Kotlin builder is filtering out output directory from classpath
// (because it may contain outdated Java classes).
if (!isChunkRebuilding && !representativeTarget.isIncrementalCompilationEnabled) {
targets.forEach { kotlinContext.rebuildAfterCacheVersionChanged[it] = true }
return CHUNK_REBUILD_REQUIRED
}
val targetsWithoutOutputDir = targets.filter { it.outputDir == null }
if (targetsWithoutOutputDir.isNotEmpty()) {
messageCollector.report(ERROR, "Output directory not specified for " + targetsWithoutOutputDir.joinToString())
return ABORT
}
val project = projectDescriptor.project
val lookupTracker = getLookupTracker(project, representativeTarget)
val exceptActualTracer = ExpectActualTrackerImpl()
val incrementalCaches = kotlinChunk.loadCaches()
val environment = createCompileEnvironment(
context,
representativeTarget,
incrementalCaches,
lookupTracker,
exceptActualTracer,
chunk,
messageCollector
) ?: return ABORT
context.testingContext?.buildLogger?.compilingFiles(
kotlinDirtyFilesHolder.allDirtyFiles,
kotlinDirtyFilesHolder.allRemovedFilesFiles
)
if (LOG.isDebugEnabled) {
LOG.debug("Compiling files: ${kotlinDirtyFilesHolder.allDirtyFiles}")
}
val start = System.nanoTime()
val outputItemCollector = doCompileModuleChunk(
kotlinChunk,
representativeTarget,
kotlinChunk.compilerArguments,
context,
kotlinDirtyFilesHolder,
fsOperations,
environment,
incrementalCaches
)
statisticsLogger.registerStatistic(chunk, System.nanoTime() - start)
if (outputItemCollector == null) {
return NOTHING_DONE
}
val compilationErrors = Utils.ERRORS_DETECTED_KEY[context, false]
if (compilationErrors) {
LOG.info("Compiled with errors")
return ABORT
} else {
LOG.info("Compiled successfully")
}
val generatedFiles = getGeneratedFiles(context, chunk, environment.outputItemsCollector)
markDirtyComplementaryMultifileClasses(generatedFiles, kotlinContext, incrementalCaches, fsOperations)
val kotlinTargets = kotlinContext.targetsBinding
for ((target, outputItems) in generatedFiles) {
val kotlinTarget = kotlinTargets[target] ?: error("Could not find Kotlin target for JPS target $target")
kotlinTarget.registerOutputItems(outputConsumer, outputItems)
}
kotlinChunk.saveVersions()
if (targets.any { kotlinContext.hasKotlinMarker[it] == null }) {
fsOperations.markChunk(recursively = false, kotlinOnly = true, excludeFiles = kotlinDirtyFilesHolder.allDirtyFiles)
}
for (target in targets) {
kotlinContext.hasKotlinMarker[target] = true
kotlinContext.rebuildAfterCacheVersionChanged.clean(target)
}
kotlinChunk.targets.forEach {
it.doAfterBuild()
}
representativeTarget.updateChunkMappings(
context,
chunk,
kotlinDirtyFilesHolder,
generatedFiles,
incrementalCaches
)
if (!representativeTarget.isIncrementalCompilationEnabled) {
return OK
}
context.checkCanceled()
environment.withProgressReporter { progress ->
progress.progress("performing incremental compilation analysis")
val changesCollector = ChangesCollector()
for ((target, files) in generatedFiles) {
val kotlinModuleBuilderTarget = kotlinContext.targetsBinding[target]!!
kotlinModuleBuilderTarget.updateCaches(
kotlinDirtyFilesHolder,
incrementalCaches[kotlinModuleBuilderTarget]!!,
files,
changesCollector,
environment
)
}
updateLookupStorage(lookupTracker, kotlinContext.lookupStorageManager, kotlinDirtyFilesHolder)
if (!isChunkRebuilding) {
changesCollector.processChangesUsingLookups(
kotlinDirtyFilesHolder.allDirtyFiles,
kotlinContext.lookupStorageManager,
fsOperations,
incrementalCaches.values
)
}
}
return OK
}
// todo(1.2.80): got rid of ModuleChunk (replace with KotlinChunk)
// todo(1.2.80): introduce KotlinRoundCompileContext, move dirtyFilesHolder, fsOperations, environment to it
private fun doCompileModuleChunk(
kotlinChunk: KotlinChunk,
representativeTarget: KotlinModuleBuildTarget<*>,
commonArguments: CommonCompilerArguments,
context: CompileContext,
dirtyFilesHolder: KotlinDirtySourceFilesHolder,
fsOperations: FSOperationsHelper,
environment: JpsCompilerEnvironment,
incrementalCaches: Map<KotlinModuleBuildTarget<*>, JpsIncrementalCache>
): OutputItemsCollector? {
loadPlugins(representativeTarget, commonArguments, context)
kotlinChunk.targets.forEach {
it.nextRound(context)
}
if (representativeTarget.isIncrementalCompilationEnabled) {
for (target in kotlinChunk.targets) {
val cache = incrementalCaches[target]
val jpsTarget = target.jpsModuleBuildTarget
val targetDirtyFiles = dirtyFilesHolder.byTarget[jpsTarget]
if (cache != null && targetDirtyFiles != null) {
val dirtyFiles = targetDirtyFiles.dirty.keys + targetDirtyFiles.removed
val complementaryFiles = cache.getComplementaryFilesRecursive(dirtyFiles)
// Get all parts of @JvmMultifileClass file for simultaneous rebuild
var dirtyMultifileClassFiles: Collection<File> = emptyList()
if (cache is IncrementalJvmCache) {
dirtyMultifileClassFiles = cache.classesBySources(dirtyFiles)
.filter { cache.isMultifileFacade(it) }
.flatMap { cache.getAllPartsOfMultifileFacade(it).orEmpty() }
.flatMap { cache.sourcesByInternalName(it) }
.distinct()
.filter { !dirtyFiles.contains(it) }
}
fsOperations.markFilesForCurrentRound(jpsTarget, complementaryFiles + dirtyMultifileClassFiles)
cache.markDirty(targetDirtyFiles.dirty.keys + targetDirtyFiles.removed)
}
}
}
val isDoneSomething = representativeTarget.compileModuleChunk(commonArguments, dirtyFilesHolder, environment)
return if (isDoneSomething) environment.outputItemsCollector else null
}
private fun loadPlugins(
representativeTarget: KotlinModuleBuildTarget<*>,
commonArguments: CommonCompilerArguments,
context: CompileContext
) {
fun concatenate(strings: Array<String>?, cp: List<String>) = arrayOf(*strings.orEmpty(), *cp.toTypedArray())
for (argumentProvider in ServiceLoader.load(KotlinJpsCompilerArgumentsProvider::class.java)) {
val jpsModuleBuildTarget = representativeTarget.jpsModuleBuildTarget
// appending to pluginOptions
commonArguments.pluginOptions = concatenate(
commonArguments.pluginOptions,
argumentProvider.getExtraArguments(jpsModuleBuildTarget, context)
)
// appending to classpath
commonArguments.pluginClasspaths = concatenate(
commonArguments.pluginClasspaths,
argumentProvider.getClasspath(jpsModuleBuildTarget, context)
)
LOG.debug("Plugin loaded: ${argumentProvider::class.java.simpleName}")
}
}
private fun createCompileEnvironment(
context: CompileContext,
kotlinModuleBuilderTarget: KotlinModuleBuildTarget<*>,
incrementalCaches: Map<KotlinModuleBuildTarget<*>, JpsIncrementalCache>,
lookupTracker: LookupTracker,
exceptActualTracer: ExpectActualTracker,
chunk: ModuleChunk,
messageCollector: MessageCollectorAdapter
): JpsCompilerEnvironment? {
val compilerServices = with(Services.Builder()) {
kotlinModuleBuilderTarget.makeServices(this, incrementalCaches, lookupTracker, exceptActualTracer)
build()
}
val paths = computeKotlinPathsForJpsPlugin()
if (paths == null || !paths.homePath.exists()) {
messageCollector.report(
ERROR, "Cannot find kotlinc home. Make sure the plugin is properly installed, " +
"or specify $JPS_KOTLIN_HOME_PROPERTY system property"
)
return null
}
return JpsCompilerEnvironment(
paths,
compilerServices,
classesToLoadByParent,
messageCollector,
OutputItemsCollectorImpl(),
ProgressReporterImpl(context, chunk)
)
}
// When JPS is run on TeamCity, it can not rely on Kotlin plugin layout,
// so the path to Kotlin is specified in a system property
private fun computeKotlinPathsForJpsPlugin(): KotlinPaths? {
if (System.getProperty("kotlin.jps.tests").equals("true", ignoreCase = true)) {
return PathUtil.kotlinPathsForDistDirectory
}
val jpsKotlinHome = System.getProperty(JPS_KOTLIN_HOME_PROPERTY)
if (jpsKotlinHome != null) {
return KotlinPathsFromHomeDir(File(jpsKotlinHome))
}
val jar = PathUtil.pathUtilJar.takeIf(File::exists)
if (jar?.name == "kotlin-jps-plugin.jar") {
val pluginHome = jar.parentFile.parentFile.parentFile
return KotlinPathsFromHomeDir(File(pluginHome, PathUtil.HOME_FOLDER_NAME))
}
return null
}
private fun getGeneratedFiles(
context: CompileContext,
chunk: ModuleChunk,
outputItemCollector: OutputItemsCollectorImpl
): Map<ModuleBuildTarget, List<GeneratedFile>> {
// If there's only one target, this map is empty: get() always returns null, and the representativeTarget will be used below
val sourceToTarget = HashMap<File, ModuleBuildTarget>()
if (chunk.targets.size > 1) {
for (target in chunk.targets) {
context.kotlinBuildTargets[target]?.sourceFiles?.forEach {
sourceToTarget[it] = target
}
}
}
val representativeTarget = chunk.representativeTarget()
fun SimpleOutputItem.target() =
sourceFiles.firstOrNull()?.let { sourceToTarget[it] }
?: chunk.targets.singleOrNull { target ->
target.outputDir?.let { outputDir ->
outputFile.startsWith(outputDir)
} ?: false
}
?: representativeTarget
return outputItemCollector.outputs
.sortedBy { it.outputFile }
.groupBy(SimpleOutputItem::target, SimpleOutputItem::toGeneratedFile)
}
private fun updateLookupStorage(
lookupTracker: LookupTracker,
lookupStorageManager: JpsLookupStorageManager,
dirtyFilesHolder: KotlinDirtySourceFilesHolder
) {
if (lookupTracker !is LookupTrackerImpl)
throw AssertionError("Lookup tracker is expected to be LookupTrackerImpl, got ${lookupTracker::class.java}")
lookupStorageManager.withLookupStorage { lookupStorage ->
lookupStorage.removeLookupsFrom(dirtyFilesHolder.allDirtyFiles.asSequence() + dirtyFilesHolder.allRemovedFilesFiles.asSequence())
lookupStorage.addAll(lookupTracker.lookups, lookupTracker.pathInterner.values)
}
}
private fun markDirtyComplementaryMultifileClasses(
generatedFiles: Map<ModuleBuildTarget, List<GeneratedFile>>,
kotlinContext: KotlinCompileContext,
incrementalCaches: Map<KotlinModuleBuildTarget<*>, JpsIncrementalCache>,
fsOperations: FSOperationsHelper
) {
for ((target, files) in generatedFiles) {
val kotlinModuleBuilderTarget = kotlinContext.targetsBinding[target] ?: continue
val cache = incrementalCaches[kotlinModuleBuilderTarget] as? IncrementalJvmCache ?: continue
val generated = files.filterIsInstance<GeneratedJvmClass>()
val multifileClasses = generated.filter { it.outputClass.classHeader.kind == KotlinClassHeader.Kind.MULTIFILE_CLASS }
val expectedAllParts = multifileClasses.flatMap { cache.getAllPartsOfMultifileFacade(it.outputClass.className).orEmpty() }
if (multifileClasses.isEmpty()) continue
val actualParts = generated.filter { it.outputClass.classHeader.kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART }
.map { it.outputClass.className.toString() }
if (!actualParts.containsAll(expectedAllParts)) {
fsOperations.markFiles(expectedAllParts.flatMap { cache.sourcesByInternalName(it) }
+ multifileClasses.flatMap { it.sourceFiles })
}
}
}
}
private class JpsICReporter : ICReporterBase() {
override fun reportCompileIteration(incremental: Boolean, sourceFiles: Collection<File>, exitCode: ExitCode) {
}
override fun report(message: () -> String) {
if (KotlinBuilder.LOG.isDebugEnabled) {
KotlinBuilder.LOG.debug(message())
}
}
override fun reportVerbose(message: () -> String) {
report(message)
}
}
private fun ChangesCollector.processChangesUsingLookups(
compiledFiles: Set<File>,
lookupStorageManager: JpsLookupStorageManager,
fsOperations: FSOperationsHelper,
caches: Iterable<JpsIncrementalCache>
) {
val allCaches = caches.flatMap { it.thisWithDependentCaches }
val reporter = JpsICReporter()
reporter.reportVerbose { "Start processing changes" }
val dirtyFiles = getDirtyFiles(allCaches, lookupStorageManager)
// if list of inheritors of sealed class has changed it should be recompiled with all the inheritors
// Here we have a small optimization. Do not recompile the bunch if ALL these files were recompiled during the previous round.
val excludeFiles = if (compiledFiles.containsAll(dirtyFiles.forceRecompileTogether))
compiledFiles
else
compiledFiles.minus(dirtyFiles.forceRecompileTogether)
fsOperations.markInChunkOrDependents(
(dirtyFiles.dirtyFiles + dirtyFiles.forceRecompileTogether).asIterable(),
excludeFiles = excludeFiles
)
reporter.reportVerbose { "End of processing changes" }
}
data class FilesToRecompile(val dirtyFiles: Set<File>, val forceRecompileTogether: Set<File>)
private fun ChangesCollector.getDirtyFiles(
caches: Iterable<IncrementalCacheCommon>,
lookupStorageManager: JpsLookupStorageManager
): FilesToRecompile {
val reporter = JpsICReporter()
val (dirtyLookupSymbols, dirtyClassFqNames, forceRecompile) = getDirtyData(caches, reporter)
val dirtyFilesFromLookups = lookupStorageManager.withLookupStorage {
mapLookupSymbolsToFiles(it, dirtyLookupSymbols, reporter)
}
return FilesToRecompile(
dirtyFilesFromLookups + mapClassesFqNamesToFiles(caches, dirtyClassFqNames, reporter),
mapClassesFqNamesToFiles(caches, forceRecompile, reporter)
)
}
private fun getLookupTracker(project: JpsProject, representativeTarget: KotlinModuleBuildTarget<*>): LookupTracker {
val testLookupTracker = project.testingContext?.lookupTracker ?: LookupTracker.DO_NOTHING
if (representativeTarget.isIncrementalCompilationEnabled) return LookupTrackerImpl(testLookupTracker)
return testLookupTracker
}
@@ -0,0 +1,32 @@
/*
* 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.jps.build;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.incremental.BuilderService;
import org.jetbrains.jps.incremental.ModuleLevelBuilder;
import java.util.Collections;
import java.util.List;
public class KotlinBuilderService extends BuilderService {
@NotNull
@Override
public List<? extends ModuleLevelBuilder> createModuleLevelBuilders() {
return Collections.singletonList(new KotlinBuilder());
}
}
@@ -0,0 +1,166 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build
import org.jetbrains.jps.incremental.ModuleBuildTarget
import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.config.VersionView
import org.jetbrains.kotlin.jps.incremental.CacheStatus
import org.jetbrains.kotlin.jps.incremental.JpsIncrementalCache
import org.jetbrains.kotlin.jps.incremental.getKotlinCache
import org.jetbrains.kotlin.jps.model.kotlinCompilerArguments
import org.jetbrains.kotlin.jps.targets.KotlinModuleBuildTarget
import org.jetbrains.kotlin.utils.keysToMapExceptNulls
import java.io.File
/**
* Chunk of cyclically dependent [KotlinModuleBuildTarget]s
*/
class KotlinChunk internal constructor(val context: KotlinCompileContext, val targets: List<KotlinModuleBuildTarget<*>>) {
val containsTests = targets.any { it.isTests }
lateinit var dependencies: List<KotlinModuleBuildTarget.Dependency>
// Should be initialized only in KotlinChunk.calculateChunkDependencies
internal set
lateinit var dependent: List<KotlinModuleBuildTarget.Dependency>
// Should be initialized only in KotlinChunk.calculateChunkDependencies
internal set
// used only during dependency calculation
internal var _dependent: MutableSet<KotlinModuleBuildTarget.Dependency>? = mutableSetOf()
val representativeTarget
get() = targets.first()
val presentableModulesToCompilersList: String
get() = targets.joinToString { "${it.module.name} (${it.globalLookupCacheId})" }
val haveSameCompiler = targets.all { it.javaClass == representativeTarget.javaClass }
private val defaultLanguageVersion = VersionView.RELEASED_VERSION
val compilerArguments = representativeTarget.jpsModuleBuildTarget.module.kotlinCompilerArguments.also {
it.reportOutputFiles = true
// Always report the version to help diagnosing user issues if they submit the compiler output
it.version = true
if (it.languageVersion == null) it.languageVersion = defaultLanguageVersion.versionString
}
val langVersion =
compilerArguments.languageVersion?.let { LanguageVersion.fromVersionString(it) }
?: defaultLanguageVersion // use default language version when version string is invalid (todo: report warning?)
val apiVersion =
compilerArguments.apiVersion?.let { ApiVersion.parse(it) }
?: ApiVersion.createByLanguageVersion(langVersion) // todo: report version parse error?
val isEnabled: Boolean = representativeTarget.isEnabled(compilerArguments)
fun shouldRebuild(): Boolean {
val buildMetaInfo = representativeTarget.buildMetaInfoFactory.create(compilerArguments)
targets.forEach { target ->
if (target.isVersionChanged(this, buildMetaInfo)) {
KotlinBuilder.LOG.info("$target version changed, rebuilding $this")
return true
}
if (target.initialLocalCacheAttributesDiff.status == CacheStatus.INVALID) {
context.testingLogger?.invalidOrUnusedCache(this, null, target.initialLocalCacheAttributesDiff)
KotlinBuilder.LOG.info("$target cache is invalid ${target.initialLocalCacheAttributesDiff}, rebuilding $this")
return true
}
}
return false
}
fun buildMetaInfoFile(target: ModuleBuildTarget): File =
File(
context.dataPaths.getTargetDataRoot(target),
representativeTarget.buildMetaInfoFileName
)
fun saveVersions() {
context.ensureLookupsCacheAttributesSaved()
targets.forEach {
it.initialLocalCacheAttributesDiff.manager.writeVersion()
}
val serializedMetaInfo = representativeTarget.buildMetaInfoFactory.serializeToString(compilerArguments)
targets.forEach {
buildMetaInfoFile(it.jpsModuleBuildTarget).writeText(serializedMetaInfo)
}
}
fun collectDependentChunksRecursivelyExportedOnly(result: MutableSet<KotlinChunk> = mutableSetOf()) {
dependent.forEach {
if (result.add(it.src.chunk)) {
if (it.exported) {
it.src.chunk.collectDependentChunksRecursivelyExportedOnly(result)
}
}
}
}
fun loadCaches(loadDependent: Boolean = true): Map<KotlinModuleBuildTarget<*>, JpsIncrementalCache> {
val dataManager = context.dataManager
val cacheByChunkTarget = targets.keysToMapExceptNulls {
dataManager.getKotlinCache(it)
}
if (loadDependent) {
addDependentCaches(cacheByChunkTarget.values)
}
return cacheByChunkTarget
}
private fun addDependentCaches(targetsCaches: Collection<JpsIncrementalCache>) {
val dependentChunks = mutableSetOf<KotlinChunk>()
collectDependentChunksRecursivelyExportedOnly(dependentChunks)
val dataManager = context.dataManager
dependentChunks.forEach { decedentChunk ->
decedentChunk.targets.forEach {
val dependentCache = dataManager.getKotlinCache(it)
if (dependentCache != null) {
for (chunkCache in targetsCaches) {
chunkCache.addJpsDependentCache(dependentCache)
}
}
}
}
}
/**
* The same as [org.jetbrains.jps.ModuleChunk.getPresentableShortName]
*/
val presentableShortName: String
get() = buildString {
if (containsTests) append("tests of ")
append(targets.first().module.name)
if (targets.size > 1) {
val andXMore = " and ${targets.size - 1} more"
val other = ", " + targets.asSequence().drop(1).joinToString()
append(if (other.length < andXMore.length) other else andXMore)
}
}
override fun toString(): String {
return "KotlinChunk<${representativeTarget.javaClass.simpleName}>" +
"(${targets.joinToString { it.jpsModuleBuildTarget.presentableName }})"
}
}
@@ -0,0 +1,314 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build
import org.jetbrains.jps.ModuleChunk
import org.jetbrains.jps.incremental.CompileContext
import org.jetbrains.jps.incremental.FSOperations
import org.jetbrains.jps.incremental.GlobalContextKey
import org.jetbrains.jps.incremental.fs.CompilationRound
import org.jetbrains.jps.incremental.messages.BuildMessage
import org.jetbrains.jps.incremental.messages.CompilerMessage
import org.jetbrains.kotlin.config.CompilerRunnerConstants
import org.jetbrains.kotlin.config.CompilerRunnerConstants.*
import org.jetbrains.kotlin.incremental.LookupSymbol
import org.jetbrains.kotlin.incremental.storage.FileToPathConverter
import org.jetbrains.kotlin.jps.incremental.*
import org.jetbrains.kotlin.jps.targets.KotlinTargetsIndex
import org.jetbrains.kotlin.jps.targets.KotlinTargetsIndexBuilder
import org.jetbrains.kotlin.jps.targets.KotlinUnsupportedModuleBuildTarget
import java.io.File
import java.util.concurrent.atomic.AtomicBoolean
/**
* KotlinCompileContext is shared between all threads (i.e. it is [GlobalContextKey]).
*
* It is initialized lazily, and only before building of first chunk with kotlin code,
* and will be disposed on build finish.
*/
internal val CompileContext.kotlin: KotlinCompileContext
get() {
val userData = getUserData(kotlinCompileContextKey)
if (userData != null) return userData
// here is error (KotlinCompilation available only at build phase)
// let's also check for concurrent initialization
val errorMessage = "KotlinCompileContext available only at build phase " +
"(between first KotlinBuilder.chunkBuildStarted and KotlinBuilder.buildFinished)"
synchronized(kotlinCompileContextKey) {
val newUsedData = getUserData(kotlinCompileContextKey)
if (newUsedData != null) {
error("Concurrent CompileContext.kotlin getter call and KotlinCompileContext initialization detected: $errorMessage")
}
}
error(errorMessage)
}
internal val kotlinCompileContextKey = GlobalContextKey<KotlinCompileContext>("kotlin")
class KotlinCompileContext(val jpsContext: CompileContext) {
val dataManager = jpsContext.projectDescriptor.dataManager
val dataPaths = dataManager.dataPaths
val testingLogger: TestingBuildLogger?
get() = jpsContext.testingContext?.buildLogger
val targetsIndex: KotlinTargetsIndex = KotlinTargetsIndexBuilder(this).build()
val targetsBinding
get() = targetsIndex.byJpsTarget
val lookupsCacheAttributesManager: CompositeLookupsCacheAttributesManager = makeLookupsCacheAttributesManager()
val shouldCheckCacheVersions = System.getProperty(KotlinBuilder.SKIP_CACHE_VERSION_CHECK_PROPERTY) == null
val hasKotlinMarker = HasKotlinMarker(dataManager)
val isInstrumentationEnabled: Boolean by lazy {
val value = System.getProperty("kotlin.jps.instrument.bytecode")?.toBoolean() ?: false
if (value) {
val message = "Experimental bytecode instrumentation for Kotlin classes is enabled"
jpsContext.processMessage(CompilerMessage(KOTLIN_COMPILER_NAME, BuildMessage.Kind.INFO, message))
}
value
}
val fileToPathConverter: FileToPathConverter =
JpsFileToPathConverter(jpsContext.projectDescriptor.project)
val lookupStorageManager = JpsLookupStorageManager(dataManager, fileToPathConverter)
/**
* Flag to prevent rebuilding twice.
*
* TODO: looks like it is not required since cache version checking are refactored
*/
val rebuildAfterCacheVersionChanged = RebuildAfterCacheVersionChangeMarker(dataManager)
var rebuildingAllKotlin = false
/**
* Note, [loadLookupsCacheStateDiff] should be initialized last as it requires initialized
* [targetsIndex], [hasKotlinMarker] and [rebuildAfterCacheVersionChanged] (see [markChunkForRebuildBeforeBuild])
*/
private val initialLookupsCacheStateDiff: CacheAttributesDiff<*> = loadLookupsCacheStateDiff()
private fun makeLookupsCacheAttributesManager(): CompositeLookupsCacheAttributesManager {
val expectedLookupsCacheComponents = mutableSetOf<String>()
targetsIndex.chunks.forEach { chunk ->
chunk.targets.forEach { target ->
if (target.isIncrementalCompilationEnabled) {
expectedLookupsCacheComponents.add(target.globalLookupCacheId)
}
}
}
val lookupsCacheRootPath = dataPaths.getTargetDataRoot(KotlinDataContainerTarget)
return CompositeLookupsCacheAttributesManager(lookupsCacheRootPath, expectedLookupsCacheComponents)
}
private fun loadLookupsCacheStateDiff(): CacheAttributesDiff<CompositeLookupsCacheAttributes> {
val diff = lookupsCacheAttributesManager.loadDiff()
if (diff.status == CacheStatus.VALID) {
// try to perform a lookup
// request rebuild if storage is corrupted
try {
lookupStorageManager.withLookupStorage {
it.get(LookupSymbol("<#NAME#>", "<#SCOPE#>"))
}
} catch (e: Exception) {
// replace to jpsReportInternalBuilderError when IDEA-201297 will be implemented
jpsContext.processMessage(
CompilerMessage(
"Kotlin", BuildMessage.Kind.WARNING,
"Incremental caches are corrupted. All Kotlin code will be rebuilt."
)
)
KotlinBuilder.LOG.info(Error("Lookup storage is corrupted, probe failed: ${e.message}", e))
markAllKotlinForRebuild("Lookup storage is corrupted")
return diff.copy(actual = null)
}
}
return diff
}
fun hasKotlin() = targetsIndex.chunks.any { chunk ->
chunk.targets.any { target ->
hasKotlinMarker[target] == true
}
}
fun checkCacheVersions() {
when (initialLookupsCacheStateDiff.status) {
CacheStatus.INVALID -> {
// global cache needs to be rebuilt
testingLogger?.invalidOrUnusedCache(null, null, initialLookupsCacheStateDiff)
if (initialLookupsCacheStateDiff.actual != null) {
markAllKotlinForRebuild("Kotlin incremental cache settings or format was changed")
clearLookupCache()
} else {
markAllKotlinForRebuild("Kotlin incremental cache is missed or corrupted")
}
}
CacheStatus.VALID -> Unit
CacheStatus.SHOULD_BE_CLEARED -> {
jpsContext.testingContext?.buildLogger?.invalidOrUnusedCache(null, null, initialLookupsCacheStateDiff)
KotlinBuilder.LOG.info("Removing global cache as it is not required anymore: $initialLookupsCacheStateDiff")
clearAllCaches()
}
CacheStatus.CLEARED -> Unit
}
}
private val lookupAttributesSaved = AtomicBoolean(false)
/**
* Called on every successful compilation
*/
fun ensureLookupsCacheAttributesSaved() {
if (lookupAttributesSaved.compareAndSet(false, true)) {
initialLookupsCacheStateDiff.manager.writeVersion()
}
}
fun checkChunkCacheVersion(chunk: KotlinChunk) {
if (shouldCheckCacheVersions && !rebuildingAllKotlin) {
if (chunk.shouldRebuild()) markChunkForRebuildBeforeBuild(chunk)
}
}
private fun logMarkDirtyForTestingBeforeRound(file: File, shouldProcess: Boolean): Boolean {
if (shouldProcess) {
testingLogger?.markedAsDirtyBeforeRound(listOf(file))
}
return shouldProcess
}
private fun markAllKotlinForRebuild(reason: String) {
if (rebuildingAllKotlin) return
rebuildingAllKotlin = true
KotlinBuilder.LOG.info("Rebuilding all Kotlin: $reason")
targetsIndex.chunks.forEach {
markChunkForRebuildBeforeBuild(it)
}
lookupStorageManager.cleanLookupStorage(KotlinBuilder.LOG)
}
private fun markChunkForRebuildBeforeBuild(chunk: KotlinChunk) {
chunk.targets.forEach {
FSOperations.markDirty(jpsContext, CompilationRound.NEXT, it.jpsModuleBuildTarget) { file ->
logMarkDirtyForTestingBeforeRound(file, file.isKotlinSourceFile)
}
dataManager.getKotlinCache(it)?.clean()
hasKotlinMarker.clean(it)
rebuildAfterCacheVersionChanged[it] = true
}
}
private fun clearAllCaches() {
clearLookupCache()
KotlinBuilder.LOG.info("Clearing caches for all targets")
targetsIndex.chunks.forEach { chunk ->
chunk.targets.forEach {
dataManager.getKotlinCache(it)?.clean()
}
}
}
private fun clearLookupCache() {
KotlinBuilder.LOG.info("Clearing lookup cache")
lookupStorageManager.cleanLookupStorage(KotlinBuilder.LOG)
initialLookupsCacheStateDiff.manager.writeVersion()
}
fun cleanupCaches() {
// todo: remove lookups for targets with disabled IC (or split global lookups cache into several caches for each compiler)
targetsIndex.chunks.forEach { chunk ->
chunk.targets.forEach { target ->
if (target.initialLocalCacheAttributesDiff.status == CacheStatus.SHOULD_BE_CLEARED) {
KotlinBuilder.LOG.info(
"$target caches is cleared as not required anymore: ${target.initialLocalCacheAttributesDiff}"
)
testingLogger?.invalidOrUnusedCache(null, target, target.initialLocalCacheAttributesDiff)
target.initialLocalCacheAttributesDiff.manager.writeVersion(null)
dataManager.getKotlinCache(target)?.clean()
}
}
}
}
fun dispose() {
}
fun getChunk(rawChunk: ModuleChunk): KotlinChunk? {
val rawRepresentativeTarget = rawChunk.representativeTarget()
if (rawRepresentativeTarget !in targetsBinding) return null
return targetsIndex.chunksByJpsRepresentativeTarget[rawRepresentativeTarget]
?: error("Kotlin binding for chunk $this is not loaded at build start")
}
fun reportUnsupportedTargets() {
// group all KotlinUnsupportedModuleBuildTarget by kind
// only representativeTarget will be added
val byKind = mutableMapOf<String?, MutableList<KotlinUnsupportedModuleBuildTarget>>()
targetsIndex.chunks.forEach {
val target = it.representativeTarget
if (target is KotlinUnsupportedModuleBuildTarget) {
if (target.sourceFiles.isNotEmpty()) {
byKind.getOrPut(target.kind) { mutableListOf() }.add(target)
}
}
}
byKind.forEach { (kind, targets) ->
targets.sortBy { it.module.name }
val chunkNames = targets.map { it.chunk.presentableShortName }
val presentableChunksListString = chunkNames.joinToReadableString()
val msg =
if (kind == null) {
"$presentableChunksListString is not yet supported in IDEA internal build system. " +
"Please use Gradle to build them (enable 'Delegate IDE build/run actions to Gradle' in Settings)."
} else {
"$kind is not yet supported in IDEA internal build system. " +
"Please use Gradle to build $presentableChunksListString (enable 'Delegate IDE build/run actions to Gradle' in Settings)."
}
testingLogger?.addCustomMessage(msg)
jpsContext.processMessage(
CompilerMessage(
KOTLIN_COMPILER_NAME,
BuildMessage.Kind.WARNING,
msg
)
)
}
}
}
fun List<String>.joinToReadableString(): String = when {
size > 5 -> take(5).joinToString() + " and ${size - 5} more"
size > 1 -> dropLast(1).joinToString() + " and ${last()}"
size == 1 -> single()
else -> ""
}
@@ -0,0 +1,111 @@
/*
* 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.jps.build
import com.intellij.openapi.util.io.FileUtilRt
import org.jetbrains.jps.ModuleChunk
import org.jetbrains.jps.builders.DirtyFilesHolder
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor
import org.jetbrains.jps.incremental.CompileContext
import org.jetbrains.jps.incremental.ModuleBuildTarget
import org.jetbrains.kotlin.jps.targets.KotlinModuleBuildTarget
import java.io.File
/**
* Holding kotlin dirty files list for particular build round.
* Dirty and removed files set are initialized from [delegate].
*
* Additional dirty files should be added only through [FSOperationsHelper.markFilesForCurrentRound]
*/
class KotlinDirtySourceFilesHolder(
val chunk: ModuleChunk,
val context: CompileContext,
delegate: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>
) {
val byTarget: Map<ModuleBuildTarget, TargetFiles>
inner class TargetFiles(val target: ModuleBuildTarget, val removed: Collection<File>) {
private val _dirty: MutableMap<File, KotlinModuleBuildTarget.Source> = mutableMapOf()
val dirty: Map<File, KotlinModuleBuildTarget.Source>
get() = _dirty
/**
* Should be called only from [FSOperationsHelper.markFilesForCurrentRound]
* and during KotlinDirtySourceFilesHolder initialization.
*/
internal fun _markDirty(file: File, root: JavaSourceRootDescriptor) {
val isCrossCompiled = root is KotlinIncludedModuleSourceRoot
val old = _dirty.put(file.canonicalFile, KotlinModuleBuildTarget.Source(file, isCrossCompiled))
check(old == null || old.isCrossCompiled == isCrossCompiled) {
"`${file.canonicalFile}` already marked as dirty: " +
"old is cross compiled: ${old!!.isCrossCompiled}, " +
"new is cross compiled: $isCrossCompiled"
}
}
}
val hasRemovedFiles: Boolean
get() = byTarget.any { it.value.removed.isNotEmpty() }
val hasDirtyFiles: Boolean
get() = byTarget.any { it.value.dirty.isNotEmpty() }
val hasDirtyOrRemovedFiles: Boolean
get() = hasRemovedFiles || hasDirtyFiles
init {
val byTarget = mutableMapOf<ModuleBuildTarget, TargetFiles>()
chunk.targets.forEach { target ->
val removedFiles = delegate.getRemovedFiles(target)
.map { File(it) }
.filter { it.isKotlinSourceFile }
byTarget[target] = TargetFiles(target, removedFiles)
}
delegate.processDirtyFiles { target, file, root ->
val targetInfo = byTarget[target]
?: error("processDirtyFiles should callback only on chunk `$chunk` targets (`$target` is not)")
if (file.isKotlinSourceFile) {
targetInfo._markDirty(file, root)
}
true
}
this.byTarget = byTarget
}
fun getDirtyFiles(target: ModuleBuildTarget): Map<File, KotlinModuleBuildTarget.Source> =
byTarget[target]?.dirty ?: mapOf()
fun getRemovedFiles(target: ModuleBuildTarget): Collection<File> =
byTarget[target]?.removed ?: listOf()
val allDirtyFiles: Set<File>
get() = byTarget.flatMapTo(mutableSetOf()) { it.value.dirty.keys }
val allRemovedFilesFiles: Set<File>
get() = byTarget.flatMapTo(mutableSetOf()) { it.value.removed }
}
val File.isKotlinSourceFile: Boolean
get() = FileUtilRt.extensionEquals(name, "kt") || FileUtilRt.extensionEquals(name, "kts")
@@ -0,0 +1,64 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build
import org.jetbrains.jps.api.BasicFuture
import org.jetbrains.jps.builders.java.JavaBuilderExtension
import org.jetbrains.jps.builders.java.dependencyView.Callbacks
import org.jetbrains.jps.incremental.CompileContext
import org.jetbrains.kotlin.incremental.LookupSymbol
import java.io.File
import java.util.concurrent.Executors
import java.util.concurrent.Future
import java.util.concurrent.TimeUnit
class KotlinJavaBuilderExtension : JavaBuilderExtension() {
override fun getConstantSearch(context: CompileContext): Callbacks.ConstantAffectionResolver {
return KotlinLookupConstantSearch(context)
}
}
private class KotlinLookupConstantSearch(context: CompileContext) : Callbacks.ConstantAffectionResolver {
private val pool = Executors.newSingleThreadExecutor()
private val kotlinContext by lazy { context.kotlin }
override fun request(
ownerClassName: String,
fieldName: String,
accessFlags: Int,
fieldRemoved: Boolean,
accessChanged: Boolean
): Future<Callbacks.ConstantAffection> {
val future = object : BasicFuture<Callbacks.ConstantAffection>() {
@Volatile
private var result: Callbacks.ConstantAffection = Callbacks.ConstantAffection.EMPTY
fun result(files: Collection<File>) {
result = Callbacks.ConstantAffection(files)
setDone()
}
override fun get(): Callbacks.ConstantAffection {
super.get()
return result
}
override fun get(timeout: Long, unit: TimeUnit): Callbacks.ConstantAffection {
super.get(timeout, unit)
return result
}
}
pool.submit {
if (!future.isCancelled) {
kotlinContext.lookupStorageManager.withLookupStorage { storage ->
val paths = storage.get(LookupSymbol(name = fieldName, scope = ownerClassName))
future.result(paths.map { File(it) })
}
}
}
return future
}
}
@@ -0,0 +1,25 @@
/*
* 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.jps.build
import org.jetbrains.jps.incremental.CompileContext
import org.jetbrains.jps.incremental.ModuleBuildTarget
interface KotlinJpsCompilerArgumentsProvider {
fun getExtraArguments(moduleBuildTarget: ModuleBuildTarget, context: CompileContext): List<String>
fun getClasspath(moduleBuildTarget: ModuleBuildTarget, context: CompileContext): List<String>
}
@@ -0,0 +1,50 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build
import org.jetbrains.jps.builders.AdditionalRootsProviderService
import org.jetbrains.jps.builders.BuildTarget
import org.jetbrains.jps.builders.java.ResourceRootDescriptor
import org.jetbrains.jps.builders.java.ResourcesTargetType
import org.jetbrains.jps.builders.storage.BuildDataPaths
import org.jetbrains.jps.incremental.ResourcesTarget
import org.jetbrains.jps.model.java.JavaResourceRootProperties
import org.jetbrains.kotlin.config.ResourceKotlinRootType
import org.jetbrains.kotlin.config.TestResourceKotlinRootType
class KotlinResourcesRootProvider : AdditionalRootsProviderService<ResourceRootDescriptor>(ResourcesTargetType.ALL_TYPES) {
override fun getAdditionalRoots(
target: BuildTarget<ResourceRootDescriptor>,
dataPaths: BuildDataPaths?
): List<ResourceRootDescriptor> {
val moduleBuildTarget = target as? ResourcesTarget ?: return listOf()
val module = moduleBuildTarget.module
val result = mutableListOf<ResourceRootDescriptor>()
// Add source roots with type KotlinResourceRootType.
// See the note in KotlinSourceRootProvider
val kotlinResourceRootType = if (target.isTests) TestResourceKotlinRootType else ResourceKotlinRootType
module.getSourceRoots(kotlinResourceRootType).forEach {
result.add(
ResourceRootDescriptor(
it.file,
target,
it.properties.packagePrefix,
setOf()
)
)
}
return result
}
}
/**
* Copied from implementation of org.jetbrains.jps.incremental.ResourcesTarget.computeRootDescriptors
*/
private val JavaResourceRootProperties.packagePrefix: String
get() = relativeOutputPath.replace('/', '.')
@@ -0,0 +1,112 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build
import org.jetbrains.jps.builders.AdditionalRootsProviderService
import org.jetbrains.jps.builders.BuildTarget
import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor
import org.jetbrains.jps.builders.storage.BuildDataPaths
import org.jetbrains.jps.incremental.ModuleBuildTarget
import org.jetbrains.jps.model.java.JavaResourceRootType
import org.jetbrains.jps.model.java.JavaSourceRootProperties
import org.jetbrains.jps.model.java.JavaSourceRootType
import org.jetbrains.jps.model.module.JpsModule
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.jps.model.expectedByModules
import org.jetbrains.kotlin.jps.model.isTestModule
import org.jetbrains.kotlin.jps.model.sourceSetModules
import java.io.File
class KotlinSourceRootProvider : AdditionalRootsProviderService<JavaSourceRootDescriptor>(JavaModuleBuildTargetType.ALL_TYPES) {
override fun getAdditionalRoots(
target: BuildTarget<JavaSourceRootDescriptor>,
dataPaths: BuildDataPaths?
): List<JavaSourceRootDescriptor> {
val moduleBuildTarget = target as? ModuleBuildTarget ?: return listOf()
val module = moduleBuildTarget.module
val result = mutableListOf<JavaSourceRootDescriptor>()
// Add source roots with type KotlinSourceRootType.
//
// Note: `KotlinSourceRootType` cannot be supported directly, since `SourceRootDescriptors` are computed by
// `ModuleBuildTarget.computeAllTargets`. `ModuleBuildTarget` is required for incremental compilation.
// We cannot define our own `ModuleBuildTarget` since it is final and `ModuleBuildTarget` supports only `JavaSourceRootDescriptor`.
// So the only one way to support `KotlinSourceRootType` is to add a fake `JavaSourceRootDescriptor` for each source root with that type.
val kotlinSourceRootType = if (target.isTests) TestSourceKotlinRootType else SourceKotlinRootType
module.getSourceRoots(kotlinSourceRootType).forEach {
result.add(
JavaSourceRootDescriptor(
it.file,
target,
false,
false,
it.properties.packagePrefix,
setOf()
)
)
}
// new multiplatform model support:
if (target.isTests == module.isTestModule) {
module.sourceSetModules.forEach { sourceSetModule ->
addModuleSourceRoots(result, sourceSetModule, target)
}
}
// legacy multiplatform model support:
module.expectedByModules.forEach { commonModule ->
addModuleSourceRoots(result, commonModule, target)
}
return result
}
private fun addModuleSourceRoots(
result: MutableList<JavaSourceRootDescriptor>,
module: JpsModule,
target: ModuleBuildTarget
) {
for (commonSourceRoot in module.sourceRoots) {
val isCommonTestsRootType = commonSourceRoot.rootType.isTestsRootType
if (isCommonTestsRootType != null && target.isTests == isCommonTestsRootType) {
val javaSourceRootProperties = commonSourceRoot.properties as? JavaSourceRootProperties
result.add(
KotlinIncludedModuleSourceRoot(
commonSourceRoot.file,
target,
javaSourceRootProperties?.isForGeneratedSources ?: false,
false,
javaSourceRootProperties?.packagePrefix ?: "",
setOf()
)
)
}
}
}
}
private val JpsModuleSourceRootType<*>.isTestsRootType
get() = when (this) {
is KotlinSourceRootType -> this == TestSourceKotlinRootType
is KotlinResourceRootType -> this == TestResourceKotlinRootType
// for compatibility:
is JavaSourceRootType -> this == JavaSourceRootType.TEST_SOURCE
is JavaResourceRootType -> this == JavaResourceRootType.TEST_RESOURCE
else -> null
}
class KotlinIncludedModuleSourceRoot(
root: File,
target: ModuleBuildTarget,
isGenerated: Boolean,
isTemp: Boolean,
packagePrefix: String,
excludes: Set<File>
) : JavaSourceRootDescriptor(root, target, isGenerated, isTemp, packagePrefix, excludes)
@@ -0,0 +1,71 @@
/*
* 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.jps.build
import org.jetbrains.jps.builders.storage.BuildDataPaths
import org.jetbrains.jps.incremental.ModuleBuildTarget
import org.jetbrains.jps.incremental.storage.BuildDataManager
import org.jetbrains.kotlin.incremental.KOTLIN_CACHE_DIRECTORY_NAME
import org.jetbrains.kotlin.jps.targets.KotlinModuleBuildTarget
import java.io.File
private val HAS_KOTLIN_MARKER_FILE_NAME = "has-kotlin-marker.txt"
private val REBUILD_AFTER_CACHE_VERSION_CHANGE_MARKER = "rebuild-after-cache-version-change-marker.txt"
abstract class MarkerFile(private val fileName: String, private val paths: BuildDataPaths) {
operator fun get(target: KotlinModuleBuildTarget<*>): Boolean? =
get(target.jpsModuleBuildTarget)
operator fun get(target: ModuleBuildTarget): Boolean? {
val file = target.markerFile
if (!file.exists()) return null
return file.readText().toBoolean()
}
operator fun set(target: KotlinModuleBuildTarget<*>, value: Boolean) =
set(target.jpsModuleBuildTarget, value)
operator fun set(target: ModuleBuildTarget, value: Boolean) {
val file = target.markerFile
if (!file.exists()) {
file.parentFile.mkdirs()
file.createNewFile()
}
file.writeText(value.toString())
}
fun clean(target: KotlinModuleBuildTarget<*>) =
clean(target.jpsModuleBuildTarget)
fun clean(target: ModuleBuildTarget) {
target.markerFile.delete()
}
private val ModuleBuildTarget.markerFile: File
get() {
val directory = File(paths.getTargetDataRoot(this), KOTLIN_CACHE_DIRECTORY_NAME)
return File(directory, fileName)
}
}
class HasKotlinMarker(dataManager: BuildDataManager) : MarkerFile(HAS_KOTLIN_MARKER_FILE_NAME, dataManager.dataPaths)
class RebuildAfterCacheVersionChangeMarker(dataManager: BuildDataManager) :
MarkerFile(REBUILD_AFTER_CACHE_VERSION_CHANGE_MARKER, dataManager.dataPaths)
@@ -0,0 +1,72 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build
import org.jetbrains.jps.incremental.CompileContext
import org.jetbrains.jps.incremental.messages.BuildMessage
import org.jetbrains.jps.incremental.messages.CompilerMessage
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.config.CompilerRunnerConstants
import org.jetbrains.kotlin.jps.targets.KotlinModuleBuildTarget
import java.io.File
class MessageCollectorAdapter(
private val context: CompileContext,
private val kotlinTarget: KotlinModuleBuildTarget<*>?
) : MessageCollector {
private var hasErrors = false
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?) {
hasErrors = hasErrors || severity.isError
var prefix = ""
if (severity == CompilerMessageSeverity.EXCEPTION) {
prefix = CompilerRunnerConstants.INTERNAL_ERROR_PREFIX
}
val kind = kind(severity)
if (kind != null) {
// Report target when cross-compiling common files
if (location != null && kotlinTarget != null && kotlinTarget.isFromIncludedSourceRoot(File(location.path))) {
val moduleName = kotlinTarget.module.name
prefix += "[$moduleName] "
}
context.processMessage(
CompilerMessage(
CompilerRunnerConstants.KOTLIN_COMPILER_NAME,
kind,
prefix + message,
location?.path,
-1, -1, -1,
location?.line?.toLong() ?: -1,
location?.column?.toLong() ?: -1
)
)
} else {
val path = if (location != null) "${location.path}:${location.line}:${location.column}: " else ""
KotlinBuilder.LOG.debug(path + message)
}
}
override fun clear() {
hasErrors = false
}
override fun hasErrors(): Boolean = hasErrors
private fun kind(severity: CompilerMessageSeverity): BuildMessage.Kind? {
return when (severity) {
CompilerMessageSeverity.INFO -> BuildMessage.Kind.INFO
CompilerMessageSeverity.ERROR, CompilerMessageSeverity.EXCEPTION -> BuildMessage.Kind.ERROR
CompilerMessageSeverity.WARNING, CompilerMessageSeverity.STRONG_WARNING -> BuildMessage.Kind.WARNING
CompilerMessageSeverity.LOGGING -> null
else -> throw IllegalArgumentException("Unsupported severity: $severity")
}
}
}
@@ -0,0 +1,87 @@
/*
* 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.jps.build
import org.jetbrains.jps.ModuleChunk
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicLong
class TeamcityStatisticsLogger {
private val isOnTeamcity = System.getenv("TEAMCITY_VERSION") != null
private val totalTime = AtomicLong()
//NOTE: mostly copied from TeamCityBuildInfoPrinter
private fun escapedChar(c: Char): Char {
return when (c) {
'\n' -> 'n'
'\r' -> 'r'
'\u0085' -> 'x' // next-line character
'\u2028' -> 'l' // line-separator character
'\u2029' -> 'p' // paragraph-separator character
'|' -> '|'
'\'' -> '\''
'[' -> '['
']' -> ']'
else -> 0.toChar()
}
}
private fun escape(text: String): String {
val escaped = StringBuilder()
for (c in text.toCharArray()) {
val escChar = escapedChar(c)
if (escChar == 0.toChar()) {
escaped.append(c)
} else {
escaped.append('|').append(escChar)
}
}
return escaped.toString()
}
fun registerStatistic(moduleChunk: ModuleChunk, timeToCompileNs: Long) {
if (!isOnTeamcity) return
totalTime.addAndGet(timeToCompileNs)
printPerChunkStatistics(moduleChunk, timeToCompileNs)
}
private fun printPerChunkStatistics(moduleChunk: ModuleChunk, timeToCompileNs: Long) {
printStatisticMessage(
"${KotlinBuilder.KOTLIN_BUILDER_NAME} for ${moduleChunk.presentableShortName} compilation time, ms",
timeToCompileNs.nanosToMillis().toString()
)
}
fun reportTotal() {
if (!isOnTeamcity) return
printStatisticMessage(
"${KotlinBuilder.KOTLIN_BUILDER_NAME} total compilation time, ms",
totalTime.get().nanosToMillis().toString()
)
}
private fun printStatisticMessage(key: String, value: String) {
println("##teamcity[buildStatisticValue key='${escape(key)}' value='${escape(value)}']")
}
private fun Long.nanosToMillis() = TimeUnit.NANOSECONDS.toMillis(this)
}
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.jps.build
import org.jetbrains.jps.incremental.CompileContext
import org.jetbrains.jps.incremental.ModuleLevelBuilder
import org.jetbrains.kotlin.jps.incremental.CacheAttributesDiff
import org.jetbrains.kotlin.jps.targets.KotlinModuleBuildTarget
import java.io.File
/**
* Used for assertions in tests.
*/
interface TestingBuildLogger {
fun invalidOrUnusedCache(chunk: KotlinChunk?, target: KotlinModuleBuildTarget<*>?, attributesDiff: CacheAttributesDiff<*>) = Unit
fun chunkBuildStarted(context: CompileContext, chunk: org.jetbrains.jps.ModuleChunk) = Unit
fun afterChunkBuildStarted(context: CompileContext, chunk: org.jetbrains.jps.ModuleChunk) = Unit
fun compilingFiles(files: Collection<File>, allRemovedFilesFiles: Collection<File>) = Unit
fun addCustomMessage(message: String) = Unit
fun buildFinished(exitCode: ModuleLevelBuilder.ExitCode) = Unit
fun markedAsDirtyBeforeRound(files: Iterable<File>) = Unit
fun markedAsDirtyAfterRound(files: Iterable<File>) = Unit
}
@@ -0,0 +1,46 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.jps.build
import org.jetbrains.annotations.TestOnly
import org.jetbrains.jps.incremental.CompileContext
import org.jetbrains.jps.model.JpsElementFactory
import org.jetbrains.jps.model.JpsProject
import org.jetbrains.jps.model.JpsSimpleElement
import org.jetbrains.jps.model.ex.JpsElementChildRoleBase
import org.jetbrains.kotlin.incremental.components.LookupTracker
private val TESTING_CONTEXT = JpsElementChildRoleBase.create<JpsSimpleElement<out TestingContext>>("Testing kcontext")
@TestOnly
fun JpsProject.setTestingContext(context: TestingContext) {
val dataContainer = JpsElementFactory.getInstance().createSimpleElement(context)
container.setChild(TESTING_CONTEXT, dataContainer)
}
val JpsProject.testingContext: TestingContext?
get() = container.getChild(TESTING_CONTEXT)?.data
val CompileContext.testingContext: TestingContext?
get() = projectDescriptor?.project?.testingContext
class TestingContext(
val lookupTracker: LookupTracker,
val buildLogger: TestingBuildLogger?
) {
var kotlinCompileContext: KotlinCompileContext? = null
}
@@ -0,0 +1,14 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build
import org.jetbrains.jps.incremental.CompileContext
import org.jetbrains.jps.incremental.messages.CompilerMessage
fun jpsReportInternalBuilderError(context: CompileContext, error: Throwable) {
val builderError = CompilerMessage.createInternalBuilderError("Kotlin", error)
context.processMessage(builderError)
}
@@ -0,0 +1,13 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build
import org.jetbrains.jps.incremental.CompileContext
import org.jetbrains.jps.incremental.messages.CompilerMessage
fun jpsReportInternalBuilderError(context: CompileContext, error: Throwable) {
KotlinBuilder.LOG.info(error)
}
@@ -0,0 +1,13 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.build
import org.jetbrains.jps.incremental.CompileContext
import org.jetbrains.jps.incremental.messages.CompilerMessage
fun jpsReportInternalBuilderError(context: CompileContext, error: Throwable) {
KotlinBuilder.LOG.info(error)
}

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