Skip to content

Commit

Permalink
fix: add plugins block below imports, if any.
Browse files Browse the repository at this point in the history
  • Loading branch information
autonomousapps committed Dec 16, 2024
1 parent 404bba4 commit ba26b45
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 7 deletions.
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

0 comments on commit ba26b45

Please sign in to comment.