make diagnostics settings language-overridable

master
Brad Cornes 2020-06-15 14:31:04 +01:00
parent 47f0a8511f
commit 20c41600db
9 changed files with 60 additions and 27 deletions

View File

@ -73,7 +73,8 @@
"tailwindCSS.validate": { "tailwindCSS.validate": {
"type": "boolean", "type": "boolean",
"default": true, "default": true,
"markdownDescription": "" "markdownDescription": "",
"scope": "language-overridable"
}, },
"tailwindCSS.lint.utilityConflicts": { "tailwindCSS.lint.utilityConflicts": {
"type": "string", "type": "string",
@ -83,7 +84,8 @@
"error" "error"
], ],
"default": "warning", "default": "warning",
"markdownDescription": "" "markdownDescription": "",
"scope": "language-overridable"
}, },
"tailwindCSS.lint.unsupportedApply": { "tailwindCSS.lint.unsupportedApply": {
"type": "string", "type": "string",
@ -93,7 +95,8 @@
"error" "error"
], ],
"default": "error", "default": "error",
"markdownDescription": "" "markdownDescription": "",
"scope": "language-overridable"
}, },
"tailwindCSS.lint.unknownScreen": { "tailwindCSS.lint.unknownScreen": {
"type": "string", "type": "string",
@ -103,7 +106,8 @@
"error" "error"
], ],
"default": "error", "default": "error",
"markdownDescription": "" "markdownDescription": "",
"scope": "language-overridable"
}, },
"tailwindCSS.lint.unknownVariant": { "tailwindCSS.lint.unknownVariant": {
"type": "string", "type": "string",
@ -113,7 +117,8 @@
"error" "error"
], ],
"default": "error", "default": "error",
"markdownDescription": "" "markdownDescription": "",
"scope": "language-overridable"
}, },
"tailwindCSS.lint.unknownConfigKey": { "tailwindCSS.lint.unknownConfigKey": {
"type": "string", "type": "string",
@ -123,7 +128,8 @@
"error" "error"
], ],
"default": "error", "default": "error",
"markdownDescription": "" "markdownDescription": "",
"scope": "language-overridable"
}, },
"tailwindCSS.lint.unsupportedTailwindDirective": { "tailwindCSS.lint.unsupportedTailwindDirective": {
"type": "string", "type": "string",
@ -133,7 +139,8 @@
"error" "error"
], ],
"default": "error", "default": "error",
"markdownDescription": "" "markdownDescription": "",
"scope": "language-overridable"
} }
} }
} }

View File

