Ejemplo n.º 1
0
class BootLintBear:
    """
    Raise several common HTML mistakes in html files that are using
    Bootstrap in a fairly "vanilla" way. Vanilla Bootstrap's components/widgets
    require their parts of the DOM to conform to certain structures that is
    checked. Also, raises issues about certain <meta> tags, HTML5 doctype
    declaration, etc. to use bootstrap properly.

    For more about the analysis, check Bootlint
    <https://github.com/twbs/bootlint#bootlint>.
    """
    LANGUAGES = {"HTML"}
    REQUIREMENTS = {NpmRequirement('bootlint', '0')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    CAN_DETECT = {'Formatting', 'Syntax'}

    @staticmethod
    def create_arguments(filename,
                         file,
                         config_file,
                         bootlint_ignore: typed_list(str) = []):
        """
        :param bootlint_ignore: List of checkers to ignore.
        """
        ignore = ','.join(part.strip() for part in bootlint_ignore)
        return '--disable=' + ignore, filename
Ejemplo n.º 2
0
class JSComplexityBear:
    """
    Calculates cyclomatic complexity using ``cr``.
    """
    LANGUAGES = {"JavaScript"}
    REQUIREMENTS = {NpmRequirement('complexity-report', '2.0.0-alpha')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    ASCIINEMA_URL = 'https://asciinema.org/a/39250'
    CAN_DETECT = {'Complexity'}

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

    def process_output(self, output, filename, file, cc_threshold: int = 10):
        """
        :param cc_threshold: Threshold value for cyclomatic complexity
        """
        message = "{} has a cyclomatic complexity of {}."
        if output:
            output = json.loads(output)
            for function in output["reports"][0]["functions"]:
                if function["cyclomatic"] >= cc_threshold:
                    yield Result.from_values(origin=self,
                                             message=message.format(
                                                 function["name"],
                                                 function["cyclomatic"]),
                                             file=filename,
                                             line=function["line"])
Ejemplo n.º 3
0
class ElmLintBear:
    """
    This bear checks the formatting of the Elm code.

    See <https://github.com/avh4/elm-format> for more information.
    """

    LANGUAGES = {'Elm'}
    REQUIREMENTS = {NpmRequirement('elm', '0.18')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    CAN_DETECT = {'Formatting'}

    @classmethod
    def check_prerequisites(cls):
        if which('elm-format') is None:
            return (
                'elm-format is missing. Download it from'
                '<https://github.com/avh4/elm-format/blob/master/README.md#for-elm-018>'
                'and put it in your PATH.')
        else:
            return True

    @staticmethod
    def create_arguments(filename, file, config_file):
        return '--stdin', filename
Ejemplo n.º 4
0
class CSSAutoPrefixBear:
    """
    This bear adds vendor prefixes to CSS rules using ``autoprefixer`` utility.
    """
    LANGUAGES = {"CSS"}
    REQUIREMENTS = {NpmRequirement('postcss-cli', '2'),
                    NpmRequirement('autoprefixer', '6')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    ASCIINEMA_URL = 'https://asciinema.org/a/40093'
    CAN_FIX = {'Syntax', 'Formatting'}

    @staticmethod
    def create_arguments(filename, file, config_file):
        return '--use', 'autoprefixer', filename
Ejemplo n.º 5
0
class JSComplexityBear:
    """
    Calculates cyclomatic complexity using ``cr``, the command line utility
    provided by the NodeJS module ``complexity-report``.
    """
    LANGUAGES = {"JavaScript"}
    REQUIREMENTS = {NpmRequirement('complexity-report', '2.0.0-alpha')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    ASCIINEMA_URL = 'https://asciinema.org/a/39250'
    CAN_DETECT = {'Complexity'}

    try:
        DecodeError = json.decoder.JSONDecodeError
    except AttributeError:
        DecodeError = ValueError

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

    def process_output(self, output, filename, file, cc_threshold: int = 10):
        """
        :param cc_threshold: Threshold value for cyclomatic complexity
        """
        message = "{} has a cyclomatic complexity of {}."
        if output:
            try:
                output = json.loads(output)
            except self.DecodeError:
                output_regex = (r'Fatal error \[getReports\]: .+: '
                                r'Line (?P<line>\d+): (?P<message>.*)')
                for match in re.finditer(output_regex, output):
                    groups = match.groupdict()
                    yield Result.from_values(origin=self,
                                             message=groups["message"].strip(),
                                             file=filename,
                                             severity=RESULT_SEVERITY.MAJOR,
                                             line=int(groups["line"]))
                return
            for function in output["reports"][0]["functions"]:
                if function["cyclomatic"] >= cc_threshold:
                    yield Result.from_values(origin=self,
                                             message=message.format(
                                                 function["name"],
                                                 function["cyclomatic"]),
                                             file=filename,
                                             line=function["line"])
Ejemplo n.º 6
0
class CSSLintBear:
    """
    Check code for syntactical or semantical problems that might lead to
    problems or inefficiencies.
    """
    LANGUAGES = {"CSS"}
    REQUIREMENTS = {NpmRequirement('csslint', '1')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    CAN_DETECT = {'Syntax', 'Code Simplification'}

    @staticmethod
    def create_arguments(filename, file, config_file):
        return '--format=compact', filename
Ejemplo n.º 7
0
class HappinessLintBear:
    """
    Checks JavaScript files for semantic and syntax errors using ``happiness``.

    See <https://github.com/JedWatson/happiness/> for more information.
    """
    LANGUAGES = {"JavaScript"}
    REQUIREMENTS = {NpmRequirement('happiness', '7.1.2')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    ASCIINEMA_URL = 'https://asciinema.org/a/80714'
    CAN_DETECT = {'Syntax'}

    @staticmethod
    def create_arguments(filename, file, config_file):
        return filename,
Ejemplo n.º 8
0
class AlexBear(LocalBear, Lint):
    executable = 'alex'
    output_regex = re.compile(r'\s+(?P<line>\d+):(?P<column>\d+)\-'
                              r'(?P<end_line>\d+):(?P<end_column>\d+)'
                              r'\s+(?:(warning))\s+(?P<message>.+)')
    arguments = "{filename}"
    LANGUAGES = {"Natural Language"}
    REQUIREMENTS = {NpmRequirement('alex', '2')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'

    def run(self, filename, file):
        '''
        Checks the markdown file with Alex - Catch insensitive,
        inconsiderate writing.
        '''
        return self.lint(filename)
Ejemplo n.º 9
0
class RAMLLintBear:
    """
    RAML Linter is a static analysis, linter-like, utility that will enforce
    rules on a given RAML document, ensuring consistency and quality.
    Note: Files should not have leading empty lines, else the bear fails to
    identify the problems correctly.
    """

    LANGUAGES = {"RAML"}
    REQUIREMENTS = {NpmRequirement('ramllint', '1.2.2')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    CAN_DETECT = {'Syntax', 'Formatting'}

    @staticmethod
    def create_arguments(filename, file, config_file):
        return filename,
Ejemplo n.º 10
0
class TSLintBear:
    """
    Check TypeScript code for style violations and possible semantical
    problems.

    Read more about the capabilities at
    <https://github.com/palantir/tslint#core-rules>.
    """

    LANGUAGES = {"TypeScript"}
    REQUIREMENTS = {NpmRequirement('tslint', '3')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    ASCIINEMA_URL = 'https://asciinema.org/a/9re9c4fv17lhn7rmvzueebb3b'
    CAN_DETECT = {'Syntax', 'Formatting', 'Smell'}

    @staticmethod
    def create_arguments(filename, file, config_file,
                         tslint_config: path="", rules_dir: path=""):
        """
        :param tslint_config: Path to configuration file.
        :param rules_dir:     Rules directory
        """
        args = ('--format', 'json')
        if tslint_config:
            args += ('--config', tslint_config)
        if rules_dir:
            args += ('--rules-dir', rules_dir)
        return args + (filename,)

    def process_output(self, output, filename, file):
        output = json.loads(output) if output else []
        for issue in output:
            yield Result.from_values(
                origin="{} ({})".format(self.__class__.__name__,
                                        issue['ruleName']),
                message=issue["failure"],
                file=issue["name"],
                line=int(issue["startPosition"]["line"]) + 1,
                end_line=int(issue["endPosition"]["line"]) + 1,
                column=int(issue["startPosition"]["character"]) + 1,
                end_column=int(issue["endPosition"]["character"]) + 1)
Ejemplo n.º 11
0
class DockerfileLintBear:
    """
    Check file syntax as well as arbitrary semantic and best practice
    in Dockerfiles. it also checks LABEL rules against docker images.

    Uses ``dockerfile_lint`` to provide the analysis.
    See <https://github.com/projectatomic/dockerfile_lint#dockerfile-lint> for
    more information .
    """
    LANGUAGES = {"Dockerfile"}
    REQUIREMENTS = {NpmRequirement('dockerfile_lint', '0')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    CAN_DETECT = {'Syntax', 'Smell'}

    severity_map = {
        "error": RESULT_SEVERITY.MAJOR,
        "warn": RESULT_SEVERITY.NORMAL,
        "info": RESULT_SEVERITY.INFO
    }

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

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

        for severity in output:
            if severity == "summary":
                continue
            for issue in output[severity]["data"]:
                yield Result.from_values(
                    origin=self,
                    message=issue["message"],
                    file=filename,
                    severity=self.severity_map[issue["level"]],
                    line=issue["line"])
Ejemplo n.º 12
0
class AlexBear:
    """
    Checks the markdown file with Alex - Catch insensitive, inconsiderate
    writing.
    """
    LANGUAGES = {'Natural Language'}
    REQUIREMENTS = {NpmRequirement('alex', '3')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'

    @classmethod
    def check_prerequisites(cls):
        parent_prereqs = super().check_prerequisites()
        if parent_prereqs is not True:  # pragma: no cover
            return parent_prereqs

        incorrect_pkg_msg = (
            'Please ensure that the package that has been installed is the '
            "one to 'Catch insensitive, inconsiderate writing'. This can be "
            'verified by running `alex --help` and seeing what it does.')
        try:
            output = subprocess.check_output(('alex', '--help'),
                                             stderr=subprocess.STDOUT)
        except (OSError, subprocess.CalledProcessError):
            return ('The `alex` package could not be verified. ' +
                    incorrect_pkg_msg)
        else:
            output = output.decode(sys.getfilesystemencoding())
            if 'Catch insensitive, inconsiderate writing' in output:
                return True
            else:
                return ("The `alex` package that's been installed seems to "
                        'be incorrect. ' + incorrect_pkg_msg)

    @staticmethod
    def create_arguments(filename, file, config_file):
        return filename,
Ejemplo n.º 13
0
class JSHintBear:
    """
    Detect errors and potential problems in JavaScript code and to enforce
    appropriate coding conventions. For example, problems like syntax errors,
    bugs due to implicit type conversion, leaking variables and much more
    can be detected.

    For more information on the analysis visit <http://jshint.com/>
    """

    LANGUAGES = {'JavaScript'}
    REQUIREMENTS = {NpmRequirement('jshint', '2')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    CAN_DETECT = {'Formatting', 'Syntax', 'Complexity', 'Unused Code'}

    @staticmethod
    @deprecate_settings(
        es_version='use_es6_syntax',
        javascript_strictness=('allow_global_strict', lambda x: 'global'
                               if x else True),
        cyclomatic_complexity='maxcomplexity',
        allow_unused_variables=('prohibit_unused', negate),
        max_parameters='maxparams',
        allow_missing_semicolon='allow_missing_semicol',
        allow_this_statements='allow_this_stmt',
        allow_with_statements='allow_with_stmt',
        allow_bitwise_operators=('prohibit_bitwise', negate),
        max_statements='maxstatements',
        max_depth='maxdepth',
        allow_comma_operator=('prohibit_comma', negate),
        allow_non_breaking_whitespace=('prohibit_non_breaking_whitespace',
                                       negate),
        allow_prototype_overwrite=('prohibit_prototype_overwrite', negate),
        allow_type_coercion=('prohibit_type_coercion', negate),
        allow_future_identifiers=('future_hostile', negate),
        allow_typeof=('prohibit_typeof', negate),
        allow_var_statement=('prohibit_variable_statements', negate),
        allow_grouping_operator=('prohibit_groups', negate),
        allow_variable_shadowing='shadow',
        use_mozilla_extension='using_mozilla',
        allow_constructor_functions=('prohibit_new', negate),
        allow_argument_caller_and_callee=('prohibit_arg', negate),
        allow_iterator_property=('iterator', negate),
        allow_filter_in_forin='force_filter_forin')
    def generate_config(filename,
                        file,
                        allow_bitwise_operators: bool = False,
                        allow_prototype_overwrite: bool = False,
                        force_braces: bool = True,
                        allow_type_coercion: bool = False,
                        allow_future_identifiers: bool = True,
                        allow_typeof: bool = True,
                        allow_filter_in_forin: bool = True,
                        allow_funcscope: bool = False,
                        allow_iterator_property: bool = True,
                        allow_argument_caller_and_callee: bool = False,
                        allow_comma_operator: bool = True,
                        allow_non_breaking_whitespace: bool = False,
                        allow_constructor_functions: bool = True,
                        allow_grouping_operator: bool = True,
                        allow_var_statement: bool = True,
                        allow_missing_semicolon: bool = False,
                        allow_debugger: bool = False,
                        allow_assignment_comparisions: bool = False,
                        allow_eval: bool = False,
                        allow_increment: bool = False,
                        allow_proto: bool = False,
                        allow_scripturls: bool = False,
                        allow_singleton: bool = False,
                        allow_this_statements: bool = False,
                        allow_with_statements: bool = False,
                        use_mozilla_extension: bool = False,
                        javascript_strictness: bool_or_str = True,
                        allow_noyield: bool = False,
                        allow_eqnull: bool = False,
                        allow_last_semicolon: bool = False,
                        allow_func_in_loop: bool = False,
                        allow_expr_in_assignments: bool = False,
                        use_es3_array: bool = False,
                        environment_mootools: bool = False,
                        environment_couch: bool = False,
                        environment_jasmine: bool = False,
                        environment_jquery: bool = False,
                        environment_node: bool = False,
                        environment_qunit: bool = False,
                        environment_rhino: bool = False,
                        environment_shelljs: bool = False,
                        environment_prototypejs: bool = False,
                        environment_yui: bool = False,
                        environment_mocha: bool = True,
                        environment_module: bool = False,
                        environment_wsh: bool = False,
                        environment_worker: bool = False,
                        environment_nonstandard: bool = False,
                        environment_browser: bool = True,
                        environment_browserify: bool = False,
                        environment_devel: bool = True,
                        environment_dojo: bool = False,
                        environment_typed: bool = False,
                        environment_phantom: bool = False,
                        max_statements: bool_or_int = False,
                        max_depth: bool_or_int = False,
                        max_parameters: bool_or_int = False,
                        cyclomatic_complexity: bool_or_int = False,
                        allow_variable_shadowing: bool_or_str = False,
                        allow_unused_variables: bool_or_str = False,
                        allow_latedef: bool_or_str = False,
                        es_version: bool_or_int = 5,
                        jshint_config: str = ''):
        """
        :param allow_bitwise_operators:
            Allows the use of bitwise operators.
        :param allow_prototype_overwrite:
            This options allows overwriting prototypes of native objects such
            as ``Array``.
        :param force_braces:
            This option requires you to always put curly braces around blocks
            in loops and conditionals.
        :param allow_type_coercion:
            This options allows the use of ``==`` and ``!=``.
        :param allow_future_identifiers:
            This option allows the use of identifiers which are defined in
            future versions of JavaScript.
        :param allow_typeof:
            This option enables warnings about invalid ``typeof`` operator
            values.
        :param allow_filter_in_forin:
            This option requires all ``for in`` loops to filter object's items.
        :param allow_iterator_property:
            This option suppresses warnings about the ``__iterator__``
            property.
        :param allow_funcscope:
            This option suppresses warnings about declaring variables inside of
            control structures while accessing them later from outside.
        :param allow_argument_caller_and_callee:
            This option allows the use of ``arguments.caller`` and
            ``arguments.callee``.
        :param allow_comma_operator:
            This option allows the use of the comma operator.
        :param allow_non_breaking_whitespace:
            Allows "non-breaking whitespace characters".
        :param allow_constructor_functions:
            Allows the use of constructor functions.
        :param allow_grouping_operator:
            This option allows the use of the grouping operator when it is
            not strictly required.
        :param allow_var_statement:
            Allows the use of the ``var`` statement while declaring a variable.
            Should use ``let`` or ``const`` while it is set to ``False``.
        :param allow_missing_semicolon:
            This option suppresses warnings about missing semicolons.
        :param allow_debugger:
            This option suppresses warnings about the ``debugger`` statements.
        :param allow_assignment_comparisions:
            This option suppresses warnings about the use of assignments in
            cases where comparisons are expected.
        :param allow_eval:
            This options suppresses warnings about the use of ``eval``
            function.
        :param allow_increment:
            This option suppresses warnings about the use of unary increment
            and decrement operators.
        :param allow_proto:
            This option suppresses warnings about the ``__proto__`` property.
        :param allow_scripturls:
            This option suppresses warnings about the use of script-targeted
            URLs.
        :param allow_singleton:
            This option suppresses warnings about constructions like
            ``new function () { ... }`` and ``new Object;`` sometimes used to
            produce singletons.
        :param allow_this_statements:
            This option suppresses warnings about possible strict violations
            when the code is running in strict mode and ``this`` is used in a
            non-constructor function.
        :param allow_with_statements:
            This option suppresses warnings about the use of the ``with``
            statement.
        :param use_mozilla_extension:
            This options tells JSHint that your code uses Mozilla JavaScript
            extensions.
        :param javascript_strictness:
            Determines what sort of strictness to use in the JavaScript code.
            The possible options are:

            - "global" - there must be a ``"use strict";`` at global level
            - "implied" - lint the code as if there is a ``"use strict";``
            - "False" - disable warnings about strict mode
            - "True" - there must be a ``"use strict";`` at function level
        :param allow_noyield:
            This option suppresses warnings about generator functions with no
            ``yield`` statement in them.
        :param allow_eqnull:
            This option suppresses warnings about ``== null`` comparisons.
        :param allow_last_semicolon:
            This option suppresses warnings about missing semicolons for the
            last statement.
        :param allow_func_in_loop:
            This option suppresses warnings about functions inside of loops.
        :param allow_expr_in_assignments:
            This option suppresses warnings about the use of expressions where
            normally assignments or function calls are expected.
        :param use_es3_array:
            This option tells JSHintBear ES3 array elision elements, or empty
            elements are used.
        :param environment_mootools:
            This option defines globals exposed by the Mootools.
        :param environment_couch:
            This option defines globals exposed by CouchDB.
        :param environment_jasmine:
            This option defines globals exposed by Jasmine.
        :param environment_jquery:
            This option defines globals exposed by Jquery.
        :param environment_node:
            This option defines globals exposed by Node.
        :param environment_qunit:
            This option defines globals exposed by Qunit.
        :param environment_rhino:
            This option defines globals exposed when the code is running inside
            rhino runtime environment.
        :param environment_shelljs:
            This option defines globals exposed by the ShellJS.
        :param environment_prototypejs:
            This option defines globals exposed by the Prototype.
        :param environment_yui:
            This option defines globals exposed by the YUI JavaScript
            Framework.
        :param environment_mocha:
            This option defines globals exposed by the "BDD" and "TDD" UIs of
            the Mocha unit testing framework.
        :param environment_module:
            This option informs JSHintBear that the input code describes an
            ECMAScript 6 module.
        :param environment_wsh:
            This option defines globals available when the code is running as a
            script for the Windows Script Host.
        :param environment_worker:
            This option defines globals available when the code is running
            inside of a Web Worker.
        :param environment_nonstandard:
            This option defines non- standard but widely adopted globals such
            as ``escape`` and ``unescape``.
        :param environment_browser:
            This option defines globals exposed by modern browsers.
        :param environment_browserify:
            This option defines globals available when using the Browserify.
        :param environment_devel:
            This option defines globals that are usually used for debugging:
            ``console``, ``alert``, etc.
        :param environment_dojo:
            This option defines globals exposed by the Dojo Toolkit.
        :param environment_typed:
            This option defines globals for typed array constructors.
        :param environment_phantom:
            This option defines globals available when your core is running
            inside of the PhantomJS runtime environment.
        :param max_statements:
            Maximum number of statements allowed per function.
        :param max_depth:
            This option lets you control how nested do you want your blocks to
            be.
        :param max_parameters:
            Maximum number of parameters allowed per function.
        :param cyclomatic_complexity:
            Maximum cyclomatic complexity in the code.
        :param allow_variable_shadowing:
            This option suppresses warnings about variable shadowing i.e.
            declaring a variable that had been already declared somewhere in
            the outer scope.

            - "inner" - check for variables defined in the same scope only
            - "outer" - check for variables defined in outer scopes as well
            - False - same as inner
            - True  - allow variable shadowing
        :param allow_unused_variables:
            Allows when variables are defined but never used. This can be set
            to ""vars"" to only check for variables, not function parameters,
            or ""strict"" to check all variables and parameters.
        :param allow_latedef:
            This option allows the use of a variable before it was defined.
            Setting this option to "nofunc" will allow function declarations to
            be ignored.
        :param es_version:
            This option is used to specify the ECMAScript version to which the
            code must adhere to.
        """
        # Assume that when es_version is bool, it is intended for the
        # deprecated use_es6_version
        if es_version is True:
            es_version = 6
        elif es_version is False:
            es_version = 5
        if not jshint_config:
            options = {
                'bitwise': not allow_bitwise_operators,
                'freeze': not allow_prototype_overwrite,
                'curly': force_braces,
                'eqeqeq': not allow_type_coercion,
                'futurehostile': not allow_future_identifiers,
                'notypeof': not allow_typeof,
                'forin': allow_filter_in_forin,
                'funcscope': allow_funcscope,
                'iterator': not allow_iterator_property,
                'noarg': not allow_argument_caller_and_callee,
                'nocomma': not allow_comma_operator,
                'nonbsp': not allow_non_breaking_whitespace,
                'nonew': not allow_constructor_functions,
                'undef': True,
                'singleGroups': not allow_grouping_operator,
                'varstmt': not allow_var_statement,
                'asi': allow_missing_semicolon,
                'debug': allow_debugger,
                'boss': allow_assignment_comparisions,
                'evil': allow_eval,
                'strict': javascript_strictness,
                'plusplus': allow_increment,
                'proto': allow_proto,
                'scripturl': allow_scripturls,
                'supernew': allow_singleton,
                'validthis': allow_this_statements,
                'withstmt': allow_with_statements,
                'moz': use_mozilla_extension,
                'noyield': allow_noyield,
                'eqnull': allow_eqnull,
                'lastsemic': allow_last_semicolon,
                'loopfunc': allow_func_in_loop,
                'expr': allow_expr_in_assignments,
                'elision': use_es3_array,
                'mootools': environment_mootools,
                'couch': environment_couch,
                'jasmine': environment_jasmine,
                'jquery': environment_jquery,
                'node': environment_node,
                'qunit': environment_qunit,
                'rhino': environment_rhino,
                'shelljs': environment_shelljs,
                'prototypejs': environment_prototypejs,
                'yui': environment_yui,
                'mocha': environment_mocha,
                'module': environment_module,
                'wsh': environment_wsh,
                'worker': environment_worker,
                'nonstandard': environment_nonstandard,
                'browser': environment_browser,
                'browserify': environment_browserify,
                'devel': environment_devel,
                'dojo': environment_dojo,
                'typed': environment_typed,
                'phantom': environment_phantom,
                'maxerr': 99999,
                'maxcomplexity': cyclomatic_complexity,
                'maxdepth': max_depth,
                'maxparams': max_parameters,
                'maxstatements': max_statements,
                'shadow': allow_variable_shadowing,
                'unused': not allow_unused_variables,
                'latedef': allow_latedef,
                'esversion': es_version
            }

            return json.dumps(options)
        else:
            return None

    @staticmethod
    def create_arguments(filename, file, config_file, jshint_config: str = ''):
        """
        :param jshint_config:
            The location of the jshintrc config file. If this option is present
            all the above options are not used. Instead the .jshintrc file is
            used as the configuration file.
        """
        args = ('--verbose', filename, '--config')
        if jshint_config:
            args += (jshint_config, )
        else:
            args += (config_file, )
        return args
Ejemplo n.º 14
0
class WriteGoodLintBear:
    """
    Lints the text files using ``write-good`` for improving proses.

    See <https://github.com/btford/write-good> for more information.
    """
    LANGUAGES = {'Natural Language'}
    REQUIREMENTS = {NpmRequirement('write-good', '0.9.1')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    ASCIINEMA_URL = 'https://asciinema.org/a/80761'
    CAN_DETECT = {'Formatting', 'Grammar'}

    @staticmethod
    @deprecate_settings(allow_passive_voice=('check_passive_voice', negate),
                        allow_so_beginning=('check_so_beginning', negate),
                        allow_adverbs=('check_adverbs', negate),
                        allow_repeated_words=('check_repeated_words', negate),
                        allow_there_is=('check_there_is', negate),
                        allow_ambiguous_words=('check_ambiguos_words', negate),
                        allow_extra_words=('check_extra_words', negate),
                        allow_cliche_phrases=('check_cliche_exists', negate))
    def create_arguments(filename, file, config_file,
                         allow_passive_voice: bool=True,
                         allow_so_beginning: bool=True,
                         allow_adverbs: bool=True,
                         allow_repeated_words: bool=True,
                         allow_there_is: bool=True,
                         allow_ambiguous_words: bool=True,
                         allow_extra_words: bool=True,
                         allow_cliche_phrases: bool=True):
        """
        Using ``False`` will enable the check.

        :param allow_passive_voice:     Allows passive voice.
        :param allow_so_beginning:      Allows ``So`` at the beginning of
                                        the sentence.
        :param allow_adverbs:           Allows adverbs that can weaken the
                                        meaning, such as: ``really``,
                                        ``very``, ``extremely``, etc.
        :param allow_repeated_words:    Allows lexical illusions – cases
                                        where a word is repeated.
        :param allow_there_is:          Allows ``There is`` or ``There are``
                                        at the beginning of the sentence.
        :param allow_ambiguous_words:   Allows ``weasel words`` for example
                                        ``often``, ``probably``
        :param allow_extra_words:       Allows wordy phrases and unnecessary
                                        words.
        :param allow_cliche_phrases:    Allows common cliche phrases in the
                                        sentence.
        """
        arg_map = {
            'allow_passive_voice': '--passive',
            'allow_so_beginning': '--so',
            'allow_adverbs': '--adverb',
            'allow_repeated_words': '--illusion',
            'allow_there_is': '--thereIs',
            'allow_ambiguous_words': '--weasel',
            'allow_extra_words': '--tooWordy',
            'allow_cliche_phrases': '--cliches'
        }
        l = locals()
        args = tuple(arg for key, arg in arg_map.items()
                     if not l[key])
        return args + (filename,)
Ejemplo n.º 15
0
class ESLintBear:
    """
    Check JavaScript and JSX code for style issues and semantic errors.

    Find out more at <http://eslint.org/docs/rules/>.
    """

    LANGUAGES = {"JavaScript", "JSX"}
    REQUIREMENTS = {NpmRequirement('eslint', '2')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    ASCIINEMA_URL = 'https://asciinema.org/a/38739'
    CAN_DETECT = {'Syntax'}
    CAN_FIX = {'Formatting'}

    severity_map = {
        2: RESULT_SEVERITY.MAJOR,
        1: RESULT_SEVERITY.NORMAL,
        0: RESULT_SEVERITY.INFO
    }

    @staticmethod
    def create_arguments(filename, file, config_file, eslint_config: str = ""):
        """
        :param eslint_config: The location of the .eslintrc config file.
        """
        args = '--no-ignore', '--no-color', '-f=json', '--stdin'
        if eslint_config:
            args += ('--config', eslint_config)
        else:
            args += ('--config', config_file)

        return args

    @staticmethod
    def generate_config(filename, file):
        return '{"extends": "eslint:recommended"}'

    def process_output(self, output, filename, file):
        if not file:
            return

        output = json.loads(output)
        lines = "".join(file)

        assert len(output) == 1

        for result in output[0]['messages']:
            if 'fix' not in result:
                diffs = None
            else:
                fix = result['fix']
                start, end = fix['range']
                replacement_text = fix['text']
                new_output = lines[:start] + replacement_text + lines[end:]
                diffs = {
                    filename:
                    Diff.from_string_arrays(lines.splitlines(True),
                                            new_output.splitlines(True))
                }

            origin = ("{class_name} ({rule})".format(
                class_name=type(self).__name__, rule=result['ruleId'])
                      if result['ruleId'] is not None else self)
            yield Result.from_values(
                origin=origin,
                message=result['message'],
                file=filename,
                line=result['line'],
                diffs=diffs,
                severity=self.severity_map[result['severity']])
Ejemplo n.º 16
0
 def test_installed_requirement(self):
     with unittest.mock.patch(
             'coalib.bears.requirements.NpmRequirement.call_without_output',
             return_value=0):
         self.assertTrue(NpmRequirement('some_good_package').is_installed())
Ejemplo n.º 17
0
 def test_not_installed_requirement(self):
     self.assertFalse(NpmRequirement('some_bad_package').is_installed())
Ejemplo n.º 18
0
class MarkdownBear:
    """
    Check and correct Markdown style violations automatically.

    See <https://github.com/wooorm/remark-lint> for details about the tool
    below.
    """

    LANGUAGES = {"Markdown"}
    REQUIREMENTS = {NpmRequirement('remark', '3')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    CAN_FIX = {'Formatting'}

    @staticmethod
    def create_arguments(filename, file, config_file,
                         markdown_bullets: str="-",
                         markdown_closed_headings: bool=False,
                         markdown_setext_headings: bool=False,
                         markdown_emphasis: str="*",
                         markdown_strong: str="*",
                         markdown_encode_entities: bool=False,
                         markdown_codefence: str="`",
                         markdown_fences: bool=True,
                         markdown_list_indent: str="1",
                         markdown_loose_tables: bool=False,
                         markdown_spaced_tables: bool=True,
                         markdown_list_increment: bool=True,
                         markdown_horizontal_rule: str='*',
                         markdown_horizontal_rule_spaces: bool=False,
                         markdown_horizontal_rule_repeat: int=3):
        """
        :param markdown_bullets:
            Character to use for bullets in lists. Can be "-", "*" or "+".
        :param markdown_closed_headings:
            Whether to close Atx headings or not. if true, extra # marks will
            be required after the heading. eg: `## Heading ##`.
        :param markdown_setext_headings:
            Whether to use setext headings. A setext heading uses underlines
            instead of # marks.
        :param markdown_emphasis:
            Character to wrap strong emphasis by. Can be "_" or "*".
        :param markdown_strong:
            Character to wrap slight emphasis by. Can be "_" or "*".
        :param markdown_encode_entities:
            Whether to encode symbols that are not ASCII into special HTML
            characters.
        :param markdown_codefence:
            Used to find which characters to use for code fences. Can be "`" or
            "~".
        :param markdown_fences:
            Use fences for code blocks.
        :param markdown_list_indent:
            Used to find spacing after bullet in lists. Can be "1", "tab" or
            "mixed".

            - "1" - 1 space after bullet.
            - "tab" - Use tab stops to begin a sentence after the bullet.
            - "mixed" - Use "1" when the list item is only 1 line, "tab" if it
              spans multiple.
        :param markdown_loose_tables:
            Whether to use pipes for the outermost borders in a table.
        :param markdown_spaced_tables:
            Whether to add space between pipes in a table.
        :param markdown_list_increment:
            Whether an ordered lists numbers should be incremented.
        :param markdown_horizontal_rule:
            The horizontal rule character. Can be '*', '_' or '-'.
        :param markdown_horizontal_rule_spaces:
            Whether spaces should be added between horizontal rule characters.
        :param markdown_horizontal_rule_repeat:
            The number of times the horizontal rule character will be repeated.
        """
        remark_configs = {
            "bullet": markdown_bullets,                         # - or *
            "closeAtx": markdown_closed_headings,               # Bool
            "setext": markdown_setext_headings,                 # Bool
            "emphasis": markdown_emphasis,                      # char (_ or *)
            "strong": markdown_strong,                          # char (_ or *)
            "entities": markdown_encode_entities,               # Bool
            "fence": markdown_codefence,                        # char (~ or `)
            "fences": markdown_fences,                          # Bool
            "listItemIndent": markdown_list_indent,             # int or "tab"
                                                                # or "mixed"
            "looseTable": markdown_loose_tables,                # Bool
            "spacedTable": markdown_spaced_tables,              # Bool
            "incrementListMarker": markdown_list_increment,     # Bool
            "rule": markdown_horizontal_rule,                   # - or * or _
            "ruleSpaces": markdown_horizontal_rule_spaces,      # Bool
            "ruleRepetition": markdown_horizontal_rule_repeat,  # int
        }

        config_json = json.dumps(remark_configs)
        # Remove { and } as remark adds them on its own
        settings = config_json[1:-1]
        return '--no-color', '--quiet', '--setting', settings
Ejemplo n.º 19
0
class CoffeeLintBear:
    """
    Check CoffeeScript code for a clean and consistent style.

    For more information about coffeelint, visit <http://www.coffeelint.org/>.
    """

    LANGUAGES = {"CoffeeScript"}
    REQUIREMENTS = {NpmRequirement('coffeelint', '1')}
    AUTHORS = {'The coala developers'}
    AUTHORS_EMAILS = {'*****@*****.**'}
    LICENSE = 'AGPL-3.0'
    CAN_DETECT = {'Syntax', 'Formatting', 'Smell', 'Complexity', 'Duplication'}

    severity_map = {'warn': RESULT_SEVERITY.NORMAL,
                    'error': RESULT_SEVERITY.MAJOR,
                    'ignore': RESULT_SEVERITY.INFO}

    @staticmethod
    def create_arguments(filename, file, config_file):
        return '--reporter=raw', '--stdin', '-f', config_file

    @staticmethod
    @deprecate_settings(indent_size='tab_width',
                        allow_increment=(
                            'no_decr_or_incrementation_operators', negate),
                        allow_no_parameters=(
                            'no_empty_parameter_list', negate),
                        allow_empty_functions=('no_empty_functions', negate),
                        allow_this_statements=('no_this', negate),
                        allow_implicit_parentheses=(
                            'no_implicit_parentheses', negate),
                        allow_interpolation_in_single_quotes=(
                            'no_interpolation_in_single_quotes', negate),
                        allow_stand_alone_at_sign=(
                            'no_stand_alone_at_sign', negate),
                        allow_throwing_strings=(
                            'disable_throwing_strings', negate),
                        allow_unnecessary_double_quotes=(
                            'no_unnecessary_double_quotes', negate),
                        allow_bitwise_operators=(
                            'use_english_operator', negate),
                        force_braces='no_implicit_braces')
    def generate_config(filename, file,
                        max_line_length: int=79,
                        max_line_length_affect_comments: bool=True,
                        space_before_and_after_arrow: bool=True,
                        check_braces_spacing: bool=False,
                        braces_spacing_width: int=1,
                        spacing_in_empty_braces: int=0,
                        class_naming_camelCase: bool=True,
                        spaces_before_and_after_colon: bool=False,
                        spaces_before_colon: int=0,
                        spaces_after_colon: int=1,
                        enforce_newline_at_EOF: bool=True,
                        use_spaces: bool=True,
                        indent_size: int=2,
                        number_of_newlines_after_classes: int=2,
                        prohibit_embedding_javascript_snippet: bool=True,
                        force_braces: bool=False,
                        allow_implicit_parentheses: bool=True,
                        allow_interpolation_in_single_quotes: bool=True,
                        allow_stand_alone_at_sign: bool=False,
                        allow_throwing_strings: bool=False,
                        allow_trailing_semicolons: bool=False,
                        allow_trailing_whitespaces: bool=False,
                        allow_unnecessary_double_quotes: bool=True,
                        allow_bitwise_operators: bool=True,
                        spaces_around_operators: bool=True,
                        space_after_comma: bool=True,
                        cyclomatic_complexity: int=0,
                        prevent_duplicate_keys: bool=True,
                        consistent_line_endings_style: str='',
                        allow_this_statements: bool=True,
                        allow_increment: bool=True,
                        allow_no_parameters: bool=True,
                        allow_empty_functions: bool=False,
                        enforce_parentheses_on_non_empty_constructors:
                            bool=True
                        ):
        """
        :param max_line_length:
            Maximum number of characters per line.
        :param max_line_length_affect_comments:
            Determines if ``max_line_length`` should also affects comments or
            not.
        :param space_before_and_after_arrow:
            Determines if spaces should be used before and after the arrow.
        :param check_braces_spacing:
            Checks if proper spacing is used inside curly braces.
        :param braces_spacing_width:
            Determines the number of blank spaces after the opening ``{`` and
            before the closing brace ``}`` given that there is something within
            the braces.
        :param spacing_in_empty_braces:
            Determines the number of blank spaces after the opening ``{`` and
            before the closing brace ``}`` given empty content.
        :param class_naming_camelCase:
            Checks whether the classes name should be in camel-case or not.
        :param spaces_before_and_after_colon:
            Checks the number of spaces before and after colon.
        :param spaces_before_colon:
            Determines the number of blank spaces before colon when
            ``spaces_before_and_after_colon == True``.
        :param spaces_after_colon:
            Determines the number of space after colon when
            ``spaces_before_and_after_colon == True``.
        :param enforce_newline_at_EOF:
            Checks if the file ends with a single newline.
        :param use_spaces:
            Forbids tabs in indentation and applies two spaces for this
            purpose.
        :param indent_size:
            Number of spaces per indentation level.
        :param number_of_newlines_after_classes:
            Determines the number of newlines that separate the class
            definition and the rest of the code.
        :param prohibit_embedding_javascript_snippet:
            Prevents some JavaScript elements like ``eval`` to affect
            CoffeeScript.
        :param force_braces:
            Prohibits implicit braces when declaring object literals.

            Example: If ``force_braces = True`` then
            ```
            1:2, 3:4
            ```
            is prohibited, whereas
            ```
            {1:2, 3:4}
            ```
            is accepted.
        :param allow_implicit_parentheses:
            Allows implicit parentheses.
        :param allow_interpolation_in_single_quotes:
            Allows string interpolation in a single quoted string.

            Example: If ``allow_interpolation_in_single_quotes = False`` then
            ```
            f = '#{bar}'
            ```
            is prohibited, whereas
            ```
            f = "#{bar}"
            ```
            is correct.
        :param allow_stand_alone_at_sign:
            Allows the use of stand alone  ``@``.

            Example: If ``allow_stand_alone_at_sign = False``
            ```
            @ notok
            not(@).ok
            @::
            ```
            are prohibited, whereas
            ```
            @alright
            @(fn)
            @ok()
            @[ok]
            @ok()
            ```
            are accepted.
        :param allow_throwing_strings:
            Allows throwing string literals or interpolation.

            Example: If ``allow_throwing_strings = False``
            ```
            throw 'my error'
            throw "#{1234}"
            ```
            will not be permitted.
        :param allow_trailing_semicolons:
            Prohibits trailing semicolons when ``False`` since they are
            not useful. The semicolon is meaningful only if there's another
            instruction on the same line.

            Example: If ``allow_trailing_semicolon = False``
            ```
            x = '1234'; console.log(x)
            ```
            Here the semicolon is meaningful.
            ```
            alert('end of line');
            ```
            This semicolon is redundant.
        :param allow_trailing_whitespaces:
            Checks whether to allow trailing whitespacess in the code or not.
        :param allow_unnecessary_double_quotes:
            Allows enclosing strings in double quotes.
        :param allow_bitwise_operators:
            Determines if ``and``, ``or``, ``is`` and ``isnt`` should be used
            instead of ``&&``, ``||``, ``==`` and ``!=``.
        :param spaces_around_operators:
            Enforces that operators have spaces around them.
        :param space_after_comma:
            Checks if there is a blank space after commas.
        :param cyclomatic_complexity:
            Maximum cyclomatic complexity of the file.
        :param prevent_duplicate_keys:
            Prevents defining duplicate keys in object literals and classes.
        :param enforce_parentheses_on_non_empty_constructors:
            Requires constructors with parameters to include parentheses.

            Example:
            ```
            class Foo
            # Warn about missing parentheses here
            a = new Foo
            b = new bar.foo.Foo
            # The parentheses make it clear no parameters are intended
            c = new Foo()
            d = new bar.foo.Foo()
            e = new Foo 1, 2
            f = new bar.foo.Foo 1, 2
            ```
        :param consistent_line_endings_style:
            The option to ``line_endings``, its value is either ``unix`` or
            ``windows``.
        :param allow_this_statements:
            Allows the use of ``this``. ``@`` should be used if ``False``.
        :param allow_increment:
            Allows the use of increment and decrement arithmetic operators.
        :param allow_no_parameters:
            Allows empty parameter lists in function definitions.
        :param allow_empty_functions:
            Allows declaring empty functions.
        """
        coffee_configs = {"max_line_length":
                          {"value": max_line_length,
                           "level": "error",
                           "limitComments":
                               max_line_length_affect_comments}}
        coffee_configs["arrow_spacing"] = (
            {"level": "error" if space_before_and_after_arrow else "ignore"})
        if check_braces_spacing:
            coffee_configs["braces_spacing"] = (
                {"level": "error",
                 "spaces": braces_spacing_width,
                 "empty_object_spaces": spacing_in_empty_braces})
        if class_naming_camelCase:
            coffee_configs["camel_case_classes"] = {"level": "error"}
        if spaces_before_and_after_colon:
            coffee_configs["colon_assignment_spacing"] = (
                {"level": "error",
                 "spacing": {"left": spaces_before_colon,
                             "right": spaces_after_colon}})
        coffee_configs["eol_last"] = (
            {"level": "error" if enforce_newline_at_EOF else "ignore"})
        coffee_configs["newlines_after_classes"] = (
            {"value": number_of_newlines_after_classes,
             "level": "error"})
        coffee_configs["no_backticks"] = (
            {"level": "error"
                if prohibit_embedding_javascript_snippet else "ignore"})
        if force_braces:
            coffee_configs["no_implicit_braces"] = (
                {"level": "error", "strict": True})
        if not allow_implicit_parentheses:
            coffee_configs["no_implicit_parens"] = (
                {"strict": True, "level": "error"})
        coffee_configs["no_interpolation_in_single_quotes"] = (
            {"level": "error"
                if not allow_interpolation_in_single_quotes else "ignore"})
        if not allow_stand_alone_at_sign:
            coffee_configs["no_stand_alone_at"] = {"level": "error"}
        if use_spaces:
            coffee_configs["no_tabs"] = {"level": "error"}
        coffee_configs["indentation"] = (
            {"value": indent_size, "level": "error"})
        coffee_configs["no_throwing_strings"] = (
            {"level": "error" if not allow_throwing_strings else "ignore"})
        coffee_configs["no_trailing_semicolons"] = (
            {"level": "error" if not allow_trailing_semicolons else "ignore"})
        if not allow_trailing_whitespaces:
            coffee_configs["no_trailing_whitespace"] = (
                {"level": "error",
                 "allowed_in_comments": True,
                 "allowed_in_empty_lines": True})
        if not allow_unnecessary_double_quotes:
            coffee_configs["no_unnecessary_double_quotes"] = {"level": "error"}
        if not allow_bitwise_operators:
            coffee_configs["prefer_english_operator"] = (
                {"level": "error", "doubleNotLevel": "ignore"})
        if spaces_around_operators:
            coffee_configs["space_operators"] = {"level": "error"}
        if space_after_comma:
            coffee_configs["spacing_after_comma"] = {"level": "warn"}
        coffee_configs["cyclomatic_complexity"] = (
                {"value": cyclomatic_complexity,
                 "level": ("error" if cyclomatic_complexity else 'ignore')})
        coffee_configs["duplicate_key"] = (
            {"level": "error" if prevent_duplicate_keys else "ignore"})
        if enforce_parentheses_on_non_empty_constructors:
            coffee_configs["non_empty_constructor_needs_parens"] = (
                {"level": "error"})
        if consistent_line_endings_style:
            coffee_configs["line_endings"] = (
                {"level": "error", "value": consistent_line_endings_style})
        if not allow_this_statements:
            coffee_configs["no_this"] = {"level": "error"}
        if not allow_increment:
            coffee_configs["no_plusplus"] = {"level": "error"}
        coffee_configs["no_empty_param_list"] = (
            {"level": "error" if not allow_no_parameters else "ignore"})
        coffee_configs["no_empty_functions"] = (
            {"level": "error" if not allow_empty_functions else "ignore"})

        return json.dumps(coffee_configs)

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

        assert len(output) == 1, (
            "More than 1 file parsed, something went wrong")
        for item in tuple(output.values())[0]:
            yield Result.from_values(
                origin="{} ({})".format(self.name, item['rule']),
                message=item['message'],
                file=filename,
                line=item.get('lineNumber', None),
                end_line=item.get('lineNumberEnd', None),
                severity=self.severity_map[item['level']],
                additional_info=item.get('description',
                                         item.get('context', "")))
Ejemplo n.º 20
0
 def test_installed_requirement(self):
     self.assertTrue(NpmRequirement('npm').is_installed())