Add automatic support for multi-config workspaces, including `@config` resolution (#633)
* wip * wip * Boot client if a CSS file contains `@config` * wip * Check document exists * wip * Fix duplicate document selector * wip * Use enum for document selector priorities * Delete unused functions * Remove unused state type * Share glob patterns * Update config file glob * fix logs * Fix filename checks on Windows * Don't show error popups * wip * handle negated content paths * Handle non-tailwind dependency installs * add package root to document selectors * tidy * wip * dedupe document selectors * Fix `@config` regex * Fix document selectors when using `experimental.configFile` * Remove logmaster
parent
68750d859b
commit
b26e122fac
|
@ -0,0 +1,3 @@
|
|||
export const CONFIG_GLOB = '{tailwind,tailwind.config,tailwind.*.config,tailwind.config.*}.{js,cjs}'
|
||||
export const PACKAGE_LOCK_GLOB = '{package-lock.json,yarn.lock,pnpm-lock.yaml}'
|
||||
export const CSS_GLOB = '*.{css,scss,sass,less,pcss}'
|
|
@ -20,15 +20,3 @@ export function clearDiagnostics(state: State, document: TextDocument): void {
|
|||
diagnostics: [],
|
||||
})
|
||||
}
|
||||
|
||||
export function clearAllDiagnostics(state: State): void {
|
||||
state.editor?.documents.all().forEach((document) => {
|
||||
clearDiagnostics(state, document)
|
||||
})
|
||||
}
|
||||
|
||||
export function updateAllDiagnostics(state: State): void {
|
||||
state.editor?.documents.all().forEach((document) => {
|
||||
provideDiagnostics(state, document)
|
||||
})
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -25,11 +25,11 @@ export function showError(
|
|||
message: string = 'Tailwind CSS'
|
||||
): void {
|
||||
console.error(formatError(message, err))
|
||||
if (!(err instanceof SilentError)) {
|
||||
connection.sendNotification('@/tailwindCSS/error', {
|
||||
message: formatError(message, err, false),
|
||||
})
|
||||
}
|
||||
// if (!(err instanceof SilentError)) {
|
||||
// connection.sendNotification('@/tailwindCSS/error', {
|
||||
// message: formatError(message, err, false),
|
||||
// })
|
||||
// }
|
||||
}
|
||||
|
||||
export function SilentError(message: string) {
|
||||
|
|
|
@ -24,6 +24,7 @@ async function getDiagnosticsFromCodeActionParams(
|
|||
only?: DiagnosticKind[]
|
||||
): Promise<AugmentedDiagnostic[]> {
|
||||
let document = state.editor.documents.get(params.textDocument.uri)
|
||||
if (!document) return []
|
||||
let diagnostics = await doValidate(state, document, only)
|
||||
|
||||
return params.context.diagnostics
|
||||
|
@ -40,6 +41,10 @@ async function getDiagnosticsFromCodeActionParams(
|
|||
}
|
||||
|
||||
export async function doCodeActions(state: State, params: CodeActionParams): Promise<CodeAction[]> {
|
||||
if (!state.enabled) {
|
||||
return []
|
||||
}
|
||||
|
||||
let diagnostics = await getDiagnosticsFromCodeActionParams(
|
||||
state,
|
||||
params,
|
||||
|
|
|
@ -25,6 +25,7 @@ export async function provideInvalidApplyCodeActions(
|
|||
diagnostic: InvalidApplyDiagnostic
|
||||
): Promise<CodeAction[]> {
|
||||
let document = state.editor.documents.get(params.textDocument.uri)
|
||||
if (!document) return []
|
||||
let documentText = getTextWithoutComments(document, 'css')
|
||||
let cssRange: Range
|
||||
let cssText = documentText
|
||||
|
|
|
@ -50,29 +50,3 @@ export async function doValidate(
|
|||
]
|
||||
: []
|
||||
}
|
||||
|
||||
export async function provideDiagnostics(state: State, document: TextDocument) {
|
||||
// state.editor.connection.sendDiagnostics({
|
||||
// uri: document.uri,
|
||||
// diagnostics: await doValidate(state, document),
|
||||
// })
|
||||
}
|
||||
|
||||
export function clearDiagnostics(state: State, document: TextDocument): void {
|
||||
// state.editor.connection.sendDiagnostics({
|
||||
// uri: document.uri,
|
||||
// diagnostics: [],
|
||||
// })
|
||||
}
|
||||
|
||||
export function clearAllDiagnostics(state: State): void {
|
||||
state.editor.documents.all().forEach((document) => {
|
||||
clearDiagnostics(state, document)
|
||||
})
|
||||
}
|
||||
|
||||
export function updateAllDiagnostics(state: State): void {
|
||||
state.editor.documents.all().forEach((document) => {
|
||||
provideDiagnostics(state, document)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ export type EditorState = {
|
|||
connection: Connection
|
||||
folder: string
|
||||
documents: TextDocuments<TextDocument>
|
||||
globalSettings: Settings
|
||||
userLanguages: Record<string, string>
|
||||
capabilities: {
|
||||
configuration: boolean
|
||||
|
|
|
@ -42,14 +42,13 @@ import isObject from 'tailwindcss-language-service/src/util/isObject'
|
|||
import { dedupe, equal } from 'tailwindcss-language-service/src/util/array'
|
||||
import namedColors from 'color-name'
|
||||
import minimatch from 'minimatch'
|
||||
import { CONFIG_GLOB, CSS_GLOB } from 'tailwindcss-language-server/src/lib/constants'
|
||||
|
||||
const colorNames = Object.keys(namedColors)
|
||||
|
||||
const CLIENT_ID = 'tailwindcss-intellisense'
|
||||
const CLIENT_NAME = 'Tailwind CSS IntelliSense'
|
||||
|
||||
const CONFIG_FILE_GLOB = '{tailwind,tailwind.config}.{js,cjs}'
|
||||
|
||||
let clients: Map<string, LanguageClient> = new Map()
|
||||
let languages: Map<string, string[]> = new Map()
|
||||
let searchedFolders: Set<string> = new Set()
|
||||
|
@ -131,6 +130,11 @@ function mergeExcludes(settings: WorkspaceConfiguration, scope: ConfigurationSco
|
|||
}
|
||||
}
|
||||
|
||||
async function fileContainsAtConfig(uri: Uri) {
|
||||
let contents = (await Workspace.fs.readFile(uri)).toString()
|
||||
return /@config\s*['"]/.test(contents)
|
||||
}
|
||||
|
||||
export async function activate(context: ExtensionContext) {
|
||||
let module = context.asAbsolutePath(path.join('dist', 'server.js'))
|
||||
let prod = path.join('dist', 'tailwindServer.js')
|
||||
|
@ -206,20 +210,36 @@ export async function activate(context: ExtensionContext) {
|
|||
// )
|
||||
// )
|
||||
|
||||
let watcher = Workspace.createFileSystemWatcher(`**/${CONFIG_FILE_GLOB}`, false, true, true)
|
||||
let configWatcher = Workspace.createFileSystemWatcher(`**/${CONFIG_GLOB}`, false, true, true)
|
||||
|
||||
watcher.onDidCreate((uri) => {
|
||||
configWatcher.onDidCreate((uri) => {
|
||||
let folder = Workspace.getWorkspaceFolder(uri)
|
||||
if (!folder) {
|
||||
if (!folder || isExcluded(uri.fsPath, folder)) {
|
||||
return
|
||||
}
|
||||
if (!isExcluded(uri.fsPath, folder)) {
|
||||
folder = getOuterMostWorkspaceFolder(folder)
|
||||
bootWorkspaceClient(folder)
|
||||
})
|
||||
|
||||
context.subscriptions.push(configWatcher)
|
||||
|
||||
let cssWatcher = Workspace.createFileSystemWatcher(`**/${CSS_GLOB}`, false, false, true)
|
||||
|
||||
async function bootClientIfCssFileContainsAtConfig(uri: Uri) {
|
||||
let folder = Workspace.getWorkspaceFolder(uri)
|
||||
if (!folder || isExcluded(uri.fsPath, folder)) {
|
||||
return
|
||||
}
|
||||
if (await fileContainsAtConfig(uri)) {
|
||||
folder = getOuterMostWorkspaceFolder(folder)
|
||||
bootWorkspaceClient(folder)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
context.subscriptions.push(watcher)
|
||||
cssWatcher.onDidCreate(bootClientIfCssFileContainsAtConfig)
|
||||
cssWatcher.onDidChange(bootClientIfCssFileContainsAtConfig)
|
||||
|
||||
context.subscriptions.push(cssWatcher)
|
||||
|
||||
// TODO: check if the actual language MAPPING changed
|
||||
// not just the language IDs
|
||||
|
@ -607,16 +627,27 @@ export async function activate(context: ExtensionContext) {
|
|||
searchedFolders.add(folder.uri.toString())
|
||||
|
||||
let [configFile] = await Workspace.findFiles(
|
||||
new RelativePattern(folder, `**/${CONFIG_FILE_GLOB}`),
|
||||
new RelativePattern(folder, `**/${CONFIG_GLOB}`),
|
||||
`{${getExcludePatterns(folder).join(',')}}`,
|
||||
1
|
||||
)
|
||||
|
||||
if (!configFile) {
|
||||
if (configFile) {
|
||||
bootWorkspaceClient(folder)
|
||||
return
|
||||
}
|
||||
|
||||
bootWorkspaceClient(folder)
|
||||
let cssFiles = await Workspace.findFiles(
|
||||
new RelativePattern(folder, `**/${CSS_GLOB}`),
|
||||
`{${getExcludePatterns(folder).join(',')}}`
|
||||
)
|
||||
|
||||
for (let cssFile of cssFiles) {
|
||||
if (await fileContainsAtConfig(cssFile)) {
|
||||
bootWorkspaceClient(folder)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.subscriptions.push(Workspace.onDidOpenTextDocument(didOpenTextDocument))
|
||||
|
|
Loading…
Reference in New Issue