1# Copyright (c) 2023 Nordic Semiconductor ASA
2# SPDX-License-Identifier: Apache-2.0
3
4from __future__ import annotations
5
6from pylint.checkers import BaseChecker
7
8import astroid
9from astroid import nodes
10
11class ZephyrArgParseChecker(BaseChecker):
12    """Class implementing function checker for Zephyr."""
13
14    # The name defines a custom section of the config for this checker.
15    name = "zephyr-arg-parse"
16
17    # Register messages emitted by the checker.
18    msgs = {
19        "E9901": (
20            "Argument parser with abbreviations is disallowed",
21            "argument-parser-with-abbreviations",
22            "An ArgumentParser object must set `allow_abbrev=false` to disable "
23            "abbreviations and prevent issues with these being used by projects"
24            " and/or scripts."
25        )
26    }
27
28    # Function that looks at evert function call for ArgumentParser invocation
29    def visit_call(self, node: nodes.Call) -> None:
30        if isinstance(node.func, astroid.nodes.node_classes.Attribute) and \
31           node.func.attrname == "ArgumentParser":
32            abbrev_disabled = False
33
34            # Check that allow_abbrev is set and that the value is False
35            for keyword in node.keywords:
36                if keyword.arg == "allow_abbrev":
37                    if not isinstance(keyword.value, astroid.nodes.node_classes.Const):
38                        continue
39                    if keyword.value.pytype() != "builtins.bool":
40                        continue
41                    if keyword.value.value is False:
42                        abbrev_disabled = True
43
44            if abbrev_disabled is False:
45                self.add_message(
46                    "argument-parser-with-abbreviations", node=node
47                )
48
49        return ()
50
51# This is called from pylint, hence PyLinter not being declared in this file
52# pylint: disable=undefined-variable
53def register(linter: PyLinter) -> None:
54    linter.register_checker(ZephyrArgParseChecker(linter))
55