Skip to content

Commit 9b2b9c3

Browse files
committed
refactor(vscode): using class
1 parent 8441046 commit 9b2b9c3

File tree

3 files changed

+381
-294
lines changed

3 files changed

+381
-294
lines changed

packages/vscode/src/commands.ts

Lines changed: 0 additions & 46 deletions
This file was deleted.

packages/vscode/src/index.ts

Lines changed: 9 additions & 248 deletions
Original file line numberDiff line numberDiff line change
@@ -1,258 +1,19 @@
1-
import { type CancellationToken, type TextEditorDecorationType } from 'vscode'
21
import * as vscode from 'vscode'
3-
import {
4-
LanguageClient,
5-
type LanguageClientOptions,
6-
type MessageSignature,
7-
type ServerOptions,
8-
TransportKind,
9-
} from 'vscode-languageclient/node'
10-
import { join } from 'pathe'
11-
import { registerClientCommands } from './commands'
12-
import { defaultSettings, getFlattenedSettings } from '@pandacss/extension-shared'
13-
import { type TsLanguageFeaturesApiV0, getTsApi } from './typescript-language-features'
2+
import { LanguageClient } from 'vscode-languageclient/node'
3+
import { PandaExtension } from './panda-extension'
144

15-
// Client entrypoint
16-
const docSelector: vscode.DocumentSelector = [
17-
'typescript',
18-
'typescriptreact',
19-
'javascript',
20-
'javascriptreact',
21-
'astro',
22-
// TODO re-enable whenever we figured out how to map transformed file AST nodes to their original positions
23-
// 'svelte',
24-
// 'vue',
25-
]
26-
27-
let client: LanguageClient
28-
const debug = false
5+
const debug = true
6+
let client: LanguageClient | undefined
297

308
export async function activate(context: vscode.ExtensionContext) {
319
debug && console.log('activate')
3210

33-
const statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left)
34-
statusBarItem.text = '🐼 Loading...'
35-
statusBarItem.show()
36-
statusBarItem.command = 'panda-css-vscode.open-config'
37-
38-
// The server is implemented in node
39-
const serverModule = context.asAbsolutePath(join('dist', 'server.js'))
40-
41-
// The debug options for the server
42-
// --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging
43-
const debugOptions = debug ? { execArgv: ['--nolazy', '--inspect=6099'] } : {}
44-
45-
// If the extension is launched in debug mode then the debug server options are used
46-
// Otherwise the run options are used
47-
const serverOptions: ServerOptions = {
48-
run: { module: serverModule, transport: TransportKind.ipc },
49-
debug: {
50-
module: serverModule,
51-
transport: TransportKind.ipc,
52-
options: debugOptions,
53-
},
54-
}
55-
const activeDocument = vscode.window.activeTextEditor?.document
56-
let tsApi: TsLanguageFeaturesApiV0 | undefined
57-
58-
let colorDecorationType: TextEditorDecorationType | undefined
59-
const clearColors = () => {
60-
if (colorDecorationType) {
61-
colorDecorationType.dispose()
62-
colorDecorationType = undefined
63-
}
64-
}
65-
context.subscriptions.push({ dispose: clearColors })
66-
67-
const getFreshPandaSettings = () =>
68-
getFlattenedSettings((vscode.workspace.getConfiguration('panda') as any) ?? defaultSettings)
69-
70-
// Options to control the language client
71-
let activeDocumentFilepath = activeDocument?.uri.fsPath
72-
const clientOptions: LanguageClientOptions = {
73-
documentSelector: docSelector as string[],
74-
diagnosticCollectionName: 'panda',
75-
synchronize: {
76-
fileEvents: [vscode.workspace.createFileSystemWatcher('**/*/panda.config.{ts,js,cjs,mjs}')],
77-
},
78-
initializationOptions: () => {
79-
return {
80-
activeDocumentFilepath: activeDocument?.uri.fsPath,
81-
}
82-
},
83-
middleware: {
84-
// emulate color hints with decorators to prevent the built-in vscode ColorPicker from showing on hover
85-
async provideDocumentColors(document, token, next) {
86-
const settings = getFreshPandaSettings()
87-
if (!settings['color-hints.enabled']) return next(document, token)
88-
if (settings['color-hints.color-preview.enabled']) return next(document, token)
89-
90-
if (!colorDecorationType) {
91-
colorDecorationType = vscode.window.createTextEditorDecorationType({
92-
before: {
93-
width: '0.8em',
94-
height: '0.8em',
95-
contentText: ' ',
96-
border: '0.1em solid',
97-
margin: '0.1em 0.2em 0',
98-
},
99-
dark: {
100-
before: {
101-
borderColor: '#eeeeee',
102-
},
103-
},
104-
light: {
105-
before: {
106-
borderColor: '#000000',
107-
},
108-
},
109-
})
110-
}
111-
112-
const colors = (await next(document, token)) ?? []
113-
const editor = vscode.window.visibleTextEditors.find((editor) => editor.document === document)
114-
115-
editor?.setDecorations(
116-
colorDecorationType,
117-
colors.map(({ range, color }) => {
118-
return {
119-
range,
120-
renderOptions: {
121-
before: {
122-
backgroundColor: `rgba(${color.red * 255}, ${color.green * 255}, ${color.blue * 255}, ${
123-
color.alpha
124-
})`,
125-
},
126-
},
127-
}
128-
}),
129-
)
130-
return []
131-
},
132-
},
133-
}
134-
135-
// Create the language client and start the client.
136-
client = new LanguageClient('panda', 'Panda IntelliSense', serverOptions, clientOptions)
137-
client.outputChannel.appendLine('Starting PandaCss client extension...')
138-
139-
// global error handler
140-
client.handleFailedRequest = (
141-
type: MessageSignature,
142-
token: CancellationToken | undefined,
143-
error: any,
144-
defaultValue: any,
145-
showNotification?: boolean,
146-
) => {
147-
console.log('handleFailedRequest', { type, token, error, defaultValue, showNotification })
148-
console.trace()
149-
return defaultValue
150-
}
151-
client.onNotification('$/clear-colors', clearColors)
152-
153-
// synchronize the active document with the extension LSP
154-
// so that we can retrieve the corresponding configPath (xxx/yyy/panda.config.ts)
155-
context.subscriptions.push(
156-
vscode.window.onDidChangeActiveTextEditor((editor) => {
157-
if (!editor) return
158-
if (!client.isRunning()) return
159-
if (editor.document.uri.scheme !== 'file') return
160-
161-
activeDocumentFilepath = editor.document.uri.fsPath
162-
client.sendNotification('$/panda-active-document-changed', { activeDocumentFilepath })
163-
}),
164-
)
11+
const extension = new PandaExtension(context, debug)
12+
await extension.connectToTsPlugin()
13+
await extension.start()
14+
client = extension.client
16515

