From 07c5b4177c0d9118be992cabb3c169ae5b9941fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Verg=C3=A9?= Date: Tue, 12 Jan 2016 23:20:33 +0100 Subject: [PATCH] Rewrite syntax errors handling and test them If a syntax errors occurs at the same place than a regular yamllint rule error, only the yamllint one is issued. --- tests/rules/test_document_end.py | 6 ---- tests/rules/test_syntax_error.py | 31 +++++++++++++++++++++ yamllint/__init__.py | 47 +++++++++++++++++++++++++------- yamllint/parser.py | 10 ------- 4 files changed, 68 insertions(+), 26 deletions(-) create mode 100644 tests/rules/test_syntax_error.py diff --git a/tests/rules/test_document_end.py b/tests/rules/test_document_end.py index 4d1305b..04389af 100644 --- a/tests/rules/test_document_end.py +++ b/tests/rules/test_document_end.py @@ -64,12 +64,6 @@ class DocumentEndTestCase(RuleTestCase): '---\n' 'third: document\n' '...\n', conf) - self.check('first: document\n' - '...\n' - 'second: document\n' - '...\n' - 'third: document\n' - '...\n', conf) self.check('---\n' 'first: document\n' '...\n' diff --git a/tests/rules/test_syntax_error.py b/tests/rules/test_syntax_error.py new file mode 100644 index 0000000..d47eca2 --- /dev/null +++ b/tests/rules/test_syntax_error.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016 Adrien Vergé +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from tests.rules.common import RuleTestCase + + +class YamlLintTestCase(RuleTestCase): + rule_id = None # syntax error + + def test_lint(self): + self.check('---\n' + 'this is not: valid: YAML\n', None, problem=(2, 19)) + self.check('---\n' + 'this is: valid YAML\n' + '\n' + 'this is an error: [\n' + '\n' + '...\n', None, problem=(6, 1)) diff --git a/yamllint/__init__.py b/yamllint/__init__.py index d8b8edc..5d5bb96 100644 --- a/yamllint/__init__.py +++ b/yamllint/__init__.py @@ -14,7 +14,10 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import yaml + from yamllint import config +from yamllint.errors import LintProblem from yamllint import parser @@ -28,23 +31,14 @@ __license__ = 'GPLv3' __version__ = APP_VERSION -def _lint(buffer, conf): +def get_costemic_problems(buffer, conf): rules = config.get_enabled_rules(conf) # Split token rules from line rules token_rules = [r for r in rules if r.TYPE == 'token'] line_rules = [r for r in rules if r.TYPE == 'line'] - # If the document contains a syntax error, save it and yield it at the - # right line - syntax_error = parser.get_syntax_error(buffer) - for elem in parser.token_or_line_generator(buffer): - if syntax_error and syntax_error.line <= elem.line_no: - syntax_error.level = 'error' - yield syntax_error - syntax_error = None - if isinstance(elem, parser.Token): for rule in token_rules: rule_conf = conf[rule.ID] @@ -62,6 +56,39 @@ def _lint(buffer, conf): yield problem +def get_syntax_error(buffer): + try: + list(yaml.safe_load_all(buffer)) + except yaml.error.MarkedYAMLError as e: + problem = LintProblem(e.problem_mark.line + 1, + e.problem_mark.column + 1, + 'syntax error: ' + e.problem) + problem.level = 'error' + return problem + + +def _lint(buffer, conf): + # If the document contains a syntax error, save it and yield it at the + # right line + syntax_error = get_syntax_error(buffer) + + for problem in get_costemic_problems(buffer, conf): + # Insert the syntax error (if any) at the right place... + if (syntax_error and syntax_error.line <= problem.line and + syntax_error.column <= problem.column): + # ... unless there is already a yamllint error, in which case the + # syntax error is probably redundant. + if (syntax_error.line != problem.line or + syntax_error.column != problem.column): + yield syntax_error + syntax_error = None + + yield problem + + if syntax_error: + yield syntax_error + + def lint(input, conf): """Lints a YAML source. diff --git a/yamllint/parser.py b/yamllint/parser.py index 2265cc0..57fc934 100644 --- a/yamllint/parser.py +++ b/yamllint/parser.py @@ -16,8 +16,6 @@ import yaml -from yamllint.errors import LintProblem - class Line(object): def __init__(self, line_no, buffer, start, end): @@ -85,11 +83,3 @@ def token_or_line_generator(buffer): else: yield token token = next(token_gen, None) - - -def get_syntax_error(buffer): - try: - yaml.safe_load_all(buffer) - except yaml.error.MarkedYAMLError as e: - return LintProblem(e.problem_mark.line + 1, e.problem_mark.column + 1, - 'syntax error: ' + e.problem)