summaryrefslogtreecommitdiff
path: root/buildscripts/linter/base.py
blob: f22f59e4f01a1f73b49db364f22b079dea98f1ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
"""Base class and support functions for linters."""
from __future__ import absolute_import
from __future__ import print_function

from abc import ABCMeta, abstractmethod
from typing import Dict, List, Optional


class LinterBase(object):
    """Base Class for all linters."""

    __metaclass__ = ABCMeta

    def __init__(self, cmd_name, required_version, cmd_location=None):
        # type: (str, str, Optional[str]) -> None
        """
        Create a linter.

        cmd_name - short friendly name
        required_version - the required version string to check against
        cmd_location - location of executable
        """
        self.cmd_name = cmd_name
        self.required_version = required_version
        self.cmd_location = cmd_location

    @abstractmethod
    def get_lint_cmd_args(self, file_name):
        # type: (str) -> List[str]
        """Get the command to run a linter."""
        pass

    def get_fix_cmd_args(self, file_name):
        # type: (str) -> Optional[List[str]]
        # pylint: disable=no-self-use,unused-argument
        """Get the command to run a linter fix."""
        return None

    @abstractmethod
    def get_lint_version_cmd_args(self):
        # type: () -> List[str]
        """Get the command to run a linter version check."""
        pass

    def needs_file_diff(self):
        # type: () -> bool
        # pylint: disable=no-self-use
        """
        Check if we need to diff the output of this linter with the original file.

        This applies to tools like clang-format and yapf which do not have a notion of linting. We
        introduce the idea of linting by formatting a file with the tool to standard out and
        comparing it to the original.
        """
        return False

    def ignore_interpreter(self):
        # type: () -> bool
        # pylint: disable=no-self-use
        """
        Check if we should ignore the interpreter when searching for the linter to run.

        This applies to mypy specifically since the pylinters are executed under Python 2 but mypy
        is executed by python 3.
        """
        return False


class LinterInstance(object):
    """A pair of a Linter and the full path of the linter cmd to run."""

    def __init__(self, linter, cmd_path):
        # type: (LinterBase, List[str]) -> None
        """Construct a LinterInstance."""
        self.linter = linter
        self.cmd_path = cmd_path