예제 #1
0
class ProhibitCommandRelyOnUser(AbstractPolicy):
    description = 'Avoid commands that rely on user settings'
    reference = get_reference_source('FRAGILE')
    level = Level.WARNING

    def listen_node_types(self):
        return [NodeType.EXCMD]

    def is_valid(self, node, lint_context):
        """ Whether the specified node is valid.

        This policy prohibit following commands:
         - normal without !
         - substitute
        """

        ea = node['ea']
        command = ea['cmd'].get('name', None)

        # It seems line jump command
        if command is None:
            return True

        is_prohibited_command = command in ProhibitedCommands
        if is_prohibited_command:
            return False

        should_be_with_bang = command in CommandsShouldBeWithBang
        if not should_be_with_bang:
            return True

        is_bang = ea.get('forceit', 0) == 1
        return is_bang
예제 #2
0
class ProhibitEqualTildeOperator(AbstractPolicy):
    level = Level.WARNING
    description = 'Use the =~# or =~? operator families over the =~ family.'
    reference = get_reference_source('MATCHING')

    def listen_node_types(self):
        return [
            NodeType.EQUAL,
            NodeType.NEQUAL,
            NodeType.GREATER,
            NodeType.GEQUAL,
            NodeType.SMALLER,
            NodeType.SEQUAL,
            NodeType.MATCH,
            NodeType.NOMATCH,
            NodeType.IS,
            NodeType.ISNOT,
        ]

    def is_valid(self, node, lint_context):
        """ Whether the specified node is valid to the policy.

        In this policy, comparing between a string and any value by
        'ignorecase'-sensitive is invalid. This policy can detect following
        script: variable =~ '1'

        But detecting exactly string comparison without evaluation is very hard.
        So this policy often get false-positive/negative results.
            False-positive case is: '1' =~ 1
            False-negative case is: ('1') =~ 1
        """
        node_type = NodeType(node['type'])

        left_type = NodeType(node['left']['type'])
        right_type = NodeType(node['right']['type'])

        is_like_string_comparison = left_type is NodeType.STRING \
            or right_type is NodeType.STRING

        is_valid = not is_like_string_comparison

        if not is_valid:
            self._make_description(node_type)

        return is_valid

    def _make_description(self, node_type):
        good_examples = [
            '`' + op + '`' for op in GoodStringComparisonOperators[node_type]
        ]
        formatted_good_examples = ' or '.join(good_examples)

        bad_example = BadStringComparisonOperators[node_type]

        params = {
            'good_example': formatted_good_examples,
            'bad_example': bad_example,
        }
        self.description = ('Use robust operators {good_example} '
                            'instead of `{bad_example}`').format(**params)
class ProhibitUnnecessaryDoubleQuote(AbstractPolicy):
    description = 'Prefer single quoted strings'
    reference = get_reference_source('STRINGS')
    level = Level.WARNING

    def listen_node_types(self):
        return [NodeType.STRING]

    def is_valid(self, node, lint_context):
        """ Whether the specified node is valid.

        In this policy, valid node is only 3 cases;
        - single quoted
        - double quoted, but including a special char
        - double quoted inside single quoted

        See `:help expr-string`. """

        value = node['value']

        is_double_quoted = value[0] == '"'
        if not is_double_quoted:
            return True

        has_escaped_char = _special_char_matcher.search(value) is not None

        if has_escaped_char:
            return True

        return is_on_string_expr_context(node)
class ProhibitCommandWithUnintendedSideEffect(AbstractPolicy):
    level = Level.WARNING
    description = 'Do not use a command that has unintended side effects'
    reference = get_reference_source('DANGEROUS')

    def listen_node_types(self):
        return [
            NodeType.EXCMD,
        ]

    def is_valid(self, node, lint_context):
        """ Whether the specified node is valid to the policy.
        This policy prohibit using `:s[ubstitute]` family.
        """

        command = node['ea']['cmd'].get('name', None)
        is_prohibited_command = any(pattern == command
                                    for pattern in PROHIBITED_COMMAND_PATTERNS)

        return not is_prohibited_command
