1- import { format } from './commands/format'
1+ /**********************************************************************
2+ * Extension entry point *
3+ *********************************************************************/
4+
25import * as vscode from 'vscode'
3- import {
4- createOutputChannel ,
5- onDidChangeConfiguration ,
6- registerCommand ,
7- } from './utilities/common/vscodeapi'
8- import { registerLogger , traceInfo , traceVerbose } from './utilities/common/log'
9- import { onDidChangePythonInterpreter } from './utilities/common/python'
10- import { LSPClient } from './lsp/lsp'
11- import { AuthenticationProviderTobikoCloud } from './auth/auth'
6+
7+ import { format } from './commands/format'
128import { signOut } from './commands/signout'
139import { signIn } from './commands/signin'
1410import { signInSpecifyFlow } from './commands/signinSpecifyFlow'
1511import { renderModel , reRenderModelForSourceFile } from './commands/renderModel'
1612import { stop } from './commands/stop'
1713import { printEnvironment } from './commands/printEnvironment'
18- import { isErr } from '@bus/result'
14+
15+ import {
16+ createOutputChannel ,
17+ onDidChangeConfiguration ,
18+ registerCommand ,
19+ } from './utilities/common/vscodeapi'
20+ import {
21+ registerLogger ,
22+ traceInfo ,
23+ traceVerbose ,
24+ traceError ,
25+ } from './utilities/common/log'
26+ import { onDidChangePythonInterpreter } from './utilities/common/python'
27+ import { sleep } from './utilities/sleep'
1928import { handleError } from './utilities/errors'
29+
2030import { selector , completionProvider } from './completion/completion'
2131import { LineagePanel } from './webviews/lineagePanel'
2232import { RenderedModelProvider } from './providers/renderedModelProvider'
23- import { sleep } from './utilities/sleep'
33+
2434import {
2535 controller as testController ,
2636 setupTestController ,
2737} from './tests/tests'
2838
39+ import { isErr } from '@bus/result'
40+ import { AuthenticationProviderTobikoCloud } from './auth/auth'
41+ import { LSPClient } from './lsp/lsp'
42+
43+ /* ------------------------------------------------------------------ */
44+ /* Globals */
45+ /* ------------------------------------------------------------------ */
46+
47+ /** Singleton LSP client for the extension. */
2948let lspClient : LSPClient | undefined
3049
31- // This method is called when your extension is activated
32- // Your extension is activated the very first time the command is executed
50+ /** Handle to the (single) test controller disposable so we can replace it on restart. */
51+ let testControllerDisposable : vscode . Disposable | undefined
52+
53+ /* ------------------------------------------------------------------ */
54+ /* Activation */
55+ /* ------------------------------------------------------------------ */
56+
3357export async function activate ( context : vscode . ExtensionContext ) {
58+ /* ---------- logging / output ---------- */
3459 const extensionOutputChannel = createOutputChannel ( 'sqlmesh' )
3560 context . subscriptions . push (
3661 extensionOutputChannel ,
3762 registerLogger ( extensionOutputChannel ) ,
3863 )
3964 traceInfo ( 'Activating SQLMesh extension' )
4065
41- traceInfo ( 'Registering authentication provider' )
66+ /* ---------- authentication provider ---------- */
4267 const authProvider = new AuthenticationProviderTobikoCloud ( )
4368 context . subscriptions . push (
4469 vscode . authentication . registerAuthenticationProvider (
@@ -48,33 +73,71 @@ export async function activate(context: vscode.ExtensionContext) {
4873 { supportsMultipleAccounts : false } ,
4974 ) ,
5075 )
51- traceInfo ( 'Authentication provider registered' )
5276
77+ /* ---------- helper: (re)start the LSP ---------- */
78+ const restartLsp = async ( invokedByUser = false ) : Promise < void > => {
79+ if ( ! lspClient ) {
80+ lspClient = new LSPClient ( )
81+ }
82+
83+ traceVerbose ( 'Restarting SQLMesh LSP client' )
84+ const result = await lspClient . restart ( invokedByUser )
85+ if ( isErr ( result ) ) {
86+ await handleError (
87+ authProvider ,
88+ restartLsp ,
89+ result . error ,
90+ 'LSP restart failed' ,
91+ )
92+ return
93+ }
94+
95+ /* push once – avoid duplicate disposables on multiple restarts */
96+ if ( ! context . subscriptions . includes ( lspClient ) ) {
97+ context . subscriptions . push ( lspClient )
98+ }
99+
100+ /* Replace the test controller each time we restart the client */
101+ if ( testControllerDisposable ) {
102+ testControllerDisposable . dispose ( )
103+ }
104+ testControllerDisposable = setupTestController ( lspClient )
105+ context . subscriptions . push ( testControllerDisposable )
106+ }
107+
108+ /* ---------- commands needing the restart helper ---------- */
53109 context . subscriptions . push (
54110 vscode . commands . registerCommand (
55111 'sqlmesh.signin' ,
56- signIn ( authProvider , async ( ) => {
57- traceInfo ( 'Restarting LSP after sign-in' )
58- await restart ( )
59- } ) ,
112+ signIn ( authProvider , ( ) => restartLsp ( ) ) ,
60113 ) ,
61- )
62- context . subscriptions . push (
63114 vscode . commands . registerCommand (
64115 'sqlmesh.signinSpecifyFlow' ,
65- signInSpecifyFlow ( authProvider , async ( ) => {
66- traceInfo ( 'Restarting LSP after sign-in' )
67- await restart ( )
68- } ) ,
116+ signInSpecifyFlow ( authProvider , ( ) => restartLsp ( ) ) ,
69117 ) ,
70- )
71- context . subscriptions . push (
72118 vscode . commands . registerCommand ( 'sqlmesh.signout' , signOut ( authProvider ) ) ,
73119 )
74120
121+ /* ---------- Instantiate the LSP client (once) ---------- */
75122 lspClient = new LSPClient ( )
123+ const startResult = await lspClient . start ( )
124+ if ( isErr ( startResult ) ) {
125+ await handleError (
126+ authProvider ,
127+ restartLsp ,
128+ startResult . error ,
129+ 'Failed to start LSP' ,
130+ )
131+ return // abort activation – nothing else to do
132+ }
133+
134+ context . subscriptions . push ( lspClient )
135+
136+ /* ---------- test controller (initial) ---------- */
137+ testControllerDisposable = setupTestController ( lspClient )
138+ context . subscriptions . push ( testControllerDisposable , testController )
76139
77- // Create and register the rendered model provider
140+ /* ---------- rendered‑ model provider & webview ---------- */
78141 const renderedModelProvider = new RenderedModelProvider ( )
79142 context . subscriptions . push (
80143 vscode . workspace . registerTextDocumentContentProvider (
@@ -91,7 +154,6 @@ export async function activate(context: vscode.ExtensionContext) {
91154 ) ,
92155 )
93156
94- // Register the webview
95157 const lineagePanel = new LineagePanel ( context . extensionUri , lspClient )
96158 context . subscriptions . push (
97159 vscode . window . registerWebviewViewProvider (
@@ -100,11 +162,10 @@ export async function activate(context: vscode.ExtensionContext) {
100162 ) ,
101163 )
102164
103- // Add file save listener for auto-rerendering models
165+ /* Re‑render model automatically when its source file is saved */
104166 context . subscriptions . push (
105167 vscode . workspace . onDidSaveTextDocument ( async document => {
106168 if (
107- lspClient &&
108169 renderedModelProvider . hasRenderedModelForSource (
109170 document . uri . toString ( true ) ,
110171 )
@@ -119,73 +180,25 @@ export async function activate(context: vscode.ExtensionContext) {
119180 } ) ,
120181 )
121182
122- const restart = async ( invokedByUser = false ) => {
123- if ( lspClient ) {
124- traceVerbose ( 'Restarting LSP client' )
125- const restartResult = await lspClient . restart ( invokedByUser )
126- if ( isErr ( restartResult ) ) {
127- return handleError (
128- authProvider ,
129- restart ,
130- restartResult . error ,
131- 'LSP restart failed' ,
132- )
133- }
134- context . subscriptions . push ( lspClient )
135- context . subscriptions . push ( setupTestController ( lspClient ) )
136- } else {
137- lspClient = new LSPClient ( )
138- const result = await lspClient . start ( invokedByUser )
139- if ( isErr ( result ) ) {
140- return handleError (
141- authProvider ,
142- restart ,
143- result . error ,
144- 'Failed to start LSP' ,
145- )
146- } else {
147- context . subscriptions . push ( lspClient )
148- context . subscriptions . push ( setupTestController ( lspClient ) )
149- }
150- }
151- }
152-
183+ /* ---------- miscellaneous commands ---------- */
153184 context . subscriptions . push (
154185 vscode . commands . registerCommand (
155186 'sqlmesh.format' ,
156- format ( authProvider , lspClient , restart ) ,
187+ format ( authProvider , lspClient , restartLsp ) ,
157188 ) ,
189+ registerCommand ( 'sqlmesh.restart' , ( ) => restartLsp ( true ) ) ,
190+ registerCommand ( 'sqlmesh.stop' , stop ( lspClient ) ) ,
191+ registerCommand ( 'sqlmesh.printEnvironment' , printEnvironment ( ) ) ,
158192 )
159193
194+ /* ---------- configuration / environment change listeners ---------- */
160195 context . subscriptions . push (
161- onDidChangePythonInterpreter ( async ( ) => {
162- await restart ( )
163- } ) ,
164- onDidChangeConfiguration ( async ( ) => {
165- await restart ( )
166- } ) ,
167- registerCommand ( `sqlmesh.restart` , async ( ) => {
168- await restart ( true )
169- } ) ,
170- registerCommand ( `sqlmesh.stop` , stop ( lspClient ) ) ,
171- registerCommand ( `sqlmesh.printEnvironment` , printEnvironment ( ) ) ,
196+ onDidChangePythonInterpreter ( ( ) => restartLsp ( ) ) ,
197+ onDidChangeConfiguration ( ( ) => restartLsp ( ) ) ,
172198 )
173199
174- const result = await lspClient . start ( )
175- if ( isErr ( result ) ) {
176- return handleError (
177- authProvider ,
178- restart ,
179- result . error ,
180- 'Failed to start LSP' ,
181- )
182- } else {
183- context . subscriptions . push ( lspClient )
184- context . subscriptions . push ( setupTestController ( lspClient ) )
185- context . subscriptions . push ( testController )
186- }
187-
188- if ( lspClient && ! lspClient . hasCompletionCapability ( ) ) {
200+ /* ---------- completion provider fallback ---------- */
201+ if ( ! lspClient . hasCompletionCapability ( ) ) {
189202 context . subscriptions . push (
190203 vscode . languages . registerCompletionItemProvider (
191204 selector ,
@@ -194,12 +207,22 @@ export async function activate(context: vscode.ExtensionContext) {
194207 )
195208 }
196209
197- traceInfo ( 'Extension activated' )
210+ traceInfo ( 'SQLMesh extension activated' )
198211}
199212
200- // This method is called when your extension is deactivated
213+ /* ------------------------------------------------------------------ */
214+ /* De‑activation */
215+ /* ------------------------------------------------------------------ */
216+
201217export async function deactivate ( ) {
202- if ( lspClient ) {
203- await lspClient . dispose ( )
218+ try {
219+ if ( testControllerDisposable ) {
220+ testControllerDisposable . dispose ( )
221+ }
222+ if ( lspClient ) {
223+ await lspClient . dispose ( )
224+ }
225+ } catch ( e ) {
226+ traceError ( `Error during deactivate: ${ e } ` )
204227 }
205228}
0 commit comments