Add `files.exclude` setting
parent
6fdef8616a
commit
ff52e815b6
|
@ -1,12 +1,17 @@
|
||||||
import { TextDocument } from 'vscode-languageserver/node'
|
import { TextDocument } from 'vscode-languageserver/node'
|
||||||
import { State } from 'tailwindcss-language-service/src/util/state'
|
import { State } from 'tailwindcss-language-service/src/util/state'
|
||||||
import { doValidate } from 'tailwindcss-language-service/src/diagnostics/diagnosticsProvider'
|
import { doValidate } from 'tailwindcss-language-service/src/diagnostics/diagnosticsProvider'
|
||||||
|
import isExcluded from '../util/isExcluded'
|
||||||
|
|
||||||
export async function provideDiagnostics(state: State, document: TextDocument) {
|
export async function provideDiagnostics(state: State, document: TextDocument) {
|
||||||
|
if (await isExcluded(state, document)) {
|
||||||
|
clearDiagnostics(state, document)
|
||||||
|
} else {
|
||||||
state.editor?.connection.sendDiagnostics({
|
state.editor?.connection.sendDiagnostics({
|
||||||
uri: document.uri,
|
uri: document.uri,
|
||||||
diagnostics: await doValidate(state, document),
|
diagnostics: await doValidate(state, document),
|
||||||
})
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function clearDiagnostics(state: State, document: TextDocument): void {
|
export function clearDiagnostics(state: State, document: TextDocument): void {
|
||||||
|
|
|
@ -78,6 +78,9 @@ import * as culori from 'culori'
|
||||||
import namedColors from 'color-name'
|
import namedColors from 'color-name'
|
||||||
import preflight from './lib/preflight'
|
import preflight from './lib/preflight'
|
||||||
import tailwindPlugins from './lib/plugins'
|
import tailwindPlugins from './lib/plugins'
|
||||||
|
import isExcluded from './util/isExcluded'
|
||||||
|
import { getFileFsPath, normalizeFileNameToFsPath } from './util/uri'
|
||||||
|
import { equal } from 'tailwindcss-language-service/src/util/array'
|
||||||
|
|
||||||
let oldReadFileSync = fs.readFileSync
|
let oldReadFileSync = fs.readFileSync
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -121,14 +124,6 @@ process.on('unhandledRejection', (e: any) => {
|
||||||
connection.console.error(formatError(`Unhandled exception`, e))
|
connection.console.error(formatError(`Unhandled exception`, e))
|
||||||
})
|
})
|
||||||
|
|
||||||
function normalizeFileNameToFsPath(fileName: string) {
|
|
||||||
return URI.file(fileName).fsPath
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFileFsPath(documentUri: string): string {
|
|
||||||
return URI.parse(documentUri).fsPath
|
|
||||||
}
|
|
||||||
|
|
||||||
function deletePropertyPath(obj: any, path: string | string[]): void {
|
function deletePropertyPath(obj: any, path: string | string[]): void {
|
||||||
if (typeof path === 'string') {
|
if (typeof path === 'string') {
|
||||||
path = path.split('.')
|
path = path.split('.')
|
||||||
|
@ -220,6 +215,7 @@ async function createProjectService(
|
||||||
enabled: false,
|
enabled: false,
|
||||||
editor: {
|
editor: {
|
||||||
connection,
|
connection,
|
||||||
|
folder,
|
||||||
globalSettings: params.initializationOptions.configuration as Settings,
|
globalSettings: params.initializationOptions.configuration as Settings,
|
||||||
userLanguages: params.initializationOptions.userLanguages
|
userLanguages: params.initializationOptions.userLanguages
|
||||||
? params.initializationOptions.userLanguages
|
? params.initializationOptions.userLanguages
|
||||||
|
@ -258,12 +254,7 @@ async function createProjectService(
|
||||||
let registrations: Promise<BulkUnregistration>
|
let registrations: Promise<BulkUnregistration>
|
||||||
|
|
||||||
let chokidarWatcher: chokidar.FSWatcher
|
let chokidarWatcher: chokidar.FSWatcher
|
||||||
let ignore = [
|
let ignore = state.editor.globalSettings.tailwindCSS.files.exclude
|
||||||
'**/.git/objects/**',
|
|
||||||
'**/.git/subtree-cache/**',
|
|
||||||
'**/node_modules/**',
|
|
||||||
'**/.hg/store/**',
|
|
||||||
]
|
|
||||||
|
|
||||||
function onFileEvents(changes: Array<{ file: string; type: FileChangeType }>): void {
|
function onFileEvents(changes: Array<{ file: string; type: FileChangeType }>): void {
|
||||||
let needsInit = false
|
let needsInit = false
|
||||||
|
@ -456,7 +447,7 @@ async function createProjectService(
|
||||||
let [configPath] = (
|
let [configPath] = (
|
||||||
await glob([`**/${CONFIG_FILE_GLOB}`], {
|
await glob([`**/${CONFIG_FILE_GLOB}`], {
|
||||||
cwd: folder,
|
cwd: folder,
|
||||||
ignore: ['**/node_modules'],
|
ignore: state.editor.globalSettings.tailwindCSS.files.exclude,
|
||||||
onlyFiles: true,
|
onlyFiles: true,
|
||||||
absolute: true,
|
absolute: true,
|
||||||
suppressErrors: true,
|
suppressErrors: true,
|
||||||
|
@ -989,6 +980,11 @@ async function createProjectService(
|
||||||
},
|
},
|
||||||
onUpdateSettings(settings: any): void {
|
onUpdateSettings(settings: any): void {
|
||||||
documentSettingsCache.clear()
|
documentSettingsCache.clear()
|
||||||
|
let previousExclude = state.editor.globalSettings.tailwindCSS.files.exclude
|
||||||
|
state.editor.globalSettings = settings
|
||||||
|
if (!equal(previousExclude, settings.tailwindCSS.files.exclude)) {
|
||||||
|
tryInit()
|
||||||
|
} else {
|
||||||
if (state.enabled) {
|
if (state.enabled) {
|
||||||
updateAllDiagnostics(state)
|
updateAllDiagnostics(state)
|
||||||
}
|
}
|
||||||
|
@ -997,17 +993,20 @@ async function createProjectService(
|
||||||
} else {
|
} else {
|
||||||
connection.sendNotification('@/tailwindCSS/clearColors')
|
connection.sendNotification('@/tailwindCSS/clearColors')
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onHover(params: TextDocumentPositionParams): Promise<Hover> {
|
async onHover(params: TextDocumentPositionParams): Promise<Hover> {
|
||||||
if (!state.enabled) return null
|
if (!state.enabled) return null
|
||||||
let document = documentService.getDocument(params.textDocument.uri)
|
let document = documentService.getDocument(params.textDocument.uri)
|
||||||
if (!document) return null
|
if (!document) return null
|
||||||
|
if (await isExcluded(state, document)) return null
|
||||||
return doHover(state, document, params.position)
|
return doHover(state, document, params.position)
|
||||||
},
|
},
|
||||||
onCompletion(params: CompletionParams): Promise<CompletionList> {
|
async onCompletion(params: CompletionParams): Promise<CompletionList> {
|
||||||
if (!state.enabled) return null
|
if (!state.enabled) return null
|
||||||
let document = documentService.getDocument(params.textDocument.uri)
|
let document = documentService.getDocument(params.textDocument.uri)
|
||||||
if (!document) return null
|
if (!document) return null
|
||||||
|
if (await isExcluded(state, document)) return null
|
||||||
return doComplete(state, document, params.position, params.context)
|
return doComplete(state, document, params.position, params.context)
|
||||||
},
|
},
|
||||||
onCompletionResolve(item: CompletionItem): Promise<CompletionItem> {
|
onCompletionResolve(item: CompletionItem): Promise<CompletionItem> {
|
||||||
|
@ -1026,6 +1025,7 @@ async function createProjectService(
|
||||||
if (!state.enabled) return []
|
if (!state.enabled) return []
|
||||||
let document = documentService.getDocument(params.textDocument.uri)
|
let document = documentService.getDocument(params.textDocument.uri)
|
||||||
if (!document) return []
|
if (!document) return []
|
||||||
|
if (await isExcluded(state, document)) return null
|
||||||
return getDocumentColors(state, document)
|
return getDocumentColors(state, document)
|
||||||
},
|
},
|
||||||
async onColorPresentation(params: ColorPresentationParams): Promise<ColorPresentation[]> {
|
async onColorPresentation(params: ColorPresentationParams): Promise<ColorPresentation[]> {
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
import minimatch from 'minimatch'
|
||||||
|
import * as path from 'path'
|
||||||
|
import { State } from 'tailwindcss-language-service/src/util/state'
|
||||||
|
import { TextDocument } from 'vscode-languageserver-textdocument'
|
||||||
|
import { getFileFsPath } from './uri'
|
||||||
|
|
||||||
|
export default async function isExcluded(state: State, document: TextDocument): Promise<boolean> {
|
||||||
|
let settings = await state.editor.getConfiguration(document.uri)
|
||||||
|
let file = getFileFsPath(document.uri)
|
||||||
|
|
||||||
|
for (let pattern of settings.tailwindCSS.files.exclude) {
|
||||||
|
if (minimatch(file, path.join(state.editor.folder, pattern))) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { URI } from 'vscode-uri'
|
||||||
|
|
||||||
|
export function normalizeFileNameToFsPath(fileName: string) {
|
||||||
|
return URI.file(fileName).fsPath
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFileFsPath(documentUri: string): string {
|
||||||
|
return URI.parse(documentUri).fsPath
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ export type ClassNames = {
|
||||||
|
|
||||||
export type EditorState = {
|
export type EditorState = {
|
||||||
connection: Connection
|
connection: Connection
|
||||||
|
folder: string
|
||||||
documents: TextDocuments<TextDocument>
|
documents: TextDocuments<TextDocument>
|
||||||
globalSettings: Settings
|
globalSettings: Settings
|
||||||
userLanguages: Record<string, string>
|
userLanguages: Record<string, string>
|
||||||
|
@ -56,6 +57,9 @@ export type Settings = {
|
||||||
experimental: {
|
experimental: {
|
||||||
classRegex: string[]
|
classRegex: string[]
|
||||||
}
|
}
|
||||||
|
files: {
|
||||||
|
exclude: string[]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,10 @@ This setting allows you to add additional language support. The key of each entr
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `tailwindCSS.files.exclude`
|
||||||
|
|
||||||
|
Configure glob patterns to exclude from all IntelliSense features. Inherits all glob patterns from the `files.exclude` setting. **Default: ["\*\*/.git/\*\*", "\*\*/node_modules/\*\*", "\*\*/.hg/\*\*"]**
|
||||||
|
|
||||||
### `tailwindCSS.emmetCompletions`
|
### `tailwindCSS.emmetCompletions`
|
||||||
|
|
||||||
Enable completions when using [Emmet](https://emmet.io/)-style syntax, for example `div.bg-red-500.uppercase`. **Default: `false`**
|
Enable completions when using [Emmet](https://emmet.io/)-style syntax, for example `div.bg-red-500.uppercase`. **Default: `false`**
|
||||||
|
|
|
@ -119,6 +119,18 @@
|
||||||
"default": {},
|
"default": {},
|
||||||
"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\"}`"
|
"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\"}`"
|
||||||
},
|
},
|
||||||
|
"tailwindCSS.files.exclude": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"default": [
|
||||||
|
"**/.git/**",
|
||||||
|
"**/node_modules/**",
|
||||||
|
"**/.hg/**"
|
||||||
|
],
|
||||||
|
"markdownDescription": "Configure glob patterns to exclude from all IntelliSense features. Inherits all glob patterns from the `#files.exclude#` setting."
|
||||||
|
},
|
||||||
"tailwindCSS.classAttributes": {
|
"tailwindCSS.classAttributes": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
|
|
|
@ -31,6 +31,7 @@ import { languages as defaultLanguages } from 'tailwindcss-language-service/src/
|
||||||
import isObject from 'tailwindcss-language-service/src/util/isObject'
|
import isObject from 'tailwindcss-language-service/src/util/isObject'
|
||||||
import { dedupe, equal } from 'tailwindcss-language-service/src/util/array'
|
import { dedupe, equal } from 'tailwindcss-language-service/src/util/array'
|
||||||
import namedColors from 'color-name'
|
import namedColors from 'color-name'
|
||||||
|
import minimatch from 'minimatch'
|
||||||
|
|
||||||
const colorNames = Object.keys(namedColors)
|
const colorNames = Object.keys(namedColors)
|
||||||
|
|
||||||
|
@ -82,6 +83,45 @@ function getUserLanguages(folder?: WorkspaceFolder): Record<string, string> {
|
||||||
return isObject(langs) ? langs : {}
|
return isObject(langs) ? langs : {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getExcludePatterns(folder: WorkspaceFolder): string[] {
|
||||||
|
let globalExclude = Workspace.getConfiguration('files', folder).get('exclude')
|
||||||
|
let exclude = Object.entries(globalExclude)
|
||||||
|
.filter(([, value]) => value)
|
||||||
|
.map(([key]) => key)
|
||||||
|
|
||||||
|
return [
|
||||||
|
...exclude,
|
||||||
|
...(<string[]>Workspace.getConfiguration('tailwindCSS', folder).get('files.exclude')),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
function isExcluded(file: string, folder: WorkspaceFolder): boolean {
|
||||||
|
let exclude = getExcludePatterns(folder)
|
||||||
|
|
||||||
|
for (let pattern of exclude) {
|
||||||
|
if (minimatch(file, path.join(folder.uri.fsPath, pattern))) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
function mergeExcludes(settings, scope) {
|
||||||
|
// merge `files.exclude` into `tailwindCSS.files.exclude`
|
||||||
|
let globalExclude = Object.entries(Workspace.getConfiguration('files', scope).get('exclude'))
|
||||||
|
.filter(([, value]) => value)
|
||||||
|
.map(([key]) => key)
|
||||||
|
|
||||||
|
return {
|
||||||
|
...settings,
|
||||||
|
files: {
|
||||||
|
...settings.files,
|
||||||
|
exclude: [...globalExclude, ...settings.files.exclude],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function activate(context: ExtensionContext) {
|
export async function activate(context: ExtensionContext) {
|
||||||
let module = context.asAbsolutePath(path.join('dist', 'server', 'index.js'))
|
let module = context.asAbsolutePath(path.join('dist', 'server', 'index.js'))
|
||||||
let prod = path.join('dist', 'server', 'tailwindServer.js')
|
let prod = path.join('dist', 'server', 'tailwindServer.js')
|
||||||
|
@ -108,8 +148,10 @@ export async function activate(context: ExtensionContext) {
|
||||||
if (!folder) {
|
if (!folder) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (!isExcluded(uri.fsPath, folder)) {
|
||||||
folder = getOuterMostWorkspaceFolder(folder)
|
folder = getOuterMostWorkspaceFolder(folder)
|
||||||
bootWorkspaceClient(folder)
|
bootWorkspaceClient(folder)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
context.subscriptions.push(watcher)
|
context.subscriptions.push(watcher)
|
||||||
|
@ -180,7 +222,7 @@ export async function activate(context: ExtensionContext) {
|
||||||
|
|
||||||
let configuration = {
|
let configuration = {
|
||||||
editor: Workspace.getConfiguration('editor', folder),
|
editor: Workspace.getConfiguration('editor', folder),
|
||||||
tailwindCSS: Workspace.getConfiguration('tailwindCSS', folder),
|
tailwindCSS: mergeExcludes(Workspace.getConfiguration('tailwindCSS', folder), folder),
|
||||||
}
|
}
|
||||||
|
|
||||||
let inspectPort = configuration.tailwindCSS.get('inspectPort')
|
let inspectPort = configuration.tailwindCSS.get('inspectPort')
|
||||||
|
@ -309,7 +351,13 @@ export async function activate(context: ExtensionContext) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Workspace.getConfiguration(section, scope)
|
let settings = Workspace.getConfiguration(section, scope)
|
||||||
|
|
||||||
|
if (section === 'tailwindCSS') {
|
||||||
|
return mergeExcludes(settings, scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
return settings
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -375,7 +423,7 @@ export async function activate(context: ExtensionContext) {
|
||||||
|
|
||||||
let [configFile] = await Workspace.findFiles(
|
let [configFile] = await Workspace.findFiles(
|
||||||
new RelativePattern(folder, `**/${CONFIG_FILE_GLOB}`),
|
new RelativePattern(folder, `**/${CONFIG_FILE_GLOB}`),
|
||||||
'**/node_modules/**',
|
`{${getExcludePatterns(folder).join(',')}}`,
|
||||||
1
|
1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue