Make line matching stricter

This commit is contained in:
Sven van Heugten 2026-04-27 23:44:43 +02:00
parent ae04034028
commit 10a460d2c3
No known key found for this signature in database
GPG key ID: D612F88666F4F660

View file

@ -178,27 +178,40 @@ let findMutation id mutations =
|> Array.tryFind (fun mutation -> mutation.Id = id)
|> Option.defaultWith (fun () -> fail $"Unknown mutation id: {id}")
let lineNumberAt (text: string) index =
let mutable line = 1
for i in 0 .. index - 1 do
if text[i] = '\n' then
line <- line + 1
line
let lineSpan (filePath: string) (text: string) (lineNumber: int) =
if lineNumber < 1 then
fail $"Line number must be positive: {lineNumber}"
let replaceNearestOccurrence (mutation: MutationCase) (text: string) =
let rec collect fromIndex acc =
let idx = text.IndexOf(mutation.Find, fromIndex, StringComparison.Ordinal)
if idx < 0 then List.rev acc
else collect (idx + 1) (idx :: acc)
let mutable currentLine = 1
let mutable lineStart = 0
let mutable index = 0
let matches = collect 0 []
match matches with
| [] -> fail $"Could not find '{mutation.Find}' in {mutation.File}"
| _ ->
let chosen =
matches
|> List.minBy (fun idx -> abs (lineNumberAt text idx - mutation.Line))
text.Remove(chosen, mutation.Find.Length).Insert(chosen, mutation.Replace)
while index < text.Length && currentLine < lineNumber do
if text[index] = '\n' then
currentLine <- currentLine + 1
lineStart <- index + 1
index <- index + 1
if currentLine <> lineNumber then
fail $"Line {lineNumber} does not exist in {filePath}"
let mutable lineEnd = lineStart
while lineEnd < text.Length && text[lineEnd] <> '\n' && text[lineEnd] <> '\r' do
lineEnd <- lineEnd + 1
lineStart, lineEnd
let replaceOccurrenceOnLine (mutation: MutationCase) (text: string) =
let lineStart, lineEnd = lineSpan mutation.File text mutation.Line
let lineText = text.Substring(lineStart, lineEnd - lineStart)
let lineOffset = lineText.IndexOf(mutation.Find, StringComparison.Ordinal)
if lineOffset < 0 then
fail $"Line {mutation.Line} in {mutation.File} does not contain '{mutation.Find}'."
let absoluteOffset = lineStart + lineOffset
text.Remove(absoluteOffset, mutation.Find.Length).Insert(absoluteOffset, mutation.Replace)
let printMutation mutation =
printfn "id: %s" mutation.Id
@ -243,7 +256,7 @@ let runMutation (mutation: MutationCase) =
fail $"Target file does not exist in worktree: {targetFile}"
let originalText = File.ReadAllText targetFile
let mutatedText = replaceNearestOccurrence mutation originalText
let mutatedText = replaceOccurrenceOnLine mutation originalText
File.WriteAllText(targetFile, mutatedText)
printfn "==> %s: %s" mutation.Id mutation.TestName