mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-01-06 07:20:30 +00:00
Use spotless for enforcing licenses
It's more verbose as the default license plugin doesn't support multiple license headers. However, it also gives us some other goodies (namely formatting Kotlin and removing unused imports), so worth doing.
This commit is contained in:
parent
57cf6084e2
commit
af5d816798
@ -24,6 +24,13 @@ repos:
|
||||
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: license
|
||||
name: Spotless
|
||||
files: ".*\\.(java|kt|kts)$"
|
||||
language: system
|
||||
entry: ./gradlew spotlessApply
|
||||
pass_filenames: false
|
||||
require_serial: true
|
||||
- id: checkstyle
|
||||
name: Check Java codestyle
|
||||
files: ".*\\.java$"
|
||||
@ -31,18 +38,11 @@ repos:
|
||||
entry: ./gradlew checkstyleMain checkstyleTest
|
||||
pass_filenames: false
|
||||
require_serial: true
|
||||
- id: license
|
||||
name: Check Java license headers
|
||||
files: ".*\\.java$"
|
||||
language: system
|
||||
entry: ./gradlew licenseFormat
|
||||
pass_filenames: false
|
||||
require_serial: true
|
||||
- id: illuaminate
|
||||
name: Check Lua code
|
||||
files: ".*\\.(lua|java|md)"
|
||||
language: system
|
||||
entry: ./gradlew lintLua -i
|
||||
entry: ./gradlew lintLua
|
||||
pass_filenames: false
|
||||
require_serial: true
|
||||
|
||||
|
21
build.gradle
21
build.gradle
@ -2,7 +2,6 @@ plugins {
|
||||
id "checkstyle"
|
||||
id "jacoco"
|
||||
id "maven-publish"
|
||||
id "org.cadixdev.licenser" version "0.6.1"
|
||||
id "com.matthewprenger.cursegradle" version "1.4.0"
|
||||
id "com.github.breadmoirai.github-release" version "2.2.12"
|
||||
id "org.jetbrains.kotlin.jvm" version "1.7.0"
|
||||
@ -11,7 +10,8 @@ plugins {
|
||||
id "org.spongepowered.mixin" version "0.7.+"
|
||||
id "org.parchmentmc.librarian.forgegradle" version "1.+"
|
||||
id "com.github.johnrengelman.shadow" version "7.1.2"
|
||||
id "cc-tweaked.illuaminate"
|
||||
id("cc-tweaked.illuaminate")
|
||||
id("cc-tweaked.java-convention")
|
||||
}
|
||||
|
||||
|
||||
@ -388,23 +388,6 @@ jacocoTestReport {
|
||||
|
||||
test.finalizedBy("jacocoTestReport")
|
||||
|
||||
license {
|
||||
header = file('config/license/main.txt')
|
||||
lineEnding = '\n'
|
||||
newLine = false
|
||||
|
||||
properties {
|
||||
year = Calendar.getInstance().get(Calendar.YEAR)
|
||||
}
|
||||
|
||||
include("**/*.java") // We could apply to Kotlin, but for now let's not
|
||||
matching("dan200/computercraft/api/**") {
|
||||
header = file('config/license/api.txt')
|
||||
}
|
||||
}
|
||||
|
||||
check.dependsOn("licenseCheck")
|
||||
|
||||
def lintLua = tasks.register("lintLua", IlluaminateExec.class) {
|
||||
group = JavaBasePlugin.VERIFICATION_GROUP
|
||||
description = "Lint Lua (and Lua docs) with illuaminate"
|
||||
|
@ -8,6 +8,10 @@ repositories {
|
||||
gradlePluginPortal()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.spotless)
|
||||
}
|
||||
|
||||
gradlePlugin {
|
||||
plugins {
|
||||
register("cc-tweaked.illuaminate") {
|
||||
|
7
buildSrc/settings.gradle.kts
Normal file
7
buildSrc/settings.gradle.kts
Normal file
@ -0,0 +1,7 @@
|
||||
dependencyResolutionManagement {
|
||||
versionCatalogs {
|
||||
create("libs") {
|
||||
from(files("../gradle/libs.versions.toml"))
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
import cc.tweaked.gradle.LicenseHeader
|
||||
import com.diffplug.gradle.spotless.FormatExtension
|
||||
import com.diffplug.spotless.LineEnding
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
plugins {
|
||||
java
|
||||
jacoco
|
||||
id("com.diffplug.spotless")
|
||||
}
|
||||
|
||||
spotless {
|
||||
encoding = StandardCharsets.UTF_8
|
||||
lineEndings = LineEnding.UNIX
|
||||
|
||||
fun FormatExtension.defaults() {
|
||||
endWithNewline()
|
||||
trimTrailingWhitespace()
|
||||
indentWithSpaces(4)
|
||||
}
|
||||
|
||||
val licenser = LicenseHeader.create(
|
||||
api = file("config/license/api.txt"),
|
||||
main = file("config/license/main.txt"),
|
||||
)
|
||||
|
||||
java {
|
||||
defaults()
|
||||
addStep(licenser)
|
||||
removeUnusedImports()
|
||||
}
|
||||
|
||||
val ktlintConfig = mapOf(
|
||||
"disabled_rules" to "no-wildcard-imports",
|
||||
"ij_kotlin_allow_trailing_comma" to "true",
|
||||
"ij_kotlin_allow_trailing_comma_on_call_site" to "true",
|
||||
)
|
||||
|
||||
kotlinGradle {
|
||||
defaults()
|
||||
ktlint().editorConfigOverride(ktlintConfig)
|
||||
}
|
||||
|
||||
kotlin {
|
||||
defaults()
|
||||
ktlint().editorConfigOverride(ktlintConfig)
|
||||
}
|
||||
}
|
73
buildSrc/src/main/kotlin/cc/tweaked/gradle/CheckLicense.kt
Normal file
73
buildSrc/src/main/kotlin/cc/tweaked/gradle/CheckLicense.kt
Normal file
@ -0,0 +1,73 @@
|
||||
package cc.tweaked.gradle
|
||||
|
||||
import com.diffplug.spotless.FormatterFunc
|
||||
import com.diffplug.spotless.FormatterStep
|
||||
import com.diffplug.spotless.generic.LicenseHeaderStep
|
||||
import java.io.File
|
||||
import java.io.Serializable
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
/**
|
||||
* Similar to [LicenseHeaderStep], but supports multiple licenses.
|
||||
*/
|
||||
object LicenseHeader {
|
||||
/**
|
||||
* The current year to use in templates. Intentionally not dynamic to avoid failing the build.
|
||||
*/
|
||||
private const val YEAR = 2022
|
||||
|
||||
private val COMMENT = Regex("""^/\*(.*?)\*/\n?""", RegexOption.DOT_MATCHES_ALL)
|
||||
|
||||
fun create(api: File, main: File): FormatterStep = FormatterStep.createLazy(
|
||||
"license",
|
||||
{ Licenses(getTemplateText(api), getTemplateText(main)) },
|
||||
{ state -> FormatterFunc.NeedsFile { contents, file -> formatFile(state, contents, file) } },
|
||||
)
|
||||
|
||||
private fun getTemplateText(file: File): String =
|
||||
file.readText(StandardCharsets.UTF_8).trim().replace("\${year}", "$YEAR")
|
||||
|
||||
private fun formatFile(licenses: Licenses, contents: String, file: File): String {
|
||||
val license = getLicense(contents)
|
||||
val expectedLicense = getExpectedLicense(licenses, file.parentFile)
|
||||
|
||||
return when {
|
||||
license == null -> setLicense(expectedLicense, contents)
|
||||
license.second != expectedLicense -> setLicense(expectedLicense, contents, license.first)
|
||||
else -> contents
|
||||
}
|
||||
}
|
||||
|
||||
private fun getExpectedLicense(licenses: Licenses, file: File): String {
|
||||
var file: File? = file
|
||||
while (file != null) {
|
||||
if (file.name == "api" && file.parentFile?.name == "computercraft") return licenses.api
|
||||
file = file.parentFile
|
||||
}
|
||||
return licenses.main
|
||||
}
|
||||
|
||||
private fun getLicense(contents: String): Pair<Int, String>? {
|
||||
val match = COMMENT.find(contents) ?: return null
|
||||
val license = match.groups[1]!!.value
|
||||
.trim().lineSequence()
|
||||
.map { it.trimStart(' ', '*') }
|
||||
.joinToString("\n")
|
||||
return Pair(match.range.last + 1, license)
|
||||
}
|
||||
|
||||
private fun setLicense(license: String, contents: String, start: Int = 0): String {
|
||||
val out = StringBuilder()
|
||||
out.append("/*\n")
|
||||
for (line in license.lineSequence()) out.append(" * ").append(line).append("\n")
|
||||
out.append(" */\n")
|
||||
out.append(contents, start, contents.length)
|
||||
return out.toString()
|
||||
}
|
||||
|
||||
private data class Licenses(val api: String, val main: String) : Serializable {
|
||||
companion object {
|
||||
private const val serialVersionUID: Long = 7741106448372435662L
|
||||
}
|
||||
}
|
||||
}
|
@ -9,6 +9,9 @@ hamcrest = "2.2"
|
||||
jqwik = "1.7.0"
|
||||
junit = "5.9.1"
|
||||
|
||||
# Build tools
|
||||
spotless = "6.8.0"
|
||||
|
||||
[libraries]
|
||||
autoService = { module = "com.google.auto.service:auto-service", version.ref = "autoService" }
|
||||
jetbrainsAnnotations = { module = "org.jetbrains:annotations", version.ref = "jetbrainsAnnotations" }
|
||||
@ -23,6 +26,9 @@ junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.re
|
||||
junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit" }
|
||||
junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params", version.ref = "junit" }
|
||||
|
||||
# Gradle plugins
|
||||
spotless = { module = "com.diffplug.spotless:spotless-plugin-gradle", version.ref = "spotless" }
|
||||
|
||||
[bundles]
|
||||
kotlin = ["kotlin-stdlib", "kotlin-coroutines"]
|
||||
|
||||
|
@ -14,4 +14,4 @@ pluginManagement {
|
||||
}
|
||||
|
||||
val mc_version: String by settings
|
||||
rootProject.name = "cc-tweaked-${mc_version}"
|
||||
rootProject.name = "cc-tweaked-$mc_version"
|
||||
|
@ -19,7 +19,6 @@ import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
import kotlin.time.ExperimentalTime
|
||||
|
||||
|
||||
abstract class NullApiEnvironment : IAPIEnvironment {
|
||||
private val computerEnv = BasicEnvironment()
|
||||
|
||||
|
@ -28,8 +28,8 @@ class TestHttpApi {
|
||||
ComputerCraft.httpRules = Collections.unmodifiableList(
|
||||
listOf(
|
||||
AddressRule.parse("\$private", null, Action.DENY.toPartial()),
|
||||
AddressRule.parse("*", null, Action.ALLOW.toPartial())
|
||||
)
|
||||
AddressRule.parse("*", null, Action.ALLOW.toPartial()),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,8 @@ class Computer_Test {
|
||||
context.assertBlockState(
|
||||
lamp,
|
||||
{ !it.getValue(RedstoneLampBlock.LIT) },
|
||||
{ "Lamp should still not be lit" })
|
||||
{ "Lamp should still not be lit" },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -15,10 +15,14 @@ class Modem_Test {
|
||||
this
|
||||
.thenComputerOk(marker = "initial")
|
||||
.thenExecute {
|
||||
helper.setBlock(position, BlockCable.correctConnections(
|
||||
helper.level, helper.absolutePos(position),
|
||||
Registry.ModBlocks.CABLE.get().defaultBlockState().setValue(BlockCable.CABLE, true)
|
||||
))
|
||||
helper.setBlock(
|
||||
position,
|
||||
BlockCable.correctConnections(
|
||||
helper.level,
|
||||
helper.absolutePos(position),
|
||||
Registry.ModBlocks.CABLE.get().defaultBlockState().setValue(BlockCable.CABLE, true),
|
||||
),
|
||||
)
|
||||
}
|
||||
.thenComputerOk()
|
||||
}
|
@ -24,7 +24,7 @@ class Monitor_Test {
|
||||
val toSet = BlockStateInput(
|
||||
Registry.ModBlocks.MONITOR_ADVANCED.get().defaultBlockState(),
|
||||
Collections.emptySet(),
|
||||
tag
|
||||
tag,
|
||||
)
|
||||
|
||||
context.setBlock(pos, Blocks.AIR.defaultBlockState())
|
@ -2,7 +2,7 @@ package dan200.computercraft.ingame
|
||||
|
||||
import dan200.computercraft.ingame.api.*
|
||||
|
||||
class PrintoutTest {
|
||||
class Printout_Test {
|
||||
@GameTest(batch = "client:Printout_Test.In_frame_at_night", timeoutTicks = Timeouts.CLIENT_TIMEOUT)
|
||||
fun In_frame_at_night(helper: GameTestHelper) = helper.sequence {
|
||||
this
|
@ -86,9 +86,9 @@ class Turtle_Test {
|
||||
DetailRegistries.ITEM_STACK.addProvider(
|
||||
object : BasicItemDetailProvider<ItemPrintout>("printout", ItemPrintout::class.java) {
|
||||
override fun provideDetails(data: MutableMap<in String, Any>, stack: ItemStack, item: ItemPrintout) {
|
||||
data["type"] = item.type.toString();
|
||||
data["type"] = item.type.toString()
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
.thenComputerOk()
|
@ -79,7 +79,8 @@ typealias GameTestSequence = TestList
|
||||
|
||||
typealias GameTestAssertException = RuntimeException
|
||||
|
||||
private fun GameTestSequence.addResult(task: () -> Unit, delay: Long? = null): GameTestSequence {
|
||||
private fun GameTestSequence.addResult(task: () -> Unit) = addResult(null, task)
|
||||
private fun GameTestSequence.addResult(delay: Long?, task: () -> Unit): GameTestSequence {
|
||||
val result = UnsafeHacks.newInstance(TestTickResult::class.java) as TestTickResult
|
||||
result.assertion = Runnable(task)
|
||||
result.expectedDelay = delay
|
||||
@ -88,29 +89,29 @@ private fun GameTestSequence.addResult(task: () -> Unit, delay: Long? = null): G
|
||||
}
|
||||
|
||||
fun GameTestSequence.thenSucceed() {
|
||||
addResult({
|
||||
addResult {
|
||||
if (parent.error != null) return@addResult
|
||||
|
||||
parent.finish()
|
||||
parent.markAsComplete()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fun GameTestSequence.thenWaitUntil(task: () -> Unit) = addResult(task)
|
||||
|
||||
fun GameTestSequence.thenExecute(task: () -> Unit) = addResult({
|
||||
fun GameTestSequence.thenExecute(task: () -> Unit) = addResult {
|
||||
try {
|
||||
task()
|
||||
} catch (e: Exception) {
|
||||
parent.fail(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun GameTestSequence.thenIdle(delay: Long) = addResult({
|
||||
fun GameTestSequence.thenIdle(delay: Long) = addResult {
|
||||
if (parent.tickCount < lastTick + delay) {
|
||||
throw GameTestAssertException("Waiting")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Proguard strips out all the "on success" code as it's never called anywhere. This is workable most of the time, but
|
||||
|
@ -99,7 +99,7 @@ fun GameTestSequence.thenScreenshot(name: String? = null): GameTestSequence {
|
||||
val screenshotPath = screenshotsPath.resolve("$fullName.png")
|
||||
val originalPath = TestMod.sourceDir.resolve("screenshots").resolve("$fullName.png")
|
||||
|
||||
if (!Files.exists(originalPath)) throw GameTestAssertException("$fullName does not exist. Use `/cctest promote' to create it.");
|
||||
if (!Files.exists(originalPath)) throw GameTestAssertException("$fullName does not exist. Use `/cctest promote' to create it.")
|
||||
|
||||
val screenshot = ImageIO.read(screenshotPath.toFile())
|
||||
?: throw GameTestAssertException("Error reading screenshot from $screenshotPath")
|
||||
@ -147,14 +147,16 @@ fun GameTestHelper.positionAtArmorStand() {
|
||||
player.connection.teleport(stand.x, stand.y, stand.z, stand.yRot, stand.xRot)
|
||||
}
|
||||
|
||||
|
||||
class ClientTestHelper {
|
||||
val minecraft: Minecraft = Minecraft.getInstance()
|
||||
|
||||
fun screenshot(name: String, callback: () -> Unit = {}) {
|
||||
ScreenShotHelper.grab(
|
||||
minecraft.gameDirectory, name,
|
||||
minecraft.window.width, minecraft.window.height, minecraft.mainRenderTarget
|
||||
minecraft.gameDirectory,
|
||||
name,
|
||||
minecraft.window.width,
|
||||
minecraft.window.height,
|
||||
minecraft.mainRenderTarget,
|
||||
) {
|
||||
TestMod.log.info(it.string)
|
||||
callback()
|
||||
|
Loading…
Reference in New Issue
Block a user