|
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