From 4d8e9ec3011fbd43945aa0dd6fe497dd2dbc1a03 Mon Sep 17 00:00:00 2001 From: Ben King <9087625+benfdking@users.noreply.github.com> Date: Tue, 29 Jul 2025 15:13:33 +0100 Subject: [PATCH] feat!: allow the linter to return fixes that affect other files - This change builds the building block to the linter to return violations whose fixes affect other files. - This is in preparation for the change where nomissingexternalmodels can add a fix that will add the model to the external models --- sqlmesh/core/linter/rule.py | 2 ++ sqlmesh/core/linter/rules/builtin.py | 4 ++++ sqlmesh/lsp/context.py | 10 +++++++--- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/sqlmesh/core/linter/rule.py b/sqlmesh/core/linter/rule.py index 6e63dd2ee6..ec942928e7 100644 --- a/sqlmesh/core/linter/rule.py +++ b/sqlmesh/core/linter/rule.py @@ -2,6 +2,7 @@ import abc from dataclasses import dataclass +from pathlib import Path from sqlmesh.core.model import Model @@ -43,6 +44,7 @@ class Range: class TextEdit: """A text edit to apply to a file.""" + path: Path range: Range new_text: str diff --git a/sqlmesh/core/linter/rules/builtin.py b/sqlmesh/core/linter/rules/builtin.py index c1a5f9b877..a166b5e1f3 100644 --- a/sqlmesh/core/linter/rules/builtin.py +++ b/sqlmesh/core/linter/rules/builtin.py @@ -53,12 +53,16 @@ def _create_fixes( columns = model.columns_to_types if not columns: return None + path = model._path + if path is None: + return None new_text = ", ".join(columns.keys()) return [ Fix( title="Replace SELECT * with explicit column list", edits=[ TextEdit( + path=path, range=violation_range, new_text=new_text, ) diff --git a/sqlmesh/lsp/context.py b/sqlmesh/lsp/context.py index 43eb9c8f16..5f79191c38 100644 --- a/sqlmesh/lsp/context.py +++ b/sqlmesh/lsp/context.py @@ -269,9 +269,13 @@ def get_code_actions( # Create code actions for each fix for fix in found_violation.fixes: # Convert our Fix to LSP TextEdits - text_edits = [] + changes: t.Dict[str, t.List[types.TextEdit]] = {} for edit in fix.edits: - text_edits.append( + uri_key = URI.from_path(edit.path).value + if uri_key not in changes: + changes[uri_key] = [] + # Create a TextEdit for the LSP + changes[uri_key].append( types.TextEdit( range=types.Range( start=types.Position( @@ -292,7 +296,7 @@ def get_code_actions( title=fix.title, kind=types.CodeActionKind.QuickFix, diagnostics=[diagnostic], - edit=types.WorkspaceEdit(changes={params.text_document.uri: text_edits}), + edit=types.WorkspaceEdit(changes=changes), ) code_actions.append(code_action)