From 20c41600db869bbb46e964ebda2319eb97c5a73e Mon Sep 17 00:00:00 2001 From: Brad Cornes Date: Mon, 15 Jun 2020 14:31:04 +0100 Subject: [PATCH] make diagnostics settings language-overridable --- package.json | 21 ++++++++++++------ src/extension.ts | 5 +++++ src/lib/emitter.ts | 7 ++++-- src/lsp/notifications.ts | 5 +++-- src/lsp/providers/completionProvider.ts | 6 +++--- src/lsp/providers/diagnosticsProvider.ts | 2 +- src/lsp/server.ts | 27 ++++++++++++++++++------ src/lsp/util/getDocumentSettings.ts | 12 +++++------ src/lsp/util/state.ts | 2 ++ 9 files changed, 60 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index 4b0281d..9b33935 100755 --- a/package.json +++ b/package.json @@ -73,7 +73,8 @@ "tailwindCSS.validate": { "type": "boolean", "default": true, - "markdownDescription": "" + "markdownDescription": "", + "scope": "language-overridable" }, "tailwindCSS.lint.utilityConflicts": { "type": "string", @@ -83,7 +84,8 @@ "error" ], "default": "warning", - "markdownDescription": "" + "markdownDescription": "", + "scope": "language-overridable" }, "tailwindCSS.lint.unsupportedApply": { "type": "string", @@ -93,7 +95,8 @@ "error" ], "default": "error", - "markdownDescription": "" + "markdownDescription": "", + "scope": "language-overridable" }, "tailwindCSS.lint.unknownScreen": { "type": "string", @@ -103,7 +106,8 @@ "error" ], "default": "error", - "markdownDescription": "" + "markdownDescription": "", + "scope": "language-overridable" }, "tailwindCSS.lint.unknownVariant": { "type": "string", @@ -113,7 +117,8 @@ "error" ], "default": "error", - "markdownDescription": "" + "markdownDescription": "", + "scope": "language-overridable" }, "tailwindCSS.lint.unknownConfigKey": { "type": "string", @@ -123,7 +128,8 @@ "error" ], "default": "error", - "markdownDescription": "" + "markdownDescription": "", + "scope": "language-overridable" }, "tailwindCSS.lint.unsupportedTailwindDirective": { "type": "string", @@ -133,7 +139,8 @@ "error" ], "default": "error", - "markdownDescription": "" + "markdownDescription": "", + "scope": "language-overridable" } } } diff --git a/src/extension.ts b/src/extension.ts index be1fe47..279ec96 100755 --- a/src/extension.ts +++ b/src/extension.ts @@ -11,6 +11,7 @@ import { OutputChannel, WorkspaceFolder, Uri, + ConfigurationScope, } from 'vscode' import { LanguageClient, @@ -22,6 +23,7 @@ import { DEFAULT_LANGUAGES } from './lib/languages' import isObject from './util/isObject' import { dedupe, equal } from './util/array' import { createEmitter } from './lib/emitter' +import { onMessage } from './lsp/notifications' const CLIENT_ID = 'tailwindcss-intellisense' const CLIENT_NAME = 'Tailwind CSS IntelliSense' @@ -150,6 +152,9 @@ export function activate(context: ExtensionContext) { client.onReady().then(() => { let emitter = createEmitter(client) registerConfigErrorHandler(emitter) + onMessage(client, 'getConfiguration', async (scope) => { + return Workspace.getConfiguration('tailwindCSS', scope) + }) }) client.start() diff --git a/src/lib/emitter.ts b/src/lib/emitter.ts index d177c2c..3ad6f05 100644 --- a/src/lib/emitter.ts +++ b/src/lib/emitter.ts @@ -1,6 +1,7 @@ import mitt from 'mitt' import { LanguageClient } from 'vscode-languageclient' import crypto from 'crypto' +import { Connection } from 'vscode-languageserver' export interface NotificationEmitter { on: (name: string, handler: (args: any) => void) => void @@ -8,7 +9,9 @@ export interface NotificationEmitter { emit: (name: string, args: any) => Promise } -export function createEmitter(client: LanguageClient): NotificationEmitter { +export function createEmitter( + client: LanguageClient | Connection +): NotificationEmitter { const emitter = mitt() const registered: string[] = [] @@ -26,7 +29,7 @@ export function createEmitter(client: LanguageClient): NotificationEmitter { emitter.off(name, handler) } - const emit = (name: string, params: any) => { + const emit = (name: string, params: Record = {}) => { return new Promise((resolve, _reject) => { const id = crypto.randomBytes(16).toString('hex') on(`${name}Response`, (result) => { diff --git a/src/lsp/notifications.ts b/src/lsp/notifications.ts index bb4e60d..e8f4ab8 100644 --- a/src/lsp/notifications.ts +++ b/src/lsp/notifications.ts @@ -1,9 +1,10 @@ import { Connection } from 'vscode-languageserver' +import { LanguageClient } from 'vscode-languageclient' export function onMessage( - connection: Connection, + connection: LanguageClient | Connection, name: string, - handler: (params: any) => any + handler: (params: any) => Thenable> ): void { connection.onNotification(`tailwindcss/${name}`, async (params: any) => { const { _id, ...rest } = params diff --git a/src/lsp/providers/completionProvider.ts b/src/lsp/providers/completionProvider.ts index 6dbb1e7..ec93d44 100644 --- a/src/lsp/providers/completionProvider.ts +++ b/src/lsp/providers/completionProvider.ts @@ -618,11 +618,11 @@ async function provideEmmetCompletions( state: State, { position, textDocument }: CompletionParams ): Promise { - let settings = await getDocumentSettings(state, textDocument.uri) - if (settings.emmetCompletions !== true) return null - let doc = state.editor.documents.get(textDocument.uri) + let settings = await getDocumentSettings(state, doc) + if (settings.emmetCompletions !== true) return null + const syntax = isHtmlContext(state, doc, position) ? 'html' : isJsContext(state, doc, position) diff --git a/src/lsp/providers/diagnosticsProvider.ts b/src/lsp/providers/diagnosticsProvider.ts index bb59ff5..42609a0 100644 --- a/src/lsp/providers/diagnosticsProvider.ts +++ b/src/lsp/providers/diagnosticsProvider.ts @@ -376,7 +376,7 @@ export async function provideDiagnostics( state: State, document: TextDocument ): Promise { - const settings = await getDocumentSettings(state, document.uri) + const settings = await getDocumentSettings(state, document) const diagnostics: Diagnostic[] = settings.validate ? [ diff --git a/src/lsp/server.ts b/src/lsp/server.ts index 9c9aa35..118c5a3 100644 --- a/src/lsp/server.ts +++ b/src/lsp/server.ts @@ -27,9 +27,10 @@ import { provideHover } from './providers/hoverProvider' import { URI } from 'vscode-uri' import { getDocumentSettings } from './util/getDocumentSettings' import { provideDiagnostics } from './providers/diagnosticsProvider' +import { createEmitter } from '../lib/emitter' -let state: State = { enabled: false } let connection = createConnection(ProposedFeatures.all) +let state: State = { enabled: false, emitter: createEmitter(connection) } let documents = new TextDocuments() let workspaceFolder: string | null @@ -50,7 +51,7 @@ let globalSettings: Settings = defaultSettings let documentSettings: Map = new Map() documents.onDidOpen((event) => { - getDocumentSettings(state, event.document.uri) + getDocumentSettings(state, event.document) }) documents.onDidClose((event) => { documentSettings.delete(event.document.uri) @@ -90,14 +91,23 @@ connection.onInitialize( // @ts-ignore onChange: (newState: State): void => { if (newState && !newState.error) { - state = { ...newState, enabled: true, editor: editorState } + state = { + ...newState, + enabled: true, + emitter: state.emitter, + editor: editorState, + } connection.sendNotification('tailwindcss/configUpdated', [ state.configPath, state.config, state.plugins, ]) } else { - state = { enabled: false, editor: editorState } + state = { + enabled: false, + emitter: state.emitter, + editor: editorState, + } if (newState && newState.error) { const payload: { message: string @@ -120,9 +130,14 @@ connection.onInitialize( ) if (tailwindState) { - state = { enabled: true, editor: editorState, ...tailwindState } + state = { + enabled: true, + emitter: state.emitter, + editor: editorState, + ...tailwindState, + } } else { - state = { enabled: false, editor: editorState } + state = { enabled: false, emitter: state.emitter, editor: editorState } } return { diff --git a/src/lsp/util/getDocumentSettings.ts b/src/lsp/util/getDocumentSettings.ts index 3ee25bd..2f127de 100644 --- a/src/lsp/util/getDocumentSettings.ts +++ b/src/lsp/util/getDocumentSettings.ts @@ -1,19 +1,19 @@ import { State, Settings } from './state' +import { TextDocument } from 'vscode-languageserver' export async function getDocumentSettings( state: State, - resource: string + document: TextDocument ): Promise { if (!state.editor.capabilities.configuration) { return Promise.resolve(state.editor.globalSettings) } - let result = state.editor.documentSettings.get(resource) + let result = state.editor.documentSettings.get(document.uri) if (!result) { - result = await state.editor.connection.workspace.getConfiguration({ - scopeUri: resource, - section: 'tailwindCSS', + result = await state.emitter.emit('getConfiguration', { + languageId: document.languageId, }) - state.editor.documentSettings.set(resource, result) + state.editor.documentSettings.set(document.uri, result) } return result } diff --git a/src/lsp/util/state.ts b/src/lsp/util/state.ts index aa9e0f5..5d7e4f4 100644 --- a/src/lsp/util/state.ts +++ b/src/lsp/util/state.ts @@ -1,4 +1,5 @@ import { TextDocuments, Connection, Range } from 'vscode-languageserver' +import { NotificationEmitter } from '../../lib/emitter' export type ClassNamesTree = { [key: string]: ClassNamesTree @@ -43,6 +44,7 @@ export type Settings = { export type State = null | { enabled: boolean + emitter: NotificationEmitter version?: string configPath?: string config?: any