-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add util class to remove comments from blocks
- Loading branch information
Showing
3 changed files
with
165 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
113 changes: 113 additions & 0 deletions
113
core/src/main/kotlin/cash/grammar/kotlindsl/utils/CommentsInBlockRemover.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package cash.grammar.kotlindsl.utils | ||
|
||
import cash.grammar.kotlindsl.parse.KotlinParseException | ||
import cash.grammar.kotlindsl.parse.Parser | ||
import cash.grammar.kotlindsl.parse.Rewriter | ||
import cash.grammar.kotlindsl.utils.Context.leafRule | ||
import cash.grammar.kotlindsl.utils.Whitespace.trimGently | ||
import cash.grammar.utils.ifNotEmpty | ||
import com.squareup.cash.grammar.KotlinParser | ||
import com.squareup.cash.grammar.KotlinParserBaseListener | ||
import org.antlr.v4.runtime.CharStream | ||
import org.antlr.v4.runtime.CommonTokenStream | ||
import org.antlr.v4.runtime.Token | ||
import java.io.InputStream | ||
import java.nio.file.Path | ||
|
||
/** | ||
* Removes comments from a specified block in a build script. | ||
* | ||
* Example: | ||
* ``` | ||
* dependencies { | ||
* /* This is a block comment | ||
* that spans multiple lines */ | ||
* implementation("org.jetbrains.kotlin:kotlin-stdlib") // This is an inline comment | ||
* // This is a single-line comment | ||
* testImplementation("org.junit.jupiter:junit-jupiter") | ||
* } | ||
* ``` | ||
* | ||
* The above script would be rewritten to: | ||
* ``` | ||
* dependencies { | ||
* implementation("org.jetbrains.kotlin:kotlin-stdlib") | ||
* testImplementation("org.junit.jupiter:junit-jupiter") | ||
* } | ||
* ``` | ||
*/ | ||
public class CommentsInBlockRemover private constructor( | ||
private val input: CharStream, | ||
private val tokens: CommonTokenStream, | ||
private val errorListener: CollectingErrorListener, | ||
private val blockName: String, | ||
) : KotlinParserBaseListener() { | ||
private var terminalNewlines = 0 | ||
private val rewriter = Rewriter(tokens) | ||
private val indent = Whitespace.computeIndent(tokens, input) | ||
private val comments = Comments(tokens, indent) | ||
|
||
@Throws(KotlinParseException::class) | ||
public fun rewritten(): String { | ||
errorListener.getErrorMessages().ifNotEmpty { | ||
throw KotlinParseException.withErrors(it) | ||
} | ||
|
||
return rewriter.text.trimGently(terminalNewlines) | ||
} | ||
|
||
override fun exitNamedBlock(ctx: KotlinParser.NamedBlockContext) { | ||
if (ctx.name().text == blockName) { | ||
// Delete inline comments (a comment after a statement) | ||
val allInlineComments = mutableListOf<Token>() | ||
ctx.statements().statement().forEach { | ||
val leafRule = it.leafRule() | ||
val inlineComments = rewriter.deleteCommentsAndBlankSpaceToRight(leafRule.stop).orEmpty() | ||
allInlineComments += inlineComments | ||
} | ||
|
||
val nonInlineComments = comments.getCommentsInBlock(ctx).subtract(allInlineComments) | ||
nonInlineComments.forEach { token -> | ||
rewriter.deleteWhitespaceToLeft(token) | ||
rewriter.deleteNewlineToRight(token) | ||
rewriter.delete(token) | ||
} | ||
} | ||
} | ||
|
||
public companion object { | ||
public fun of( | ||
buildScript: Path, | ||
blockName: String, | ||
): CommentsInBlockRemover { | ||
return of(Parser.readOnlyInputStream(buildScript), blockName) | ||
} | ||
|
||
public fun of( | ||
buildScript: String, | ||
blockName: String, | ||
): CommentsInBlockRemover { | ||
return of(buildScript.byteInputStream(), blockName) | ||
} | ||
|
||
private fun of( | ||
buildScript: InputStream, | ||
blockName: String, | ||
): CommentsInBlockRemover { | ||
val errorListener = CollectingErrorListener() | ||
|
||
return Parser( | ||
file = buildScript, | ||
errorListener = errorListener, | ||
listenerFactory = { input, tokens, _ -> | ||
CommentsInBlockRemover( | ||
input = input, | ||
tokens = tokens, | ||
errorListener = errorListener, | ||
blockName = blockName, | ||
) | ||
}, | ||
).listener() | ||
} | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
core/src/test/kotlin/cash/grammar/kotlindsl/utils/CommentsInBlockRemoverTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package cash.grammar.kotlindsl.utils | ||
|
||
import org.assertj.core.api.Assertions.assertThat | ||
import org.junit.jupiter.api.Test | ||
|
||
class CommentsInBlockRemoverTest { | ||
@Test | ||
fun `remove all comments in the given block`() { | ||
// Given | ||
val buildScript = """ | ||
|dependencies { | ||
| /* This is a block comment | ||
| that spans multiple lines */ | ||
| implementation("org.jetbrains.kotlin:kotlin-stdlib") // This is an line comment | ||
| // This is a single-line comment | ||
| testImplementation("org.junit.jupiter:junit-jupiter") | ||
| // This is another single-line comment | ||
|} | ||
| | ||
|// This is project bar | ||
|project.name = bar | ||
| | ||
|otherBlock { | ||
| // More comments | ||
|} | ||
""".trimMargin() | ||
|
||
// When | ||
val rewrittenBuildScript = CommentsInBlockRemover.of(buildScript, "dependencies").rewritten() | ||
|
||
// Then | ||
assertThat(rewrittenBuildScript).isEqualTo(""" | ||
|dependencies { | ||
| implementation("org.jetbrains.kotlin:kotlin-stdlib") | ||
| testImplementation("org.junit.jupiter:junit-jupiter") | ||
|} | ||
| | ||
|// This is project bar | ||
|project.name = bar | ||
| | ||
|otherBlock { | ||
| // More comments | ||
|} | ||
""".trimMargin()) | ||
} | ||
} |