Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions scripts/vale/changed_lines_to_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,14 @@ def get_changed_lines(file_path, base_sha, head_sha):
changed_lines = []
for line in diff_output.splitlines():
if line.startswith("@@"):
# Extract line number from git diff header
match = re.search(r"^@@ -[0-9]+(?:,[0-9]+)? \+([0-9]+)(?:,[0-9]+)? @@", line)
# Extract the full added range from a unified=0 hunk header.
# Format: @@ -A,B +C[,D] @@ — D is omitted when exactly 1 line
# was added; D is 0 for pure deletions.
match = re.search(r"^@@ -[0-9]+(?:,[0-9]+)? \+([0-9]+)(?:,([0-9]+))? @@", line)
if match:
line_number = int(match.group(1))
changed_lines.append(line_number)
start = int(match.group(1))
count = int(match.group(2)) if match.group(2) is not None else 1
changed_lines.extend(range(start, start + count))

return changed_lines
except subprocess.CalledProcessError as e:
Expand Down
55 changes: 55 additions & 0 deletions scripts/vale/test/test_changed_lines_to_json.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env python3
"""
Unit tests for changed_lines_to_json.get_changed_lines().

Run from the repo root:
python3 scripts/vale/test/test_changed_lines_to_json.py
"""
import os
import sys
import unittest
from unittest.mock import patch

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

import changed_lines_to_json
from changed_lines_to_json import get_changed_lines


class GetChangedLinesTest(unittest.TestCase):
def _run(self, diff_output):
with patch.object(changed_lines_to_json.subprocess, "check_output", return_value=diff_output):
return get_changed_lines("dummy.md", "BASE", "HEAD")

def test_single_line_addition_no_count(self):
# `+26` (count omitted) means exactly one added line
self.assertEqual(self._run("@@ -25,0 +26 @@"), [26])

def test_multi_line_addition(self):
# `+43,26` means 26 lines starting at 43 — this is the case PR #6183 hit
self.assertEqual(self._run("@@ -41,0 +43,26 @@"), list(range(43, 69)))

def test_pure_deletion_yields_no_lines(self):
# `+9,0` is a pure deletion — no lines exist in the new file to lint
self.assertEqual(self._run("@@ -10,5 +9,0 @@"), [])

def test_modified_hunk(self):
self.assertEqual(self._run("@@ -10,3 +10,5 @@"), [10, 11, 12, 13, 14])

def test_multiple_hunks_concatenated(self):
diff = "\n".join([
"@@ -25,0 +26 @@",
"@@ -41,0 +43,3 @@",
])
self.assertEqual(self._run(diff), [26, 43, 44, 45])

def test_hunk_header_with_trailing_context(self):
# Real git output often appends a context line after the second @@
self.assertEqual(
self._run("@@ -41,0 +43,2 @@ Some context line"),
[43, 44],
)


if __name__ == "__main__":
unittest.main()
Loading