From e28fe3f539ce15b2022d2119ace36a2ce4890e2d Mon Sep 17 00:00:00 2001 From: kimzuni Date: Thu, 18 Dec 2025 18:16:14 +0900 Subject: [PATCH 1/2] context: Support usage in line-type rules --- yamllint/linter.py | 4 +++- yamllint/rules/empty_lines.py | 2 +- yamllint/rules/line_length.py | 2 +- yamllint/rules/new_line_at_end_of_file.py | 2 +- yamllint/rules/new_lines.py | 2 +- yamllint/rules/trailing_spaces.py | 2 +- 6 files changed, 8 insertions(+), 6 deletions(-) diff --git a/yamllint/linter.py b/yamllint/linter.py index 2230a6002..452a475ab 100644 --- a/yamllint/linter.py +++ b/yamllint/linter.py @@ -76,6 +76,8 @@ def get_cosmetic_problems(buffer, conf, filepath): context = {} for rule in token_rules: context[rule.ID] = {} + for rule in line_rules: + context[rule.ID] = {} class DisableDirective: def __init__(self): @@ -156,7 +158,7 @@ def process_comment(self, comment): elif isinstance(elem, parser.Line): for rule in line_rules: rule_conf = conf.rules[rule.ID] - for problem in rule.check(rule_conf, elem): + for problem in rule.check(rule_conf, elem, context[rule.ID]): problem.rule = rule.ID problem.level = rule_conf['level'] cache.append(problem) diff --git a/yamllint/rules/empty_lines.py b/yamllint/rules/empty_lines.py index 7ccbedf02..f2ea144c8 100644 --- a/yamllint/rules/empty_lines.py +++ b/yamllint/rules/empty_lines.py @@ -71,7 +71,7 @@ 'max-end': 0} -def check(conf, line): +def check(conf, line, context): if line.start == line.end and line.end < len(line.buffer): # Only alert on the last blank line of a series if (line.end + 2 <= len(line.buffer) and diff --git a/yamllint/rules/line_length.py b/yamllint/rules/line_length.py index 49ca45858..a7b90a811 100644 --- a/yamllint/rules/line_length.py +++ b/yamllint/rules/line_length.py @@ -128,7 +128,7 @@ def check_inline_mapping(line): return False -def check(conf, line): +def check(conf, line, context): max_length = conf['max'] length = line.end - line.start if length > max_length: diff --git a/yamllint/rules/new_line_at_end_of_file.py b/yamllint/rules/new_line_at_end_of_file.py index f49edb956..4396e9300 100644 --- a/yamllint/rules/new_line_at_end_of_file.py +++ b/yamllint/rules/new_line_at_end_of_file.py @@ -29,7 +29,7 @@ TYPE = 'line' -def check(conf, line): +def check(conf, line, context): if line.end == len(line.buffer) and line.end > line.start: yield LintProblem(line.line_no, line.end - line.start + 1, 'no new line character at the end of file') diff --git a/yamllint/rules/new_lines.py b/yamllint/rules/new_lines.py index 2ee5512a5..b60e69b64 100644 --- a/yamllint/rules/new_lines.py +++ b/yamllint/rules/new_lines.py @@ -43,7 +43,7 @@ DEFAULT = {'type': 'unix'} -def check(conf, line): +def check(conf, line, context): if conf['type'] == 'unix': newline_char = '\n' elif conf['type'] == 'platform': diff --git a/yamllint/rules/trailing_spaces.py b/yamllint/rules/trailing_spaces.py index b1906005f..984fc4ef6 100644 --- a/yamllint/rules/trailing_spaces.py +++ b/yamllint/rules/trailing_spaces.py @@ -44,7 +44,7 @@ TYPE = 'line' -def check(conf, line): +def check(conf, line, context): if line.end == 0: return From 9190237379dcf1a245f25e3abbbdbf57f660d87f Mon Sep 17 00:00:00 2001 From: kimzuni Date: Thu, 18 Dec 2025 18:21:34 +0900 Subject: [PATCH 2/2] new-lines: stop after first detected problem Previously, the rule only checked the first line. It now checks all lines, but stops further checks once the first problem is detected, ensuring that only a single problem is reported per file. --- tests/rules/test_new_lines.py | 16 ++++------------ yamllint/rules/new_lines.py | 8 ++++++-- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/tests/rules/test_new_lines.py b/tests/rules/test_new_lines.py index 80334eade..82b80160c 100644 --- a/tests/rules/test_new_lines.py +++ b/tests/rules/test_new_lines.py @@ -74,12 +74,8 @@ def test_platform_type(self): self.check('---\ntext\n', conf) self.check('---\r\ntext\r\n', conf, problem=(1, 4)) self.check('---\r\ntext\n', conf, problem=(1, 4)) - # FIXME: the following tests currently don't work - # because only the first line is checked for line-endings - # see: issue #475 - # --- - # self.check('---\ntext\r\nfoo\n', conf, problem=(2, 4)) - # self.check('---\ntext\r\n', conf, problem=(2, 4)) + self.check('---\ntext\r\nfoo\n', conf, problem=(2, 5)) + self.check('---\ntext\r\n', conf, problem=(2, 5)) # mock the Windows new-line-character with mock.patch('yamllint.rules.new_lines.linesep', '\r\n'): @@ -88,9 +84,5 @@ def test_platform_type(self): self.check('---\r\ntext\r\n', conf) self.check('---\ntext\n', conf, problem=(1, 4)) self.check('---\ntext\r\n', conf, problem=(1, 4)) - # FIXME: the following tests currently don't work - # because only the first line is checked for line-endings - # see: issue #475 - # --- - # self.check('---\r\ntext\nfoo\r\n', conf, problem=(2, 4)) - # self.check('---\r\ntext\n', conf, problem=(2, 4)) + self.check('---\r\ntext\nfoo\r\n', conf, problem=(2, 5)) + self.check('---\r\ntext\n', conf, problem=(2, 5)) diff --git a/yamllint/rules/new_lines.py b/yamllint/rules/new_lines.py index b60e69b64..6257154ac 100644 --- a/yamllint/rules/new_lines.py +++ b/yamllint/rules/new_lines.py @@ -44,6 +44,9 @@ def check(conf, line, context): + if context.get("has_shown_problem") is True: + return + if conf['type'] == 'unix': newline_char = '\n' elif conf['type'] == 'platform': @@ -51,8 +54,9 @@ def check(conf, line, context): elif conf['type'] == 'dos': newline_char = '\r\n' - if line.start == 0 and len(line.buffer) > line.end: + if len(line.buffer) > line.end: if line.buffer[line.end:line.end + len(newline_char)] != newline_char: + context["has_shown_problem"] = True c = repr(newline_char).strip('\'') - yield LintProblem(1, line.end - line.start + 1, + yield LintProblem(line.line_no, line.end - line.start + 1, f'wrong new line character: expected {c}')