diff --git a/src/cfengine_cli/lint.py b/src/cfengine_cli/lint.py index 47691d7..a23bc0f 100644 --- a/src/cfengine_cli/lint.py +++ b/src/cfengine_cli/lint.py @@ -492,6 +492,15 @@ def _lint_node(node: Node, policy_file: PolicyFile, state: State) -> int: f"Error: Bundle type must be one of ({', '.join(ALLOWED_BUNDLE_TYPES)}), not '{_text(node)}' {location}" ) return 1 + if state.strict and ( + node.type in ("bundle_block_name", "body_block_name") + and _text(node) in BUILTIN_FUNCTIONS + ): + _highlight_range(node, lines) + print( + f"Error: {"Bundle" if "bundle" in node.type else "Body"} '{_text(node)}' conflicts with built-in function with the same name {location}" + ) + return 1 if node.type == "calling_identifier": name = _text(node) qualified_name = _qualify(name, state.namespace) @@ -515,6 +524,26 @@ def _lint_node(node: Node, policy_file: PolicyFile, state: State) -> int: f"Error: Call to unknown function / bundle / body '{name}' {location}" ) return 1 + if ( + name not in BUILTIN_FUNCTIONS + and state.promise_type == "vars" + and state.attribute_name not in ("action", "classes") + ): + _highlight_range(node, lines) + print( + f"Error: Call to unknown function '{name}' inside 'vars'-promise {location}" + ) + return 1 + if ( + state.promise_type == "vars" + and state.attribute_name in ("action", "classes") + and qualified_name not in state.bodies + ): + _highlight_range(node, lines) + print( + f"Error: '{name}' is not a defined body. Only bodies may be called with '{state.attribute_name}' {location}" + ) + return 1 return 0 diff --git a/tests/lint/009_bundle_shadows_function.cf b/tests/lint/009_bundle_shadows_function.cf new file mode 100644 index 0000000..f06235a --- /dev/null +++ b/tests/lint/009_bundle_shadows_function.cf @@ -0,0 +1,5 @@ +bundle agent isvariab +{ + reports: + "isvariab is not a built-in function"; +} diff --git a/tests/lint/009_bundle_shadows_function.expected.txt b/tests/lint/009_bundle_shadows_function.expected.txt new file mode 100644 index 0000000..4ad2733 --- /dev/null +++ b/tests/lint/009_bundle_shadows_function.expected.txt @@ -0,0 +1,6 @@ + +bundle agent isvariable + ^--------^ +Error: Bundle 'isvariable' conflicts with built-in function with the same name at tests/lint/009_bundle_shadows_function.x.cf:1:14 +FAIL: tests/lint/009_bundle_shadows_function.x.cf (1 error) +Failure, 1 error in total. diff --git a/tests/lint/009_bundle_shadows_function.x.cf b/tests/lint/009_bundle_shadows_function.x.cf new file mode 100644 index 0000000..81d46a3 --- /dev/null +++ b/tests/lint/009_bundle_shadows_function.x.cf @@ -0,0 +1,5 @@ +bundle agent isvariable +{ + reports: + "isvariable is a built-in function"; +} diff --git a/tests/lint/010_unknown_function_inside_vars.cf b/tests/lint/010_unknown_function_inside_vars.cf new file mode 100644 index 0000000..afd0bcd --- /dev/null +++ b/tests/lint/010_unknown_function_inside_vars.cf @@ -0,0 +1,22 @@ +body classes bundle_class(a) +{ + scope => "bundle"; + promise_kept => { "$(a):bundle_context" }; +} + +bundle agent target(a) +{ + reports: + "Hello, $(a)"; +} + +bundle agent helper +{ + vars: + "x" string => isvariable("arg"); + "y" + classes => bundle_class("arg"), + string => ""; + methods: + "x" usebundle => target("arg"); +} diff --git a/tests/lint/010_unknown_function_inside_vars.expected.txt b/tests/lint/010_unknown_function_inside_vars.expected.txt new file mode 100644 index 0000000..ce55a44 --- /dev/null +++ b/tests/lint/010_unknown_function_inside_vars.expected.txt @@ -0,0 +1,12 @@ + + vars: + "x" string => target("arg"); + ^----^ +Error: Call to unknown function 'target' inside 'vars'-promise at tests/lint/010_unknown_function_inside_vars.x.cf:16:19 + + "y" + classes => isvariable("arg"), + ^--------^ +Error: 'isvariable' is not a defined body. Only bodies may be called with 'classes' at tests/lint/010_unknown_function_inside_vars.x.cf:18:18 +FAIL: tests/lint/010_unknown_function_inside_vars.x.cf (2 errors) +Failure, 2 errors in total. diff --git a/tests/lint/010_unknown_function_inside_vars.x.cf b/tests/lint/010_unknown_function_inside_vars.x.cf new file mode 100644 index 0000000..cfeadca --- /dev/null +++ b/tests/lint/010_unknown_function_inside_vars.x.cf @@ -0,0 +1,22 @@ +body classes bundle_class(a) +{ + scope => "bundle"; + promise_kept => { "$(a):bundle_context" }; +} + +bundle agent target(a) +{ + reports: + "Hello, $(a)"; +} + +bundle agent helper +{ + vars: + "x" string => target("arg"); + "y" + classes => isvariable("arg"), + string => ""; + methods: + "x" usebundle => target("arg"); +}