Skip to content

Commit 72b51d2

Browse files
Merge pull request #45 from gerardorodriguezdev/plugin-upgrades
plugin-upgrades
2 parents 377f136 + 6e45d06 commit 72b51d2

File tree

19 files changed

+328
-95
lines changed

19 files changed

+328
-95
lines changed

gradle-plugin/README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ plugins {
1919
> This plugin is hosted on
2020
> the [Gradle Plugins Portal](https://plugins.gradle.org/plugin/io.github.gerardorodriguezdev.chamaleon)
2121
22-
### 2. Run `./gradlew :chamaleonGenerateSample`
22+
### 2. Run `./gradlew :generateSample`
2323

2424
This task will generate the following files:
2525

@@ -195,7 +195,7 @@ You would need to generate your production environment file programmatically, as
195195
secrets.
196196
Here is an example of how to do it:
197197

198-
`./gradlew :chamaleonGenerateEnvironment -Pchamaleon.environment="myProductionEnvironment.jvm.properties[mySecretName=mySecretValue]"`
198+
`./gradlew :generateEnvironment -Pchamaleon.environment="myProductionEnvironment.jvm.properties[mySecretName=mySecretValue]"`
199199

200200
The input command, in this case `myProductionEnvironment.jvm.properties[mySecretName=mySecretValue]`, has the following
201201
structure:
@@ -209,7 +209,7 @@ After running this task, your production environment file will be generated on y
209209
> If you want to create an environment with more than one platform, you can run the same command with each of the
210210
> additional platforms, and they will be merged in the environment
211211
>
212-
> ./gradlew :chamaleonGenerateEnvironment
212+
> ./gradlew :generateEnvironment
213213
>
214214
> -Pchamaleon.environment="myProductionEnvironment.jvm.properties[mySecretName=mySecretValue]"
215215
>
@@ -221,7 +221,7 @@ After running this task, your production environment file will be generated on y
221221

222222
Finally, the only remaining thing to do is to select the generated environment like this:
223223

224-
`./gradlew :chamaleonSelectEnvironment -Pchamaleon.newSelectedEnvironment=myProductionEnvironment`
224+
`./gradlew :selectEnvironment -Pchamaleon.newSelectedEnvironment=myProductionEnvironment`
225225

226226
It will create or update the `properties.chamaleon.json` file to point to your `myProductionEnvironment`
227227

@@ -230,8 +230,8 @@ It will create or update the `properties.chamaleon.json` file to point to your `
230230
```yaml
231231
- name: Generate and select production environment # Your step name
232232
run: |
233-
./gradlew :chamaleonGenerateEnvironment -Pchamaleon.environment="myProductionEnvironment.jvm.properties[mySecretName=${{ secrets.MY_GITHUB_SECRET }}]"
234-
./gradlew :chamaleonSelectEnvironment -Pchamaleon.newSelectedEnvironment=myProductionEnvironment
233+
./gradlew :generateEnvironment -Pchamaleon.environment="myProductionEnvironment.jvm.properties[mySecretName=${{ secrets.MY_GITHUB_SECRET }}]"
234+
./gradlew :selectEnvironment -Pchamaleon.newSelectedEnvironment=myProductionEnvironment
235235
```
236236
237237
### Restricting some properties only for certain platforms

gradle-plugin/src/main/kotlin/io/github/gerardorodriguezdev/chamaleon/gradle/plugin/ChamaleonGradlePlugin.kt

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ public class ChamaleonGradlePlugin : Plugin<Project> {
7070

7171
private fun Project.registerGenerateSampleTask(): TaskProvider<GenerateSampleTask> =
7272
tasks.register(GENERATE_SAMPLE_TASK_NAME, GenerateSampleTask::class.java) {
73+
group = EXTENSION_NAME
74+
7375
val generateSampleCommandLineArgument =
7476
providers.gradleProperty(GENERATE_SAMPLE_COMMAND_LINE_ARGUMENT).orNull
7577

@@ -86,6 +88,8 @@ public class ChamaleonGradlePlugin : Plugin<Project> {
8688
extension: ChamaleonExtension,
8789
): TaskProvider<SelectEnvironmentTask> =
8890
tasks.register(SELECT_ENVIRONMENT_TASK_NAME, SelectEnvironmentTask::class.java) {
91+
group = EXTENSION_NAME
92+
8993
val newSelectedEnvironmentNameString =
9094
providers.gradleProperty(SELECT_ENVIRONMENT_COMMAND_LINE_ARGUMENT).orNull
9195

@@ -106,6 +110,8 @@ public class ChamaleonGradlePlugin : Plugin<Project> {
106110
extension: ChamaleonExtension,
107111
): TaskProvider<GenerateEnvironmentTask> =
108112
tasks.register(GENERATE_ENVIRONMENT_TASK_NAME, GenerateEnvironmentTask::class.java) {
113+
group = EXTENSION_NAME
114+
109115
val generateEnvironmentCommands =
110116
providers.gradlePropertiesPrefixedBy(GENERATE_ENVIRONMENT_COMMAND_LINE_ARGUMENT).orNull
111117

@@ -116,7 +122,9 @@ public class ChamaleonGradlePlugin : Plugin<Project> {
116122

117123
private fun Project.registerVersionTask(): TaskProvider<DefaultTask> =
118124
tasks.register(VERSION_TASK_NAME, DefaultTask::class.java) {
119-
logger.chamaleonLog("Chamaleon version: ${Versions.CORE}")
125+
group = EXTENSION_NAME
126+
127+
logger.chamaleonLog("Version: ${Versions.CORE}")
120128
}
121129

122130
private fun Project.environmentsDirectory(): Directory = layout.projectDirectory.dir(ENVIRONMENTS_DIRECTORY_NAME)
@@ -129,12 +137,12 @@ public class ChamaleonGradlePlugin : Plugin<Project> {
129137
internal companion object {
130138
const val EXTENSION_NAME = "chamaleon"
131139

132-
const val GENERATE_SAMPLE_TASK_NAME = "chamaleonGenerateSample"
133-
const val SELECT_ENVIRONMENT_TASK_NAME = "chamaleonSelectEnvironment"
134-
const val GENERATE_ENVIRONMENT_TASK_NAME = "chamaleonGenerateEnvironment"
135-
const val VERSION_TASK_NAME = "chamaleonVersion"
140+
const val GENERATE_SAMPLE_TASK_NAME = "generateSample"
141+
const val SELECT_ENVIRONMENT_TASK_NAME = "selectEnvironment"
142+
const val GENERATE_ENVIRONMENT_TASK_NAME = "generateEnvironment"
143+
const val VERSION_TASK_NAME = "version"
136144

137-
const val GENERATE_SAMPLE_COMMAND_LINE_ARGUMENT = "chamaleon.sampleOutputDirectory"
145+
const val GENERATE_SAMPLE_COMMAND_LINE_ARGUMENT = "chamaleon.outputDirectory"
138146
const val SELECT_ENVIRONMENT_COMMAND_LINE_ARGUMENT = "chamaleon.newSelectedEnvironment"
139147
const val GENERATE_ENVIRONMENT_COMMAND_LINE_ARGUMENT = "chamaleon.environment"
140148
}

gradle/libs.versions.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[versions]
22
# Platforms
33
kotlin = "2.1.10"
4-
java = "17"
4+
java = "21"
55

66
# Libraries
77
kmp-serialization = "1.8.0"
@@ -19,7 +19,7 @@ kmp-arrow = "2.0.1"
1919
jvm-test-parameterized = "5.12.1"
2020

2121
# Releases
22-
release = "1.0.11"
22+
release = "1.0.12"
2323

2424
[libraries]
2525
detekt-formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detekt" }

intellij-plugin/plugin/build.gradle.kts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import org.jetbrains.intellij.platform.gradle.TestFrameworkType
2+
import org.jetbrains.intellij.platform.gradle.tasks.RunIdeTask
23

34
plugins {
45
kotlin("jvm")
@@ -59,12 +60,17 @@ kotlin {
5960
implementation(projects.intellijPlugin.presentation) {
6061
exclude(group = "org.jetbrains.kotlinx")
6162
}
63+
implementation(libs.kmp.arrow.core) {
64+
exclude(group = "org.jetbrains.kotlinx")
65+
}
6266

6367
testImplementation(libs.kmp.test)
6468
testImplementation(libs.kmp.test.coroutines)
6569

6670
intellijPlatform {
67-
intellijIdeaCommunity("2023.3")
71+
intellijIdeaCommunity("2024.2.1")
72+
73+
bundledPlugin("org.jetbrains.kotlin")
6874

6975
pluginVerifier()
7076
zipSigner()
@@ -80,8 +86,8 @@ intellijPlatform {
8086
version = libs.versions.release.get()
8187

8288
ideaVersion {
83-
sinceBuild = "233"
84-
untilBuild = "243.*"
89+
sinceBuild = "242"
90+
untilBuild = "252.*"
8591
}
8692
}
8793

@@ -121,4 +127,10 @@ intellijPlatformTesting {
121127
}
122128
}
123129
}
130+
}
131+
132+
tasks.named<RunIdeTask>("runIde") {
133+
jvmArgumentProviders += CommandLineArgumentProvider {
134+
listOf("-Didea.kotlin.plugin.use.k2=true")
135+
}
124136
}

intellij-plugin/plugin/src/main/kotlin/io/github/gerardorodriguezdev/chamaleon/intellij/plugin/dialogs/BaseDialog.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,13 @@ internal abstract class BaseDialog(dialogTitle: String) : DialogWrapper(false) {
2828
finishButton()?.isEnabled = dialogsButtonsState.isFinishButtonEnabled
2929
}
3030

31-
override fun createActions(): Array<Action> {
32-
return arrayOf(
31+
override fun createActions(): Array<Action> =
32+
arrayOf(
3333
cancel,
3434
previous,
3535
next,
3636
finish,
3737
)
38-
}
3938

4039
private fun previousButton(): JButton? = getButton(previous)
4140

intellij-plugin/plugin/src/main/kotlin/io/github/gerardorodriguezdev/chamaleon/intellij/plugin/dialogs/createProjectDialog/CreateProjectDialog.kt

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -65,23 +65,6 @@ internal class CreateProjectDialog(
6565
)
6666
}
6767

68-
private fun collectState() {
69-
uiScope.launch {
70-
presenter.stateFlow.collect { createProjectState ->
71-
setDialogButtonsState(createProjectState.toDialogButtonsState())
72-
73-
val newCreateProjectWindowState =
74-
createProjectState.toCreateProjectWindowState(
75-
projectDirectoryPath = projectDirectory.path.value,
76-
stringsProvider = BundleStringsProvider,
77-
)
78-
newCreateProjectWindowState?.let {
79-
createProjectWindowState.value = newCreateProjectWindowState
80-
}
81-
}
82-
}
83-
}
84-
8568
@OptIn(ExperimentalComposeUiApi::class, ExperimentalJewelApi::class)
8669
override fun createCenterPanel(): JComponent {
8770
enableNewSwingCompositing()
@@ -103,6 +86,23 @@ internal class CreateProjectDialog(
10386
}
10487
}
10588

89+
private fun collectState() {
90+
uiScope.launch {
91+
presenter.stateFlow.collect { createProjectState ->
92+
setDialogButtonsState(createProjectState.toDialogButtonsState())
93+
94+
val newCreateProjectWindowState =
95+
createProjectState.toCreateProjectWindowState(
96+
projectDirectoryPath = projectDirectory.path.value,
97+
stringsProvider = BundleStringsProvider,
98+
)
99+
newCreateProjectWindowState?.let {
100+
createProjectWindowState.value = newCreateProjectWindowState
101+
}
102+
}
103+
}
104+
}
105+
106106
override fun onDialogAction(action: DialogAction) {
107107
presenter.dispatch(action.toCreateProjectAction())
108108
}

intellij-plugin/plugin/src/main/kotlin/io/github/gerardorodriguezdev/chamaleon/intellij/plugin/dialogs/createProjectDialog/mappers/CreateProjectStateToCreateProjectWindowState.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ private fun Context.toSetupEnvironment(
4444

4545
private fun Context.toEnvironmentsDirectoryPathField(
4646
projectDeserializationState: ProjectDeserializationState?
47-
): Field<String> {
48-
return when (projectDeserializationState) {
47+
): Field<String> =
48+
when (projectDeserializationState) {
4949
null -> Field(value = "", verification = null)
5050

5151
is ProjectDeserializationState.Valid -> Field(
@@ -65,7 +65,6 @@ private fun Context.toEnvironmentsDirectoryPathField(
6565
verification = Verification.Invalid(projectDeserializationState.errorMessage),
6666
)
6767
}
68-
}
6968

7069
private fun Context.environmentsDirectoryPathValue(projectDeserializationState: ProjectDeserializationState): String =
7170
projectDeserializationState.environmentsDirectoryPath.value.removePrefix(projectDirectoryPath)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package io.github.gerardorodriguezdev.chamaleon.intellij.plugin.fileTypes
2+
3+
import com.intellij.json.JsonLanguage
4+
import com.intellij.openapi.fileTypes.LanguageFileType
5+
import io.github.gerardorodriguezdev.chamaleon.intellij.plugin.icons.Icons
6+
import io.github.gerardorodriguezdev.chamaleon.intellij.plugin.shared.strings.StringsKeys
7+
import io.github.gerardorodriguezdev.chamaleon.intellij.plugin.ui.strings.BundleStringsProvider.string
8+
import javax.swing.Icon
9+
10+
internal class ChamaleonFileType private constructor() : LanguageFileType(JsonLanguage.INSTANCE, true) {
11+
override fun getName(): String = "Chamaleon"
12+
override fun getDescription(): String = string(StringsKeys.fileTypeForChamaleonConfigFiles)
13+
override fun getDefaultExtension(): String = "json"
14+
override fun getIcon(): Icon = Icons.pluginIcon
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package io.github.gerardorodriguezdev.chamaleon.intellij.plugin.psi
2+
3+
import arrow.core.Option
4+
import arrow.core.raise.option
5+
import com.intellij.extapi.psi.ASTDelegatePsiElement
6+
import com.intellij.json.psi.JsonArray
7+
import com.intellij.json.psi.JsonFile
8+
import com.intellij.json.psi.JsonObject
9+
import com.intellij.json.psi.JsonValue
10+
import com.intellij.openapi.module.ModuleUtilCore
11+
import com.intellij.openapi.project.Project
12+
import com.intellij.openapi.roots.ModuleRootManager
13+
import com.intellij.openapi.vfs.VfsUtil
14+
import com.intellij.openapi.vfs.VirtualFile
15+
import com.intellij.psi.PsiElement
16+
import com.intellij.psi.PsiFile
17+
import com.intellij.psi.PsiManager
18+
import com.intellij.psi.PsiReferenceBase
19+
import io.github.gerardorodriguezdev.chamaleon.core.models.Project.Companion.ENVIRONMENTS_DIRECTORY_NAME
20+
import io.github.gerardorodriguezdev.chamaleon.core.models.Project.Companion.SCHEMA_FILE
21+
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
22+
23+
class PropertyDefinitionPsiReference(element: KtStringTemplateExpression) :
24+
PsiReferenceBase<KtStringTemplateExpression>(element, true) {
25+
26+
override fun resolve(): PsiElement? =
27+
option {
28+
val project = element.project
29+
30+
val schemaPsiFile = project.schemaPsiFile().bind()
31+
val schemaJsonFile = (schemaPsiFile as? JsonFile).bind()
32+
33+
val schemaJsonObject = (schemaJsonFile.topLevelValue as? JsonObject).bind()
34+
35+
val propertyDefinitionsJsonValue = schemaJsonObject.findProperty(
36+
PROPERTY_DEFINITIONS_PROPERTY_NAME
37+
)?.value.bind()
38+
39+
propertyDefinitionPsiElement(
40+
propertyDefinitionValueToFind = element.cleanedText(),
41+
propertyDefinitionsJsonArray = (propertyDefinitionsJsonValue as? JsonArray).bind(),
42+
).bind()
43+
}.getOrNull()
44+
45+
private fun Project.schemaPsiFile(): Option<PsiFile> =
46+
option {
47+
val module = ModuleUtilCore.findModuleForPsiElement(element).bind()
48+
val moduleRootManager = ModuleRootManager.getInstance(module)
49+
val virtualFiles = moduleRootManager.contentRoots
50+
schemaPsiFile(this@schemaPsiFile, virtualFiles).bind()
51+
}
52+
53+
private fun schemaPsiFile(
54+
project: Project,
55+
virtualFiles: Array<VirtualFile>,
56+
): Option<PsiFile> =
57+
option {
58+
val schemaVirtualFile = virtualFiles.firstNotNullOfOrNull { root ->
59+
VfsUtil.findRelativeFile(SCHEMA_RELATIVE_PATH, root)
60+
}.bind()
61+
PsiManager.getInstance(project).findFile(schemaVirtualFile).bind()
62+
}
63+
64+
private fun propertyDefinitionPsiElement(
65+
propertyDefinitionValueToFind: String,
66+
propertyDefinitionsJsonArray: JsonArray,
67+
): Option<PsiElement> =
68+
option {
69+
propertyDefinitionsJsonArray
70+
.valueList
71+
.firstOrNull { propertyDefinition ->
72+
val propertyDefinitionJsonObject = propertyDefinition as? JsonObject
73+
val propertyDefinitionJsonProperty = propertyDefinitionJsonObject?.findProperty(
74+
PROPERTY_DEFINITION_PROPERTY_NAME
75+
)
76+
propertyDefinitionJsonProperty?.value?.cleanedText() == propertyDefinitionValueToFind
77+
}
78+
.bind()
79+
.firstChild
80+
}
81+
82+
private fun String.clean(): String = removeSurrounding("\"")
83+
84+
private fun ASTDelegatePsiElement.cleanedText(): String = text.clean()
85+
86+
private fun JsonValue.cleanedText(): String = text.clean()
87+
88+
override fun getVariants(): Array<Any> = emptyArray()
89+
90+
private companion object {
91+
const val PROPERTY_DEFINITIONS_PROPERTY_NAME = "propertyDefinitions"
92+
const val PROPERTY_DEFINITION_PROPERTY_NAME = "name"
93+
const val SCHEMA_RELATIVE_PATH = "$ENVIRONMENTS_DIRECTORY_NAME/$SCHEMA_FILE"
94+
}
95+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package io.github.gerardorodriguezdev.chamaleon.intellij.plugin.psi
2+
3+
import com.intellij.patterns.PlatformPatterns
4+
import com.intellij.patterns.PlatformPatterns.psiFile
5+
import com.intellij.psi.PsiReferenceContributor
6+
import com.intellij.psi.PsiReferenceRegistrar
7+
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
8+
9+
internal class PropertyDefinitionReferenceContributor : PsiReferenceContributor() {
10+
override fun registerReferenceProviders(registrar: PsiReferenceRegistrar) {
11+
registrar.registerReferenceProvider(
12+
PlatformPatterns
13+
.psiElement(KtStringTemplateExpression::class.java)
14+
.inFile(psiFile().withName(BUILD_GRADLE_FILE_NAME)),
15+
PropertyDefinitionReferenceProvider(),
16+
)
17+
}
18+
19+
private companion object {
20+
const val BUILD_GRADLE_FILE_NAME = "build.gradle.kts"
21+
}
22+
}

0 commit comments

Comments
 (0)