Skip to content

Commit

Permalink
Support escaping commas in extra flags (#443)
Browse files Browse the repository at this point in the history
* Support escaping commas in extra flags
  • Loading branch information
petertrr committed Aug 30, 2022
1 parent c3fce0e commit 6c7c3d8
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ class ExtraFlagsExtractor(private val generalConfig: GeneralConfig,
* @return [ExtraFlags] or null if no match occurred
*/
internal fun extractExtraFlagsFrom(line: String) = line
.split(",", ", ")
.splitByNonEscaped(',')
.map { it.replace("\\,", ",") }
.associate { part ->
val pair = part.split("=", limit = 2).map {
it.replace("\\=", "=")
Expand Down Expand Up @@ -69,6 +70,29 @@ internal fun List<String>.filterAndJoinBy(regex: Regex, ending: Char): List<Stri
}
}

/**
* Split [this] string by [delimiter] unless it's prepended by `\`.
*
* @param delimiter
* @return list of string parts
*/
@Suppress("IDENTIFIER_LENGTH")
internal fun String.splitByNonEscaped(delimiter: Char): List<String> {
val indicesToSplit = mapIndexed { index, c -> index to c }
.filter { (index, c) ->
c == delimiter && (index == 0 || get(index - 1) != '\\')
}
.map { (index, _) -> index }
val result: MutableList<String> = mutableListOf()
var currentOffset = 0
indicesToSplit.forEach {
result.add(substring(currentOffset, it))
currentOffset = it + 1
}
result.add(substring(currentOffset, length))
return result
}

/**
* Substitute placeholders in `this.execFlags` with values from provided arguments
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@ import com.saveourtool.save.core.plugin.ExtraFlagsExtractor
import com.saveourtool.save.core.plugin.GeneralConfig
import com.saveourtool.save.core.plugin.filterAndJoinBy
import com.saveourtool.save.core.plugin.resolvePlaceholdersFrom
import com.saveourtool.save.core.plugin.splitByNonEscaped

import okio.fakefilesystem.FakeFileSystem

import kotlin.test.Test
import kotlin.test.assertEquals

@Suppress(
"TOO_LONG_FUNCTION",
"WRONG_INDENTATION", // issue in diktat
)
class ExtraFlagsExtractorTest {
@Test
fun `basic test`() {
Expand All @@ -26,6 +31,9 @@ class ExtraFlagsExtractorTest {
"Unparseable nonsense" to ExtraFlags.empty,
"args1=--flag --opt,args2=-debug --flag2" to ExtraFlags("--flag --opt", "-debug --flag2"),
"args1=--flag\\=value,args2=--foo=bar" to ExtraFlags("--flag=value", "--foo=bar"),
"args1=option1\\,option2,args2=option3\\,option4" to ExtraFlags("option1,option2", "option3,option4"),
"args1=option1\\,option2" to ExtraFlags("option1,option2", ""),
"args2=option3\\,option4" to ExtraFlags("", "option3,option4"),
)
.forEach { (line, extraFlags) ->
assertEquals(extraFlags, extraFlagsExtractor.extractExtraFlagsFrom(line))
Expand Down Expand Up @@ -105,6 +113,52 @@ class ExtraFlagsExtractorTest {
"another-cmd --flag"
)
)

checkMultilineDirectives(
Regex("""// RUN: (.*([^\\]=)?.*)\\?"""),
listOf(
"// RUN: command --flag=option\\,\\",
"// RUN: another-option --another-flag",
"// RUN: another-cmd\\=\\",
"// RUN: --flag=option\\,another-option",
),
listOf(
"command --flag=option\\,another-option --another-flag",
"another-cmd\\=--flag=option\\,another-option"
)
)
}

@Test
fun `test for splitByNonEscaped`() {
assertEquals(
listOf("this string\\, not split"),
"this string\\, not split".splitByNonEscaped(','),
)
assertEquals(
listOf("this string", " but split"),
"this string, but split".splitByNonEscaped(','),
)
assertEquals(
listOf("this string\\, not split", " but here - it's split"),
"this string\\, not split, but here - it's split".splitByNonEscaped(','),
)
assertEquals(
listOf("", ""),
",".splitByNonEscaped(','),
)
assertEquals(
listOf("", "text"),
",text".splitByNonEscaped(','),
)
assertEquals(
listOf("\\,"),
"\\,".splitByNonEscaped(','),
)
assertEquals(
listOf("\\,text"),
"\\,text".splitByNonEscaped(','),
)
}

private fun checkMultilineDirectives(
Expand Down

0 comments on commit 6c7c3d8

Please sign in to comment.