Skip to content

Commit 8677b1b

Browse files
committed
Add support for yaml inline comments
- consider YAML inline comments, e.g. key1:value1 #comment1 - add respective TCs
1 parent 8b11ab6 commit 8677b1b

File tree

2 files changed

+156
-1
lines changed

2 files changed

+156
-1
lines changed

src/sphinx_codelinks/analyse/utils.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,33 @@ def find_yaml_next_structure(node: TreeSitterNode) -> TreeSitterNode | None:
181181
return None
182182

183183

184+
def find_yaml_prev_sibling_on_same_row(node: TreeSitterNode) -> TreeSitterNode | None:
185+
"""Find a previous named sibling that is on the same row as the comment."""
186+
comment_row = node.start_point.row
187+
current = node.prev_named_sibling
188+
189+
while current:
190+
# Check if this sibling ends on the same row as the comment starts
191+
# This indicates it's an inline comment
192+
if current.end_point.row == comment_row:
193+
return current
194+
# If we find a sibling that ends before the comment row, we can stop
195+
# as we won't find any siblings on the same row going backwards
196+
if current.end_point.row < comment_row:
197+
break
198+
current = current.prev_named_sibling
199+
200+
return None
201+
202+
184203
def find_yaml_associated_structure(node: TreeSitterNode) -> TreeSitterNode | None:
185204
"""Find the YAML structure (key-value pair, list item, etc.) associated with a comment."""
186-
# First, try to find the next named sibling (structure after the comment)
205+
# First, check if this is an inline comment by looking for a previous sibling on the same row
206+
prev_sibling_same_row = find_yaml_prev_sibling_on_same_row(node)
207+
if prev_sibling_same_row:
208+
return prev_sibling_same_row
209+
210+
# If no previous sibling on same row, try to find the next named sibling (structure after the comment)
187211
structure = find_yaml_next_structure(node)
188212
if structure:
189213
return structure

tests/test_analyse_utils.py

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,3 +1242,134 @@ def test_yaml_document_structure(init_yaml_tree_sitter):
12421242
assert second_structure, "No structure found for second comment"
12431243
second_text = second_structure.text.decode("utf-8")
12441244
assert "config.yml:" in second_text
1245+
1246+
1247+
def test_yaml_inline_comments_current_behavior(init_yaml_tree_sitter):
1248+
"""Test improved behavior of inline comments in YAML after the fix."""
1249+
code = b"""key1: value1 # inline comment about key1
1250+
key2: value2
1251+
key3: value3 # inline comment about key3
1252+
"""
1253+
1254+
parser, query = init_yaml_tree_sitter
1255+
comments = utils.extract_comments(code, parser, query)
1256+
comments.sort(key=lambda x: x.start_point.row)
1257+
1258+
assert len(comments) == 2, f"Expected 2 comments, found {len(comments)}"
1259+
1260+
# Fixed behavior: inline comment about key1 now correctly associates with key1
1261+
first_structure = utils.find_yaml_associated_structure(comments[0])
1262+
assert first_structure, "No structure found for first comment"
1263+
first_text = first_structure.text.decode("utf-8")
1264+
assert "key1:" in first_text, f"Expected 'key1:' in '{first_text}'"
1265+
1266+
# Fixed behavior: inline comment about key3 now correctly associates with key3
1267+
second_structure = utils.find_yaml_associated_structure(comments[1])
1268+
assert second_structure, "No structure found for second comment"
1269+
second_text = second_structure.text.decode("utf-8")
1270+
assert "key3:" in second_text, f"Expected 'key3:' in '{second_text}'"
1271+
1272+
1273+
@pytest.mark.parametrize(
1274+
("code", "expected_associations"),
1275+
[
1276+
# Basic inline comment case
1277+
(
1278+
b"""key1: value1 # comment about key1
1279+
key2: value2
1280+
""",
1281+
["key1:"], # Now correctly associates with key1
1282+
),
1283+
# Multiple inline comments
1284+
(
1285+
b"""database:
1286+
host: localhost # production server
1287+
port: 5432 # default postgres port
1288+
user: admin
1289+
""",
1290+
[
1291+
"host: localhost",
1292+
"port: 5432",
1293+
], # Now correctly associates with the right structures
1294+
),
1295+
],
1296+
)
1297+
def test_yaml_inline_comments_fixed_behavior(
1298+
code, expected_associations, init_yaml_tree_sitter
1299+
):
1300+
"""Test that inline comments now correctly associate with the structure they comment on."""
1301+
parser, query = init_yaml_tree_sitter
1302+
comments = utils.extract_comments(code, parser, query)
1303+
comments.sort(key=lambda x: x.start_point.row)
1304+
1305+
assert len(comments) == len(expected_associations), (
1306+
f"Expected {len(expected_associations)} comments, found {len(comments)}"
1307+
)
1308+
1309+
for i, comment in enumerate(comments):
1310+
structure = utils.find_yaml_associated_structure(comment)
1311+
assert structure, f"No structure found for comment {i}"
1312+
structure_text = structure.text.decode("utf-8")
1313+
assert expected_associations[i] in structure_text, (
1314+
f"Expected '{expected_associations[i]}' in structure text: '{structure_text}'"
1315+
)
1316+
1317+
1318+
@pytest.mark.parametrize(
1319+
("code", "expected_associations"),
1320+
[
1321+
# Inline comments with list items
1322+
(
1323+
b"""items:
1324+
- name: item1 # first item
1325+
- name: item2 # second item
1326+
""",
1327+
[
1328+
"name: item1",
1329+
"name: item2",
1330+
], # The inline comment finds the key-value pair within the list item
1331+
),
1332+
# Mixed inline and block comments
1333+
(
1334+
b"""# Block comment for database
1335+
database:
1336+
host: localhost # inline comment for host
1337+
port: 5432
1338+
# Block comment for user
1339+
user: admin
1340+
""",
1341+
["database:", "host: localhost", "user: admin"],
1342+
),
1343+
# Inline comments in nested structures
1344+
(
1345+
b"""services:
1346+
web:
1347+
image: nginx # web server image
1348+
ports:
1349+
- "80:80" # http port
1350+
""",
1351+
["image: nginx", '- "80:80"'],
1352+
),
1353+
],
1354+
)
1355+
def test_yaml_inline_comments_comprehensive(
1356+
code, expected_associations, init_yaml_tree_sitter
1357+
):
1358+
"""Comprehensive test for inline comment behavior in various YAML structures."""
1359+
parser, query = init_yaml_tree_sitter
1360+
comments = utils.extract_comments(code, parser, query)
1361+
comments.sort(key=lambda x: x.start_point.row)
1362+
1363+
assert len(comments) == len(expected_associations), (
1364+
f"Expected {len(expected_associations)} comments, found {len(comments)}"
1365+
)
1366+
1367+
for i, comment in enumerate(comments):
1368+
structure = utils.find_yaml_associated_structure(comment)
1369+
assert structure, (
1370+
f"No structure found for comment {i}: '{comment.text.decode('utf-8')}'"
1371+
)
1372+
structure_text = structure.text.decode("utf-8")
1373+
assert expected_associations[i] in structure_text, (
1374+
f"Comment {i} '{comment.text.decode('utf-8')}' -> Expected '{expected_associations[i]}' in '{structure_text}'"
1375+
)

0 commit comments

Comments
 (0)