|
71 | 71 | from sqlmesh.lsp.uri import URI |
72 | 72 | from sqlmesh.utils.errors import ConfigError |
73 | 73 | from sqlmesh.utils.lineage import ExternalModelReference |
| 74 | +from sqlmesh.utils.pydantic import PydanticModel |
74 | 75 | from web.server.api.endpoints.lineage import column_lineage, model_lineage |
75 | 76 | from web.server.api.endpoints.models import get_models |
76 | 77 | from typing import Union |
77 | 78 | from dataclasses import dataclass, field |
78 | 79 |
|
79 | 80 |
|
| 81 | +class InitializationOptions(PydanticModel): |
| 82 | + """Initialization options for the SQLMesh Language Server, that |
| 83 | + are passed from the client to the server.""" |
| 84 | + |
| 85 | + project_paths: t.Optional[t.List[str]] = None |
| 86 | + |
| 87 | + |
80 | 88 | @dataclass |
81 | 89 | class NoContext: |
82 | 90 | """State when no context has been attempted to load.""" |
@@ -105,6 +113,11 @@ class ContextFailed: |
105 | 113 |
|
106 | 114 |
|
107 | 115 | class SQLMeshLanguageServer: |
| 116 | + # Specified folders take precedence over workspace folders or looking |
| 117 | + # for a config files. They are explicitly set by the user and optionally |
| 118 | + # pass in at init |
| 119 | + specified_paths: t.Optional[t.List[Path]] = None |
| 120 | + |
108 | 121 | def __init__( |
109 | 122 | self, |
110 | 123 | context_class: t.Type[Context], |
@@ -411,6 +424,12 @@ def command_external_models_update_columns(ls: LanguageServer, raw: t.Any) -> No |
411 | 424 | def initialize(ls: LanguageServer, params: types.InitializeParams) -> None: |
412 | 425 | """Initialize the server when the client connects.""" |
413 | 426 | try: |
| 427 | + # Check the custom options |
| 428 | + if params.initialization_options: |
| 429 | + options = InitializationOptions.model_validate(params.initialization_options) |
| 430 | + if options.project_paths is not None: |
| 431 | + self.specified_paths = [Path(path) for path in options.project_paths] |
| 432 | + |
414 | 433 | # Check if the client supports pull diagnostics |
415 | 434 | if params.capabilities and params.capabilities.text_document: |
416 | 435 | diagnostics = getattr(params.capabilities.text_document, "diagnostic", None) |
@@ -906,7 +925,12 @@ def _context_get_or_load(self, document_uri: t.Optional[URI] = None) -> LSPConte |
906 | 925 | raise Exception(state.error) |
907 | 926 | raise state.error |
908 | 927 | if isinstance(state, NoContext): |
909 | | - self._ensure_context_for_document(document_uri) |
| 928 | + if self.specified_paths is not None: |
| 929 | + # If specified paths are provided, create context from them |
| 930 | + if self._create_lsp_context(self.specified_paths): |
| 931 | + loaded_sqlmesh_message(self.server) |
| 932 | + else: |
| 933 | + self._ensure_context_for_document(document_uri) |
910 | 934 | if isinstance(state, ContextLoaded): |
911 | 935 | return state.lsp_context |
912 | 936 | raise RuntimeError("Context failed to load") |
|
0 commit comments