-
Notifications
You must be signed in to change notification settings - Fork 380
Expand file tree
/
Copy pathrenderModel.ts
More file actions
199 lines (167 loc) · 5.6 KB
/
renderModel.ts
File metadata and controls
199 lines (167 loc) · 5.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
import * as vscode from 'vscode'
import { LSPClient } from '../lsp/lsp'
import { isErr } from '@bus/result'
import { RenderModelEntry } from '../lsp/custom'
import { RenderedModelProvider } from '../providers/renderedModelProvider'
export async function reRenderModelForSourceFile(
sourceUri: string,
lspClient: LSPClient | undefined,
renderedModelProvider: RenderedModelProvider,
): Promise<void> {
const renderedUri = renderedModelProvider.getRenderedUriForSource(sourceUri)
if (!renderedUri) {
return // No rendered model exists for this source file
}
if (!lspClient) {
return
}
// Call the render model API
const result = await lspClient.call_custom_method('sqlmesh/render_model', {
textDocumentUri: sourceUri,
})
if (isErr(result)) {
// Silently fail on auto-rerender errors to avoid spamming user
return
}
// Check if we got any models
if (!result.value.models || result.value.models.length === 0) {
return
}
// Get the originally rendered model information
const originalModelInfo =
renderedModelProvider.getModelInfoForRendered(renderedUri)
// Find the specific model that was originally rendered, or fall back to the first model
const selectedModel = originalModelInfo
? result.value.models.find(
model =>
model.name === originalModelInfo.name &&
model.fqn === originalModelInfo.fqn,
) || result.value.models[0]
: result.value.models[0]
// Update the existing rendered model content
renderedModelProvider.updateRenderedModel(
renderedUri,
selectedModel.rendered_query,
)
}
export function renderModel(
lspClient?: LSPClient,
renderedModelProvider?: RenderedModelProvider,
) {
return async () => {
if (!lspClient) {
vscode.window.showErrorMessage('LSP client not available')
return
}
// Get the current active editor
const activeEditor = vscode.window.activeTextEditor
let documentUri: string
if (!activeEditor) {
// No active editor, show a list of all models
const allModelsResult = await lspClient.call_custom_method(
'sqlmesh/all_models_for_render',
{},
)
if (isErr(allModelsResult)) {
vscode.window.showErrorMessage(
`Failed to get models: ${allModelsResult.error.message}`,
)
return
}
if (
!allModelsResult.value.models ||
allModelsResult.value.models.length === 0
) {
vscode.window.showInformationMessage('No models found in the project')
return
}
// Let user choose from all models
const items = allModelsResult.value.models.map(model => ({
label: model.name,
description: model.fqn,
detail: model.description ? model.description : undefined,
model: model,
}))
const selected = await vscode.window.showQuickPick(items, {
placeHolder: 'Select a model to render',
})
if (!selected) {
return
}
// Use the selected model's URI
documentUri = selected.model.uri
} else {
// Get the current document URI
documentUri = activeEditor.document.uri.toString(true)
}
// Call the render model API
const result = await lspClient.call_custom_method('sqlmesh/render_model', {
textDocumentUri: documentUri,
})
if (isErr(result)) {
vscode.window.showErrorMessage(
`Failed to render model: ${result.error.message}`,
)
return
}
// Check if we got any models
if (!result.value.models || result.value.models.length === 0) {
vscode.window.showInformationMessage(
'No models found in the current file',
)
return
}
// If multiple models, let user choose
let selectedModel: RenderModelEntry
if (result.value.models.length > 1) {
const items = result.value.models.map(model => ({
label: model.name,
description: model.fqn,
detail: model.description ? model.description : undefined,
model: model,
}))
const selected = await vscode.window.showQuickPick(items, {
placeHolder: 'Select a model to render',
})
if (!selected) {
return
}
selectedModel = selected.model
} else {
selectedModel = result.value.models[0]
}
if (!renderedModelProvider) {
vscode.window.showErrorMessage('Rendered model provider not available')
return
}
// Store the rendered content and get a virtual URI
const uri = renderedModelProvider.storeRenderedModel(
selectedModel.name,
selectedModel.rendered_query,
documentUri,
selectedModel,
)
// Open the virtual document
const document = await vscode.workspace.openTextDocument(uri)
// Determine the view column for side-by-side display
// Find the rightmost column with an editor
let maxColumn = vscode.ViewColumn.One
for (const editor of vscode.window.visibleTextEditors) {
if (editor.viewColumn && editor.viewColumn > maxColumn) {
maxColumn = editor.viewColumn
}
}
// Open in the next column after the rightmost editor
const viewColumn = maxColumn + 1
// Open the document in the editor as a preview (preview: true is default)
await vscode.window.showTextDocument(document, {
viewColumn: viewColumn,
preview: true,
preserveFocus: false,
})
// Execute "Keep Open" command to convert preview tab to permanent tab
await vscode.commands.executeCommand('workbench.action.keepEditor')
// Explicitly set the language mode to SQL for syntax highlighting
await vscode.languages.setTextDocumentLanguage(document, 'sql')
}
}