Skip to content

Commit

Permalink
XML-style headers, Kotlin, extra patterns
Browse files Browse the repository at this point in the history
  • Loading branch information
gdude2002 committed Jun 26, 2024
1 parent 689da02 commit 8cd6f27
Show file tree
Hide file tree
Showing 5 changed files with 224 additions and 8 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@
*.war binary

# Custom
src/functionalTest/resources/scenarios/**/* text eol=lf
src/functionalTest/resources/scenarios/base_java/src/main/java/test/TestClassCrlf*.java text eol=crlf
21 changes: 15 additions & 6 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
plugins {
id("dev.yumi.gradle.licenser").version("1.1.+")
id("com.gradle.plugin-publish").version("1.2.0")
id("maven-publish")
id("signing")
id("dev.yumi.gradle.licenser") version "1.1.+"
id("com.gradle.plugin-publish") version "1.2.0"

kotlin("jvm") version "1.9.24"

`maven-publish`
signing
}

group = "dev.yumi"
version = "1.1.2"
version = "1.1.3"
val javaVersion = 17

repositories {
Expand All @@ -33,7 +36,8 @@ gradlePlugin {
create("yumi_gradle_licenser") {
id = "dev.yumi.gradle.licenser"
displayName = "Yumi Gradle Licenser"
description = "A plugin to automatically manage license headers in project files, designed to be flexible to easily support many use cases like having different header kinds for different files."
description =
"A plugin to automatically manage license headers in project files, designed to be flexible to easily support many use cases like having different header kinds for different files."
tags = listOf("licenser", "licensing", "licenses", "license-header")
implementationClass = "dev.yumi.gradle.licenser.YumiLicenserGradlePlugin"
}
Expand All @@ -53,6 +57,11 @@ java {
testResultsDir.set(layout.buildDirectory.dir("junit-xml"))
}

kotlin {
// Require explicit visibility/type definitions for public types, among other things
explicitApi()
}

tasks.withType<JavaCompile>().configureEach {
options.encoding = "UTF-8"
options.isDeprecation = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,65 @@ public class HeaderCommentManager {
public HeaderCommentManager() {
this.register(new PatternSet()
.include(
// C/++
"**/*.c",
"**/*.cpp",
"**/*.cxx",
"**/*.h",
"**/*.hpp",
"**/*.hxx",

// Java
"**/*.java",

// Kotlin
"**/*.kt",
"**/*.kts",
"**/*.scala"

// Scala
"**/*.scala",

// Web languages
"**/*.dart", // Dart language
"**/*.js", // JavaScript
"**/*.jsx", // JavaScript XML
"**/*.ts", // TypeScript
"**/*.tsx", // TypeScript XML

// Stylesheets
"**/*.css", // CSS stylesheets
"**/*.less", // Less (Extended CSS)
"**/*.scss", // SCSS (CSS syntax for SASS)
"**/*.styl" // Stylus (Alternative CSS syntax)
),
CStyleHeaderComment.INSTANCE
);

this.register(new PatternSet()
.include(
// Web markup
"**/*.htm",
"**/*.html",
"**/*.xhtml",

// Extended HTML
"**/*.vue",
"**/*.svelte",

// Data formats
"**/*.xml",

// Image formats
"**/*.svg"
),
XmlStyleHeaderComment.INSTANCE
);
}

/**
* Registers a header comment implementation for a given file pattern.
*
* @param filePattern the file pattern to match files for which the given header comment implementation applies
* @param filePattern the file pattern to match files for which the given header comment implementation applies
* @param headerComment the header comment implementation
*/
public void register(@NotNull PatternSet filePattern, @NotNull HeaderComment headerComment) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright 2023 Yumi Project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

package dev.yumi.gradle.licenser.api.comment

private const val COMMENT_START = "<!--"
private const val COMMENT_END = "-->"

/**
* [HeaderComment] implementation for XML-style comments.
*
* @author gdude2002
* @since 1.1.3
*/
public open class XmlStyleHeaderComment protected constructor() : HeaderComment {
override fun readHeaderComment(source: String): HeaderComment.Result {
val separator = this.extractLineSeparator(source)

// Find the first comment block using a blank line
val firstBlock = source.split(separator.repeat(2)).first()

// Find the start of the comment by its opening characters
val start = firstBlock.indexOf(COMMENT_START)

if (start != 0) { // If the comment doesn't open on the first character of the block...
// ...check whether all prefixing characters are spaces.
val allWhitespacePrefixed = (0 until start).all { source[it] in arrayOf(' ', separator) }

if (!allWhitespacePrefixed) { // If not, this isn't a licence header – bail out.
return HeaderComment.Result(0, 0, null, separator)
}
}

// Find the last character of the comment, including the closing characters.
val end = firstBlock.indexOf(COMMENT_END) + COMMENT_END.length

if (start < 0 || end < 0) {
// If we can't find the start or end of the block, there's no licence header – bail out.
return HeaderComment.Result(0, 0, null, separator)
}

// Grab the licence header comment, and split it into lines.
val result: MutableList<String> = source.substring(start, end).split(separator).toMutableList()

// Remove the first and last lines, as those are simply comment start/end characters, and not the licence text.
result.removeFirst()
result.removeLast()

// Remove any indents from the licence header text, and return the result.
return HeaderComment.Result(start, end, result.map { it.trimIndent() }, separator)
}

override fun writeHeaderComment(header: List<String>, separator: String): String =
buildString { // Use a string builder to generate the licence header.
append("$COMMENT_START$separator")

header.forEach {
append("\t$it$separator")
}

append(COMMENT_END)
}

public companion object {
/** Instance of this header comment type. **/
@JvmField // Otherwise this would be `XmlStyleHeaderComment.Companion.getINSTANCE`
public val INSTANCE: XmlStyleHeaderComment = XmlStyleHeaderComment()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Copyright 2023 Yumi Project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

package dev.yumi.gradle.licenser.test.comment

import dev.yumi.gradle.licenser.api.comment.XmlStyleHeaderComment
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Test

class XmlStyleHeaderCommentTest {
@Test
fun `Parsing with existing header`() {
val result = XmlStyleHeaderComment.INSTANCE.readHeaderComment(
"""
<!--
Sample License Header
Yippee
-->
<!doctype html>
<html>
<head>
</head>
<body>
</body>
</html
""".trimIndent()
)

assertEquals(0, result.start)
assertEquals(41, result.end)
assertEquals("\n", result.separator)

assertNotNull(result.existing)

assertEquals(3, result.existing?.size)
assertEquals("Sample License Header", result.existing?.first())
assertEquals("Yippee", result.existing?.last())

assert(result.existing != null)
}

@Test
fun `Parsing with missing header`() {
val result = XmlStyleHeaderComment.INSTANCE.readHeaderComment(
"""
<!doctype html>
<html>
<head>
</head>
<body>
</body>
</html
""".trimIndent()
)

assertEquals(0, result.start)
assertEquals(0, result.end)
assertEquals("\n", result.separator)

assertNull(result.existing) { "Expected no result." }
}

@Test
fun `Writing a header`() {
val expected = """
<!--
Sample License Header
Yippee
-->
""".trimIndent()

val result = XmlStyleHeaderComment.INSTANCE.writeHeaderComment(
listOf(
"Sample License Header",
"",
"Yippee",
),

"\n"
)

assertEquals(expected, result)
}
}

0 comments on commit 8cd6f27

Please sign in to comment.