166-
// synchronize the extension settings with the TS server plugin
167-
// so that we can disable removing built-ins from the completion list if the user has disabled completions in the settings
168-
context.subscriptions.push(
169-
vscode.workspace.onDidChangeConfiguration((update) => {
170-
debug && console.log('onDidChangeConfiguration', update)
171-
if (!tsApi) return
172-
173-
const settings = getFreshPandaSettings()
174-
tsApi.configurePlugin('@pandacss/ts-plugin', {
175-
type: 'update-settings',
176-
data: settings,
177-
})
178-
}),
179-
)
180-
181-
// send initial config to the TS server plugin
182-
// so that it doesn't have to wait for the first file to be opened or settings to be changed
183-
context.subscriptions.push(
184-
client.onNotification('$/panda-lsp-ready', async () => {
185-
if (!activeDocumentFilepath) return
186-
187-
try {
188-
// no need to await this one
189-
client.sendNotification('$/panda-active-document-changed', { activeDocumentFilepath })
190-
if (!tsApi) return
191-
192-
const configPath = await client.sendRequest<string>('$/get-config-path', { activeDocumentFilepath })
193-
if (!configPath) return
194-
195-
tsApi.configurePlugin('@pandacss/ts-plugin', {
196-
type: 'active-doc',
197-
data: { activeDocumentFilepath, configPath },
198-
})
199-
200-
const settings = getFreshPandaSettings()
201-
tsApi.configurePlugin('@pandacss/ts-plugin', {
202-
type: 'update-settings',
203-
data: settings,
204-
})
205-
} catch (err) {
206-
debug && console.log('error sending doc notif', err)
207-
}
208-
}),
209-
)
210-
211-
// synchronize the active document + its config path with the TS server plugin
212-
// so that it can remove the corresponding built-ins tokens names from the completion list
213-
context.subscriptions.push(
214-
client.onNotification(
215-
'$/panda-doc-config-path',
216-
(notif: { activeDocumentFilepath: string; configPath: string }) => {
217-
if (!tsApi) return
218-
219-
tsApi.configurePlugin('@pandacss/ts-plugin', { type: 'active-doc', data: notif })
220-
debug && console.log({ type: 'active-doc', data: notif })
221-
},
222-
),
223-
)
224-
225-
// synchronize token names by configPath to the TS server plugin
226-
context.subscriptions.push(
227-
client.onNotification('$/panda-token-names', (notif: { configPath: string; tokenNames: string[] }) => {
228-
if (!tsApi) return
229-
230-
tsApi.configurePlugin('@pandacss/ts-plugin', { type: 'setup', data: notif })
231-
debug && console.log({ type: 'setup', data: notif })
232-
}),
233-
)
234-
235-
debug && console.log('before start')
236-
237-
registerClientCommands({ context, debug, client, loadingStatusBarItem: statusBarItem })
238-
239-
try {
240-
tsApi = await getTsApi()
241-
} catch (err) {
242-
debug && console.log('error loading TS', err)
243-
}
244-
245-
try {
246-
// Start the client. This will also launch the server
247-
statusBarItem.text = '🐼 Starting...'
248-
249-
await client.start()
250-
debug && console.log('starting...')
251-
statusBarItem.text = '🐼'
252-
statusBarItem.tooltip = 'Open current panda config'
253-
} catch (err) {
254-
debug && console.log('error starting client', err)
255-
}
16+
debug && console.log('activation successful !')
25617
}
25718

25819
export function deactivate(): Thenable<void> | undefined {

0 commit comments

Comments
 (0)