Skip to content

Commit c504db6

Browse files
committed
Merge branch '2022.1' into 2022.2
2 parents 15199cb + 75e9365 commit c504db6

File tree

13 files changed

+304
-238
lines changed

13 files changed

+304
-238
lines changed

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ kotlin.code.style=official
1414
ideaVersion = 2022.2
1515
ideaVersionName = 2022.2
1616

17-
coreVersion = 1.6.0
17+
coreVersion = 1.6.1
1818
downloadIdeaSources = true
1919

2020
pluginTomlVersion = 222.3345.108

src/main/kotlin/creator/PlatformVersion.kt

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import com.intellij.util.proxy.CommonProxy
2323
import java.io.IOException
2424
import java.net.Proxy
2525
import java.net.URI
26-
import javax.swing.JComboBox
2726
import kotlin.reflect.KClass
2827

2928
private const val CLOUDFLARE_BASE_URL = "https://minecraftdev.org/versions/"
@@ -93,12 +92,4 @@ fun selectProxy(urlText: String): Proxy? {
9392
return null
9493
}
9594

96-
data class PlatformVersion(var versions: List<String>, var selectedIndex: Int) {
97-
fun set(combo: JComboBox<String>) {
98-
combo.removeAllItems()
99-
for (version in this.versions) {
100-
combo.addItem(version)
101-
}
102-
combo.selectedIndex = this.selectedIndex
103-
}
104-
}
95+
data class PlatformVersion(var versions: List<String>, var selectedIndex: Int)
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
/*
2+
* Minecraft Dev for IntelliJ
3+
*
4+
* https://minecraftdev.org
5+
*
6+
* Copyright (c) 2023 minecraft-dev
7+
*
8+
* MIT License
9+
*/
10+
11+
package com.demonwav.mcdev.creator.buildsystem
12+
13+
import com.demonwav.mcdev.util.childrenOfType
14+
import com.demonwav.mcdev.util.mapFirstNotNull
15+
import com.intellij.openapi.extensions.ExtensionPointName
16+
import com.intellij.openapi.project.Project
17+
import com.intellij.openapi.util.text.StringUtil
18+
import com.intellij.psi.PsiFile
19+
import org.jetbrains.annotations.ApiStatus.Internal
20+
import org.jetbrains.kotlin.psi.KtBinaryExpression
21+
import org.jetbrains.kotlin.psi.KtBlockExpression
22+
import org.jetbrains.kotlin.psi.KtCallExpression
23+
import org.jetbrains.kotlin.psi.KtFile
24+
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
25+
import org.jetbrains.kotlin.psi.KtPsiFactory
26+
import org.jetbrains.kotlin.psi.KtScriptInitializer
27+
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile
28+
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory
29+
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock
30+
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression
31+
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner
32+
33+
@Internal
34+
interface GradleFile {
35+
companion object {
36+
val EP_NAME = ExtensionPointName<Type>("com.demonwav.minecraft-dev.gradleFileType")
37+
}
38+
39+
val psi: PsiFile
40+
41+
fun addRepositories(project: Project, repositories: List<BuildRepository>)
42+
fun addDependencies(project: Project, dependencies: List<BuildDependency>)
43+
fun addPlugins(project: Project, plugins: List<GradlePlugin>)
44+
45+
interface Type {
46+
fun createGradleFile(psiFile: PsiFile): GradleFile?
47+
}
48+
}
49+
50+
class GroovyGradleFile(override val psi: GroovyFile) : GradleFile {
51+
override fun addRepositories(project: Project, repositories: List<BuildRepository>) {
52+
val reposBlock = findOrCreateGroovyBlock(project, psi, "repositories")
53+
val elementFactory = GroovyPsiElementFactory.getInstance(project)
54+
for (repo in repositories) {
55+
if (BuildSystemType.GRADLE !in repo.buildSystems) {
56+
continue
57+
}
58+
val mavenBlock =
59+
elementFactory.createStatementFromText("maven {\n}", reposBlock) as GrMethodCallExpression
60+
val mavenClosure = mavenBlock.closureArguments[0]
61+
if (repo.id.isNotBlank()) {
62+
val idStatement =
63+
elementFactory.createStatementFromText("name = ${makeStringLiteral(repo.id)}")
64+
mavenClosure.addStatementBefore(idStatement, null)
65+
}
66+
val urlStatement =
67+
elementFactory.createStatementFromText("url = ${makeStringLiteral(repo.url)}")
68+
mavenClosure.addStatementBefore(urlStatement, null)
69+
reposBlock.addStatementBefore(mavenBlock, null)
70+
}
71+
}
72+
73+
override fun addDependencies(project: Project, dependencies: List<BuildDependency>) {
74+
val depsBlock = findOrCreateGroovyBlock(project, psi, "dependencies")
75+
val elementFactory = GroovyPsiElementFactory.getInstance(project)
76+
for (dep in dependencies) {
77+
val gradleConfig = dep.gradleConfiguration ?: continue
78+
val stmt = elementFactory.createStatementFromText(
79+
"$gradleConfig \"${escapeGString(dep.groupId)}:${
80+
escapeGString(dep.artifactId)
81+
}:${escapeGString(dep.version)}\"",
82+
depsBlock,
83+
)
84+
depsBlock.addStatementBefore(stmt, null)
85+
}
86+
}
87+
88+
override fun addPlugins(project: Project, plugins: List<GradlePlugin>) {
89+
val pluginsBlock = findOrCreateGroovyBlock(project, psi, "plugins", first = true)
90+
val elementFactory = GroovyPsiElementFactory.getInstance(project)
91+
for (plugin in plugins) {
92+
val stmt = elementFactory.createStatementFromText(makePluginStatement(plugin, false))
93+
pluginsBlock.addStatementBefore(stmt, null)
94+
}
95+
}
96+
97+
private fun findGroovyBlock(element: GrStatementOwner, name: String): GrClosableBlock? {
98+
return element.statements
99+
.mapFirstNotNull { call ->
100+
if (call is GrMethodCallExpression && call.callReference?.methodName == name) {
101+
call.closureArguments.firstOrNull()
102+
} else {
103+
null
104+
}
105+
}
106+
}
107+
108+
private fun findOrCreateGroovyBlock(
109+
project: Project,
110+
element: GrStatementOwner,
111+
name: String,
112+
first: Boolean = false,
113+
): GrClosableBlock {
114+
findGroovyBlock(element, name)?.let { return it }
115+
val block = GroovyPsiElementFactory.getInstance(project).createStatementFromText("$name {\n}", element)
116+
val anchor = if (first) {
117+
element.statements.firstOrNull()
118+
} else {
119+
null
120+
}
121+
return (element.addStatementBefore(block, anchor) as GrMethodCallExpression).closureArguments.first()
122+
}
123+
124+
class Type : GradleFile.Type {
125+
override fun createGradleFile(psiFile: PsiFile) = (psiFile as? GroovyFile)?.let(::GroovyGradleFile)
126+
}
127+
}
128+
129+
class KotlinGradleFile(override val psi: KtFile) : GradleFile {
130+
override fun addRepositories(project: Project, repositories: List<BuildRepository>) {
131+
val script = psi.script?.blockExpression ?: return
132+
val reposBlock = findOrCreateKotlinBlock(project, script, "repositories")
133+
val elementFactory = KtPsiFactory(project)
134+
for (repo in repositories) {
135+
if (BuildSystemType.GRADLE !in repo.buildSystems) {
136+
continue
137+
}
138+
val mavenBlock = elementFactory.createExpression("maven {\n}") as KtCallExpression
139+
val mavenLambda = mavenBlock.lambdaArguments[0].getLambdaExpression()!!.bodyExpression!!
140+
if (repo.id.isNotBlank()) {
141+
val idStatement = elementFactory.createAssignment("name = ${makeStringLiteral(repo.id)}")
142+
mavenLambda.addBefore(idStatement, mavenLambda.rBrace)
143+
}
144+
val urlStatement = elementFactory.createAssignment("url = uri(${makeStringLiteral(repo.url)})")
145+
mavenLambda.addBefore(urlStatement, mavenLambda.rBrace)
146+
reposBlock.addBefore(mavenBlock, reposBlock.rBrace)
147+
}
148+
}
149+
150+
override fun addDependencies(project: Project, dependencies: List<BuildDependency>) {
151+
val script = psi.script?.blockExpression ?: return
152+
val depsBlock = findOrCreateKotlinBlock(project, script, "dependencies")
153+
val elementFactory = KtPsiFactory(project)
154+
for (dep in dependencies) {
155+
val gradleConfig = dep.gradleConfiguration ?: continue
156+
val stmt = elementFactory.createExpression(
157+
"$gradleConfig(\"${escapeGString(dep.groupId)}:${
158+
escapeGString(dep.artifactId)
159+
}:${escapeGString(dep.version)}\")",
160+
)
161+
depsBlock.addBefore(stmt, depsBlock.rBrace)
162+
}
163+
}
164+
165+
override fun addPlugins(project: Project, plugins: List<GradlePlugin>) {
166+
val script = psi.script?.blockExpression ?: return
167+
val pluginsBlock = findOrCreateKotlinBlock(project, script, "plugins", first = true)
168+
val elementFactory = KtPsiFactory(project)
169+
for (plugin in plugins) {
170+
val stmt = elementFactory.createExpression(makePluginStatement(plugin, true))
171+
pluginsBlock.addBefore(stmt, pluginsBlock.rBrace)
172+
}
173+
}
174+
175+
private fun findKotlinBlock(element: KtBlockExpression, name: String): KtBlockExpression? {
176+
return element.childrenOfType<KtScriptInitializer>()
177+
.flatMap { it.childrenOfType<KtCallExpression>() }
178+
.mapFirstNotNull { call ->
179+
if ((call.calleeExpression as? KtNameReferenceExpression)?.getReferencedName() == name) {
180+
call.lambdaArguments.firstOrNull()?.getLambdaExpression()?.bodyExpression
181+
} else {
182+
null
183+
}
184+
}
185+
}
186+
187+
private fun findOrCreateKotlinBlock(
188+
project: Project,
189+
element: KtBlockExpression,
190+
name: String,
191+
first: Boolean = false,
192+
): KtBlockExpression {
193+
findKotlinBlock(element, name)?.let { return it }
194+
val block = KtPsiFactory(project).createExpression("$name {\n}")
195+
val addedBlock = if (first) {
196+
element.addAfter(block, element.lBrace)
197+
} else {
198+
element.addBefore(block, element.rBrace)
199+
}
200+
return (addedBlock as KtCallExpression).lambdaArguments.first().getLambdaExpression()!!.bodyExpression!!
201+
}
202+
203+
private fun KtPsiFactory.createAssignment(text: String): KtBinaryExpression {
204+
return this.createBlock(text).firstStatement as KtBinaryExpression
205+
}
206+
207+
class Type : GradleFile.Type {
208+
override fun createGradleFile(psiFile: PsiFile) = (psiFile as? KtFile)?.let(::KotlinGradleFile)
209+
}
210+
}
211+
212+
private fun makeStringLiteral(str: String): String {
213+
return "\"${escapeGString(str)}\""
214+
}
215+
216+
private fun escapeGString(str: String): String {
217+
return StringUtil.escapeStringCharacters(str.length, str, "\"\$", StringBuilder()).toString()
218+
}
219+
220+
private fun makePluginStatement(plugin: GradlePlugin, kotlin: Boolean): String {
221+
return buildString {
222+
if (kotlin) {
223+
append("id(${makeStringLiteral(plugin.id)})")
224+
} else {
225+
append("id ${makeStringLiteral(plugin.id)}")
226+
}
227+
plugin.version?.let { append(" version ${makeStringLiteral(it)}") }
228+
if (!plugin.apply) {
229+
append(" apply false")
230+
}
231+
}
232+
}

0 commit comments

Comments
 (0)