mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 11:50:54 +07:00
Refactor theme generator gradle plugin and optimize sarif results (#95)
* "Refactor theme generator and optimize sarif results" This commit includes the optimization and refactor of the codebase. In the build.gradle files, the 'intUiLight' and 'intUiDark' themes have been registered and their properties have been updated. The Theme Generation plugin has been changed to use project conventions and the color group reading process was simplified. There is an optimized caching strategy particularly for SVG loading. Sarif results are now generated with kotlinx.sarif, which allows fluent API for handling the sarif format. Also, it includes switching from the java-sarif library to kotlin-sarif. The changes enhance the robustness and reliability of the code. They also make it easier to understand, modify, and maintain the code. And using Kotlin-based libraries optimizes the performance and simplifies future changes in the project. * Update build config for cleaner syntax The build config file has been updated to use a cleaner syntax. The redundant use of .set() has been replaced with direct assignment for better readability. Also, added a suppression for UnstableApiUsage warning at the top of the files. GitOrigin-RevId: 729a71a47ee0126f69f3f4ef36293661df48b3f7
This commit is contained in:
committed by
intellij-monorepo-bot
parent
4356963934
commit
14f6afe0fc
@@ -2,16 +2,25 @@ plugins {
|
||||
alias(libs.plugins.composeDesktop) apply false
|
||||
}
|
||||
|
||||
tasks {
|
||||
val check by registering {
|
||||
group = "verification"
|
||||
}
|
||||
register<MergeSarifTask>("mergeSarifReports") {
|
||||
dependsOn(check)
|
||||
source = rootProject.fileTree("build/reports") {
|
||||
include("*.sarif")
|
||||
exclude("static-analysis.sarif")
|
||||
}
|
||||
outputs.file(rootProject.file("build/reports/static-analysis.sarif"))
|
||||
val sarif: Configuration by configurations.creating {
|
||||
isCanBeResolved = true
|
||||
attributes {
|
||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named("sarif"))
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
sarif(projects.foundation)
|
||||
sarif(projects.core)
|
||||
sarif(projects.composeUtils)
|
||||
sarif(projects.samples.standalone)
|
||||
sarif(projects.themes.intUi.intUiStandalone)
|
||||
sarif(projects.themes.intUi.intUiCore)
|
||||
}
|
||||
|
||||
tasks {
|
||||
register<MergeSarifTask>("mergeSarifReports") {
|
||||
source(sarif)
|
||||
include { it.file.extension == "sarif" }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,12 +12,21 @@ gradlePlugin {
|
||||
}
|
||||
}
|
||||
|
||||
kotlin {
|
||||
sourceSets {
|
||||
all {
|
||||
languageSettings {
|
||||
optIn("kotlinx.serialization.ExperimentalSerializationApi")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.kotlin.gradlePlugin)
|
||||
implementation(libs.kotlinter.gradlePlugin)
|
||||
implementation(libs.detekt.gradlePlugin)
|
||||
implementation(libs.javaSarif)
|
||||
implementation(libs.kotlinSarif)
|
||||
implementation(libs.dokka.gradlePlugin)
|
||||
implementation(libs.kotlinpoet)
|
||||
implementation(libs.kotlinx.serialization.json)
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import com.contrastsecurity.sarif.Run
|
||||
import com.contrastsecurity.sarif.SarifSchema210
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import java.io.File
|
||||
import java.net.URI
|
||||
import io.github.detekt.sarif4k.SarifSchema210
|
||||
import io.github.detekt.sarif4k.Version
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.decodeFromStream
|
||||
import kotlinx.serialization.json.encodeToStream
|
||||
import org.gradle.api.file.FileTree
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.tasks.CacheableTask
|
||||
import org.gradle.api.tasks.IgnoreEmptyDirectories
|
||||
import org.gradle.api.tasks.InputFiles
|
||||
@@ -13,85 +14,43 @@ import org.gradle.api.tasks.PathSensitivity
|
||||
import org.gradle.api.tasks.SkipWhenEmpty
|
||||
import org.gradle.api.tasks.SourceTask
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import com.contrastsecurity.sarif.Result
|
||||
|
||||
@CacheableTask
|
||||
open class MergeSarifTask : SourceTask() {
|
||||
|
||||
@InputFiles
|
||||
@SkipWhenEmpty
|
||||
@IgnoreEmptyDirectories
|
||||
@PathSensitive(PathSensitivity.RELATIVE)
|
||||
override fun getSource(): FileTree = super.getSource()
|
||||
init {
|
||||
group = "verification"
|
||||
}
|
||||
|
||||
@get:OutputFile
|
||||
val mergedSarifPath: File
|
||||
get() = project.rootProject.file("build/reports/static-analysis.sarif")
|
||||
val mergedSarifPath: RegularFileProperty = project.objects.fileProperty()
|
||||
.convention(project.layout.buildDirectory.file("reports/static-analysis.sarif"))
|
||||
|
||||
@TaskAction
|
||||
fun merge() {
|
||||
val sarifFiles = source.files
|
||||
val json = Json { prettyPrint = true }
|
||||
|
||||
logger.lifecycle("Merging ${sarifFiles.size} SARIF file(s)...")
|
||||
logger.debug(sarifFiles.joinToString("\n") { " * ${it.path}" })
|
||||
|
||||
val objectMapper = ObjectMapper()
|
||||
val merged = SarifSchema210()
|
||||
.`with$schema`(URI.create("https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json"))
|
||||
.withVersion(SarifSchema210.Version._2_1_0)
|
||||
.withRuns(mutableListOf())
|
||||
|
||||
sarifFiles.map { file -> objectMapper.readValue(file.readText(), SarifSchema210::class.java) }
|
||||
.flatMap { report -> report.runs }
|
||||
.groupBy { run -> run.tool.driver.guid ?: run.tool.driver.name }
|
||||
.values
|
||||
.filter { it.isNotEmpty() }
|
||||
.forEach { runs ->
|
||||
val mergedResults = mutableListOf<Result>()
|
||||
runs.forEach { mergedResults.addAll(it.results) }
|
||||
val mergedRun = runs.first().copy(mergedResults)
|
||||
merged.runs.add(mergedRun)
|
||||
}
|
||||
logger.lifecycle("Merging ${source.files.size} SARIF file(s)...")
|
||||
logger.lifecycle(source.files.joinToString("\n") { " * ~${it.path.removePrefix(project.rootDir.path)}" })
|
||||
|
||||
val merged = SarifSchema210(
|
||||
schema = "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
|
||||
version = Version.The210,
|
||||
runs = source.files
|
||||
.asSequence()
|
||||
.filter { it.extension == "sarif" }
|
||||
.map { file -> file.inputStream().use { json.decodeFromStream<SarifSchema210>(it) } }
|
||||
.flatMap { report -> report.runs }
|
||||
.groupBy { run -> run.tool.driver.guid ?: run.tool.driver.name }
|
||||
.values
|
||||
.asSequence()
|
||||
.filter { it.isNotEmpty() }
|
||||
.map { it.first().copy(results = it.flatMap { it.results ?: emptyList() }) }
|
||||
.toList()
|
||||
)
|
||||
logger.lifecycle("Merged SARIF file contains ${merged.runs.size} run(s)")
|
||||
logger.info("Writing merged SARIF file to $mergedSarifPath...")
|
||||
objectMapper.writerWithDefaultPrettyPrinter()
|
||||
.writeValue(mergedSarifPath, merged)
|
||||
mergedSarifPath.asFile.get().outputStream()
|
||||
.use { json.encodeToStream(merged, it) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Poor man's copying of a Run.
|
||||
*
|
||||
* Note that this is NOT a deep copy; we're not defensively cloning field values,
|
||||
* so mutating the copy will also mutate the original.
|
||||
*/
|
||||
private fun Run.copy(newResults: List<Result> = this.results) = Run()
|
||||
.withAddresses(addresses)
|
||||
.withArtifacts(artifacts)
|
||||
.withAutomationDetails(automationDetails)
|
||||
.withBaselineGuid(baselineGuid)
|
||||
.withColumnKind(columnKind)
|
||||
.withConversion(conversion)
|
||||
.withDefaultEncoding(defaultEncoding)
|
||||
.withDefaultSourceLanguage(defaultSourceLanguage)
|
||||
.withExternalPropertyFileReferences(externalPropertyFileReferences)
|
||||
.withGraphs(graphs)
|
||||
.withInvocations(invocations)
|
||||
.withLanguage(language)
|
||||
.withLogicalLocations(logicalLocations)
|
||||
.withNewlineSequences(newlineSequences)
|
||||
.withOriginalUriBaseIds(originalUriBaseIds)
|
||||
.withPolicies(policies)
|
||||
.withProperties(properties)
|
||||
.withRedactionTokens(redactionTokens)
|
||||
.withResults(newResults)
|
||||
.withRunAggregates(runAggregates)
|
||||
.withSpecialLocations(specialLocations)
|
||||
.withTaxonomies(taxonomies)
|
||||
.withThreadFlowLocations(threadFlowLocations)
|
||||
.withTool(tool)
|
||||
.withTranslations(translations)
|
||||
.withVersionControlProvenance(versionControlProvenance)
|
||||
.withWebRequests(webRequests)
|
||||
.withWebResponses(webResponses)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
@file:Suppress("UnstableApiUsage")
|
||||
|
||||
plugins {
|
||||
`maven-publish`
|
||||
id("org.jetbrains.dokka")
|
||||
@@ -6,14 +8,14 @@ plugins {
|
||||
|
||||
val sourcesJar by tasks.registering(Jar::class) {
|
||||
from(kotlin.sourceSets.main.get().kotlin)
|
||||
archiveClassifier.set("sources")
|
||||
into("$buildDir/artifacts")
|
||||
archiveClassifier = "sources"
|
||||
into(layout.buildDirectory.dir("artifacts"))
|
||||
}
|
||||
|
||||
val javadocJar by tasks.registering(Jar::class) {
|
||||
from(tasks.dokkaHtml)
|
||||
archiveClassifier.set("javadoc")
|
||||
into("$buildDir/artifacts")
|
||||
archiveClassifier = "javadoc"
|
||||
into(layout.buildDirectory.dir("artifacts"))
|
||||
}
|
||||
|
||||
publishing {
|
||||
@@ -34,19 +36,19 @@ publishing {
|
||||
version = project.version.toString()
|
||||
artifactId = "jewel-${project.name}"
|
||||
pom {
|
||||
name.set("Jewel")
|
||||
description.set("intelliJ theming system in for Compose.")
|
||||
url.set("https://github.com/JetBrains/jewel")
|
||||
name = "Jewel"
|
||||
description = "intelliJ theming system in for Compose."
|
||||
url = "https://github.com/JetBrains/jewel"
|
||||
licenses {
|
||||
license {
|
||||
name.set("Apache License 2.0")
|
||||
url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
|
||||
name = "Apache License 2.0"
|
||||
url = "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
}
|
||||
}
|
||||
scm {
|
||||
connection.set("scm:git:https://github.com/JetBrains/jewel.git")
|
||||
developerConnection.set("scm:git:https://github.com/JetBrains/jewel.git")
|
||||
url.set("https://github.com/JetBrains/jewel")
|
||||
connection = "scm:git:https://github.com/JetBrains/jewel.git"
|
||||
developerConnection = "scm:git:https://github.com/JetBrains/jewel.git"
|
||||
url = "https://github.com/JetBrains/jewel"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
@file:Suppress("UnstableApiUsage")
|
||||
|
||||
import io.gitlab.arturbosch.detekt.Detekt
|
||||
import org.jmailen.gradle.kotlinter.tasks.LintTask
|
||||
|
||||
@@ -15,6 +17,7 @@ version = when {
|
||||
gitHubRef.substringAfter("refs/tags/")
|
||||
.removePrefix("v")
|
||||
}
|
||||
|
||||
else -> "1.0.0-SNAPSHOT"
|
||||
}
|
||||
|
||||
@@ -42,29 +45,42 @@ detekt {
|
||||
buildUponDefaultConfig = true
|
||||
}
|
||||
|
||||
tasks {
|
||||
register<MergeSarifTask>("mergeSarifReports") {
|
||||
dependsOn(check)
|
||||
source = rootProject.fileTree("build/reports") {
|
||||
include("*.sarif")
|
||||
exclude("static-analysis.sarif")
|
||||
}
|
||||
outputs.file(rootProject.file("build/reports/static-analysis.sarif"))
|
||||
}
|
||||
withType<Detekt> {
|
||||
reports {
|
||||
sarif.required.set(true)
|
||||
sarif.outputLocation.set(file(rootDir.resolve("build/reports/detekt-${project.name}.sarif")))
|
||||
}
|
||||
}
|
||||
tasks.withType<LintTask> {
|
||||
exclude { it.file.absolutePath.startsWith(buildDir.absolutePath) }
|
||||
reports.set(
|
||||
mapOf(
|
||||
"plain" to rootDir.resolve("build/reports/ktlint-${project.name}.txt"),
|
||||
"html" to rootDir.resolve("build/reports/ktlint-${project.name}.html"),
|
||||
"sarif" to rootDir.resolve("build/reports/ktlint-${project.name}.sarif")
|
||||
)
|
||||
)
|
||||
val sarif by configurations.creating {
|
||||
isCanBeConsumed = true
|
||||
attributes {
|
||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named("sarif"))
|
||||
}
|
||||
}
|
||||
|
||||
tasks {
|
||||
withType<Detekt> {
|
||||
val sarifOutputFile = layout.buildDirectory.file("reports/detekt-${project.name}.sarif")
|
||||
exclude { it.file.absolutePath.startsWith(layout.buildDirectory.asFile.get().absolutePath) }
|
||||
reports {
|
||||
sarif.required = true
|
||||
sarif.outputLocation = sarifOutputFile
|
||||
}
|
||||
sarif.outgoing {
|
||||
artifact(sarifOutputFile) {
|
||||
builtBy(this@withType)
|
||||
}
|
||||
}
|
||||
}
|
||||
withType<LintTask> {
|
||||
exclude { it.file.absolutePath.startsWith(layout.buildDirectory.asFile.get().absolutePath) }
|
||||
val sarifReport = layout.buildDirectory.file("reports/ktlint-${project.name}.sarif")
|
||||
reports = provider {
|
||||
mapOf(
|
||||
"plain" to layout.buildDirectory.file("reports/ktlint-${project.name}.txt").get().asFile,
|
||||
"html" to layout.buildDirectory.file("reports/ktlint-${project.name}.html").get().asFile,
|
||||
"sarif" to sarifReport.get().asFile
|
||||
)
|
||||
}
|
||||
|
||||
sarif.outgoing {
|
||||
artifact(sarifReport) {
|
||||
builtBy(this@withType)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
package org.jetbrains.jewel.buildlogic.theme
|
||||
|
||||
import org.gradle.api.NamedDomainObjectContainer
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.Directory
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.tasks.SourceSetContainer
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.gradle.kotlin.dsl.getByType
|
||||
import org.gradle.kotlin.dsl.property
|
||||
import java.io.File
|
||||
|
||||
abstract class BaseIntelliJThemeGeneratorPlugin : Plugin<Project> {
|
||||
|
||||
final override fun apply(target: Project) {
|
||||
val extension = createExtension(target)
|
||||
|
||||
target.afterEvaluate {
|
||||
val tasks = createGenerateTask(target, extension)
|
||||
val sourceSets = target.extensions.getByType<SourceSetContainer>()
|
||||
val mainSourceSet = sourceSets.getByName("main")
|
||||
|
||||
mainSourceSet.java {
|
||||
extension.map { it.targetDir }.forEach {
|
||||
srcDir(it)
|
||||
}
|
||||
}
|
||||
|
||||
target.tasks.findByName("compileKotlin")?.dependsOn(*tasks.toTypedArray())
|
||||
target.tasks.findByName("lintKotlinMain")?.dependsOn(*tasks.toTypedArray())
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun createExtension(project: Project): ThemeGeneratorContainer
|
||||
|
||||
protected abstract fun createGenerateTask(project: Project, extension: ThemeGeneratorContainer): List<TaskProvider<out BaseThemeGeneratorTask>>
|
||||
}
|
||||
|
||||
class ThemeGeneratorContainer(container: NamedDomainObjectContainer<ThemeGeneration>) : NamedDomainObjectContainer<ThemeGeneration> by container
|
||||
|
||||
class ThemeGeneration(val name: String, private val project: Project) {
|
||||
|
||||
val targetDir: DirectoryProperty = project.objects.directoryProperty()
|
||||
val ideaVersion = project.objects.property<String>()
|
||||
val themeClassName = project.objects.property<String>()
|
||||
val themeFile = project.objects.property<String>()
|
||||
|
||||
fun targetDir(): String = targetDir.get().asFile.absolutePath
|
||||
|
||||
fun targetDir(path: File) {
|
||||
targetDir.set(path)
|
||||
}
|
||||
|
||||
fun targetDir(path: Directory) {
|
||||
targetDir.set(path)
|
||||
}
|
||||
|
||||
fun ideaVersion(): String = ideaVersion.get()
|
||||
|
||||
fun ideaVersion(version: String) {
|
||||
ideaVersion.set(version)
|
||||
}
|
||||
|
||||
fun themeClassName(): String = themeClassName.get()
|
||||
|
||||
fun themeClassName(name: String) {
|
||||
themeClassName.set(name)
|
||||
}
|
||||
|
||||
fun themeFile(): String = themeFile.get()
|
||||
|
||||
fun themeFile(path: String) {
|
||||
themeFile.set(path)
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package org.jetbrains.jewel.buildlogic.theme
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.kotlin.dsl.property
|
||||
|
||||
abstract class BaseThemeGeneratorTask : DefaultTask() {
|
||||
|
||||
@get:OutputFile
|
||||
val output = project.objects.fileProperty()
|
||||
|
||||
@get:Input
|
||||
val ideaVersion = project.objects.property<String>()
|
||||
|
||||
@get:Input
|
||||
val themeFile = project.objects.property<String>()
|
||||
|
||||
@get:Input
|
||||
val themeClassName = project.objects.property<String>()
|
||||
|
||||
init {
|
||||
group = "jewel"
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun generate() {
|
||||
doGenerate()
|
||||
}
|
||||
|
||||
protected abstract fun doGenerate()
|
||||
}
|
||||
@@ -1,55 +1,94 @@
|
||||
package org.jetbrains.jewel.buildlogic.theme
|
||||
|
||||
import com.squareup.kotlinpoet.ClassName
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.gradle.util.internal.GUtil
|
||||
import io.gitlab.arturbosch.detekt.Detekt
|
||||
import java.net.URL
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import kotlinx.serialization.json.decodeFromStream
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.NamedDomainObjectContainer
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.kotlin.dsl.container
|
||||
import org.gradle.kotlin.dsl.get
|
||||
import org.gradle.kotlin.dsl.getByType
|
||||
import org.gradle.kotlin.dsl.property
|
||||
import org.gradle.kotlin.dsl.register
|
||||
import org.gradle.kotlin.dsl.withType
|
||||
import org.gradle.util.internal.GUtil
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
class IntelliJThemeGeneratorPlugin : BaseIntelliJThemeGeneratorPlugin() {
|
||||
abstract class IntelliJThemeGeneratorPlugin : Plugin<Project> {
|
||||
|
||||
override fun createExtension(project: Project): ThemeGeneratorContainer =
|
||||
ThemeGeneratorContainer(project.container(ThemeGeneration::class.java) {
|
||||
ThemeGeneration(it, project).apply {
|
||||
targetDir.set(project.layout.buildDirectory.dir("generated/theme"))
|
||||
ideaVersion.set("232.6734")
|
||||
final override fun apply(target: Project): Unit = with(target) {
|
||||
val extension = ThemeGeneratorContainer(container<ThemeGeneration> { ThemeGeneration(it, project) })
|
||||
extensions.add("intelliJThemeGenerator", extension)
|
||||
|
||||
extension.all {
|
||||
val task = tasks.register<IntelliJThemeGeneratorTask>("generate${GUtil.toCamelCase(name)}Theme") {
|
||||
outputFile.set(targetDir.file(this@all.themeClassName.map {
|
||||
val className = ClassName.bestGuess(it)
|
||||
className.packageName.replace(".", "/")
|
||||
.plus("/${className.simpleName}.kt")
|
||||
}))
|
||||
themeClassName.set(this@all.themeClassName)
|
||||
ideaVersion.set(this@all.ideaVersion)
|
||||
themeFile.set(this@all.themeFile)
|
||||
}
|
||||
}).apply {
|
||||
project.extensions.add("intelliJThemeGenerator", this)
|
||||
}
|
||||
|
||||
override fun createGenerateTask(
|
||||
project: Project,
|
||||
extension: ThemeGeneratorContainer
|
||||
): List<TaskProvider<out BaseThemeGeneratorTask>> =
|
||||
extension.map { config ->
|
||||
project.tasks.register(
|
||||
"generate${GUtil.toCamelCase(config.name)}Theme",
|
||||
IntelliJThemeGeneratorTask::class.java
|
||||
).apply {
|
||||
configure {
|
||||
output.set(config.targetDir.file(config.themeClassName.map {
|
||||
val className = ClassName.bestGuess(it)
|
||||
className.packageName.replace('.', '/') + "/${className.simpleName}.kt"
|
||||
}))
|
||||
themeClassName.set(config.themeClassName)
|
||||
ideaVersion.set(config.ideaVersion)
|
||||
themeFile.set(config.themeFile)
|
||||
tasks.withType<KotlinCompile> {
|
||||
dependsOn(task)
|
||||
}
|
||||
tasks.withType<Detekt> {
|
||||
dependsOn(task)
|
||||
}
|
||||
pluginManager.withPlugin("org.jetbrains.kotlin.jvm") {
|
||||
extensions.getByType<KotlinJvmProjectExtension>().apply {
|
||||
sourceSets["main"].kotlin.srcDir(targetDir)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class IntelliJThemeGeneratorTask : BaseThemeGeneratorTask() {
|
||||
class ThemeGeneratorContainer(container: NamedDomainObjectContainer<ThemeGeneration>) : NamedDomainObjectContainer<ThemeGeneration> by container
|
||||
|
||||
private val json = Json {
|
||||
ignoreUnknownKeys = true
|
||||
class ThemeGeneration(val name: String, project: Project) {
|
||||
val targetDir: DirectoryProperty = project.objects.directoryProperty()
|
||||
.convention(project.layout.buildDirectory.dir("generated/theme"))
|
||||
val ideaVersion = project.objects.property<String>()
|
||||
.convention("232.6734")
|
||||
val themeClassName = project.objects.property<String>()
|
||||
val themeFile = project.objects.property<String>()
|
||||
}
|
||||
|
||||
open class IntelliJThemeGeneratorTask : DefaultTask() {
|
||||
|
||||
@get:OutputFile
|
||||
val outputFile = project.objects.fileProperty()
|
||||
|
||||
@get:Input
|
||||
val ideaVersion = project.objects.property<String>()
|
||||
|
||||
@get:Input
|
||||
val themeFile = project.objects.property<String>()
|
||||
|
||||
@get:Input
|
||||
val themeClassName = project.objects.property<String>()
|
||||
|
||||
init {
|
||||
group = "jewel"
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
override fun doGenerate() {
|
||||
@TaskAction
|
||||
fun generate() {
|
||||
val json = Json { ignoreUnknownKeys = true }
|
||||
val url = buildString {
|
||||
append("https://raw.githubusercontent.com/JetBrains/intellij-community/")
|
||||
append(ideaVersion.get())
|
||||
@@ -58,23 +97,27 @@ open class IntelliJThemeGeneratorTask : BaseThemeGeneratorTask() {
|
||||
}
|
||||
|
||||
logger.lifecycle("Fetching theme descriptor from $url...")
|
||||
val themeDescriptor = URL(url).openStream()
|
||||
.use { json.decodeFromStream<IntellijThemeDescriptor>(it) }
|
||||
|
||||
val themeDescriptor = URL(url).openStream().use {
|
||||
json.decodeFromString<IntellijThemeDescriptor>(it.reader().readText())
|
||||
}
|
||||
|
||||
logger.info("Theme descriptor fetched, parsing...")
|
||||
val className = ClassName.bestGuess(themeClassName.get())
|
||||
|
||||
// TODO handle non-Int UI themes, too
|
||||
val file = IntUiThemeDescriptorReader.readThemeFrom(themeDescriptor, className, ideaVersion.get(), url)
|
||||
|
||||
logger.info("Theme descriptor parsed, writing generated code to disk...")
|
||||
val outputFile = output.get().asFile
|
||||
outputFile.bufferedWriter().use {
|
||||
file.writeTo(it)
|
||||
}
|
||||
|
||||
val outputFile = outputFile.get().asFile
|
||||
logger.lifecycle("Theme descriptor for ${themeDescriptor.name} parsed and code generated into ${outputFile.path}")
|
||||
outputFile.bufferedWriter().use { file.writeTo(it) }
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class IntellijThemeDescriptor(
|
||||
val name: String,
|
||||
val author: String = "",
|
||||
val dark: Boolean = false,
|
||||
val editorScheme: String,
|
||||
val colors: Map<String, String> = emptyMap(),
|
||||
val ui: Map<String, JsonElement> = emptyMap(),
|
||||
val icons: Map<String, JsonElement> = emptyMap(),
|
||||
)
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
package org.jetbrains.jewel.buildlogic.theme
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
|
||||
@Serializable
|
||||
data class IntellijThemeDescriptor(
|
||||
val name: String,
|
||||
val author: String = "",
|
||||
val dark: Boolean = false,
|
||||
val editorScheme: String,
|
||||
val colors: Map<String, String> = emptyMap(),
|
||||
val ui: Map<String, JsonElement> = emptyMap(),
|
||||
val icons: Map<String, JsonElement> = emptyMap(),
|
||||
)
|
||||
@@ -5,6 +5,7 @@ detekt = "1.22.0"
|
||||
idea = "232.8660.185"
|
||||
ideaGradlePlugin = "1.13.0"
|
||||
javaSarif = "2.0"
|
||||
kotlinSarif = "0.4.0"
|
||||
jna = "5.10.0"
|
||||
kotlin = "1.8.20"
|
||||
dokka = "1.8.20"
|
||||
@@ -15,6 +16,7 @@ kotlinpoet = "1.14.2"
|
||||
[libraries]
|
||||
compose-components-splitpane = { module = "org.jetbrains.compose.components:components-splitpane", version.ref = "composeDesktop" }
|
||||
javaSarif = { module = "com.contrastsecurity:java-sarif", version.ref = "javaSarif" }
|
||||
kotlinSarif = { module = "io.github.detekt.sarif4k:sarif4k", version.ref = "kotlinSarif" }
|
||||
jna = { module = "net.java.dev.jna:jna-platform", version.ref = "jna" }
|
||||
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerialization" }
|
||||
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
@file:Suppress("UnstableApiUsage")
|
||||
|
||||
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
|
||||
|
||||
plugins {
|
||||
@@ -21,12 +23,12 @@ compose.desktop {
|
||||
packageVersion = "1.0"
|
||||
description = "Jewel Sample Application"
|
||||
vendor = "JetBrains"
|
||||
licenseFile.set(File(rootDir, "LICENSE"))
|
||||
licenseFile = rootProject.file("LICENSE")
|
||||
|
||||
macOS {
|
||||
dockName = "Jewel Sample"
|
||||
bundleID = "org.jetbrains.jewel.sample.standalone"
|
||||
iconFile.set(File(projectDir, "icons/jewel.icns"))
|
||||
iconFile = file("icons/jewel.icns")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
@file:Suppress("UnstableApiUsage")
|
||||
|
||||
plugins {
|
||||
`jewel-publish`
|
||||
alias(libs.plugins.composeDesktop)
|
||||
@@ -11,17 +13,15 @@ dependencies {
|
||||
}
|
||||
|
||||
intelliJThemeGenerator {
|
||||
val ideaVersion = "232.6734"
|
||||
|
||||
create("intUiLight") {
|
||||
themeClassName("org.jetbrains.jewel.themes.intui.core.theme.IntUiLightTheme")
|
||||
themeFile("platform/platform-resources/src/themes/expUI/expUI_light.theme.json")
|
||||
ideaVersion(ideaVersion)
|
||||
register("intUiLight") {
|
||||
themeClassName = "org.jetbrains.jewel.themes.intui.core.theme.IntUiLightTheme"
|
||||
themeFile = "platform/platform-resources/src/themes/expUI/expUI_light.theme.json"
|
||||
ideaVersion = "232.6734"
|
||||
}
|
||||
create("intUiDark") {
|
||||
themeClassName("org.jetbrains.jewel.themes.intui.core.theme.IntUiDarkTheme")
|
||||
themeFile("platform/platform-resources/src/themes/expUI/expUI_dark.theme.json")
|
||||
ideaVersion(ideaVersion)
|
||||
register("intUiDark") {
|
||||
themeClassName = "org.jetbrains.jewel.themes.intui.core.theme.IntUiDarkTheme"
|
||||
themeFile = "platform/platform-resources/src/themes/expUI/expUI_dark.theme.json"
|
||||
ideaVersion = "232.6734"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,3 +36,4 @@ tasks {
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ class IntelliJSvgLoader(private val svgPatcher: SvgPatcher) : SvgLoader {
|
||||
pathPatcher: @Composable (String) -> String,
|
||||
): Painter {
|
||||
val patchedPath = pathPatcher(originalPath)
|
||||
if (cache.containsKey(patchedPath)) return cache[patchedPath]!!
|
||||
cache[patchedPath]?.let { return it }
|
||||
|
||||
val painter = rememberPatchedSvgResource(originalPath, patchedPath, resourceLoader)
|
||||
cache[patchedPath] = painter
|
||||
|
||||
Reference in New Issue
Block a user