diff --git a/README.md b/README.md index bafcc63..e79644c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Flake8 extension for Visual Studio Code +# Flake8 extension for Visual Studio Code -A Visual Studio Code extension with support for the Flake8 linter. The extension ships with `flake8==7.1.1`. +A Visual Studio Code extension with support for the Flake8 linter. The extension ships with `flake8==7.3.0`. > **Note**: The minimum version of Flake8 this extension supports is 7.0.0. If you are having issues with Flake8, please report it to [this issue tracker](https://github.com/PyCQA/flake8/issues) as this extension is just a wrapper around Flake8. diff --git a/bundled/tool/lsp_server.py b/bundled/tool/lsp_server.py index dcc3d04..2dd98d7 100644 --- a/bundled/tool/lsp_server.py +++ b/bundled/tool/lsp_server.py @@ -63,14 +63,16 @@ def update_environ_path() -> None: import lsp_jsonrpc as jsonrpc import lsp_utils as utils from lsprotocol import types as lsp -from pygls import server, uris, workspace +from pygls import uris +from pygls.lsp.server import LanguageServer +from pygls.workspace import TextDocument WORKSPACE_SETTINGS = {} GLOBAL_SETTINGS = {} RUNNER = pathlib.Path(__file__).parent / "lsp_runner.py" MAX_WORKERS = 5 -LSP_SERVER = server.LanguageServer( +LSP_SERVER = LanguageServer( name="flake8-server", version="v0.1.0", max_workers=MAX_WORKERS ) @@ -95,28 +97,34 @@ def update_environ_path() -> None: @LSP_SERVER.feature(lsp.TEXT_DOCUMENT_DID_OPEN) def did_open(params: lsp.DidOpenTextDocumentParams) -> None: """LSP handler for textDocument/didOpen request.""" - document = LSP_SERVER.workspace.get_document(params.text_document.uri) + document = LSP_SERVER.workspace.get_text_document(params.text_document.uri) diagnostics: list[lsp.Diagnostic] = _linting_helper(document) - LSP_SERVER.publish_diagnostics(document.uri, diagnostics) + LSP_SERVER.text_document_publish_diagnostics( + lsp.PublishDiagnosticsParams(uri=document.uri, diagnostics=diagnostics) + ) @LSP_SERVER.feature(lsp.TEXT_DOCUMENT_DID_SAVE) def did_save(params: lsp.DidSaveTextDocumentParams) -> None: """LSP handler for textDocument/didSave request.""" - document = LSP_SERVER.workspace.get_document(params.text_document.uri) + document = LSP_SERVER.workspace.get_text_document(params.text_document.uri) diagnostics: list[lsp.Diagnostic] = _linting_helper(document) - LSP_SERVER.publish_diagnostics(document.uri, diagnostics) + LSP_SERVER.text_document_publish_diagnostics( + lsp.PublishDiagnosticsParams(uri=document.uri, diagnostics=diagnostics) + ) @LSP_SERVER.feature(lsp.TEXT_DOCUMENT_DID_CLOSE) def did_close(params: lsp.DidCloseTextDocumentParams) -> None: """LSP handler for textDocument/didClose request.""" - document = LSP_SERVER.workspace.get_document(params.text_document.uri) + document = LSP_SERVER.workspace.get_text_document(params.text_document.uri) # Publishing empty diagnostics to clear the entries for this file. - LSP_SERVER.publish_diagnostics(document.uri, []) + LSP_SERVER.text_document_publish_diagnostics( + lsp.PublishDiagnosticsParams(uri=document.uri, diagnostics=[]) + ) -def _is_supported_file(document: workspace.Document) -> bool: +def _is_supported_file(document: TextDocument) -> bool: """Checks if the given document is supported by this tool.""" if document.path: file_path = pathlib.Path(document.path) @@ -125,7 +133,7 @@ def _is_supported_file(document: workspace.Document) -> bool: return False -def _linting_helper(document: workspace.Document) -> list[lsp.Diagnostic]: +def _linting_helper(document: TextDocument) -> list[lsp.Diagnostic]: try: if not _is_supported_file(document): log_always(f"Skipping linting for {document.uri} skipped: not supported") @@ -141,9 +149,11 @@ def _linting_helper(document: workspace.Document) -> list[lsp.Diagnostic]: result.stdout, severity=settings["severity"] ) except Exception: - LSP_SERVER.show_message_log( - f"Linting failed with error:\r\n{traceback.format_exc()}", - lsp.MessageType.Error, + LSP_SERVER.window_log_message( + lsp.LogMessageParams( + message=f"Linting failed with error:\r\n{traceback.format_exc()}", + type=lsp.MessageType.Error, + ) ) return [] @@ -224,7 +234,7 @@ class QuickFixSolutions: def __init__(self): self._solutions: Dict[ str, - Callable[[workspace.Document, List[lsp.Diagnostic]], List[lsp.CodeAction]], + Callable[[TextDocument, List[lsp.Diagnostic]], List[lsp.CodeAction]], ] = {} def quick_fix( @@ -234,9 +244,7 @@ def quick_fix( """Decorator used for registering quick fixes.""" def decorator( - func: Callable[ - [workspace.Document, List[lsp.Diagnostic]], List[lsp.CodeAction] - ], + func: Callable[[TextDocument, List[lsp.Diagnostic]], List[lsp.CodeAction]], ): if isinstance(codes, str): if codes in self._solutions: @@ -252,9 +260,7 @@ def decorator( def solutions( self, code: str - ) -> Optional[ - Callable[[workspace.Document, List[lsp.Diagnostic]], List[lsp.CodeAction]] - ]: + ) -> Optional[Callable[[TextDocument, List[lsp.Diagnostic]], List[lsp.CodeAction]]]: """Given a flake8 error code returns a function, if available, that provides quick fix code actions.""" @@ -273,7 +279,7 @@ def solutions( ) def code_action(params: lsp.CodeActionParams) -> List[lsp.CodeAction]: """LSP handler for textDocument/codeAction request.""" - document = LSP_SERVER.workspace.get_document(params.text_document.uri) + document = LSP_SERVER.workspace.get_text_document(params.text_document.uri) settings = copy.deepcopy(_get_settings_by_document(document)) code_actions = [] @@ -323,7 +329,7 @@ def code_action(params: lsp.CodeActionParams) -> List[lsp.CodeAction]: ] ) def fix_format( - _document: workspace.Document, diagnostics: List[lsp.Diagnostic] + _document: TextDocument, diagnostics: List[lsp.Diagnostic] ) -> List[lsp.CodeAction]: """Provides quick fixes which involve formatting document.""" return [ @@ -350,7 +356,7 @@ def _command_quick_fix( def _create_workspace_edits( - document: workspace.Document, results: Optional[List[lsp.TextEdit]] + document: TextDocument, results: Optional[List[lsp.TextEdit]] ): return lsp.WorkspaceEdit( document_changes=[ @@ -496,7 +502,7 @@ def _update_workspace_settings(settings): } -def _get_document_key(document: workspace.Document): +def _get_document_key(document: TextDocument): if WORKSPACE_SETTINGS: document_workspace = pathlib.Path(document.path) workspaces = {s["workspaceFS"] for s in WORKSPACE_SETTINGS.values()} @@ -512,7 +518,7 @@ def _get_document_key(document: workspace.Document): return None -def _get_settings_by_document(document: workspace.Document | None): +def _get_settings_by_document(document: TextDocument | None): # If not document, return first workspace settings if document is None or document.path is None: return list(WORKSPACE_SETTINGS.values())[0] @@ -539,7 +545,7 @@ def _get_settings_by_document(document: workspace.Document | None): # ***************************************************** # Internal execution APIs. # ***************************************************** -def get_cwd(settings: Dict[str, Any], document: Optional[workspace.Document]) -> str: +def get_cwd(settings: Dict[str, Any], document: Optional[TextDocument]) -> str: """Returns cwd for the given settings and document.""" if settings["cwd"] == "${workspaceFolder}": return settings["workspaceFS"] @@ -553,7 +559,7 @@ def get_cwd(settings: Dict[str, Any], document: Optional[workspace.Document]) -> def _run_tool_on_document( - document: workspace.Document, + document: TextDocument, use_stdin: bool = False, extra_args: Sequence[str] = [], ) -> utils.RunResult | None: @@ -752,28 +758,40 @@ def log_to_output( message: str, msg_type: lsp.MessageType = lsp.MessageType.Log ) -> None: """Logs messages to Output > Flake8 channel only.""" - LSP_SERVER.show_message_log(message, msg_type) + LSP_SERVER.window_log_message(lsp.LogMessageParams(message=message, type=msg_type)) def log_error(message: str) -> None: """Logs messages with notification on error.""" - LSP_SERVER.show_message_log(message, lsp.MessageType.Error) + LSP_SERVER.window_log_message( + lsp.LogMessageParams(message=message, type=lsp.MessageType.Error) + ) if os.getenv("LS_SHOW_NOTIFICATION", "off") in ["onError", "onWarning", "always"]: - LSP_SERVER.show_message(message, lsp.MessageType.Error) + LSP_SERVER.window_show_message( + lsp.ShowMessageParams(message=message, type=lsp.MessageType.Error) + ) def log_warning(message: str) -> None: """Logs messages with notification on warning.""" - LSP_SERVER.show_message_log(message, lsp.MessageType.Warning) + LSP_SERVER.window_log_message( + lsp.LogMessageParams(message=message, type=lsp.MessageType.Warning) + ) if os.getenv("LS_SHOW_NOTIFICATION", "off") in ["onWarning", "always"]: - LSP_SERVER.show_message(message, lsp.MessageType.Warning) + LSP_SERVER.window_show_message( + lsp.ShowMessageParams(message=message, type=lsp.MessageType.Warning) + ) def log_always(message: str) -> None: """Logs messages with notification.""" - LSP_SERVER.show_message_log(message, lsp.MessageType.Info) + LSP_SERVER.window_log_message( + lsp.LogMessageParams(message=message, type=lsp.MessageType.Info) + ) if os.getenv("LS_SHOW_NOTIFICATION", "off") in ["always"]: - LSP_SERVER.show_message(message, lsp.MessageType.Info) + LSP_SERVER.window_show_message( + lsp.ShowMessageParams(message=message, type=lsp.MessageType.Info) + ) # ***************************************************** diff --git a/requirements.txt b/requirements.txt index 52a6849..3406828 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,50 +1,47 @@ # This file was autogenerated by uv via the following command: # uv pip compile --generate-hashes ./requirements.in -attrs==25.1.0 \ - --hash=sha256:1c97078a80c814273a76b2a298a932eb681c87415c11dee0a6921de7f1b02c3e \ - --hash=sha256:c75a69e28a550a7e93789579c22aa26b0f5b83b75dc4e08fe092980051e1090a +attrs==25.4.0 \ + --hash=sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11 \ + --hash=sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373 # via # cattrs # lsprotocol -cattrs==24.1.2 \ - --hash=sha256:67c7495b760168d931a10233f979b28dc04daf853b30752246f4f8471c6d68d0 \ - --hash=sha256:8028cfe1ff5382df59dd36474a86e02d817b06eaf8af84555441bac915d2ef85 + # pygls +cattrs==25.3.0 \ + --hash=sha256:1ac88d9e5eda10436c4517e390a4142d88638fe682c436c93db7ce4a277b884a \ + --hash=sha256:9896e84e0a5bf723bc7b4b68f4481785367ce07a8a02e7e9ee6eb2819bc306ff # via # lsprotocol # pygls -exceptiongroup==1.2.2 \ - --hash=sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b \ - --hash=sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc - # via cattrs -flake8==7.1.1 \ - --hash=sha256:049d058491e228e03e67b390f311bbf88fce2dbaa8fa673e7aea87b7198b8d38 \ - --hash=sha256:597477df7860daa5aa0fdd84bf5208a043ab96b8e96ab708770ae0364dd03213 +flake8==7.3.0 \ + --hash=sha256:b9696257b9ce8beb888cdbe31cf885c90d31928fe202be0889a7cdafad32f01e \ + --hash=sha256:fe044858146b9fc69b551a4b490d69cf960fcb78ad1edcb84e7fbb1b4a8e3872 # via -r ./requirements.in -lsprotocol==2023.0.1 \ - --hash=sha256:c75223c9e4af2f24272b14c6375787438279369236cd568f596d4951052a60f2 \ - --hash=sha256:cc5c15130d2403c18b734304339e51242d3018a05c4f7d0f198ad6e0cd21861d +lsprotocol==2025.0.0 \ + --hash=sha256:e879da2b9301e82cfc3e60d805630487ac2f7ab17492f4f5ba5aaba94fe56c29 \ + --hash=sha256:f9d78f25221f2a60eaa4a96d3b4ffae011b107537facee61d3da3313880995c7 # via pygls mccabe==0.7.0 \ --hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325 \ --hash=sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e # via flake8 -packaging==24.2 \ - --hash=sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759 \ - --hash=sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f +packaging==26.0 \ + --hash=sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4 \ + --hash=sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529 # via -r ./requirements.in -pycodestyle==2.12.1 \ - --hash=sha256:46f0fb92069a7c28ab7bb558f05bfc0110dac69a0cd23c61ea0040283a9d78b3 \ - --hash=sha256:6838eae08bbce4f6accd5d5572075c63626a15ee3e6f842df996bf62f6d73521 +pycodestyle==2.14.0 \ + --hash=sha256:c4b5b517d278089ff9d0abdec919cd97262a3367449ea1c8b49b91529167b783 \ + --hash=sha256:dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d # via flake8 -pyflakes==3.2.0 \ - --hash=sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f \ - --hash=sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a +pyflakes==3.4.0 \ + --hash=sha256:b24f96fafb7d2ab0ec5075b7350b3d2d2218eab42003821c06344973d3ea2f58 \ + --hash=sha256:f742a7dbd0d9cb9ea41e9a24a918996e8170c799fa528688d40dd582c8265f4f # via flake8 -pygls==1.3.1 \ - --hash=sha256:140edceefa0da0e9b3c533547c892a42a7d2fd9217ae848c330c53d266a55018 \ - --hash=sha256:6e00f11efc56321bdeb6eac04f6d86131f654c7d49124344a9ebb968da3dd91e +pygls==2.0.1 \ + --hash=sha256:2f774a669fbe2ece977d302786f01f9b0c5df7d0204ea0fa371ecb08288d6b86 \ + --hash=sha256:d29748042cea5bedc98285eb3e2c0c60bf3fc73786319519001bf72bbe8f36cc # via -r ./requirements.in -typing-extensions==4.12.2 \ - --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ - --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 +typing-extensions==4.15.0 \ + --hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \ + --hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548 # via cattrs