From 619f34876b6a3e72203e847d70ca5ac3e738f2d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?W=C3=BCstengecko?= Date: Tue, 9 Apr 2024 01:10:57 +0200 Subject: [PATCH] Infer end position for Pylint diagnostics Pylint only supplies the start position of markers, but not the end. Always extending the marker until the end of the line leads to undesirable highlighting in editors, for example: ```python def my_func(unused_arg, used_arg): print(used_arg) ``` Starting an "unused argument" diagnostic at `unused_arg` and extending It until EOL would also highlight `used_arg`, even though the diagnostic doesn't apply there. With this commit, the end position sent to the editor is automatically determined by looking for an identifier at the indicated start position. If there is no valid identifier at that position, the entire line is highlighted as before. --- pylsp/plugins/pylint_lint.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/pylsp/plugins/pylint_lint.py b/pylsp/plugins/pylint_lint.py index beffe6f3..722e831b 100644 --- a/pylsp/plugins/pylint_lint.py +++ b/pylsp/plugins/pylint_lint.py @@ -151,7 +151,11 @@ def lint(cls, document, is_saved, flags=""): "line": line, # It's possible that we're linting an empty file. Even an empty # file might fail linting if it isn't named properly. - "character": len(document.lines[line]) if document.lines else 0, + "character": ( + _find_end_of_identifier(document.lines[line], diag["column"]) + if document.lines + else 0 + ), }, } @@ -338,8 +342,9 @@ def _parse_pylint_stdio_result(document, stdout): "start": {"line": line, "character": character}, "end": { "line": line, - # no way to determine the column - "character": len(document.lines[line]) - 1, + "character": _find_end_of_identifier( + document.lines[line], character + ), }, }, "message": msg, @@ -352,3 +357,11 @@ def _parse_pylint_stdio_result(document, stdout): diagnostics.append(diagnostic) return diagnostics + + +def _find_end_of_identifier(string, start): + """Find the end of the identifier starting at the given position.""" + for i in range(len(string), start, -1): + if string[start:i].isidentifier(): + return i + return len(string) - 1