Skip to content

Commit

Permalink
Extract lexer and parser tasks into their own classes
Browse files Browse the repository at this point in the history
This makes those tasks compatible with build and configuration cache

Unfortunately two other issues prevent us from using the configuration
 cache, one is the licenser plugin, the other is the access of
  testLibs in the test task configuration
  • Loading branch information
RedNesto committed Jul 3, 2024
1 parent 9da3841 commit d20f5e7
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 75 deletions.
5 changes: 4 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,10 @@ val generateNbttParser by parser("NbttParser", "com/demonwav/mcdev/nbt/lang/gen"
val generateLangLexer by lexer("LangLexer", "com/demonwav/mcdev/translations/lang/gen")
val generateLangParser by parser("LangParser", "com/demonwav/mcdev/translations/lang/gen")

val generateTranslationTemplateLexer by lexer("TranslationTemplateLexer", "com/demonwav/mcdev/translations/lang/gen")
val generateTranslationTemplateLexer by lexer(
"TranslationTemplateLexer",
"com/demonwav/mcdev/translations/template/gen"
)

val generate by tasks.registering {
group = "minecraft"
Expand Down
84 changes: 84 additions & 0 deletions buildSrc/src/main/kotlin/JFlexExec.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Minecraft Development for IntelliJ
*
* https://mcdev.io/
*
* Copyright (C) 2024 minecraft-dev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, version 3.0 only.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import java.io.ByteArrayOutputStream
import javax.inject.Inject
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.ConfigurableFileTree
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.FileCollection
import org.gradle.api.file.FileSystemOperations
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.JavaExec
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.OutputFile

abstract class JFlexExec : JavaExec() {

@get:InputFile
abstract val sourceFile: RegularFileProperty

@get:InputFiles
abstract val jflex: ConfigurableFileCollection

@get:InputFile
abstract val skeletonFile: RegularFileProperty

@get:OutputDirectory
abstract val destinationDirectory: DirectoryProperty

@get:OutputFile
abstract val destinationFile: RegularFileProperty

@get:Internal
abstract val logFile: RegularFileProperty

@get:Inject
abstract val fs: FileSystemOperations

init {
mainClass.set("jflex.Main")
}

override fun exec() {
classpath = jflex

args(
"--skel", skeletonFile.get().asFile.absolutePath,
"-d", destinationDirectory.get().asFile.absolutePath,
sourceFile.get().asFile.absolutePath
)

fs.delete { delete(destinationDirectory) }

val taskOutput = ByteArrayOutputStream()
standardOutput = taskOutput
errorOutput = taskOutput

super.exec()

val log = logFile.get().asFile
log.parentFile.mkdirs()
log.writeBytes(taskOutput.toByteArray())
}
}
88 changes: 88 additions & 0 deletions buildSrc/src/main/kotlin/ParserExec.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Minecraft Development for IntelliJ
*
* https://mcdev.io/
*
* Copyright (C) 2024 minecraft-dev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, version 3.0 only.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import java.io.ByteArrayOutputStream
import javax.inject.Inject
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.FileSystemOperations
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.JavaExec
import org.gradle.api.tasks.OutputDirectory

abstract class ParserExec : JavaExec() {

@get:InputFile
abstract val sourceFile: RegularFileProperty

@get:InputFiles
abstract val grammarKit: ConfigurableFileCollection

@get:OutputDirectory
abstract val destinationRootDirectory: DirectoryProperty

@get:OutputDirectory
abstract val destinationDirectory: DirectoryProperty

@get:OutputDirectory
abstract val psiDirectory: DirectoryProperty

@get:OutputDirectory
abstract val parserDirectory: DirectoryProperty

@get:Internal
abstract val logFile: RegularFileProperty

@get:Inject
abstract val fs: FileSystemOperations

init {
mainClass.set("org.intellij.grammar.Main")

jvmArgs(
"--add-opens", "java.base/java.lang=ALL-UNNAMED",
"--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED",
"--add-opens", "java.base/java.util=ALL-UNNAMED"
)
}

override fun exec() {
classpath = grammarKit
args(
destinationRootDirectory.get().asFile,
sourceFile.get().asFile
)

fs.delete { delete(psiDirectory, parserDirectory) }

val taskOutput = ByteArrayOutputStream()
standardOutput = taskOutput
errorOutput = taskOutput

super.exec()

val log = logFile.get().asFile
log.parentFile.mkdirs()
log.writeBytes(taskOutput.toByteArray())
}
}
92 changes: 20 additions & 72 deletions buildSrc/src/main/kotlin/util.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,94 +32,42 @@ import org.gradle.kotlin.dsl.configure

typealias TaskDelegate<T> = RegisteringDomainObjectDelegateProviderWithTypeAndAction<out TaskContainer, T>

fun Project.lexer(flex: String, pack: String): TaskDelegate<JavaExec> {
fun Project.lexer(flex: String, pack: String): TaskDelegate<JFlexExec> {
configure<LicenseExtension> {
exclude(pack.removeSuffix("/") + "/**")
}

return tasks.registering(JavaExec::class) {
val src = layout.projectDirectory.file("src/main/grammars/$flex.flex")
val dst = layout.buildDirectory.dir("gen/$pack")
val output = layout.buildDirectory.file("gen/$pack/$flex.java")
val logOutout = layout.buildDirectory.file("logs/generate$flex.log")
return tasks.registering(JFlexExec::class) {
sourceFile.set(layout.projectDirectory.file("src/main/grammars/$flex.flex"))
destinationDirectory.set(layout.buildDirectory.dir("gen/$pack"))
destinationFile.set(layout.buildDirectory.file("gen/$pack/$flex.java"))
logFile.set(layout.buildDirectory.file("logs/generate$flex.log"))

val jflex by project.configurations
val jflexSkeleton by project.configurations

classpath = jflex
mainClass.set("jflex.Main")

val taskOutput = ByteArrayOutputStream()
standardOutput = taskOutput
errorOutput = taskOutput

doFirst {
args(
"--skel", jflexSkeleton.singleFile.absolutePath,
"-d", dst.get().asFile.absolutePath,
src.asFile.absolutePath
)

// Delete current lexer
project.delete(output)
logOutout.get().asFile.parentFile.mkdirs()
}

doLast {
logOutout.get().asFile.writeBytes(taskOutput.toByteArray())
}
this.jflex.setFrom(jflex)

inputs.files(src, jflexSkeleton)
outputs.file(output)
val jflexSkeleton by project.configurations
skeletonFile.set(jflexSkeleton.singleFile)
}
}

fun Project.parser(bnf: String, pack: String): TaskDelegate<JavaExec> {
fun Project.parser(bnf: String, pack: String): TaskDelegate<ParserExec> {
configure<LicenseExtension> {
exclude(pack.removeSuffix("/") + "/**")
}

return tasks.registering(JavaExec::class) {
val src = project.layout.projectDirectory.file("src/main/grammars/$bnf.bnf")
val dstRoot = project.layout.buildDirectory.dir("gen")
val dst = dstRoot.map { it.dir(pack) }
val psiDir = dst.map { it.dir("psi") }
val parserDir = dst.map { it.dir("parser") }
val logOutout = layout.buildDirectory.file("logs/generate$bnf.log")
return tasks.registering(ParserExec::class) {
val destRoot = project.layout.buildDirectory.dir("gen")
val dest = destRoot.map { it.dir(pack) }
sourceFile.set(project.layout.projectDirectory.file("src/main/grammars/$bnf.bnf"))
destinationRootDirectory.set(destRoot)
destinationDirectory.set(dest)
psiDirectory.set(dest.map { it.dir("psi") })
parserDirectory.set(dest.map { it.dir("parser") })
logFile.set(layout.buildDirectory.file("logs/generate$bnf.log"))

val grammarKit by project.configurations

val taskOutput = ByteArrayOutputStream()
standardOutput = taskOutput
errorOutput = taskOutput

classpath = grammarKit
mainClass.set("org.intellij.grammar.Main")

if (JavaVersion.current().isJava9Compatible) {
jvmArgs(
"--add-opens", "java.base/java.lang=ALL-UNNAMED",
"--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED",
"--add-opens", "java.base/java.util=ALL-UNNAMED"
)
}

doFirst {
project.delete(psiDir, parserDir)
args(dstRoot.get().asFile, src.asFile)
logOutout.get().asFile.parentFile.mkdirs()
}
doLast {
logOutout.get().asFile.writeBytes(taskOutput.toByteArray())
}

inputs.file(src)
outputs.dirs(
mapOf(
"psi" to psiDir,
"parser" to parserDir
)
)
this.grammarKit.setFrom(grammarKit)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/grammars/TranslationTemplateLexer.flex
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package com.demonwav.mcdev.translations.lang.gen;
package com.demonwav.mcdev.translations.template.gen;

import com.intellij.lexer.*;
import com.intellij.psi.tree.IElementType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

package com.demonwav.mcdev.translations.sorting

import com.demonwav.mcdev.translations.lang.gen.TranslationTemplateLexer
import com.demonwav.mcdev.translations.template.gen.TranslationTemplateLexer
import com.intellij.lexer.FlexAdapter

class TranslationTemplateLexerAdapter : FlexAdapter(TranslationTemplateLexer())

0 comments on commit d20f5e7

Please sign in to comment.