class ProhibitNoAbortFunction(AbstractPolicy):
    description = 'Use the abort attribute and ! for functions in autoload'
    reference = get_reference_source('FUNCTIONS')
    level = Level.WARNING

    def listen_node_types(self):
        return [NodeType.FUNCTION]

    def is_valid(self, node, lint_context):
        """ Whether the specified node is valid.

        This policy prohibits functions in autoload that have no 'abort' or bang
        """

        if 'autoload' not in lint_context['lint_target'].path.parts:
            return True

        has_bang = node['ea']['forceit'] != 0
        has_abort = node['attr']['abort'] != 0

        return has_bang and has_abort
 def __init__(self):
     super(ProhibitCommandWithUnintendedSideEffect, self).__init__()
     self.level = Level.WARNING
     self.description = 'Do not use the command that has unintended side effect'
     self.reference = get_reference_source('DANGEROUS')
 def __init__(self):
     super(ProhibitEqualTildeOperator, self).__init__()
     self.level = Level.WARNING
     self.description = 'Use the =~# or =~? operator families over the =~ family.'
     self.reference = get_reference_source('MATCHING')
    def test_get_reference_source(self):
        actual_ref_source = get_reference_source('STRINGS')
        expected_ref_source = 'Google VimScript Style Guide (Strings)'

        self.assertEqual(actual_ref_source, expected_ref_source)
예제 #9
0
 def __init__(self):
     super(ProhibitCommandRelyOnUser, self).__init__()
     self.description = 'Avoid commands that rely on user settings'
     self.reference = get_reference_source('FRAGILE')
     self.level = Level.WARNING
예제 #10
0
 def __init__(self):
     super(ProhibitCommandRelyOnUser, self).__init__()
     self.description = 'Avoid commands that rely on user settings'
     self.reference = get_reference_source('FRAGILE')
     self.level = Level.WARNING
예제 #11
0
    def test_get_reference_source(self):
        actual_ref_source = get_reference_source('STRINGS')
        expected_ref_source = 'Google VimScript Style Guide (Strings)'

        self.assertEqual(actual_ref_source, expected_ref_source)
예제 #12
0
 def __init__(self):
     super(ProhibitNoAbortFunction, self).__init__()
     self.description = 'Use abort attribute for functions in autoload/'
     self.reference = get_reference_source('FUNCTIONS')
     self.level = Level.WARNING
예제 #13
0
 def __init__(self):
     super(ProhibitEqualTildeOperator, self).__init__()
     self.level = Level.WARNING
     self.description = 'Use the =~# or =~? operator families over the =~ family.'
     self.reference = get_reference_source('MATCHING')
예제 #14
0
 def __init__(self):
     super(ProhibitCommandWithUnintendedSideEffect, self).__init__()
     self.level = Level.WARNING
     self.description = 'Do not use a command that has unintended side effects'
     self.reference = get_reference_source('DANGEROUS')
예제 #15
0
 def __init__(self):
     super(ProhibitCommandRelyOnUser, self).__init__()
     self.description = 'Prefer single quoted strings'
     self.reference = get_reference_source('FRAGILE')
     self.level = Level.WARNING
예제 #16
0
 def __init__(self):
     super(ProhibitUnnecessaryDoubleQuote, self).__init__()
     self.description = 'Prefer single quoted strings'
     self.reference = get_reference_source('STRINGS')
     self.level = Level.WARNING
 def __init__(self):
     super(ProhibitNoAbortFunction, self).__init__()
     self.description = 'Use the abort attribute for functions in autoload'
     self.reference = get_reference_source('FUNCTIONS')
     self.level = Level.WARNING
예제 #18
0
 def __init__(self):
     super(ProhibitCommandRelyOnUser, self).__init__()
     self.description = 'Prefer single quoted strings'
     self.reference = get_reference_source('FRAGILE')
     self.level = Level.WARNING