Example #1
0
class PerlCriticBear:
    """
    Check the code with perlcritic. This will run perlcritic over
    each of the files seperately.
    """

    LANGUAGES = {'Perl'}
    REQUIREMENTS = {
        DistributionRequirement(apt_get='perl'),
        DistributionRequirement(apt_get='libperl-critic-perl')
    }
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    CAN_DETECT = {'Syntax', 'Formatting', 'Code Simplification'}

    @staticmethod
    def create_arguments(filename,
                         file,
                         config_file,
                         perlcritic_profile: str = ''):
        """
        :param perlcritic_profile: Location of the perlcriticrc config file.
        """
        args = ('--no-color', )
        if perlcritic_profile:
            args += ('--profile', perlcritic_profile)
        return args + (filename, )
Example #2
0
class VerilogLintBear:
    """
    Analyze Verilog code using ``verilator`` and checks for all lint
    related and code style related warning messages. It supports the
    synthesis subset of Verilog, plus initial statements, proper
    blocking/non-blocking assignments, functions, tasks.

    It also warns about unused code when a specified signal is never sinked,
    and unoptimized code due to some construct, with which the
    optimization of the specified signal or block is disabled.

    This is done using the ``--lint-only`` command. For more information visit
    <http://www.veripool.org/projects/verilator/wiki/Manual-verilator>.
    """
    LANGUAGES = {'Verilog'}
    REQUIREMENTS = {DistributionRequirement(apt_get='verilator')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    ASCIINEMA_URL = 'https://asciinema.org/a/45275'
    CAN_DETECT = {'Formatting', 'Code Simplification', 'Syntax', 'Unused Code'}

    @staticmethod
    def create_arguments(filename, file, config_file):
        return '--lint-only', filename
Example #3
0
class CSecurityBear:
    """
    Report possible security weaknesses for C/C++.

    For more information, consult <http://www.dwheeler.com/flawfinder/>.
    """

    LANGUAGES = {'C', 'C++'}
    REQUIREMENTS = {DistributionRequirement(apt='flawfinder')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    ASCIINEMA_URL = 'https://asciinema.org/a/7z8ol9mpsgtuo1096c6jk8hi6'
    CAN_DETECT = {'Security', 'Memory Leak', 'Code Simplification'}

    @staticmethod
    def create_arguments(filename,
                         file,
                         config_file,
                         neverignore: bool = False):
        """
        :param neverignore:
            Never ignore security issues, even if they have an ``ignore``
            directive in a comment.
        """
        args = "--columns", "--dataonly", "--quiet", "--singleline"
        args += ("--neverignore", filename) if neverignore else (filename, )
        return args
Example #4
0
class CPPCheckBear:
    """
    Report possible security weaknesses for C/C++.
    For more information, consult <https://github.com/danmar/cppcheck>.
    """

    LANGUAGES = {"C", "C++"}
    REQUIREMENTS = {DistributionRequirement(apt='cppcheck')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    CAN_DETECT = {'Security', 'Unused Code', 'Unreachable Code', 'Smell'}

    @staticmethod
    def create_arguments(filename,
                         file,
                         config_file,
                         enable: typed_list(str) = []):
        """
        :param enable:
            Choose specific issues to report. Issues that can be
            reported are: all, warning, style, performance,
            portability, information, unusedFunction,
            missingInclude
        """
        args = ("--template={line}:{severity}:{id}:{message}", )

        if enable:
            args += ('--enable=' + ",".join(enable), )

        return args + (filename, )
Example #5
0
class XMLBear:
    """
    Checks the code with ``xmllint``.

    See http://xmlsoft.org/xmllint.html
    """
    LANGUAGES = {'XML'}
    REQUIREMENTS = {DistributionRequirement(apt_get='libxml2')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    CAN_DETECT = {'Formatting', 'Syntax'}

    _output_regex = re.compile(
        r'.*:(?P<line>\d+):.*(?P<severity>error|warning)\s?: '
        r'(?P<message>.*)\n.*\n.*')

    @staticmethod
    def create_arguments(filename,
                         file,
                         config_file,
                         xml_schema: path = '',
                         xml_dtd: path_or_url = ''):
        """
        :param xml_schema: ``W3C XML Schema`` file used for validation.
        :param xml_dtd:    ``Document type Definition (DTD)`` file or
                           url used for validation.
        """
        args = (filename, )
        if xml_schema:
            args += ('-schema', xml_schema)
        if xml_dtd:
            args += ('-dtdvalid', xml_dtd)

        return args

    def process_output(self, output, filename, file):
        stdout, stderr = output
        if stdout:
            # Return issues from stderr and stdout if stdout is not empty
            return itertools.chain(
                self.process_output_regex(stderr,
                                          filename,
                                          file,
                                          output_regex=self._output_regex),
                self.process_output_corrected(
                    stdout,
                    filename,
                    file,
                    diff_severity=RESULT_SEVERITY.INFO,
                    result_message='XML can be formatted better.'))
        else:
            # Return issues from stderr if stdout is empty
            return self.process_output_regex(stderr,
                                             filename,
                                             file,
                                             output_regex=self._output_regex)
Example #6
0
class LatexLintBear:
    """
    Checks the code with ``chktex``.
    """
    LANGUAGES = {"Tex"}
    REQUIREMENTS = {DistributionRequirement(apt_get='chktex')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    CAN_DETECT = {'Syntax', 'Formatting'}

    @staticmethod
    def create_arguments(filename, file, config_file):
        return filename,
Example #7
0
class CSharpLintBear:
    """
    Checks C# code for syntactical correctness using the ``mcs`` compiler.
    """

    LANGUAGES = {"C#"}
    REQUIREMENTS = {DistributionRequirement(apt_get='mono-mcs')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    CAN_DETECT = {'Syntax'}

    @staticmethod
    def create_arguments(filename, file, config_file):
        return filename,
Example #8
0
class LuaLintBear:
    """
    Check Lua code for possible semantic problems, like unused code.

    Read more at <https://github.com/mpeterv/luacheck>.
    """

    LANGUAGES = {'Lua'}
    REQUIREMENTS = {DistributionRequirement(apt_get='luarocks')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    CAN_DETECT = {'Unreachable Code', 'Unused Code', 'Variable Misuse'}

    @staticmethod
    def create_arguments(filename, file, config_file):
        return '-', '--formatter=plain', '--ranges', '--codes'
Example #9
0
class CSecurityBear:
    """
    Report possible security weaknesses for C/C++.

    For more information, consult <http://www.dwheeler.com/flawfinder/>.
    """

    LANGUAGES = {'C', 'C++'}
    REQUIREMENTS = {DistributionRequirement(apt_get='flawfinder')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    ASCIINEMA_URL = 'https://asciinema.org/a/7z8ol9mpsgtuo1096c6jk8hi6'
    CAN_DETECT = {'Security', 'Memory Leak', 'Code Simplification'}

    @staticmethod
    def create_arguments(filename, file, config_file):
        return "--columns", "--dataonly", "--quiet", "--singleline", filename
Example #10
0
class HaskellLintBear:
    """
    Check Haskell code for possible problems. This bear can propose patches for
    using alternative functions, simplifying code and removing redundancies.

    See <http://community.haskell.org/~ndm/darcs/hlint/hlint.htm> for more
    information.
    """

    LANGUAGES = {"Haskell"}
    REQUIREMENTS = {DistributionRequirement(apt_get='hlint')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    CAN_DETECT = {'Duplication'}
    CAN_FIX = {'Unused Code', 'Code Simplification'}

    severity_map = {"Error": RESULT_SEVERITY.MAJOR,
                    "Warning": RESULT_SEVERITY.NORMAL,
                    "Suggestion": RESULT_SEVERITY.INFO}

    @staticmethod
    def create_arguments(filename, file, config_file):
        return '--json', filename

    def process_output(self, output, filename, file):
        output = json.loads(output)

        for issue in output:
            assert issue["startLine"] == issue["endLine"]
            diff = Diff(file)
            line_nr = issue["startLine"]
            line_to_change = file[line_nr-1]
            newline = line_to_change.replace(issue["from"], issue["to"])
            diff.change_line(line_nr, line_to_change, newline)

            yield Result.from_values(
                origin=self,
                message=issue["hint"],
                file=filename,
                severity=self.severity_map[issue["severity"]],
                line=issue["startLine"],
                diffs={filename: diff})
Example #11
0
class XMLBear(LocalBear, Lint):
    executable = 'xmllint'
    diff_message = "XML can be formatted better."
    output_regex = r'(.*\.xml):(?P<line>\d+): (?P<message>.*)\n.*\n.*'
    gives_corrected = True
    use_stderr = True
    LANGUAGES = {"XML"}
    REQUIREMENTS = {DistributionRequirement(apt='libxml2')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    CAN_DETECT = {'Formatting', 'Syntax'}

    def process_output(self, output, filename, file):
        if self.stdout_output:
            # Return issues from stderr and stdout if stdout is not empty
            return itertools.chain(
                self._process_issues(self.stderr_output, filename),
                self._process_corrected(self.stdout_output, filename, file))
        else:  # Return issues from stderr if stdout is empty
            return self._process_issues(self.stderr_output, filename)

    def run(self,
            filename,
            file,
            xml_schema: path = "",
            xml_dtd: path_or_url = ""):
        '''
        Checks the code with ``xmllint``.

        :param xml_schema: ``W3C XML Schema`` file used for validation.
        :param xml_dtd:    ``Document type Definition (DTD)`` file or
                           url used for validation.
        '''
        self.arguments = "{filename} "
        if xml_schema:
            self.arguments += " -schema " + escape_path_argument(xml_schema)
        if xml_dtd:
            self.arguments += " -dtdvalid " + xml_dtd
        return self.lint(filename, file)
Example #12
0
class JuliaLintBear:
    """
    Provide analysis related to common bugs and potential issues in Julia like
    dead code, undefined variable usage, duplicate keys in dicts, incorrect
    ADT usage, wrongfully using ellipsis, and much more.

    See <https://lintjl.readthedocs.org/en/stable/> for more information
    on the analysis provided.
    """
    LANGUAGES = {"Julia"}
    REQUIREMENTS = {DistributionRequirement(apt='julia')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    CAN_DETECT = {
        'Unused Code', 'Syntax', 'Redundancy', 'Duplication',
        'Unreachable Code', 'Security', 'Formatting'
    }

    @staticmethod
    def create_arguments(filename, file, config_file):
        lintcode = ('import Lint.lintfile; display(lintfile("' +
                    escape(filename, '"\\') + '"))')
        return '-e', lintcode
Example #13
0
class PHPCodeSnifferBear:
    """
    Ensures that your PHP, JavaScript or CSS code remains clean and consistent.

    See <https://github.com/squizlabs/PHP_CodeSniffer> for more information.
    """

    LANGUAGES = {"PHP", "JavaScript", "CSS"}
    REQUIREMENTS = {DistributionRequirement(apt_get='php-codesniffer')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    CAN_DETECT = {
        'Formatting', 'Syntax', 'Documentation', 'Code Simplification'
    }
    ASCIINEMA_URL = 'https://asciinema.org/a/efawv96vdalck73tc3hwcabov'

    @staticmethod
    def create_arguments(filename, file, config_file):
        return '--report=emacs', '--standard=' + config_file, filename

    @staticmethod
    def generate_config(filename,
                        file,
                        max_line_length: int = 79,
                        line_ending_character: str = "\\n",
                        indent_size: int = SpacingHelper.DEFAULT_TAB_WIDTH,
                        use_spaces: bool = True,
                        allow_multiple_statements_per_line: bool = False,
                        force_lower_case_keywords: bool = True,
                        force_lower_case_constants: bool = True,
                        blank_line_after_namespace_declaration: bool = True,
                        check_use_blocks: bool = True,
                        check_class_declaration: bool = True,
                        check_property_declaration: bool = True,
                        force_scope_modifier_on_method: bool = True,
                        function_declaration_argument_spacing: int = 1,
                        allow_multiline_function_declaration: bool = True):
        """
        :param max_line_length:
            Maximum number of characters for a line.
        :param line_ending_character:
            Checks that end of line characters correspond to the one provided.
        :param indent_size:
            Number of spaces per indentation level.
        :param use_spaces:
            True if spaces are to be used instead of tabs.
        :param allow_multiple_statements_per_line:
            Allows having multiple statements on one line.
        :param force_lower_case_keyword:
            Checks that ``PHP`` keywords are lowercase.
        :param force_lower_case_constant:
            Checks that all uses of ``true``, ``false`` and ``null`` are
            lowercase.
        :param blank_line_after_namespace_declaration:
            Ensures that there is a blank line after a namespace declaration.
        :param check_use_blocks:
            Ensures that there is one blank line after a ``use`` block,
            that there is only one use block per line, and that all ``use``
            declaration are done after namespaces declaration.
        :param check_class_declaration:
            Ensures that ``extends`` and ``implements`` keywords are declared
            on the same line as the class name, that the opening brace for a
            class is on the next line, and that the closing brace for a class
            is on the next line after the body. Allows splitting implements
            list accross multiple lines.
        :param check_property_declaration:
            Ensures that visibility is declared on all properties, that the
            ``var`` keyword is not used to declare a property, that there is
            not more that one property declared on a line, that properties are
            not prefixed with an underscore.
        :param force_scope_modifier_on_method:
            Verifies that class methods have scope modifiers.
        :param function_declaration_argument_spacing:
            Number of spaces between arguments in function declaration.
        :param allow_multiline_function_declaration:
            Allows argument lists to be split accross multiple lines correctly
            indented.
        """
        rules_map = {
            "Generic.WhiteSpace.DisallowTabIndent":
            use_spaces,
            "Generic.Formatting.DisallowMultipleStatements":
            not allow_multiple_statements_per_line,
            "Generic.PHP.LowerCaseKeyword":
            force_lower_case_keywords,
            "Generic.PHP.LowerCaseConstant":
            force_lower_case_constants,
            "PSR2.Namespaces.UseDeclaration":
            check_use_blocks,
            "PSR2.Namespaces.NamespaceDeclaration":
            blank_line_after_namespace_declaration,
            "PSR2.Classes.ClassDeclaration":
            check_class_declaration,
            "PSR2.Classes.PropertyDeclaration":
            check_property_declaration,
            "Squiz.Scope.MethodScope":
            force_scope_modifier_on_method,
            "Squiz.Functions.MultiLineFunctionDeclaration":
            allow_multiline_function_declaration
        }
        rules = ''
        for k, v in rules_map.items():
            rules += '<rule ref="{}"/>\n'.format(k) if v else ''
        configs = '''<?xml version="1.0"?>
<ruleset name="Custom Standard">
 <description>A custom coding standard</description>
 <rule ref="Generic.Files.LineLength">
  <properties>
   <property name="lineLimit" value="{max_line_length}"/>
  </properties>
 </rule>
 <rule ref="Generic.Files.LineEndings">
  <properties>
   <property name="eolChar" value="{line_ending_character}"/>
  </properties>
 </rule>
 <rule ref="Generic.WhiteSpace.ScopeIndent">
  <properties>
   <property name="ignoreIndentationTokens" type="array"
   value="T_COMMENT,T_DOC_COMMENT_OPEN_TAG"/>
  </properties>
  <properties>
   <property name="indent" value="{indent_size}"/>
  </properties>
  <properties>
   <property name="exact" value="true"/>
  </properties>
 </rule>
 {some_rules}
 <rule ref="Squiz.WhiteSpace.ScopeKeywordSpacing"/>
 <rule ref="Squiz.Functions.FunctionDeclarationArgumentSpacing">
  <properties>
   <property name="equalsSpacing"
   value="{function_declaration_argument_spacing}"/>
  </properties>
 </rule>
 <rule
 ref="Squiz.Functions.FunctionDeclarationArgumentSpacing.SpacingAfterHint">
  <severity>0</severity>
 </rule>
</ruleset>
'''.format(max_line_length=max_line_length,
           line_ending_character=line_ending_character,
           indent_size=indent_size,
           some_rules=rules,
           function_declaration_argument_spacing=(
               function_declaration_argument_spacing))
        return configs
Example #14
0
 def test_install_command_mock_incompatible_os(self, call_mock):
     self.assertEqual(platform.linux_distribution()[0], 'bad_os')
     with self.assertRaises(OSError):
         DistributionRequirement(dnf='libclang',
                                 apt_get='libclangs').install_command()
Example #15
0
 def test_install_command_mock_fedora(self, call_mock):
     self.assertEqual(platform.linux_distribution()[0], 'Fedora')
     self.assertEqual(
         DistributionRequirement(dnf='libclang',
                                 apt_get='libclangs').install_command(),
         ['dnf', 'install', 'libclang'])
Example #16
0
class GNUIndentBear:
    """
    This bear checks and corrects spacing and indentation via the well known
    Indent utility.

    C++ support is considered experimental.
    """

    LANGUAGES = {'C', 'C++'}
    REQUIREMENTS = {DistributionRequirement(apt_get='indent')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    CAN_FIX = {'Formatting'}

    @staticmethod
    @deprecate_settings(indent_size='tab_width')
    def create_arguments(filename,
                         file,
                         config_file,
                         max_line_length: int = 79,
                         use_spaces: bool = True,
                         blank_lines_after_declarations: bool = False,
                         blank_lines_after_procedures: bool = False,
                         blank_lines_after_commas: bool = False,
                         braces_on_if_line: bool = False,
                         braces_on_func_def_line: bool = False,
                         cuddle_else: bool = False,
                         while_and_brace_on_same_line: bool = False,
                         case_indentation: int = 0,
                         space_before_semicolon_after_empty_loop: bool = True,
                         delete_optional_blank_lines: bool = True,
                         declaration_indent: int = 0,
                         brace_indent: int = 2,
                         gnu_style: bool = False,
                         k_and_r_style: bool = False,
                         linux_style: bool = False,
                         indent_size: int = SpacingHelper.DEFAULT_TAB_WIDTH,
                         indent_cli_options: str = ''):
        """
        :param max_line_length:
            Maximum number of characters for a line.
        :param use_spaces:
            True if spaces are to be used, else tabs.
        :param blank_lines_after_declarations:
            Forces blank lines after the declarations.

            Example:
                If ``blank_lines_after_declarations = True`` then
                ```
                int a;
                return ...;
                ```
                changes to
                ```
                int a;

                return ...;
                ```

        :param blank_lines_after_procedures:
            Force blank lines after procedure bodies.
        :param blank_lines_after_commas:
            Forces newline after comma in declaration.

            Example:
                If ``blank_lines_after_commas = True`` then
                ```
                int a, b;
                ```
                changes to
                ```
                int a,
                  b;
                ```
        :param braces_on_if_line:
            Puts the brace ``{`` on same line with if.

            Example:
                If ``braces_on_if_line = True``  then
                ```
                if (x > 0)
                {
                ```
                changes to
                ```
                if (x > 0) {
                ```
        :param braces_on_func_def_line:
            Puts the brace `{` on same line with the function declaration.
        :param cuddle_else:
            Cuddle else and preceding ``}``.

            Example:
                If ``cuddle_else = True`` then
                ```
                if (...) {
                    ....
                }
                else {
                ```
                changes to
                ```
                if (...) {
                    ....
                } else {
                ```

        :param while_and_brace_on_same_line:
            Cuddles while of ``do {} while``; and preceding ``}``.
        :param case_indentation:
            Specifies the number of spaces by which ``case`` in the ``switch``
            are indented.
        :param space_before_semicolon_after_empty_loop:
            Forces a blank before the semicolon ``;`` on one-line ``for`` and
            ``while`` statements.
        :param delete_optional_blank_lines:
             Deletes blank lines that are not needed. An example of needed
             blank line, is the blank line following a declaration when
             ``blank_line_after_declaration=True``.
        :param declaration_indent:
            Forces variables names to be aligned in column ``n`` with
            ``n = declaration_indent``  in declaration.

            Example:
                If ``declaration_indent = 8`` then,
                ```
                int a;
                float b;
                ```
                changes to
                ```
                int     a;
                float   b;
                ```
        :param brace_indent:
            Specifies the number of spaces by which braces are indented. Its
            default value is 2.
        :param gnu_style:
            Uses GNU coding style.
        :param k_and_r_style:
            Uses Kernighan & Ritchie coding style.
        :param linux_style:
            Uses Linux coding style.
        :param indent_size:
            Number of spaces per indentation level.
        :param indent_cli_options:
            Any command line options the indent binary understands. They
            will be simply passed through.
        """
        indent_options = (
            '--no-tabs' if use_spaces else '--use-tabs',
            '--line-length',
            str(max_line_length),
            '--indent-level',
            str(indent_size),
            '--tab-size',
            str(indent_size),
        )
        indent_options += (('--cuddle-do-while', )
                           if while_and_brace_on_same_line else
                           ('--dont-cuddle-do-while', ))
        indent_options += (('--swallow-optional-blank-lines', )
                           if delete_optional_blank_lines else ('-nsob', ))
        indent_options += (('--blank-lines-after-declarations', )
                           if blank_lines_after_declarations else ('-nbad', ))
        indent_options += (('--blank-lines-after-commas', )
                           if blank_lines_after_commas else ('-nbc', ))
        indent_options += (('--blank-lines-after-procedures', )
                           if blank_lines_after_procedures else ('-nbap', ))
        indent_options += (('-di' + str(declaration_indent), )
                           if declaration_indent != 0 else ())
        indent_options += (('--case-indentation' + str(case_indentation), )
                           if case_indentation != 0 else ())
        indent_options += (('--space-special-semicolon', )
                           if space_before_semicolon_after_empty_loop else
                           ('-nss', ))
        indent_options += ('--brace-indent' + str(brace_indent), )
        indent_options += (('--braces-on-func-def-line', )
                           if braces_on_func_def_line else ('-blf', ))
        indent_options += ((('-ce', ) if cuddle_else else ('-nce', )) +
                           ('-br', )) if braces_on_if_line else ('-bl', )
        indent_style_option = ()
        indent_style_option += ('--gnu-style', ) if gnu_style else ()
        indent_style_option += (('--k-and-r-style', ) if k_and_r_style
                                and indent_style_option is () else ())
        indent_style_option += (('--linux-style', ) if linux_style
                                and indent_style_option is () else ())
        # If a style is chosen the other configs aren't passed to `indent`
        return (indent_style_option if indent_style_option is not () else
                indent_options) + tuple(shlex.split(indent_cli_options))