From f9ec407bf0d6de0249737c4b1c2f7cdc7cd220a2 Mon Sep 17 00:00:00 2001 From: Ryan Chou <88779759+ryanchou1994@users.noreply.github.com> Date: Mon, 21 Sep 2026 01:46:31 +0800 Subject: [PATCH] Clamp Flake8 diagnostic columns to nonnegative positions --- pylsp/plugins/flake8_lint.py | 3 ++- test/plugins/test_flake8_lint.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/pylsp/plugins/flake8_lint.py b/pylsp/plugins/flake8_lint.py index b0a71b88..93161c3a 100644 --- a/pylsp/plugins/flake8_lint.py +++ b/pylsp/plugins/flake8_lint.py @@ -223,7 +223,8 @@ def parse_stdout(source, stdout): _, line, character, code, msg = parsed_line line = int(line) - 1 - character = int(character) - 1 + # Some plugins report column zero when no precise column is available. + character = max(0, int(character) - 1) # show also the code in message msg = code + " " + msg severity = lsp.DiagnosticSeverity.Warning diff --git a/test/plugins/test_flake8_lint.py b/test/plugins/test_flake8_lint.py index ad1dc4ff..b19c8ba8 100644 --- a/test/plugins/test_flake8_lint.py +++ b/test/plugins/test_flake8_lint.py @@ -6,6 +6,8 @@ from textwrap import dedent from unittest.mock import patch +import pytest + from pylsp import lsp, uris from pylsp.plugins import flake8_lint from pylsp.workspace import Document @@ -60,6 +62,33 @@ def test_flake8_lint(workspace) -> None: os.remove(name) +@pytest.mark.parametrize( + "line, column, expected_character", + [ + (" # comment", 0, 0), + ("", 0, 0), + (" # comment", 1, 0), + (" # comment", 5, 4), + ], +) +def test_flake8_diagnostic_columns(workspace, line, column, expected_character) -> None: + source = f"def myfun():\n{line}\n pass\n" + doc = Document("", workspace, source) + output = ( + f"stdin:2:{column}: ANN201 Missing return type annotation for public function\n" + ) + + with patch("pylsp.plugins.flake8_lint.run_flake8", return_value=output): + diagnostics = flake8_lint.pylsp_lint(workspace, doc) + + assert len(diagnostics) == 1 + assert diagnostics[0]["range"] == { + "start": {"line": 1, "character": expected_character}, + "end": {"line": 1, "character": len(line) + 1}, + } + assert diagnostics[0]["code"] == "ANN201" + + def test_flake8_respecting_configuration(workspace) -> None: docs = [ ("src/__init__.py", ""),