Skip to content

Commit ff52e81

Browse files
committed
Add files.exclude setting
1 parent 6fdef86 commit ff52e81

File tree

8 files changed

+132
-32
lines changed

8 files changed

+132
-32
lines changed

packages/tailwindcss-language-server/src/lsp/diagnosticsProvider.ts

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
import { TextDocument } from 'vscode-languageserver/node'
22
import { State } from 'tailwindcss-language-service/src/util/state'
33
import { doValidate } from 'tailwindcss-language-service/src/diagnostics/diagnosticsProvider'
4+
import isExcluded from '../util/isExcluded'
45

56
export async function provideDiagnostics(state: State, document: TextDocument) {
6-
state.editor?.connection.sendDiagnostics({
7-
uri: document.uri,
8-
diagnostics: await doValidate(state, document),
9-
})
7+
if (await isExcluded(state, document)) {
8+
clearDiagnostics(state, document)
9+
} else {
10+
state.editor?.connection.sendDiagnostics({
11+
uri: document.uri,
12+
diagnostics: await doValidate(state, document),
13+
})
14+
}
1015
}
1116

1217
export function clearDiagnostics(state: State, document: TextDocument): void {

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

+23-23
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ import * as culori from 'culori'
7878
import namedColors from 'color-name'
7979
import preflight from './lib/preflight'
8080
import tailwindPlugins from './lib/plugins'
81+
import isExcluded from './util/isExcluded'
82+
import { getFileFsPath, normalizeFileNameToFsPath } from './util/uri'
83+
import { equal } from 'tailwindcss-language-service/src/util/array'
8184

8285
let oldReadFileSync = fs.readFileSync
8386
// @ts-ignore
@@ -121,14 +124,6 @@ process.on('unhandledRejection', (e: any) => {
121124
connection.console.error(formatError(`Unhandled exception`, e))
122125
})
123126

124-
function normalizeFileNameToFsPath(fileName: string) {
125-
return URI.file(fileName).fsPath
126-
}
127-
128-
function getFileFsPath(documentUri: string): string {
129-
return URI.parse(documentUri).fsPath
130-
}
131-
132127
function deletePropertyPath(obj: any, path: string | string[]): void {
133128
if (typeof path === 'string') {
134129
path = path.split('.')
@@ -220,6 +215,7 @@ async function createProjectService(
220215
enabled: false,
221216
editor: {
222217
connection,
218+
folder,
223219
globalSettings: params.initializationOptions.configuration as Settings,
224220
userLanguages: params.initializationOptions.userLanguages
225221
? params.initializationOptions.userLanguages
@@ -258,12 +254,7 @@ async function createProjectService(
258254
let registrations: Promise<BulkUnregistration>
259255

260256
let chokidarWatcher: chokidar.FSWatcher
261-
let ignore = [
262-
'**/.git/objects/**',
263-
'**/.git/subtree-cache/**',
264-
'**/node_modules/**',
265-
'**/.hg/store/**',
266-
]
257+
let ignore = state.editor.globalSettings.tailwindCSS.files.exclude
267258

268259
function onFileEvents(changes: Array<{ file: string; type: FileChangeType }>): void {
269260
let needsInit = false
@@ -456,7 +447,7 @@ async function createProjectService(
456447
let [configPath] = (
457448
await glob([`**/${CONFIG_FILE_GLOB}`], {
458449
cwd: folder,
459-
ignore: ['**/node_modules'],
450+
ignore: state.editor.globalSettings.tailwindCSS.files.exclude,
460451
onlyFiles: true,
461452
absolute: true,
462453
suppressErrors: true,
@@ -989,25 +980,33 @@ async function createProjectService(
989980
},
990981
onUpdateSettings(settings: any): void {
991982
documentSettingsCache.clear()
992-
if (state.enabled) {
993-
updateAllDiagnostics(state)
994-
}
995-
if (settings.editor.colorDecorators) {
996-
registerCapabilities(state.dependencies)
983+
let previousExclude = state.editor.globalSettings.tailwindCSS.files.exclude
984+
state.editor.globalSettings = settings
985+
if (!equal(previousExclude, settings.tailwindCSS.files.exclude)) {
986+
tryInit()
997987
} else {
998-
connection.sendNotification('@/tailwindCSS/clearColors')
988+
if (state.enabled) {
989+
updateAllDiagnostics(state)
990+
}
991+
if (settings.editor.colorDecorators) {
992+
registerCapabilities(state.dependencies)
993+
} else {
994+
connection.sendNotification('@/tailwindCSS/clearColors')
995+
}
999996
}
1000997
},
1001-
onHover(params: TextDocumentPositionParams): Promise<Hover> {
998+
async onHover(params: TextDocumentPositionParams): Promise<Hover> {
1002999
if (!state.enabled) return null
10031000
let document = documentService.getDocument(params.textDocument.uri)
10041001
if (!document) return null
1002+
if (await isExcluded(state, document)) return null
10051003
return doHover(state, document, params.position)
10061004
},
1007-
onCompletion(params: CompletionParams): Promise<CompletionList> {
1005+
async onCompletion(params: CompletionParams): Promise<CompletionList> {
10081006
if (!state.enabled) return null
10091007
let document = documentService.getDocument(params.textDocument.uri)
10101008
if (!document) return null
1009+
if (await isExcluded(state, document)) return null
10111010
return doComplete(state, document, params.position, params.context)
10121011
},
10131012
onCompletionResolve(item: CompletionItem): Promise<CompletionItem> {
@@ -1026,6 +1025,7 @@ async function createProjectService(
10261025
if (!state.enabled) return []
10271026
let document = documentService.getDocument(params.textDocument.uri)
10281027
if (!document) return []
1028+
if (await isExcluded(state, document)) return null
10291029
return getDocumentColors(state, document)
10301030
},
10311031
async onColorPresentation(params: ColorPresentationParams): Promise<ColorPresentation[]> {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import minimatch from 'minimatch'
2+
import * as path from 'path'
3+
import { State } from 'tailwindcss-language-service/src/util/state'
4+
import { TextDocument } from 'vscode-languageserver-textdocument'
5+
import { getFileFsPath } from './uri'
6+
7+
export default async function isExcluded(state: State, document: TextDocument): Promise<boolean> {
8+
let settings = await state.editor.getConfiguration(document.uri)
9+
let file = getFileFsPath(document.uri)
10+
11+
for (let pattern of settings.tailwindCSS.files.exclude) {
12+
if (minimatch(file, path.join(state.editor.folder, pattern))) {
13+
return true
14+
}
15+
}
16+
17+
return false
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { URI } from 'vscode-uri'
2+
3+
export function normalizeFileNameToFsPath(fileName: string) {
4+
return URI.file(fileName).fsPath
5+
}
6+
7+
export function getFileFsPath(documentUri: string): string {
8+
return URI.parse(documentUri).fsPath
9+
}

packages/tailwindcss-language-service/src/util/state.ts

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export type ClassNames = {
1919

2020
export type EditorState = {
2121
connection: Connection
22+
folder: string
2223
documents: TextDocuments<TextDocument>
2324
globalSettings: Settings
2425
userLanguages: Record<string, string>
@@ -56,6 +57,9 @@ export type Settings = {
5657
experimental: {
5758
classRegex: string[]
5859
}
60+
files: {
61+
exclude: string[]
62+
}
5963
}
6064
}
6165

packages/vscode-tailwindcss/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ This setting allows you to add additional language support. The key of each entr
6262
}
6363
```
6464

65+
### `tailwindCSS.files.exclude`
66+
67+
Configure glob patterns to exclude from all IntelliSense features. Inherits all glob patterns from the `files.exclude` setting. **Default: ["\*\*/.git/\*\*", "\*\*/node_modules/\*\*", "\*\*/.hg/\*\*"]**
68+
6569
### `tailwindCSS.emmetCompletions`
6670

6771
Enable completions when using [Emmet](https://emmet.io/)-style syntax, for example `div.bg-red-500.uppercase`. **Default: `false`**

packages/vscode-tailwindcss/package.json

+12
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,18 @@
119119
"default": {},
120120
"markdownDescription": "Enable features in languages that are not supported by default. Add a mapping here between the new language and an already supported language.\n E.g.: `{\"plaintext\": \"html\"}`"
121121
},
122+
"tailwindCSS.files.exclude": {
123+
"type": "array",
124+
"items": {
125+
"type": "string"
126+
},
127+
"default": [
128+
"**/.git/**",
129+
"**/node_modules/**",
130+
"**/.hg/**"
131+
],
132+
"markdownDescription": "Configure glob patterns to exclude from all IntelliSense features. Inherits all glob patterns from the `#files.exclude#` setting."
133+
},
122134
"tailwindCSS.classAttributes": {
123135
"type": "array",
124136
"items": {

packages/vscode-tailwindcss/src/extension.ts

+53-5
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { languages as defaultLanguages } from 'tailwindcss-language-service/src/
3131
import isObject from 'tailwindcss-language-service/src/util/isObject'
3232
import { dedupe, equal } from 'tailwindcss-language-service/src/util/array'
3333
import namedColors from 'color-name'
34+
import minimatch from 'minimatch'
3435

3536
const colorNames = Object.keys(namedColors)
3637

@@ -82,6 +83,45 @@ function getUserLanguages(folder?: WorkspaceFolder): Record<string, string> {
8283
return isObject(langs) ? langs : {}
8384
}
8485

86+
function getExcludePatterns(folder: WorkspaceFolder): string[] {
87+
let globalExclude = Workspace.getConfiguration('files', folder).get('exclude')
88+
let exclude = Object.entries(globalExclude)
89+
.filter(([, value]) => value)
90+
.map(([key]) => key)
91+
92+
return [
93+
...exclude,
94+
...(<string[]>Workspace.getConfiguration('tailwindCSS', folder).get('files.exclude')),
95+
]
96+
}
97+
98+
function isExcluded(file: string, folder: WorkspaceFolder): boolean {
99+
let exclude = getExcludePatterns(folder)
100+
101+
for (let pattern of exclude) {
102+
if (minimatch(file, path.join(folder.uri.fsPath, pattern))) {
103+
return true
104+
}
105+
}
106+
107+
return false
108+
}
109+
110+
function mergeExcludes(settings, scope) {
111+
// merge `files.exclude` into `tailwindCSS.files.exclude`
112+
let globalExclude = Object.entries(Workspace.getConfiguration('files', scope).get('exclude'))
113+
.filter(([, value]) => value)
114+
.map(([key]) => key)
115+
116+
return {
117+
...settings,
118+
files: {
119+
...settings.files,
120+
exclude: [...globalExclude, ...settings.files.exclude],
121+
},
122+
}
123+
}
124+
85125
export async function activate(context: ExtensionContext) {
86126
let module = context.asAbsolutePath(path.join('dist', 'server', 'index.js'))
87127
let prod = path.join('dist', 'server', 'tailwindServer.js')
@@ -108,8 +148,10 @@ export async function activate(context: ExtensionContext) {
108148
if (!folder) {
109149
return
110150
}
111-
folder = getOuterMostWorkspaceFolder(folder)
112-
bootWorkspaceClient(folder)
151+
if (!isExcluded(uri.fsPath, folder)) {
152+
folder = getOuterMostWorkspaceFolder(folder)
153+
bootWorkspaceClient(folder)
154+
}
113155
})
114156

115157
context.subscriptions.push(watcher)
@@ -180,7 +222,7 @@ export async function activate(context: ExtensionContext) {
180222

181223
let configuration = {
182224
editor: Workspace.getConfiguration('editor', folder),
183-
tailwindCSS: Workspace.getConfiguration('tailwindCSS', folder),
225+
tailwindCSS: mergeExcludes(Workspace.getConfiguration('tailwindCSS', folder), folder),
184226
}
185227

186228
let inspectPort = configuration.tailwindCSS.get('inspectPort')
@@ -309,7 +351,13 @@ export async function activate(context: ExtensionContext) {
309351
}
310352
}
311353
}
312-
return Workspace.getConfiguration(section, scope)
354+
let settings = Workspace.getConfiguration(section, scope)
355+
356+
if (section === 'tailwindCSS') {
357+
return mergeExcludes(settings, scope)
358+
}
359+
360+
return settings
313361
})
314362
},
315363
},
@@ -375,7 +423,7 @@ export async function activate(context: ExtensionContext) {
375423

376424
let [configFile] = await Workspace.findFiles(
377425
new RelativePattern(folder, `**/${CONFIG_FILE_GLOB}`),
378-
'**/node_modules/**',
426+
`{${getExcludePatterns(folder).join(',')}}`,
379427
1
380428
)
381429

0 commit comments

Comments
 (0)