diff --git a/bundled/tool/lsp_server.py b/bundled/tool/lsp_server.py index 6e2de27..484fdce 100644 --- a/bundled/tool/lsp_server.py +++ b/bundled/tool/lsp_server.py @@ -255,6 +255,56 @@ def _get_args_by_file_extension(document: workspace.Document) -> List[str]: # ********************************************************** +# ********************************************************** +# Check file features ends here +# ********************************************************** + + +@LSP_SERVER.feature( + lsp.TEXT_DOCUMENT_DIAGNOSTIC, + lsp.DiagnosticRegistrationOptions( + inter_file_dependencies=False, + workspace_diagnostics=False, + ), +) +def diagnostics(params: lsp.DocumentDiagnosticParams) -> lsp.DocumentDiagnosticReport: + """LSP handler for textDocument/diagnostic request.""" + document = LSP_SERVER.workspace.get_text_document(params.text_document.uri) + settings = _get_settings_by_document(document) + diagnostics = [] + if settings.get("check", False): + diagnostics = _check_document(document) + return lsp.RelatedFullDocumentDiagnosticReport(items=diagnostics) + + +def _check_document(document: workspace.Document) -> lsp.DocumentDiagnosticReport: + """Runs black in check mode to get diagnostics.""" + extra_args = ["--check"] + _get_args_by_file_extension(document) + extra_args += [ "--stdin-filename", _get_filename_for_black(document)] + result = _run_tool_on_document(document, use_stdin=True, extra_args=extra_args) + diagnostics = [] + if result and result.stderr and "would reformat" in result.stderr: + log_to_output(result.stderr) + diagnostics = [ + lsp.Diagnostic( + range=lsp.Range( + start=lsp.Position(line=0, character=0), + end=lsp.Position(line=0, character=0), + ), + message=f"Black would reformat this file.", + severity=lsp.DiagnosticSeverity.Warning, + source=TOOL_DISPLAY, + code="black", + ) + ] + return diagnostics + + +# ********************************************************** +# Check file features ends here +# ********************************************************** + + # ********************************************************** # Required Language Server Initialization and Exit handlers. # ********************************************************** @@ -350,6 +400,7 @@ def _update_workspace_settings_with_version_info( # ***************************************************** def _get_global_defaults(): return { + "check": False, "path": GLOBAL_SETTINGS.get("path", []), "interpreter": GLOBAL_SETTINGS.get("interpreter", [sys.executable]), "args": GLOBAL_SETTINGS.get("args", []), diff --git a/package.json b/package.json index 6053950..083f724 100644 --- a/package.json +++ b/package.json @@ -87,6 +87,15 @@ "scope": "resource", "type": "array" }, + "black-formatter.check": { + "default": false, + "markdownDescription": "%settings.check.description%", + "scope": "resource", + "type": "boolean", + "tags": [ + "experimental" + ] + }, "black-formatter.cwd": { "default": "${workspaceFolder}", "markdownDescription": "%settings.cwd.description%", diff --git a/package.nls.json b/package.nls.json index 5a9cae6..324448b 100644 --- a/package.nls.json +++ b/package.nls.json @@ -2,6 +2,7 @@ "extension.description": "Formatting support for Python files using the Black formatter.", "command.restartServer": "Restart Server", "settings.args.description": "Arguments passed to Black to format Python files. Each argument should be provided as a separate string in the array. \n Example: \n `\"black-formatter.args\" = [\"--config\", \"\"]`", + "settings.check.description": "When enabled, the extension will run `black` with `--check` on open, save or changes.", "settings.cwd.description": "Sets the current working directory used to format Python files with Black. By default, it uses the root directory of the workspace `${workspaceFolder}`. You can set it to `${fileDirname}` to use the parent folder of the file being formatted as the working directory for Black.", "settings.path.description": "Path or command to be used by the extension to format Python files with Black. Accepts an array of a single or multiple strings. If passing a command, each argument should be provided as a separate string in the array. If set to `[\"black\"]`, it will use the version of Black available in the `PATH` environment variable. Note: Using this option may slowdown formatting. \n Examples: \n - `[\"~/global_env/black\"]` \n - `[\"conda\", \"run\", \"-n\", \"lint_env\", \"python\", \"-m\", \"black\"]`", "settings.importStrategy.description": "Defines which Black formatter binary to be used to format Python files. When set to `useBundled`, the extension will use the Black formatter binary that is shipped with the extension. When set to `fromEnvironment`, the extension will attempt to use the Black formatter binary and all dependencies that are available in the currently selected environment. **Note**: If the extension can't find a valid Black formatter binary in the selected environment, it will fallback to using the binary that is shipped with the extension. The `black-formatter.path` setting takes precedence and overrides the behavior of `black-formatter.importStrategy`.", diff --git a/src/common/settings.ts b/src/common/settings.ts index e59612f..dd5a349 100644 --- a/src/common/settings.ts +++ b/src/common/settings.ts @@ -11,6 +11,7 @@ import { trace } from 'console'; export interface ISettings { cwd: string; + check: boolean; workspace: string; args: string[]; path: string[]; @@ -128,6 +129,7 @@ export async function getWorkspaceSettings( const workspaceSetting = { cwd: getCwd(config, workspace), + check: config.get('check', false), workspace: workspace.uri.toString(), args: resolveVariables(config.get('args', []), 'args', workspace), path: resolveVariables(config.get('path', []), 'path', workspace, interpreter), @@ -159,6 +161,7 @@ export async function getGlobalSettings(namespace: string, includeInterpreter?: const setting = { cwd: process.cwd(), + check: config.get('check', false), workspace: process.cwd(), args: getGlobalValue(config, 'args') ?? [], path: getGlobalValue(config, 'path') ?? [],