def find_block_end(node):
        """
            Find where the keyword/test case/block ends. If there are only comments and new lines left, the
            first comment that starts from col 1 is considered outside your block::

                Keyword
                    Line
                    # comment
                    Other Line
                   # comment belonging to Keyword

                # This should not belong to Keyword
                  # Since there was comment starting from col 1, this comment is also outside block
        """
        for index, child in reversed(list(enumerate(node.body))):
            node_type = getattr(child, 'type', '')
            if not node_type:
                return len(node.body) - 1
            if node_type not in (Token.COMMENT, Token.EOL):
                break
        else:
            return len(node.body) - 1
        for block_index, child in enumerate(node.body[index + 1:]):
            if getattr(child, 'type',
                       'invalid') == Token.COMMENT and token_col(
                           child, Token.COMMENT) == 1:
                return block_index + index + 1
        return len(node.body) - 1
 def check_standalone_comments_indent(self, node):
     for child in node.body:
         if getattr(child, 'type', '') == Token.COMMENT and \
                 getattr(child, 'tokens', None) and child.tokens[0].type == Token.SEPARATOR:
             self.report("uneven-indent",
                         'over',
                         node=child,
                         col=token_col(child, Token.COMMENT))
     self.generic_visit(node)
Beispiel #3
0
 def check_statement_in_loop(self, node, token_type):
     if self.loops or node.errors and f"{token_type} can only be used inside a loop." not in node.errors:
         return
     self.report(
         "statement-outside-loop",
         name=token_type,
         statement_type="statement",
         node=node,
         col=token_col(node, token_type),
     )
 def check_bdd_keywords(self, keyword_name, node):
     if keyword_name.lower() not in self.bdd or isinstance(node, Keyword):
         return
     arg = node.get_token(Token.ARGUMENT)
     suffix = f". Use one space between: '{keyword_name.title()} {arg.value}'" if arg else ""
     col = token_col(node, Token.NAME, Token.KEYWORD)
     self.report("bdd-without-keyword-call",
                 keyword_name=keyword_name,
                 error_msg=suffix,
                 node=node,
                 col=col)
    def validate_standalone_comments(self, comments_and_eols):
        """
        Report any comment that does not start from col 1.

        :param comments_and_eols: list of comments and empty lines (outside keyword and test case definitions)
        """
        for child in comments_and_eols:
            if getattr(child, 'type', 'invalid') != Token.COMMENT:
                continue
            col = token_col(child, Token.COMMENT)
            if col != 1:
                self.report('uneven-indent', 'over', node=child, col=col)
 def visit_Return(self, node):  # noqa
     """For RETURN use visit_ReturnStatement - visit_Return will most likely visit RETURN in the future"""
     if ROBOT_VERSION.major < 5:
         return
     self.report(
         "deprecated-statement",
         statement_name="[Return]",
         alternative="RETURN",
         node=node,
         col=token_col(node, Token.RETURN),
         version="5.*",
     )
 def check_standalone_comments_indent(self, node):
     # comments before first test case / keyword
     for child in node.body:
         if (getattr(child, "type", "") == Token.COMMENT
                 and getattr(child, "tokens", None)
                 and child.tokens[0].type == Token.SEPARATOR):
             self.report(
                 "uneven-indent",
                 over_or_under="over",
                 node=child,
                 col=token_col(child, Token.COMMENT),
             )
     self.generic_visit(node)
 def check_if_keyword_is_deprecated(self, keyword_name, node):
     normalized_keyword_name = normalize_robot_name(
         keyword_name, remove_prefix="builtin.")
     deprecated_statements = self.deprecated_keywords.get(
         ROBOT_VERSION.major, {})
     if normalized_keyword_name in deprecated_statements:
         alternative = deprecated_statements[normalized_keyword_name]
         col = token_col(node, Token.NAME, Token.KEYWORD)
         self.report(
             "deprecated-statement",
             statement_name=keyword_name,
             alternative=alternative,
             node=node,
             col=col,
             version=f"{ROBOT_VERSION.major}.*",
         )
 def handle_error(self, node, error, error_index=0):  # noqa
     if not error:
         return
     if any(should_ignore in error for should_ignore in self.ignore_errors):
         return
     if "Invalid argument syntax" in error:
         self.handle_invalid_syntax(node, error)
     elif "Non-existing setting" in error:
         self.handle_invalid_setting(node, error)
     elif "Invalid variable name" in error:
         self.handle_invalid_variable(node, error)
     elif "RETURN can only be used inside" in error:
         self.report("return-in-test-case", node=node, col=token_col(node, "RETURN STATEMENT"))
     elif "IF" in error or ("ELSE" in error and If and isinstance(self.in_block, If)):
         self.handle_invalid_block(node, error, "invalid-if")
     elif "FOR loop" in error:
         self.handle_invalid_block(node, error, "invalid-for-loop")
     elif "Non-default argument after default arguments" in error or "Only last argument can be kwargs" in error:
         self.handle_positional_after_named(node, error_index)
     elif "is allowed only once. Only the first value is used" in error:
         return
     else:
         error = error.replace("\n   ", "")
         self.report("parsing-error", error_msg=error, node=node)