@ -11,6 +11,7 @@ import {
OutputChannel, OutputChannel,
WorkspaceFolder, WorkspaceFolder,
Uri, Uri,
ConfigurationScope,
} from 'vscode' } from 'vscode'
import { import {
LanguageClient, LanguageClient,
@ -22,6 +23,7 @@ import { DEFAULT_LANGUAGES } from './lib/languages'
import isObject from './util/isObject' import isObject from './util/isObject'
import { dedupe, equal } from './util/array' import { dedupe, equal } from './util/array'
import { createEmitter } from './lib/emitter' import { createEmitter } from './lib/emitter'
import { onMessage } from './lsp/notifications'
const CLIENT_ID = 'tailwindcss-intellisense' const CLIENT_ID = 'tailwindcss-intellisense'
const CLIENT_NAME = 'Tailwind CSS IntelliSense' const CLIENT_NAME = 'Tailwind CSS IntelliSense'
@ -150,6 +152,9 @@ export function activate(context: ExtensionContext) {
client.onReady().then(() => { client.onReady().then(() => {
let emitter = createEmitter(client) let emitter = createEmitter(client)
registerConfigErrorHandler(emitter) registerConfigErrorHandler(emitter)
onMessage(client, 'getConfiguration', async (scope) => {
return Workspace.getConfiguration('tailwindCSS', scope)
})
}) })
client.start() client.start()

View File

@ -1,6 +1,7 @@
import mitt from 'mitt' import mitt from 'mitt'
import { LanguageClient } from 'vscode-languageclient' import { LanguageClient } from 'vscode-languageclient'
import crypto from 'crypto' import crypto from 'crypto'
import { Connection } from 'vscode-languageserver'
export interface NotificationEmitter { export interface NotificationEmitter {
on: (name: string, handler: (args: any) => void) => void on: (name: string, handler: (args: any) => void) => void
@ -8,7 +9,9 @@ export interface NotificationEmitter {
emit: (name: string, args: any) => Promise<any> emit: (name: string, args: any) => Promise<any>
} }
export function createEmitter(client: LanguageClient): NotificationEmitter { export function createEmitter(
client: LanguageClient | Connection
): NotificationEmitter {
const emitter = mitt() const emitter = mitt()
const registered: string[] = [] const registered: string[] = []
@ -26,7 +29,7 @@ export function createEmitter(client: LanguageClient): NotificationEmitter {
emitter.off(name, handler) emitter.off(name, handler)
} }
const emit = (name: string, params: any) => { const emit = (name: string, params: Record<string, any> = {}) => {
return new Promise((resolve, _reject) => { return new Promise((resolve, _reject) => {
const id = crypto.randomBytes(16).toString('hex') const id = crypto.randomBytes(16).toString('hex')
on(`${name}Response`, (result) => { on(`${name}Response`, (result) => {

View File

@ -1,9 +1,10 @@
import { Connection } from 'vscode-languageserver' import { Connection } from 'vscode-languageserver'
import { LanguageClient } from 'vscode-languageclient'
export function onMessage( export function onMessage(
connection: Connection, connection: LanguageClient | Connection,
name: string, name: string,
handler: (params: any) => any handler: (params: any) => Thenable<Record<string, any>>
): void { ): void {
connection.onNotification(`tailwindcss/${name}`, async (params: any) => { connection.onNotification(`tailwindcss/${name}`, async (params: any) => {
const { _id, ...rest } = params const { _id, ...rest } = params

View File

@ -618,11 +618,11 @@ async function provideEmmetCompletions(
state: State, state: State,
{ position, textDocument }: CompletionParams { position, textDocument }: CompletionParams
): Promise<CompletionList> { ): Promise<CompletionList> {
let settings = await getDocumentSettings(state, textDocument.uri)
if (settings.emmetCompletions !== true) return null
let doc = state.editor.documents.get(textDocument.uri) 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) const syntax = isHtmlContext(state, doc, position)
? 'html' ? 'html'
: isJsContext(state, doc, position) : isJsContext(state, doc, position)

View File

@ -376,7 +376,7 @@ export async function provideDiagnostics(
state: State, state: State,
document: TextDocument document: TextDocument
): Promise<void> { ): Promise<void> {
const settings = await getDocumentSettings(state, document.uri) const settings = await getDocumentSettings(state, document)
const diagnostics: Diagnostic[] = settings.validate const diagnostics: Diagnostic[] = settings.validate
? [ ? [

View File

@ -27,9 +27,10 @@ import { provideHover } from './providers/hoverProvider'
import { URI } from 'vscode-uri' import { URI } from 'vscode-uri'
import { getDocumentSettings } from './util/getDocumentSettings' import { getDocumentSettings } from './util/getDocumentSettings'
import { provideDiagnostics } from './providers/diagnosticsProvider' import { provideDiagnostics } from './providers/diagnosticsProvider'
import { createEmitter } from '../lib/emitter'
let state: State = { enabled: false }
let connection = createConnection(ProposedFeatures.all) let connection = createConnection(ProposedFeatures.all)
let state: State = { enabled: false, emitter: createEmitter(connection) }
let documents = new TextDocuments() let documents = new TextDocuments()
let workspaceFolder: string | null let workspaceFolder: string | null
@ -50,7 +51,7 @@ let globalSettings: Settings = defaultSettings
let documentSettings: Map<string, Settings> = new Map() let documentSettings: Map<string, Settings> = new Map()
documents.onDidOpen((event) => { documents.onDidOpen((event) => {
getDocumentSettings(state, event.document.uri) getDocumentSettings(state, event.document)
}) })
documents.onDidClose((event) => { documents.onDidClose((event) => {
documentSettings.delete(event.document.uri) documentSettings.delete(event.document.uri)
@ -90,14 +91,23 @@ connection.onInitialize(
// @ts-ignore // @ts-ignore
onChange: (newState: State): void => { onChange: (newState: State): void => {
if (newState && !newState.error) { if (newState && !newState.error) {
state = { ...newState, enabled: true, editor: editorState } state = {
...newState,
enabled: true,
emitter: state.emitter,
editor: editorState,
}
connection.sendNotification('tailwindcss/configUpdated', [ connection.sendNotification('tailwindcss/configUpdated', [
state.configPath, state.configPath,
state.config, state.config,
state.plugins, state.plugins,
]) ])
} else { } else {
state = { enabled: false, editor: editorState } state = {
enabled: false,
emitter: state.emitter,
editor: editorState,
}
if (newState && newState.error) { if (newState && newState.error) {
const payload: { const payload: {
message: string message: string
@ -120,9 +130,14 @@ connection.onInitialize(
) )
if (tailwindState) { if (tailwindState) {
state = { enabled: true, editor: editorState, ...tailwindState } state = {
enabled: true,
emitter: state.emitter,
editor: editorState,
...tailwindState,
}
} else { } else {
state = { enabled: false, editor: editorState } state = { enabled: false, emitter: state.emitter, editor: editorState }
} }
return { return {

View File

@ -1,19 +1,19 @@
import { State, Settings } from './state' import { State, Settings } from './state'
import { TextDocument } from 'vscode-languageserver'
export async function getDocumentSettings( export async function getDocumentSettings(
state: State, state: State,
resource: string document: TextDocument
): Promise<Settings> { ): Promise<Settings> {
if (!state.editor.capabilities.configuration) { if (!state.editor.capabilities.configuration) {
return Promise.resolve(state.editor.globalSettings) return Promise.resolve(state.editor.globalSettings)
} }
let result = state.editor.documentSettings.get(resource) let result = state.editor.documentSettings.get(document.uri)
if (!result) { if (!result) {
result = await state.editor.connection.workspace.getConfiguration({ result = await state.emitter.emit('getConfiguration', {
scopeUri: resource, languageId: document.languageId,
section: 'tailwindCSS',
}) })
state.editor.documentSettings.set(resource, result) state.editor.documentSettings.set(document.uri, result)
} }
return result return result
} }

View File

@ -1,4 +1,5 @@
import { TextDocuments, Connection, Range } from 'vscode-languageserver' import { TextDocuments, Connection, Range } from 'vscode-languageserver'
import { NotificationEmitter } from '../../lib/emitter'
export type ClassNamesTree = { export type ClassNamesTree = {
[key: string]: ClassNamesTree [key: string]: ClassNamesTree
@ -43,6 +44,7 @@ export type Settings = {
export type State = null | { export type State = null | {
enabled: boolean enabled: boolean
emitter: NotificationEmitter
version?: string version?: string
configPath?: string configPath?: string
config?: any config?: any