Skip to content

Commit adabf27

Browse files
committed
Update settings handling, debounce validation
1 parent e246893 commit adabf27

File tree

2 files changed

+65
-21
lines changed

2 files changed

+65
-21
lines changed

packages/tailwindcss-language-server/src/language/cssServer.ts

Lines changed: 64 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import {
1010
TextDocuments,
1111
TextDocumentSyncKind,
1212
WorkspaceFolder,
13+
Disposable,
14+
ConfigurationRequest,
1315
} from 'vscode-languageserver/node'
1416
import { TextDocument } from 'vscode-languageserver-textdocument'
1517
import { Utils, URI } from 'vscode-uri'
@@ -116,15 +118,18 @@ function getDocumentContext(
116118
async function withDocumentAndSettings<T>(
117119
uri: string,
118120
augmentCss: boolean,
119-
callback: (result: { document: TextDocument; settings: LanguageSettings }) => T | Promise<T>
121+
callback: (result: {
122+
document: TextDocument
123+
settings: LanguageSettings | undefined
124+
}) => T | Promise<T>
120125
): Promise<T> {
121126
let document = documents.get(uri)
122127
if (!document) {
123128
return null
124129
}
125130
return await callback({
126131
document: augmentCss ? createVirtualCssDocument(document) : document,
127-
settings: await getDocumentSettings(uri),
132+
settings: await getDocumentSettings(document),
128133
})
129134
}
130135

@@ -135,14 +140,14 @@ connection.onCompletion(async ({ textDocument, position }, _token) =>
135140
position,
136141
stylesheets.get(document),
137142
getDocumentContext(document.uri, workspaceFolders),
138-
settings.completion
143+
settings?.completion
139144
)
140145
)
141146
)
142147

143148
connection.onHover(({ textDocument, position }, _token) =>
144149
withDocumentAndSettings(textDocument.uri, true, ({ document, settings }) =>
145-
cssLanguageService.doHover(document, position, stylesheets.get(document), settings.hover)
150+
cssLanguageService.doHover(document, position, stylesheets.get(document), settings?.hover)
146151
)
147152
)
148153

@@ -226,32 +231,70 @@ connection.onRenameRequest(({ textDocument, position, newName }) =>
226231
)
227232
)
228233

229-
let documentSettings: Map<string, Thenable<LanguageSettings>> = new Map()
230-
function getDocumentSettings(resource: string): Thenable<LanguageSettings> {
231-
let result = documentSettings.get(resource)
232-
if (!result) {
233-
result = connection.workspace.getConfiguration({
234-
scopeUri: resource,
235-
section: 'css',
236-
})
237-
documentSettings.set(resource, result)
234+
let documentSettings: { [key: string]: Thenable<LanguageSettings | undefined> } = {}
235+
documents.onDidClose((e) => {
236+
delete documentSettings[e.document.uri]
237+
})
238+
function getDocumentSettings(textDocument: TextDocument): Thenable<LanguageSettings | undefined> {
239+
let promise = documentSettings[textDocument.uri]
240+
if (!promise) {
241+
const configRequestParam = {
242+
items: [{ scopeUri: textDocument.uri, section: 'css' }],
243+
}
244+
promise = connection
245+
.sendRequest(ConfigurationRequest.type, configRequestParam)
246+
.then((s) => s[0])
247+
documentSettings[textDocument.uri] = promise
238248
}
239-
return result
249+
return promise
240250
}
241251

242-
connection.onDidChangeConfiguration((_change) => {
243-
documentSettings.clear()
244-
documents.all().forEach(validateTextDocument)
252+
connection.onDidChangeConfiguration((change) => {
253+
updateConfiguration(<LanguageSettings>change.settings.css)
245254
})
246255

256+
function updateConfiguration(settings: LanguageSettings) {
257+
cssLanguageService.configure(settings)
258+
// reset all document settings
259+
documentSettings = {}
260+
documents.all().forEach(triggerValidation)
261+
}
262+
263+
const pendingValidationRequests: { [uri: string]: Disposable } = {}
264+
const validationDelayMs = 500
265+
266+
const timer = {
267+
setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): Disposable {
268+
const handle = setTimeout(callback, ms, ...args)
269+
return { dispose: () => clearTimeout(handle) }
270+
},
271+
}
272+
247273
documents.onDidChangeContent((change) => {
248-
validateTextDocument(change.document)
274+
triggerValidation(change.document)
249275
})
250276

251-
documents.onDidClose((e) => {
252-
documentSettings.delete(e.document.uri)
277+
documents.onDidClose((event) => {
278+
cleanPendingValidation(event.document)
279+
connection.sendDiagnostics({ uri: event.document.uri, diagnostics: [] })
253280
})
254281

282+
function cleanPendingValidation(textDocument: TextDocument): void {
283+
const request = pendingValidationRequests[textDocument.uri]
284+
if (request) {
285+
request.dispose()
286+
delete pendingValidationRequests[textDocument.uri]
287+
}
288+
}
289+
290+
function triggerValidation(textDocument: TextDocument): void {
291+
cleanPendingValidation(textDocument)
292+
pendingValidationRequests[textDocument.uri] = timer.setTimeout(() => {
293+
delete pendingValidationRequests[textDocument.uri]
294+
validateTextDocument(textDocument)
295+
}, validationDelayMs)
296+
}
297+
255298
function replace(delta = 0) {
256299
return (_match: string, p1: string) => {
257300
let lines = p1.split('\n')
@@ -281,7 +324,7 @@ function createVirtualCssDocument(textDocument: TextDocument): TextDocument {
281324
async function validateTextDocument(textDocument: TextDocument): Promise<void> {
282325
textDocument = createVirtualCssDocument(textDocument)
283326

284-
let settings = await getDocumentSettings(textDocument.uri)
327+
let settings = await getDocumentSettings(textDocument)
285328

286329
// let stylesheet = cssLanguageService.parseStylesheet(textDocument) as any
287330
// stylesheet.acceptVisitor({

packages/vscode-tailwindcss/src/extension.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ export async function activate(context: ExtensionContext) {
215215
{
216216
documentSelector: [{ language: 'tailwindcss' }],
217217
outputChannelName: 'Tailwind CSS Language Mode',
218+
synchronize: { configurationSection: ['css'] },
218219
middleware: {
219220
provideCompletionItem(document, position, context, token, next) {
220221
function updateRanges(item: CompletionItem) {

0 commit comments

Comments
 (0)