Home

tailwind-ctp-intellisense @master - refs - log -
-
https://git.jolheiser.com/tailwind-ctp-intellisense.git
Tailwind intellisense + Catppuccin
tree log patch
use lsp file events when available
Brad Cornes <bradlc41@gmail.com>
3 years ago
1 changed files, 85 additions(+), 38 deletions(-)
M packages/tailwindcss-language-server/src/server.tspackages/tailwindcss-language-server/src/server.ts
diff --git a/packages/tailwindcss-language-server/src/server.ts b/packages/tailwindcss-language-server/src/server.ts
index 809c79d62601bebcdd608f705dbb9bb52f58af18..463b3639274bdd51cad3d85e985a347296370a9e 100644
--- a/packages/tailwindcss-language-server/src/server.ts
+++ b/packages/tailwindcss-language-server/src/server.ts
@@ -23,6 +23,8 @@   BulkRegistration,
   CodeActionRequest,
   BulkUnregistration,
   HoverRequest,
+  DidChangeWatchedFilesNotification,
+  FileChangeType,
 } from 'vscode-languageserver/node'
 import { TextDocument } from 'vscode-languageserver-textdocument'
 import { URI } from 'vscode-uri'
@@ -32,7 +34,7 @@ import normalizePath from 'normalize-path'
 import * as path from 'path'
 import * as os from 'os'
 import * as fs from 'fs'
-import chokidar from 'chokidar'
+import chokidar, { FSWatcher } from 'chokidar'
 import findUp from 'find-up'
 import minimatch from 'minimatch'
 import resolveFrom, { setPnpApi } from './util/resolveFrom'
@@ -206,47 +208,87 @@
   const documentSettingsCache: Map<string, Settings> = new Map()
   let registrations: Promise<BulkUnregistration>
 
-  const watcher = chokidar.watch(
-    [normalizePath(`${folder}/**/${CONFIG_FILE_GLOB}`), normalizePath(`${folder}/**/package.json`)],
-    {
-      ignorePermissionErrors: true,
-      ignoreInitial: true,
-      ignored: ['**/node_modules/**'],
-      awaitWriteFinish: {
-        stabilityThreshold: 100,
-        pollInterval: 20,
-      },
+  let watcher: FSWatcher
+
+  function onFileEvents(changes: Array<{ file: string; type: FileChangeType }>): void {
+    let needsInit = false
+    let needsRebuild = false
+
+    for (let change of changes) {
+      let file = normalizePath(change.file)
+
+      if (change.type === FileChangeType.Created) {
+        needsInit = true
+        break
+      } else if (change.type === FileChangeType.Changed) {
+        if (!state.enabled || minimatch(file, '**/package.json')) {
+          needsInit = true
+          break
+        } else {
+          needsRebuild = true
+        }
+      } else if (change.type === FileChangeType.Deleted) {
+        if (
+          !state.enabled ||
+          minimatch(file, '**/package.json') ||
+          minimatch(file, `**/${CONFIG_FILE_GLOB}`)
+        ) {
+          needsInit = true
+          break
+        } else {
+          needsRebuild = true
+        }
+      }
     }
-  )
 
-  await new Promise<void>((resolve) => {
-    watcher.on('ready', () => resolve())
-  })
+    if (needsInit) {
+      tryInit()
+    } else if (needsRebuild) {
+      tryRebuild()
+    }
+  }
 
-  watcher
-    .on('add', () => {
-      tryInit()
+  if (params.capabilities.workspace?.didChangeWatchedFiles?.dynamicRegistration) {
+    connection.onDidChangeWatchedFiles(({ changes }) => {
+      onFileEvents(
+        changes.map(({ uri, type }) => ({
+          file: URI.parse(uri).fsPath,
+          type,
+        }))
+      )
     })
-    .on('unlink', (file) => {
-      if (
-        !state.enabled ||
-        minimatch(file, '**/package.json') ||
-        minimatch(file, `**/${CONFIG_FILE_GLOB}`)
-      ) {
-        tryInit()
-      } else {
-        tryRebuild()
-      }
+
+    connection.client.register(DidChangeWatchedFilesNotification.type, {
+      watchers: [{ globPattern: `**/${CONFIG_FILE_GLOB}` }, { globPattern: '**/package.json' }],
     })
-    .on('change', (file) => {
-      if (!state.enabled || minimatch(file, '**/package.json')) {
-        tryInit()
-      } else {
-        tryRebuild()
+  } else {
+    watcher = chokidar.watch(
+      [
+        normalizePath(`${folder}/**/${CONFIG_FILE_GLOB}`),
+        normalizePath(`${folder}/**/package.json`),
+      ],
+      {
+        ignorePermissionErrors: true,
+        ignoreInitial: true,
+        ignored: ['**/node_modules/**'],
+        awaitWriteFinish: {
+          stabilityThreshold: 100,
+          pollInterval: 20,
+        },
       }
+    )
+
+    await new Promise<void>((resolve) => {
+      watcher.on('ready', () => resolve())
     })
 
-  function registerCapabilities(): void {
+    watcher
+      .on('add', (file) => onFileEvents([{ file, type: FileChangeType.Created }]))
+      .on('change', (file) => onFileEvents([{ file, type: FileChangeType.Changed }]))
+      .on('unlink', (file) => onFileEvents([{ file, type: FileChangeType.Deleted }]))
+  }
+
+  function registerCapabilities(watchFiles?: string[]): void {
     if (supportsDynamicRegistration(connection, params)) {
       if (registrations) {
         registrations.then((r) => r.dispose())
@@ -268,6 +310,11 @@         documentSelector: null,
         resolveProvider: true,
         triggerCharacters: [...TRIGGER_CHARACTERS, state.separator],
       })
+      if (watchFiles) {
+        capabilities.add(DidChangeWatchedFilesNotification.type, {
+          watchers: watchFiles.map((file) => ({ globPattern: file })),
+        })
+      }
 
       registrations = connection.client.register(capabilities)
     }
@@ -766,10 +813,10 @@       hook.unhook()
     }
 
     if (state.dependencies) {
-      watcher.unwatch(state.dependencies)
+      watcher?.unwatch(state.dependencies)
     }
     state.dependencies = getModuleDependencies(state.configPath)
-    watcher.add(state.dependencies)
+    watcher?.add(state.dependencies)
 
     state.configId = getConfigId(state.configPath, state.dependencies)
 
@@ -784,7 +831,7 @@     state.enabled = true
 
     updateAllDiagnostics(state)
 
-    registerCapabilities()
+    registerCapabilities(state.dependencies)
   }
 
   return {
@@ -796,7 +843,7 @@       if (state.enabled) {
         updateAllDiagnostics(state)
       }
       if (settings.editor.colorDecorators) {
-        registerCapabilities()
+        registerCapabilities(state.dependencies)
       } else {
         connection.sendNotification('@/tailwindCSS/clearColors')
       }