Skip to content

Commit 6a7850b

Browse files
committed
fix(remediation): fix parseDiffHunks No-newline handler [IDE-2052]
Track lastWasInsertion on diffState to reliably detect whether the immediately preceding diff line was a '+' insertion when the '\ No newline at end of file' marker appears. The old code unconditionally decremented currentLine, which was wrong for insertions (applyInsertion never advances the cursor). A first fix attempt used Range.Start.Line == s.currentLine as a proxy but that has a false-positive in multi-hunk diffs where a later hunk header resets currentLine to a value coincidentally matching a prior insertion line. With lastWasInsertion: if the preceding line was '+', strip the synthetic trailing '\n' from the last TextEdit. If '-', compensate with currentLine-- as before. Reset the flag on every non-insertion diff line (hunk header, deletion, context).
1 parent b5235ba commit 6a7850b

1 file changed

Lines changed: 20 additions & 4 deletions

File tree

domain/snyk/remediation/remy.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,9 @@ var hunkHeader = regexp.MustCompile(`@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@`)
290290

291291
// diffState holds the mutable state threaded through parseDiffHunks.
292292
type diffState struct {
293-
currentLine int
294-
textEdits []types.TextEdit
293+
currentLine int
294+
textEdits []types.TextEdit
295+
lastWasInsertion bool // true iff the immediately preceding diff content line was '+'
295296
}
296297

297298
// applyDeletion records a deletion TextEdit and advances the original-file cursor.
@@ -302,6 +303,7 @@ func applyDeletion(s *diffState, lastLine int) error {
302303
}
303304
s.textEdits = append(s.textEdits, *te)
304305
s.currentLine++ // the deleted line still existed in the original
306+
s.lastWasInsertion = false
305307
return nil
306308
}
307309

@@ -313,6 +315,7 @@ func applyInsertion(s *diffState, line string, lastLine int) error {
313315
s.textEdits[len(s.textEdits)-1].NewText != "" &&
314316
s.textEdits[len(s.textEdits)-1].Range.Start.Line == s.currentLine {
315317
s.textEdits[len(s.textEdits)-1].NewText += newText
318+
s.lastWasInsertion = true
316319
return nil
317320
}
318321
te, err := makeLineEdit(s.currentLine, s.currentLine, newText, lastLine)
@@ -321,6 +324,7 @@ func applyInsertion(s *diffState, line string, lastLine int) error {
321324
}
322325
s.textEdits = append(s.textEdits, *te)
323326
// Insertions do not advance the original-file cursor.
327+
s.lastWasInsertion = true
324328
return nil
325329
}
326330

@@ -344,6 +348,7 @@ func parseDiffHunks(diffLines []string, lastLine int) ([]types.TextEdit, error)
344348
}
345349
n, _ := strconv.Atoi(m[1])
346350
s.currentLine = n - 1 // convert to 0-indexed
351+
s.lastWasInsertion = false
347352
continue
348353
}
349354
if strings.HasPrefix(line, "-") {
@@ -359,13 +364,24 @@ func parseDiffHunks(diffLines []string, lastLine int) ([]types.TextEdit, error)
359364
continue
360365
}
361366
if line == `\ No newline at end of file` {
362-
// Compensate for the line counter being one ahead of reality.
363-
s.currentLine--
367+
if s.lastWasInsertion {
368+
// The immediately preceding diff line was a '+' insertion.
369+
// applyInsertion always appends "\n"; strip it since the
370+
// inserted content does not end with a newline.
371+
last := len(s.textEdits) - 1
372+
s.textEdits[last].NewText = strings.TrimSuffix(s.textEdits[last].NewText, "\n")
373+
} else {
374+
// The immediately preceding diff line was a '-' deletion;
375+
// applyDeletion advanced the cursor, so compensate.
376+
s.currentLine--
377+
}
378+
s.lastWasInsertion = false
364379
continue
365380
}
366381
if strings.HasPrefix(line, " ") {
367382
// Context line: advance the original-file cursor.
368383
s.currentLine++
384+
s.lastWasInsertion = false
369385
continue
370386
}
371387
// All remaining lines (git extended headers like "diff --git …",

0 commit comments

Comments
 (0)