Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add plugins block below imports, if any. #32

Merged
merged 1 commit into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import cash.grammar.kotlindsl.utils.Whitespace
import cash.grammar.kotlindsl.utils.Whitespace.trimGently
import cash.grammar.utils.ifNotEmpty
import cash.recipes.plugins.exception.NonNormalizedScriptException
import com.squareup.cash.grammar.KotlinParser.ImportListContext
import com.squareup.cash.grammar.KotlinParser.NamedBlockContext
import com.squareup.cash.grammar.KotlinParser.PostfixUnaryExpressionContext
import com.squareup.cash.grammar.KotlinParser.ScriptContext
Expand Down Expand Up @@ -46,11 +47,14 @@ public class PluginMutator private constructor(
private val pluginsToRemove: Set<String>,
) : KotlinParserBaseListener() {

// TODO(tsr): use System.lineSeparator() universally
private val newline = System.lineSeparator()
private val rewriter = Rewriter(tokens)
private val smartIndent = SmartIndent(tokens)
private val terminalNewlines = Whitespace.countTerminalNewlines(tokens)

private val blockStack = ArrayDeque<NamedBlockContext>()
private var importsList: ImportListContext? = null
private var pluginsBlock: NamedBlockContext? = null

private val pluginIds = mutableSetOf<String>()
Expand All @@ -63,7 +67,14 @@ public class PluginMutator private constructor(
throw KotlinParseException.withErrors(it)
}

return rewriter.text.trimGently(terminalNewlines)
return rewriter.text
// Simplifies conditional logic elsewhere. We never want two blank lines in a row.
.replace("$newline$newline$newline", "$newline$newline")
.trimGently(terminalNewlines)
}

override fun enterImportList(ctx: ImportListContext) {
importsList = ctx
}

override fun enterNamedBlock(ctx: NamedBlockContext) {
Expand Down Expand Up @@ -143,21 +154,30 @@ public class PluginMutator private constructor(

rewriter.insertBefore(
tokenToInsertBefore,
contentToAdd.joinToString(separator = "\n") + "\n"
contentToAdd.joinToString(separator = newline) + newline
)
}

private fun addNewPluginBlock(script: ScriptContext) {
if (pluginsToAdd.isEmpty()) return

val hasImports = importsList != null

val pluginsContentToAdd: List<String> = pluginContentToAdd(emptyList())
val pluginBlockContent = buildString {
if (hasImports) {
appendLine()
}

appendLine("plugins {")
pluginsContentToAdd.forEach { appendLine(it) }
append("}")
appendLine("}")
appendLine()
}

rewriter.insertBefore(script.start, "$pluginBlockContent\n\n")
val insertLocation = importsList?.stop ?: script.start

rewriter.insertBefore(insertLocation, pluginBlockContent)
}

private fun removeBlockIdPlugins(ctx: List<ParserRuleContext>) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,41 @@ internal class PluginMutatorTest {
assertThat(rewrittenContent).isEqualTo(expectedContent)
}

@Test
fun `can add plugins when no existing plugin block is present, below imports`() {
val pluginToAdd = setOf("foo", "bar")
val pluginsToRemove = emptySet<String>()

val buildScript =
"""
import magic

extension {
foo = bar
}
""".trimIndent()

// When...
val pluginMutator = PluginMutator.of(buildScript, pluginToAdd, pluginsToRemove)
val rewrittenContent = pluginMutator.rewritten()
val expectedContent =
"""
import magic

plugins {
id("foo")
id("bar")
}

extension {
foo = bar
}
""".trimIndent()

// Then...
assertThat(rewrittenContent).isEqualTo(expectedContent)
}

@Test
fun `skip adding plugins that are already present`() {
val pluginToAdd = setOf("cash.server")
Expand Down Expand Up @@ -184,7 +219,7 @@ internal class PluginMutatorTest {

@Test
fun `throw error when same plugins are in add and remove sets`() {
val pluginToAdd = setOf("bar")
val pluginToAdd = setOf("bar")
val pluginToRemove = setOf("foo", "bar")

val buildScript =
Expand All @@ -202,7 +237,7 @@ internal class PluginMutatorTest {

@Test
fun `throws error for non-normalized script, with non-BlockId plugins`() {
val pluginToAdd = setOf("foo")
val pluginToAdd = setOf("foo")
val pluginToRemove = setOf("bar")

val buildScript =
Expand All @@ -220,7 +255,7 @@ internal class PluginMutatorTest {

@Test
fun `throws error for non-normalized script, with apply plugins`() {
val pluginToAdd = setOf("foo")
val pluginToAdd = setOf("foo")
val pluginToRemove = setOf("bar")

val buildScript =
Expand Down
Loading