[Gradle] Read 'local.properties' in project isolation compatible way
^KT-59826 In Progress
This commit is contained in:
committed by
Space Team
parent
b1965e746f
commit
d6becee2ce
+54
-75
@@ -55,68 +55,57 @@ import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinIrJsGeneratedTSValidation
|
||||
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrOutputGranularity
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy
|
||||
import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader
|
||||
import org.jetbrains.kotlin.gradle.utils.loadProperty
|
||||
import org.jetbrains.kotlin.gradle.utils.localProperties
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.target.presetName
|
||||
import org.jetbrains.kotlin.statistics.metrics.StringMetrics
|
||||
import org.jetbrains.kotlin.tooling.core.UnsafeApi
|
||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
|
||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toUpperCaseAsciiOnly
|
||||
import org.jetbrains.kotlin.util.prefixIfNot
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
@OptIn(UnsafeApi::class)
|
||||
internal class PropertiesProvider private constructor(private val project: Project) {
|
||||
private val localProperties: Properties by lazy {
|
||||
Properties().apply {
|
||||
val localPropertiesFile = File(project.rootDir, "local.properties")
|
||||
if (localPropertiesFile.isFile) {
|
||||
localPropertiesFile.inputStream().use {
|
||||
load(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated(message = "Please use kotlin.build.report.output=SINGLE_FILE and kotlin.build.report.single_file ")
|
||||
val singleBuildMetricsFile: File?
|
||||
get() = this.property("kotlin.internal.single.build.metrics.file")?.let { File(it) }
|
||||
get() = property("kotlin.internal.single.build.metrics.file").orNull?.let { File(it) }
|
||||
|
||||
val buildReportSingleFile: File?
|
||||
get() = this.property(PropertyNames.KOTLIN_BUILD_REPORT_SINGLE_FILE)?.let { File(it) }
|
||||
get() = property(PropertyNames.KOTLIN_BUILD_REPORT_SINGLE_FILE).orNull?.let { File(it) }
|
||||
|
||||
val buildReportOutputs: List<String>
|
||||
get() = this.property("kotlin.build.report.output")?.split(",") ?: emptyList()
|
||||
get() = property("kotlin.build.report.output").orNull?.split(",") ?: emptyList()
|
||||
|
||||
val buildReportLabel: String?
|
||||
get() = this.property("kotlin.build.report.label")
|
||||
get() = property("kotlin.build.report.label").orNull
|
||||
|
||||
val buildReportFileOutputDir: File?
|
||||
get() = this.property("kotlin.build.report.file.output_dir")?.let { File(it) }
|
||||
get() = property("kotlin.build.report.file.output_dir").orNull?.let { File(it) }
|
||||
|
||||
val buildReportHttpUrl: String?
|
||||
get() = this.property(PropertyNames.KOTLIN_BUILD_REPORT_HTTP_URL)
|
||||
get() = property(PropertyNames.KOTLIN_BUILD_REPORT_HTTP_URL).orNull
|
||||
|
||||
val buildReportHttpUser: String?
|
||||
get() = this.property("kotlin.build.report.http.user")
|
||||
get() = property("kotlin.build.report.http.user").orNull
|
||||
|
||||
val buildReportHttpPassword: String?
|
||||
get() = this.property("kotlin.build.report.http.password")
|
||||
get() = property("kotlin.build.report.http.password").orNull
|
||||
|
||||
val buildReportHttpVerboseEnvironment: Boolean
|
||||
get() = property("kotlin.build.report.http.verbose_environment")?.toBoolean() ?: false
|
||||
get() = property("kotlin.build.report.http.verbose_environment").orNull?.toBoolean() ?: false
|
||||
|
||||
val buildReportHttpIncludeGitBranchName: Boolean
|
||||
get() = property("kotlin.build.report.http.include_git_branch.name")?.toBoolean() ?: false
|
||||
get() = property("kotlin.build.report.http.include_git_branch.name").orNull?.toBoolean() ?: false
|
||||
|
||||
val buildReportIncludeCompilerArguments: Boolean
|
||||
get() = booleanProperty("kotlin.build.report.include_compiler_arguments") ?: true
|
||||
|
||||
val buildReportBuildScanCustomValuesLimit: Int
|
||||
get() = property("kotlin.build.report.build_scan.custom_values_limit")?.toInt() ?: 1000
|
||||
get() = property("kotlin.build.report.build_scan.custom_values_limit").orNull?.toInt() ?: 1000
|
||||
|
||||
val buildReportBuildScanMetrics: String?
|
||||
get() = property("kotlin.build.report.build_scan.metrics")
|
||||
get() = property("kotlin.build.report.build_scan.metrics").orNull
|
||||
|
||||
val buildReportMetrics: Boolean
|
||||
get() = booleanProperty("kotlin.build.report.metrics") ?: false
|
||||
@@ -126,7 +115,7 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
||||
|
||||
@Deprecated("Please use \"kotlin.build.report.file.output_dir\" property instead")
|
||||
val buildReportDir: File?
|
||||
get() = this.property("kotlin.build.report.dir")?.let { File(it) }
|
||||
get() = property("kotlin.build.report.dir").orNull?.let { File(it) }
|
||||
|
||||
val incrementalJvm: Boolean?
|
||||
get() = booleanProperty("kotlin.incremental")
|
||||
@@ -144,22 +133,24 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
||||
get() = booleanProperty(PropertyNames.KOTLIN_NATIVE_INCREMENTAL_COMPILATION)
|
||||
|
||||
val jsIrOutputGranularity: KotlinJsIrOutputGranularity
|
||||
get() = this.property("kotlin.js.ir.output.granularity")?.let { KotlinJsIrOutputGranularity.byArgument(it) }
|
||||
get() = property("kotlin.js.ir.output.granularity").orNull?.let { KotlinJsIrOutputGranularity.byArgument(it) }
|
||||
?: KotlinJsIrOutputGranularity.PER_MODULE
|
||||
|
||||
val jsIrGeneratedTypeScriptValidationDevStrategy: KotlinIrJsGeneratedTSValidationStrategy
|
||||
get() = this.property("kotlin.js.ir.development.typescript.validation.strategy")?.let {
|
||||
KotlinIrJsGeneratedTSValidationStrategy.byArgument(
|
||||
it
|
||||
)
|
||||
} ?: KotlinIrJsGeneratedTSValidationStrategy.IGNORE
|
||||
get() = property("kotlin.js.ir.development.typescript.validation.strategy")
|
||||
.orNull?.let {
|
||||
KotlinIrJsGeneratedTSValidationStrategy.byArgument(
|
||||
it
|
||||
)
|
||||
} ?: KotlinIrJsGeneratedTSValidationStrategy.IGNORE
|
||||
|
||||
val jsIrGeneratedTypeScriptValidationProdStrategy: KotlinIrJsGeneratedTSValidationStrategy
|
||||
get() = this.property("kotlin.js.ir.production.typescript.validation.strategy")?.let {
|
||||
KotlinIrJsGeneratedTSValidationStrategy.byArgument(
|
||||
it
|
||||
)
|
||||
} ?: KotlinIrJsGeneratedTSValidationStrategy.IGNORE
|
||||
get() = property("kotlin.js.ir.production.typescript.validation.strategy")
|
||||
.orNull?.let {
|
||||
KotlinIrJsGeneratedTSValidationStrategy.byArgument(
|
||||
it
|
||||
)
|
||||
} ?: KotlinIrJsGeneratedTSValidationStrategy.IGNORE
|
||||
|
||||
val incrementalMultiplatform: Boolean?
|
||||
get() = booleanProperty("kotlin.incremental.multiplatform")
|
||||
@@ -251,7 +242,7 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
||||
get() = booleanProperty(KOTLIN_MPP_ANDROID_GRADLE_PLUGIN_COMPATIBILITY_NO_WARN) ?: false
|
||||
|
||||
val mppAndroidSourceSetLayoutVersion: Int?
|
||||
get() = this.property(KOTLIN_MPP_ANDROID_SOURCE_SET_LAYOUT_VERSION)?.toIntOrNull()
|
||||
get() = this.property(KOTLIN_MPP_ANDROID_SOURCE_SET_LAYOUT_VERSION).orNull?.toIntOrNull()
|
||||
|
||||
val ignoreMppAndroidSourceSetLayoutV2AndroidStyleDirs: Boolean
|
||||
get() = booleanProperty(KOTLIN_MPP_ANDROID_SOURCE_SET_LAYOUT_ANDROID_STYLE_NO_WARN) ?: false
|
||||
@@ -280,7 +271,7 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
||||
* - prebuilt - Includes all platform libraries.
|
||||
*/
|
||||
val nativeDistributionType: String?
|
||||
get() = this.property("kotlin.native.distribution.type")
|
||||
get() = property("kotlin.native.distribution.type").orNull
|
||||
|
||||
/**
|
||||
* Allows overriding Kotlin/Native base download url.
|
||||
@@ -288,7 +279,7 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
||||
* When Kotlin/native will try to download native compiler, it will append compiler version and os type to this url.
|
||||
*/
|
||||
val nativeBaseDownloadUrl: String
|
||||
get() = this.property("kotlin.native.distribution.baseDownloadUrl") ?: NativeCompilerDownloader.BASE_DOWNLOAD_URL
|
||||
get() = property("kotlin.native.distribution.baseDownloadUrl").orNull ?: NativeCompilerDownloader.BASE_DOWNLOAD_URL
|
||||
|
||||
/**
|
||||
* Allows downloading Kotlin/Native distribution with maven.
|
||||
@@ -332,7 +323,7 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
||||
* Allows a user to specify free compiler arguments for K/N linker.
|
||||
*/
|
||||
val nativeLinkArgs: List<String>
|
||||
get() = this.property("kotlin.native.linkArgs").orEmpty().split(' ').filterNot { it.isBlank() }
|
||||
get() = property("kotlin.native.linkArgs").orNull.orEmpty().split(' ').filterNot { it.isBlank() }
|
||||
|
||||
/**
|
||||
* Forces to run a compilation in a separate JVM.
|
||||
@@ -390,7 +381,7 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
||||
}
|
||||
|
||||
val commonizerLogLevel: String?
|
||||
get() = this.property("kotlin.mpp.commonizerLogLevel")
|
||||
get() = property("kotlin.mpp.commonizerLogLevel").orNull
|
||||
|
||||
val enableNativeDistributionCommonizationCache: Boolean
|
||||
get() = booleanProperty("kotlin.mpp.enableNativeDistributionCommonizationCache") ?: true
|
||||
@@ -408,25 +399,25 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
||||
* Dependencies caching strategy for all targets that support caches.
|
||||
*/
|
||||
val nativeCacheKind: NativeCacheKind?
|
||||
get() = this.property("kotlin.native.cacheKind")?.let { NativeCacheKind.byCompilerArgument(it) }
|
||||
get() = property("kotlin.native.cacheKind").orNull?.let { NativeCacheKind.byCompilerArgument(it) }
|
||||
|
||||
/**
|
||||
* Dependencies caching strategy for [target].
|
||||
*/
|
||||
fun nativeCacheKindForTarget(target: KonanTarget): NativeCacheKind? =
|
||||
this.property("kotlin.native.cacheKind.${target.presetName}")?.let { NativeCacheKind.byCompilerArgument(it) }
|
||||
property("kotlin.native.cacheKind.${target.presetName}").orNull?.let { NativeCacheKind.byCompilerArgument(it) }
|
||||
|
||||
/**
|
||||
* Dependencies caching orchestration machinery.
|
||||
*/
|
||||
val nativeCacheOrchestration: NativeCacheOrchestration?
|
||||
get() = this.property(PropertyNames.KOTLIN_NATIVE_CACHE_ORCHESTRATION)?.let { NativeCacheOrchestration.byCompilerArgument(it) }
|
||||
get() = property(PropertyNames.KOTLIN_NATIVE_CACHE_ORCHESTRATION).orNull?.let { NativeCacheOrchestration.byCompilerArgument(it) }
|
||||
|
||||
/**
|
||||
* Native backend threads.
|
||||
*/
|
||||
val nativeParallelThreads: Int?
|
||||
get() = this.property(PropertyNames.KOTLIN_NATIVE_PARALLEL_THREADS)?.toInt()
|
||||
get() = this.property(PropertyNames.KOTLIN_NATIVE_PARALLEL_THREADS).orNull?.toInt()
|
||||
|
||||
/**
|
||||
* Ignore overflow in [org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessageOutputStreamHandler]
|
||||
@@ -441,7 +432,7 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
||||
* Use Kotlin/JS backend compiler type
|
||||
*/
|
||||
val jsCompiler: KotlinJsCompilerType?
|
||||
get() = this.property(jsCompilerProperty)?.let { KotlinJsCompilerType.byArgumentOrNull(it) }
|
||||
get() = this.property(jsCompilerProperty).orNull?.let { KotlinJsCompilerType.byArgumentOrNull(it) }
|
||||
|
||||
/**
|
||||
* Use Kotlin/JS backend compiler publishing attribute
|
||||
@@ -480,11 +471,11 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
||||
)
|
||||
|
||||
val kotlinDaemonJvmArgs: String?
|
||||
get() = this.property("kotlin.daemon.jvmargs")
|
||||
get() = property("kotlin.daemon.jvmargs").orNull
|
||||
|
||||
val kotlinCompilerExecutionStrategy: KotlinCompilerExecutionStrategy
|
||||
get() = KotlinCompilerExecutionStrategy.fromProperty(
|
||||
this.property("kotlin.compiler.execution.strategy")?.toLowerCaseAsciiOnly()
|
||||
this.property("kotlin.compiler.execution.strategy").orNull?.toLowerCaseAsciiOnly()
|
||||
)
|
||||
|
||||
val kotlinDaemonUseFallbackStrategy: Boolean
|
||||
@@ -534,10 +525,10 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
||||
get() = booleanProperty(KOTLIN_INTERNAL_DIAGNOSTICS_SHOW_STACKTRACE)
|
||||
|
||||
val suppressedGradlePluginWarnings: List<String>
|
||||
get() = property(PropertyNames.KOTLIN_SUPPRESS_GRADLE_PLUGIN_WARNINGS)?.split(",").orEmpty()
|
||||
get() = property(PropertyNames.KOTLIN_SUPPRESS_GRADLE_PLUGIN_WARNINGS).orNull?.split(",").orEmpty()
|
||||
|
||||
val suppressedGradlePluginErrors: List<String>
|
||||
get() = property(PropertyNames.KOTLIN_SUPPRESS_GRADLE_PLUGIN_ERRORS)?.split(",").orEmpty()
|
||||
get() = property(PropertyNames.KOTLIN_SUPPRESS_GRADLE_PLUGIN_ERRORS).orNull?.split(",").orEmpty()
|
||||
|
||||
val suppressExperimentalArtifactsDslWarning: Boolean
|
||||
get() = booleanProperty(KOTLIN_NATIVE_SUPPRESS_EXPERIMENTAL_ARTIFACTS_DSL_WARNING) ?: false
|
||||
@@ -547,7 +538,7 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
||||
* This property takes precedence over the 'KONAN_DATA_DIR' environment variable.
|
||||
*/
|
||||
val konanDataDir: String?
|
||||
get() = property(PropertyNames.KONAN_DATA_DIR)
|
||||
get() = property(PropertyNames.KONAN_DATA_DIR).orNull
|
||||
|
||||
/**
|
||||
* Allows suppressing the diagnostic [KotlinToolingDiagnostics.BuildToolsApiVersionInconsistency].
|
||||
@@ -561,49 +552,37 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
||||
* @see KOTLIN_JS_KARMA_BROWSERS
|
||||
*/
|
||||
fun jsKarmaBrowsers(target: KotlinTarget? = null): String? =
|
||||
target?.name?.prefixIfNot("$KOTLIN_JS_KARMA_BROWSERS.")?.let(::property) ?: property(KOTLIN_JS_KARMA_BROWSERS)
|
||||
target?.name?.prefixIfNot("$KOTLIN_JS_KARMA_BROWSERS.")?.let { property(it).orNull }
|
||||
?: property(KOTLIN_JS_KARMA_BROWSERS).orNull
|
||||
|
||||
private fun propertyWithDeprecatedVariant(propName: String, deprecatedPropName: String): String? {
|
||||
val deprecatedProperty = this.property(deprecatedPropName)
|
||||
val deprecatedProperty = property(deprecatedPropName).orNull
|
||||
if (deprecatedProperty != null) {
|
||||
project.reportDiagnosticOncePerBuild(KotlinToolingDiagnostics.DeprecatedPropertyWithReplacement(deprecatedProperty, propName))
|
||||
}
|
||||
return this.property(propName) ?: deprecatedProperty
|
||||
return property(propName).orNull ?: deprecatedProperty
|
||||
}
|
||||
|
||||
private fun booleanProperty(propName: String): Boolean? =
|
||||
this.property(propName)?.toBoolean()
|
||||
property(propName).orNull?.toBoolean()
|
||||
|
||||
private inline fun <reified T : Enum<T>> enumProperty(
|
||||
propName: String,
|
||||
defaultValue: T,
|
||||
): T = this.property(propName)?.let { enumValueOf<T>(it.toUpperCaseAsciiOnly()) } ?: defaultValue
|
||||
): T = this.property(propName).orNull?.let { enumValueOf<T>(it.toUpperCaseAsciiOnly()) } ?: defaultValue
|
||||
|
||||
/**
|
||||
* Looks up the property in the following sources with decreasing priority:
|
||||
* 1. Project properties (-P, gradle.properties, etc...)
|
||||
* 2. `local.properties`
|
||||
*
|
||||
* Please prefer using dedicated properties for proper defaults handling.
|
||||
* Use this API only if you specifically need declared project properties disregarding defaults.
|
||||
*/
|
||||
@UnsafeApi
|
||||
internal fun property(propName: String): String? =
|
||||
if (project.hasProperty(propName)) {
|
||||
project.property(propName) as? String
|
||||
} else {
|
||||
localProperties.getProperty(propName)
|
||||
}
|
||||
private val localProperties = project.localProperties
|
||||
internal fun property(propName: String): Provider<String> = project.loadProperty(propName, localProperties)
|
||||
|
||||
private fun propertiesWithPrefix(prefix: String): Map<String, String> {
|
||||
val result: MutableMap<String, String> = mutableMapOf()
|
||||
project.properties.forEach { (name, value) ->
|
||||
if (name.startsWith(prefix) && value is String) {
|
||||
result.put(name, value)
|
||||
result[name] = value
|
||||
}
|
||||
}
|
||||
localProperties.forEach { (name, value) ->
|
||||
if (name is String && name.startsWith(prefix) && value is String) {
|
||||
localProperties.orNull?.forEach { (name, value) ->
|
||||
if (name.startsWith(prefix)) {
|
||||
// Project properties have higher priority.
|
||||
result.putIfAbsent(name, value)
|
||||
}
|
||||
|
||||
+1
-3
@@ -12,15 +12,13 @@ import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinGradleProjectChecker
|
||||
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinGradleProjectCheckerContext
|
||||
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics
|
||||
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnosticsCollector
|
||||
import org.jetbrains.kotlin.tooling.core.UnsafeApi
|
||||
|
||||
internal object InternalGradlePropertiesUsageChecker : KotlinGradleProjectChecker {
|
||||
override suspend fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) {
|
||||
KotlinPluginLifecycle.Stage.ReadyForExecution.await()
|
||||
|
||||
val internalPropertiesUsed = PropertiesProvider.PropertyNames.allInternalProperties().filter { name ->
|
||||
@OptIn(UnsafeApi::class)
|
||||
kotlinPropertiesProvider.property(name) != null
|
||||
kotlinPropertiesProvider.property(name).orNull != null
|
||||
}
|
||||
val internalPropertiesFiltered = internalPropertiesUsed.minus(PropertiesProvider.PropertyNames.MPP_13X_FLAGS_SET_BY_PLUGIN)
|
||||
if (internalPropertiesFiltered.isEmpty()) return
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.gradle.plugin.internal
|
||||
|
||||
import org.gradle.api.Describable
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.ValueSource
|
||||
import org.gradle.api.provider.ValueSourceParameters
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Allow loading a properties file content in configuration cache and project isolation compatible way by specifying
|
||||
* [Parameters.propertiesFile].
|
||||
*
|
||||
* Returned type is `Map<String, String>` due to the following [bug in Gradle](https://github.com/gradle/gradle/pull/24846) which
|
||||
* prevents proper serialization of [Properties] type.
|
||||
*
|
||||
* If the file does not exist - returned provider will be empty.
|
||||
*
|
||||
* Usage:
|
||||
* ```
|
||||
* project
|
||||
* .providers
|
||||
* .of(CustomFileValueSource::class.java) {
|
||||
* it.parameters.propertiesFile.set(project.layout.projectDirectory.file("my-properties-file-to-load"))
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
internal abstract class CustomPropertiesFileValueSource : ValueSource<Map<String, String>, CustomPropertiesFileValueSource.Parameters>,
|
||||
Describable {
|
||||
|
||||
interface Parameters : ValueSourceParameters {
|
||||
val propertiesFile: RegularFileProperty
|
||||
}
|
||||
|
||||
override fun getDisplayName(): String = "properties file ${parameters.propertiesFile.get().asFile.absolutePath}"
|
||||
|
||||
override fun obtain(): Map<String, String>? {
|
||||
val customFile = parameters.propertiesFile.get().asFile
|
||||
return if (customFile.exists()) {
|
||||
customFile.bufferedReader().use {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
Properties().apply { load(it) }.toMap() as Map<String, String>
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-3
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLI
|
||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_NATIVE_DEPENDENCY_PROPAGATION
|
||||
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics
|
||||
import org.jetbrains.kotlin.gradle.plugin.diagnostics.kotlinToolingDiagnosticsCollector
|
||||
import org.jetbrains.kotlin.tooling.core.UnsafeApi
|
||||
|
||||
internal fun runDeprecationDiagnostics(project: Project) {
|
||||
checkAndReportDeprecatedMppProperties(project)
|
||||
@@ -32,8 +31,7 @@ private fun checkAndReportDeprecatedMppProperties(project: Project) {
|
||||
if (propertyName in propertiesSetByPlugin && projectProperties.mpp13XFlagsSetByPlugin)
|
||||
return@mapNotNull null
|
||||
|
||||
@OptIn(UnsafeApi::class)
|
||||
propertyName.takeIf { projectProperties.property(propertyName) != null }
|
||||
propertyName.takeIf { projectProperties.property(propertyName).orNull != null }
|
||||
}
|
||||
|
||||
if (usedProperties.isEmpty()) return
|
||||
|
||||
+47
-21
@@ -9,16 +9,16 @@ import org.gradle.api.Project
|
||||
import org.gradle.api.file.Directory
|
||||
import org.gradle.api.file.RegularFile
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.jetbrains.kotlin.gradle.plugin.extraProperties
|
||||
import org.jetbrains.kotlin.gradle.plugin.getOrNull
|
||||
import org.jetbrains.kotlin.gradle.plugin.internal.CustomPropertiesFileValueSource
|
||||
import org.jetbrains.kotlin.gradle.plugin.internal.configurationTimePropertiesAccessor
|
||||
import org.jetbrains.kotlin.gradle.plugin.internal.usedAtConfigurationTime
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
|
||||
internal fun File.isJavaFile() =
|
||||
extension.equals("java", ignoreCase = true)
|
||||
|
||||
internal fun File.isKotlinFile(sourceFilesExtensions: List<String>): Boolean =
|
||||
!isJavaFile() && sourceFilesExtensions.any { it.equals(extension, ignoreCase = true) }
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Create all possible case-sensitive permutations for given [String].
|
||||
@@ -52,9 +52,6 @@ internal fun File.relativeOrAbsolute(base: File): String =
|
||||
internal fun Iterable<File>.pathsAsStringRelativeTo(base: File): String =
|
||||
map { it.relativeOrAbsolute(base) }.sorted().joinToString()
|
||||
|
||||
internal fun File.relativeToRoot(project: Project): String =
|
||||
relativeOrAbsolute(project.rootProject.rootDir)
|
||||
|
||||
internal fun Iterable<File>.toPathsArray(): Array<String> =
|
||||
map { it.normalize().absolutePath }.toTypedArray()
|
||||
|
||||
@@ -89,22 +86,13 @@ internal fun File.absolutePathWithoutExtension(): String =
|
||||
|
||||
internal fun File.listFilesOrEmpty() = (if (exists()) listFiles() else null).orEmpty()
|
||||
|
||||
internal inline fun <T> withTemporaryDirectory(prefix: String, action: (directory: File) -> T): T {
|
||||
val directory = Files.createTempDirectory(prefix).toFile()
|
||||
return try {
|
||||
action(directory)
|
||||
} finally {
|
||||
directory.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
fun contentEquals(file1: File, file2: File): Boolean {
|
||||
file1.useLines { seq1 ->
|
||||
file2.useLines { seq2 ->
|
||||
val iterator1 = seq1.iterator()
|
||||
val iterator2 = seq2.iterator()
|
||||
|
||||
while(iterator1.hasNext() == iterator2.hasNext()) {
|
||||
while (iterator1.hasNext() == iterator2.hasNext()) {
|
||||
|
||||
if (!iterator1.hasNext()) return true
|
||||
|
||||
@@ -130,7 +118,6 @@ internal fun Provider<RegularFile>.getFile(): File = get().asFile
|
||||
@JvmName("getDirectoryAsFile") // avoids jvm signature clash
|
||||
internal fun Provider<Directory>.getFile(): File = get().asFile
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the file exists, taking into account compatibility with different versions of Gradle.
|
||||
* It should be used instead of [File.exists] in checking UPD inputs. See KT-54232 for more info.
|
||||
@@ -144,4 +131,43 @@ internal fun File.existsCompat(): Boolean =
|
||||
true
|
||||
} else {
|
||||
exists()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up the property in the following sources with decreasing priority:
|
||||
* 1. Current project extra properties
|
||||
* 2. Project Gradle properties (-P, gradle.properties, etc...)
|
||||
* 3. `local.properties` file located in the rootDir
|
||||
*
|
||||
* If multiple properties are loaded from a same caller, it is better to cache `localProperties` into local variable.
|
||||
*/
|
||||
internal fun Project.loadProperty(
|
||||
propName: String,
|
||||
localPropertiesProvider: Provider<Map<String, String>> = localProperties
|
||||
): Provider<String> = providers
|
||||
.provider<String> {
|
||||
extraProperties.getOrNull(propName) as? String
|
||||
}
|
||||
.orElse(
|
||||
project.providers
|
||||
.gradleProperty(propName)
|
||||
.usedAtConfigurationTime(configurationTimePropertiesAccessor)
|
||||
)
|
||||
.orElse(
|
||||
@Suppress("TYPE_MISMATCH")
|
||||
localPropertiesProvider.map { it[propName] }
|
||||
)
|
||||
|
||||
/**
|
||||
* Loads 'local.properties' file content as [Properties].
|
||||
*
|
||||
* If it does not exist, returned [Provider] will be empty.
|
||||
*/
|
||||
internal val Project.localProperties: Provider<Map<String, String>>
|
||||
get() = providers
|
||||
.of(CustomPropertiesFileValueSource::class.java) {
|
||||
it.parameters.propertiesFile.set(
|
||||
project.rootDir.resolve("local.properties")
|
||||
)
|
||||
}
|
||||
.usedAtConfigurationTime(configurationTimePropertiesAccessor)
|
||||
|
||||
+19
-7
@@ -20,14 +20,20 @@ import kotlin.test.Test
|
||||
import kotlin.test.fail
|
||||
|
||||
class KT60388PlainJvmDependingOnJvmWithJavaTest {
|
||||
private val rootProject = buildProject {
|
||||
allprojects { project -> project.enableDefaultStdlibDependency(false) }
|
||||
}
|
||||
private val rootProject = buildProject()
|
||||
|
||||
@Test
|
||||
fun `test - plain jvm - depends on - jvm withJava`() {
|
||||
val producer = buildProjectWithMPP(projectBuilder = { withName("producer").withParent(rootProject) })
|
||||
val consumer = buildProjectWithJvm(projectBuilder = { withName("consumer").withParent(rootProject) })
|
||||
val producer = buildProjectWithMPP(
|
||||
projectBuilder = { withName("producer").withParent(rootProject) },
|
||||
preApplyCode = {
|
||||
enableDefaultStdlibDependency(false)
|
||||
}
|
||||
)
|
||||
val consumer = buildProjectWithJvm(
|
||||
projectBuilder = { withName("consumer").withParent(rootProject) },
|
||||
preApplyCode = { enableDefaultStdlibDependency(false) }
|
||||
)
|
||||
|
||||
producer.multiplatformExtension.apply {
|
||||
jvm().withJava()
|
||||
@@ -44,8 +50,14 @@ class KT60388PlainJvmDependingOnJvmWithJavaTest {
|
||||
|
||||
@Test
|
||||
fun `test - plain jvm - depends on - jvm withJava and java plugin`() {
|
||||
val producer = buildProjectWithMPP(projectBuilder = { withName("producer").withParent(rootProject) })
|
||||
val consumer = buildProjectWithJvm(projectBuilder = { withName("consumer").withParent(rootProject) })
|
||||
val producer = buildProjectWithMPP(
|
||||
projectBuilder = { withName("producer").withParent(rootProject) },
|
||||
preApplyCode = { enableDefaultStdlibDependency(false) }
|
||||
)
|
||||
val consumer = buildProjectWithJvm(
|
||||
projectBuilder = { withName("consumer").withParent(rootProject) },
|
||||
preApplyCode = { enableDefaultStdlibDependency(false) }
|
||||
)
|
||||
|
||||
producer.multiplatformExtension.apply {
|
||||
producer.plugins.apply("java")
|
||||
|
||||
+12
-2
@@ -37,7 +37,12 @@ fun buildProject(
|
||||
.apply(configureProject)
|
||||
.let { it as ProjectInternal }
|
||||
|
||||
fun buildProjectWithMPP(projectBuilder: ProjectBuilder.() -> Unit = { }, code: Project.() -> Unit = {}) = buildProject(projectBuilder) {
|
||||
fun buildProjectWithMPP(
|
||||
projectBuilder: ProjectBuilder.() -> Unit = { },
|
||||
preApplyCode: Project.() -> Unit = {},
|
||||
code: Project.() -> Unit = {}
|
||||
) = buildProject(projectBuilder) {
|
||||
preApplyCode()
|
||||
project.applyMultiplatformPlugin()
|
||||
disableLegacyWarning(project)
|
||||
code()
|
||||
@@ -48,7 +53,12 @@ fun buildProjectWithKPM(projectBuilder: ProjectBuilder.() -> Unit = { }, code: P
|
||||
code()
|
||||
}
|
||||
|
||||
fun buildProjectWithJvm(projectBuilder: ProjectBuilder.() -> Unit = {}, code: Project.() -> Unit = {}) = buildProject(projectBuilder) {
|
||||
fun buildProjectWithJvm(
|
||||
projectBuilder: ProjectBuilder.() -> Unit = {},
|
||||
preApplyCode: Project.() -> Unit = {},
|
||||
code: Project.() -> Unit = {}
|
||||
) = buildProject(projectBuilder) {
|
||||
preApplyCode()
|
||||
project.applyKotlinJvmPlugin()
|
||||
code()
|
||||
}
|
||||
|
||||
+1
-1
@@ -131,8 +131,8 @@ open class KotlinPlatformAndroidPlugin : KotlinPlatformImplementationPluginBase(
|
||||
|
||||
open class KotlinPlatformCommonPlugin : KotlinPlatformPluginBase("common") {
|
||||
override fun apply(project: Project) {
|
||||
warnAboutKotlin12xMppDeprecation(project)
|
||||
project.applyPlugin<KotlinCommonPluginWrapper>()
|
||||
warnAboutKotlin12xMppDeprecation(project)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -136,8 +136,8 @@ open class KotlinPlatformAndroidPlugin : KotlinPlatformImplementationPluginBase(
|
||||
|
||||
open class KotlinPlatformCommonPlugin : KotlinPlatformPluginBase("common") {
|
||||
override fun apply(project: Project) {
|
||||
warnAboutKotlin12xMppDeprecation(project)
|
||||
project.applyPlugin<KotlinCommonPluginWrapper>()
|
||||
warnAboutKotlin12xMppDeprecation(project)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -134,8 +134,8 @@ open class KotlinPlatformAndroidPlugin : KotlinPlatformImplementationPluginBase(
|
||||
|
||||
open class KotlinPlatformCommonPlugin : KotlinPlatformPluginBase("common") {
|
||||
override fun apply(project: Project) {
|
||||
warnAboutKotlin12xMppDeprecation(project)
|
||||
project.applyPlugin<KotlinCommonPluginWrapper>()
|
||||
warnAboutKotlin12xMppDeprecation(project)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -133,8 +133,8 @@ open class KotlinPlatformAndroidPlugin : KotlinPlatformImplementationPluginBase(
|
||||
|
||||
open class KotlinPlatformCommonPlugin : KotlinPlatformPluginBase("common") {
|
||||
override fun apply(project: Project) {
|
||||
warnAboutKotlin12xMppDeprecation(project)
|
||||
project.applyPlugin<KotlinCommonPluginWrapper>()
|
||||
warnAboutKotlin12xMppDeprecation(project)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -133,8 +133,8 @@ open class KotlinPlatformAndroidPlugin : KotlinPlatformImplementationPluginBase(
|
||||
|
||||
open class KotlinPlatformCommonPlugin : KotlinPlatformPluginBase("common") {
|
||||
override fun apply(project: Project) {
|
||||
warnAboutKotlin12xMppDeprecation(project)
|
||||
project.applyPlugin<KotlinCommonPluginWrapper>()
|
||||
warnAboutKotlin12xMppDeprecation(project)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -133,8 +133,8 @@ open class KotlinPlatformAndroidPlugin : KotlinPlatformImplementationPluginBase(
|
||||
|
||||
open class KotlinPlatformCommonPlugin : KotlinPlatformPluginBase("common") {
|
||||
override fun apply(project: Project) {
|
||||
warnAboutKotlin12xMppDeprecation(project)
|
||||
project.applyPlugin<KotlinCommonPluginWrapper>()
|
||||
warnAboutKotlin12xMppDeprecation(project)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -133,8 +133,8 @@ open class KotlinPlatformAndroidPlugin : KotlinPlatformImplementationPluginBase(
|
||||
|
||||
open class KotlinPlatformCommonPlugin : KotlinPlatformPluginBase("common") {
|
||||
override fun apply(project: Project) {
|
||||
warnAboutKotlin12xMppDeprecation(project)
|
||||
project.applyPlugin<KotlinCommonPluginWrapper>()
|
||||
warnAboutKotlin12xMppDeprecation(project)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -135,8 +135,8 @@ open class KotlinPlatformAndroidPlugin : KotlinPlatformImplementationPluginBase(
|
||||
|
||||
open class KotlinPlatformCommonPlugin : KotlinPlatformPluginBase("common") {
|
||||
override fun apply(project: Project) {
|
||||
warnAboutKotlin12xMppDeprecation(project)
|
||||
project.applyPlugin<KotlinCommonPluginWrapper>()
|
||||
warnAboutKotlin12xMppDeprecation(project)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user