Make line matching stricter
This commit is contained in:
parent
ae04034028
commit
10a460d2c3
1 changed files with 33 additions and 20 deletions
53
mutannot.fsx
53
mutannot.fsx
|
|
@ -178,27 +178,40 @@ let findMutation id mutations =
|
||||||
|> Array.tryFind (fun mutation -> mutation.Id = id)
|
|> Array.tryFind (fun mutation -> mutation.Id = id)
|
||||||
|> Option.defaultWith (fun () -> fail $"Unknown mutation id: {id}")
|
|> Option.defaultWith (fun () -> fail $"Unknown mutation id: {id}")
|
||||||
|
|
||||||
let lineNumberAt (text: string) index =
|
let lineSpan (filePath: string) (text: string) (lineNumber: int) =
|
||||||
let mutable line = 1
|
if lineNumber < 1 then
|
||||||
for i in 0 .. index - 1 do
|
fail $"Line number must be positive: {lineNumber}"
|
||||||
if text[i] = '\n' then
|
|
||||||
line <- line + 1
|
|
||||||
line
|
|
||||||
|
|
||||||
let replaceNearestOccurrence (mutation: MutationCase) (text: string) =
|
let mutable currentLine = 1
|
||||||
let rec collect fromIndex acc =
|
let mutable lineStart = 0
|
||||||
let idx = text.IndexOf(mutation.Find, fromIndex, StringComparison.Ordinal)
|
let mutable index = 0
|
||||||
if idx < 0 then List.rev acc
|
|
||||||
else collect (idx + 1) (idx :: acc)
|
|
||||||
|
|
||||||
let matches = collect 0 []
|
while index < text.Length && currentLine < lineNumber do
|
||||||
match matches with
|
if text[index] = '\n' then
|
||||||
| [] -> fail $"Could not find '{mutation.Find}' in {mutation.File}"
|
currentLine <- currentLine + 1
|
||||||
| _ ->
|
lineStart <- index + 1
|
||||||
let chosen =
|
|
||||||
matches
|
index <- index + 1
|
||||||
|> List.minBy (fun idx -> abs (lineNumberAt text idx - mutation.Line))
|
|
||||||
text.Remove(chosen, mutation.Find.Length).Insert(chosen, mutation.Replace)
|
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 =
|
let printMutation mutation =
|
||||||
printfn "id: %s" mutation.Id
|
printfn "id: %s" mutation.Id
|
||||||
|
|
@ -243,7 +256,7 @@ let runMutation (mutation: MutationCase) =
|
||||||
fail $"Target file does not exist in worktree: {targetFile}"
|
fail $"Target file does not exist in worktree: {targetFile}"
|
||||||
|
|
||||||
let originalText = File.ReadAllText targetFile
|
let originalText = File.ReadAllText targetFile
|
||||||
let mutatedText = replaceNearestOccurrence mutation originalText
|
let mutatedText = replaceOccurrenceOnLine mutation originalText
|
||||||
File.WriteAllText(targetFile, mutatedText)
|
File.WriteAllText(targetFile, mutatedText)
|
||||||
|
|
||||||
printfn "==> %s: %s" mutation.Id mutation.TestName
|
printfn "==> %s: %s" mutation.Id mutation.TestName
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue