Skip to content

Commit 4f7ff74

Browse files
ENT-14274: Added linter-errors for MISSING-nodes
Ticket: ENT-14274 Changelog: None Signed-off-by: Simon Halvorsen <simon.halvorsen@northern.tech>
1 parent 53770c0 commit 4f7ff74

5 files changed

Lines changed: 80 additions & 10 deletions

File tree

src/cfengine_cli/lint.py

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -493,14 +493,26 @@ def navigate(self, node) -> None:
493493
return
494494

495495

496+
def _last_real_sibling_before(node: Node) -> Node | None:
497+
"""Walk backwards from node through its preceding siblings, skipping
498+
comments and macros, to find the last real (content) sibling."""
499+
sib = node.prev_sibling
500+
while sib is not None and sib.type in ("comment", "macro"):
501+
sib = sib.prev_sibling
502+
return sib
503+
504+
496505
def _check_syntax(policy_file: PolicyFile, state: State) -> int:
497-
"""Iterate over a syntax tree and print errors if it is empty or has syntax
498-
errors.
506+
"""Iterate over a syntax tree and print errors if it is empty, has syntax
507+
errors, or is missing expected tokens (e.g. a dropped ';').
499508
500509
Notably, printing syntax errors _does not happen during parsing_.
501510
502511
Tree sitter has already fully parsed the policy, we iterate over the result
503-
and see if it has inserted any "ERROR" nodes.
512+
and see if it has inserted any "ERROR" nodes, or any "MISSING" nodes
513+
(tree-sitter's error recovery can silently insert a synthetic token,
514+
e.g. a missing ';' right before a closing '}', without ever producing
515+
an ERROR node.
504516
505517
Stops at first error. Returns number of errors, always 0 or 1 in this case.
506518
"""
@@ -522,15 +534,26 @@ def _check_syntax(policy_file: PolicyFile, state: State) -> int:
522534
state.start_file(policy_file)
523535
for node in policy_file.nodes:
524536
state.navigate(node)
525-
if node.type != "ERROR":
526-
continue
527537
line = node.range.start_point[0] + 1
528538
column = node.range.start_point[1] + 1
529-
_highlight_range(node, lines)
530-
location = state.get_location_extended(line, column)
531-
print(f"Error: Syntax error {location}")
532-
state.end_file()
533-
return 1
539+
if node.type == "ERROR":
540+
_highlight_range(node, lines)
541+
location = state.get_location_extended(line, column)
542+
print(f"Error: Syntax error {location}")
543+
state.end_file()
544+
return 1
545+
if node.is_missing:
546+
# To avoid pointing at #comment/@macro -lines
547+
prev = _last_real_sibling_before(node)
548+
report_node = prev if prev is not None else node
549+
_highlight_range(report_node, lines)
550+
line = report_node.range.end_point[0] + 1
551+
column = report_node.range.end_point[1] + 1
552+
missing = node.type if not node.is_named else f"token: {node.type}"
553+
location = state.get_location_extended(line, column)
554+
print(f"Error: Missing '{missing}' {location}")
555+
state.end_file()
556+
return 1
534557
state.end_file()
535558
return 0
536559

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
"handlers" slist => { "my_bundle_name" };
3+
"args" slist => { "foo" ;
4+
^---^
5+
Error: Missing '}' at tests/lint/020_missing_braces.x.cf:11:28
6+
FAIL: tests/lint/020_missing_braces.x.cf (1 error)
7+
Failure, 1 error in total.

tests/lint/020_missing_braces.x.cf

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
bundle agent my_bundle_name(arg)
2+
{
3+
reports:
4+
"$(arg)";
5+
}
6+
7+
bundle agent main
8+
{
9+
vars:
10+
"handlers" slist => { "my_bundle_name" };
11+
"args" slist => { "foo" ;
12+
13+
methods:
14+
"" usebundle => $(handlers)(@(args));
15+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
methods:
3+
"" usebundle => $(handlers)(@(args))
4+
^-------------------------------^
5+
Error: Missing ';' at tests/lint/020_missing_semicolon.x.cf:14:41
6+
FAIL: tests/lint/020_missing_semicolon.x.cf (1 error)
7+
Failure, 1 error in total.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
bundle agent my_bundle_name(arg)
2+
{
3+
reports:
4+
"$(arg)";
5+
}
6+
7+
bundle agent main
8+
{
9+
vars:
10+
"handlers" slist => { "my_bundle_name" };
11+
"args" slist => { "foo" };
12+
13+
methods:
14+
""
15+
usebundle => $(handlers)(@(args))
16+
# Comments and such stuff point ^ not this line in error
17+
18+
}

0 commit comments

Comments
 (0)