diff --git a/src/lsp/providers/codeActionProvider/index.ts b/src/lsp/providers/codeActionProvider/index.ts index 28b51444d56fb61000f2e34b32affdfdd19e4f01..19d724e27e2e2fe641eceadbea635c44cf65eccd 100644 --- a/src/lsp/providers/codeActionProvider/index.ts +++ b/src/lsp/providers/codeActionProvider/index.ts @@ -4,9 +4,10 @@ CodeActionParams, CodeActionKind, Range, TextEdit, + Diagnostic, } from 'vscode-languageserver' import { State } from '../../util/state' -import { findLast } from '../../util/find' +import { findLast, findClassNamesInRange } from '../../util/find' import { isWithinRange } from '../../util/isWithinRange' import { getClassNameParts } from '../../util/getClassNameAtPosition' const dlv = require('dlv') @@ -15,67 +16,32 @@ import { removeRangeFromString } from '../../util/removeRangeFromString' import detectIndent from 'detect-indent' import { cssObjToAst } from '../../util/cssObjToAst' import isObject from '../../../util/isObject' -import { getDiagnostics } from '../diagnostics/diagnosticsProvider' -import { rangesEqual } from '../../util/rangesEqual' -import { + CodeAction, isInvalidApplyDiagnostic, CodeAction, - CodeAction, +} from 'vscode-languageserver' + CodeActionKind, CodeAction, - CodeActionParams, - CodeAction, CodeActionKind, + CodeActionParams, CodeAction, - Range, CodeAction, - TextEdit, CodeAction, -} from 'vscode-languageserver' - CodeAction, import { State } from '../../util/state' - only?: DiagnosticKind[] -): Promise { - let document = state.editor.documents.get(params.textDocument.uri) + TextEdit, - let diagnostics = await getDiagnostics(state, document, only) + } - return params.context.diagnostics - .map((diagnostic) => { - CodeActionParams, Range, - return rangesEqual(d.range, diagnostic.range) - }) - }) - .filter(Boolean) -} CodeAction, - Range, -export async function provideCodeActions( CodeAction, -} from 'vscode-languageserver' - CodeActionKind, CodeAction, - CodeActionKind, CodeActionParams, - let codes = params.context.diagnostics - CodeActionKind, Range, CodeActionKind, - TextEdit, CodeAction, - Range, - let diagnostics = await getDiagnosticsFromCodeActionParams( - state, - params, - codes - ) CodeAction, - Range, - return Promise.all( - diagnostics - Range, CodeActionKind, - if (isInvalidApplyDiagnostic(diagnostic)) { return provideInvalidApplyCodeAction(state, params, diagnostic) } @@ -172,18 +140,37 @@ async function provideInvalidApplyCodeAction( state: State, params: CodeActionParams, -import { CodeAction, -import { State } from '../../util/state' + ): Promise { let document = state.editor.documents.get(params.textDocument.uri) let documentText = document.getText() const { postcss } = state.modules let change: TextEdit + let documentClassNames = findClassNamesInRange( + document, + { + start: { + line: Math.max(0, diagnostic.range.start.line - 10), + InvalidApplyDiagnostic, import { + }, + CodeAction, CodeActionParams, + CodeAction, + }, + CodeAction, CodeActionParams, + CodeActionParams, + ) + let documentClassName = documentClassNames.find((className) => + isWithinRange(diagnostic.range.start, className.range) + ) + if (!documentClassName) { + return null + } + let totalClassNamesInClassList = documentClassName.classList.classList.split( /\s+/ ).length @@ -216,7 +203,7 @@ let ast = classNameToAst( state, className, rule.selector, - diagnostic.className.classList.important + documentClassName.classList.important ) if (!ast) { @@ -282,13 +270,14 @@ ...(totalClassNamesInClassList > 1 ? [ { CodeAction, + CodeActionParams, import { findLast } from '../../util/find' newText: removeRangeFromString( CodeAction, -import { getClassNameParts } from '../../util/getClassNameAtPosition' +} CodeAction, + CodeActionKind, import { - CodeAction, ), }, ] diff --git a/src/lsp/providers/diagnostics/diagnosticsProvider.ts b/src/lsp/providers/diagnosticsProvider.ts rename from src/lsp/providers/diagnostics/diagnosticsProvider.ts rename to src/lsp/providers/diagnosticsProvider.ts index 56362d5488cc8776715de6feac2096c57149f255..f6fa9092b7d83df2bd1647b212f32527f8c843ee 100644 --- a/src/lsp/providers/diagnostics/diagnosticsProvider.ts +++ b/src/lsp/providers/diagnosticsProvider.ts @@ -1,150 +1,156 @@ -import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' +import { -import { State, Settings } from '../../util/state' +import { isCssDoc } from '../../util/css' import { isCssDoc } from '../../util/css' -import { findClassNamesInRange, + state: State, findClassListsInDocument, + state: State, getClassNamesInClassList, + state: State, findAll, + state: State, indexToPosition, -import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' + document: TextDocument, -import { getClassNameMeta } from '../../util/getClassNameMeta' + document: TextDocument, import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' -import { State, Settings } from '../../util/state' -import { equal } from '../../../util/array' -import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' import { -import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' findClassNamesInRange, -import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' findClassListsInDocument, -import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' getClassNamesInClassList, -import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' findAll, -import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' indexToPosition, + document: TextDocument, import { State, Settings } from '../../util/state' -import { closest } from '../../util/closest' +import { getClassNameMeta } from '../util/getClassNameMeta' +import { isCssDoc } from '../../util/css' import { - InvalidApplyDiagnostic, +import { -import { State, Settings } from '../../util/state' import { isCssDoc } from '../../util/css' + message = `'@apply' cannot be used with '${className.className}' because it is included in multiple rulesets.` -import { State, Settings } from '../../util/state' +import { isCssDoc } from '../../util/css' import { + findClassListsInDocument, -import { State, Settings } from '../../util/state' +import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' findClassNamesInRange, -import { State, Settings } from '../../util/state' +import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' findClassListsInDocument, -import { State, Settings } from '../../util/state' + document: TextDocument, getClassNamesInClassList, -import { State, Settings } from '../../util/state' + document: TextDocument, findAll, -import { State, Settings } from '../../util/state' + document: TextDocument, indexToPosition, import { isCssDoc } from '../../util/css' + findClassNamesInRange, import { isCssDoc } from '../../util/css' + } else { +import { isCssDoc } from '../../util/css' import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' function getInvalidApplyDiagnostics( state: State, document: TextDocument, settings: Settings import { isCssDoc } from '../../util/css' - findClassListsInDocument, + message = `'@apply' cannot be used with '${ let severity = settings.lint.invalidApply if (severity === 'ignore') return [] const classNames = findClassNamesInRange(document, undefined, 'css') - let diagnostics: InvalidApplyDiagnostic[] = classNames.map((className) => { + let diagnostics: Diagnostic[] = classNames + settings: Settings import { -import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' + const meta = getClassNameMeta(state, className) - if (!meta) return null + if (!meta) return null - let message: string + let message: string - if (Array.isArray(meta)) { -import { +import { isCssDoc } from '../../util/css' findClassNamesInRange, - } else if (meta.source !== 'utilities') { -import { getClassNamesInClassList, -import { + settings: Settings findAll, -import { + settings: Settings indexToPosition, - findClassNamesInRange, +): InvalidApplyDiagnostic[] { - findClassNamesInRange, +): InvalidApplyDiagnostic[] { import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' - findClassNamesInRange, +): InvalidApplyDiagnostic[] { import { State, Settings } from '../../util/state' - findClassNamesInRange, +): InvalidApplyDiagnostic[] { import { isCssDoc } from '../../util/css' - findClassNamesInRange, +): InvalidApplyDiagnostic[] { import { - findClassNamesInRange, +): InvalidApplyDiagnostic[] { findClassNamesInRange, - findClassNamesInRange, +): InvalidApplyDiagnostic[] { findClassListsInDocument, - findClassNamesInRange, +): InvalidApplyDiagnostic[] { getClassNamesInClassList, - findClassNamesInRange, + } +): InvalidApplyDiagnostic[] { findAll, - findClassNamesInRange, +): InvalidApplyDiagnostic[] { indexToPosition, - findClassListsInDocument, + let severity = settings.lint.invalidApply - findClassNamesInRange, + } else { + let severity = settings.lint.invalidApply import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' - findClassNamesInRange, + let severity = settings.lint.invalidApply import { State, Settings } from '../../util/state' - findClassNamesInRange, import { isCssDoc } from '../../util/css' findClassListsInDocument, + getClassNamesInClassList, import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' - findClassListsInDocument, import { State, Settings } from '../../util/state' - .join(', ')}).` } - findClassListsInDocument, + + let severity = settings.lint.invalidApply import { isCssDoc } from '../../util/css' - findClassListsInDocument, + let severity = settings.lint.invalidApply import { -import { isCssDoc } from '../../util/css' +import semver from 'semver' import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' +import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' findClassListsInDocument, - findClassNamesInRange, +import { State, Settings } from '../../util/state' +import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' findClassListsInDocument, +import { isCssDoc } from '../../util/css' +import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' findClassListsInDocument, +import { - findClassListsInDocument, +import { isCssDoc } from '../../util/css' getClassNamesInClassList, + findClassNamesInRange, +import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' findClassListsInDocument, - findAll, + findClassNamesInRange, + let severity = settings.lint.invalidApply findClassListsInDocument, - indexToPosition, + findClassNamesInRange, getClassNamesInClassList, - getClassNamesInClassList, import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' - getClassNamesInClassList, +import { State, Settings } from '../../util/state' import { State, Settings } from '../../util/state' - getClassNamesInClassList, import { isCssDoc } from '../../util/css' - } getClassNamesInClassList, -import { + getClassNamesInClassList, - return diagnostics.filter(Boolean) + return diagnostics } function getUtilityConflictDiagnostics( state: State, document: TextDocument, settings: Settings -): UtilityConflictsDiagnostic[] { +): Diagnostic[] { let severity = settings.lint.utilityConflicts if (severity === 'ignore') return [] + let severity = settings.lint.invalidApply findAll, const classLists = findClassListsInDocument(state, document) classLists.forEach((classList) => { @@ -167,10 +176,6 @@ equal(meta.pseudo, otherMeta.pseudo) ) { diagnostics.push({ } from '../../util/find' -import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' - className, - otherClassName, -} from '../../util/find' import { severity: severity === 'error' @@ -199,13 +204,15 @@ function getInvalidScreenDiagnostics( state: State, document: TextDocument, settings: Settings -import { getClassNameDecls } from '../../util/getClassNameDecls' +import { isCssDoc } from '../../util/css' findClassNamesInRange, +import { State, Settings } from '../../util/state' let severity = settings.lint.invalidScreen if (severity === 'ignore') return [] -import { getClassNameDecls } from '../../util/getClassNameDecls' +import { isCssDoc } from '../../util/css' getClassNamesInClassList, + findAll, let ranges: Range[] = [] if (isCssDoc(state, document)) { @@ -237,7 +244,6 @@ } diagnostics.push({ const dlv = require('dlv') -const dlv = require('dlv') import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' { start: indexToPosition( @@ -264,11 +270,11 @@ function getInvalidVariantDiagnostics( state: State, document: TextDocument, settings: Settings -): InvalidVariantDiagnostic[] { +): Diagnostic[] { let severity = settings.lint.invalidVariant if (severity === 'ignore') return [] - let diagnostics: InvalidVariantDiagnostic[] = [] + let diagnostics: Diagnostic[] = [] let ranges: Range[] = [] if (isCssDoc(state, document)) { @@ -305,8 +311,6 @@ listStartIndex + variants.slice(0, i).join('').length diagnostics.push({ import { absoluteRange } from '../../util/absoluteRange' - findClassNamesInRange, -import { absoluteRange } from '../../util/absoluteRange' findClassListsInDocument, { start: indexToPosition(text, variantStartIndex), @@ -331,11 +335,12 @@ function getInvalidConfigPathDiagnostics( state: State, document: TextDocument, settings: Settings + settings: Settings import { State, Settings } from '../../util/state' let severity = settings.lint.invalidConfigPath if (severity === 'ignore') return [] - let diagnostics: InvalidConfigPathDiagnostic[] = [] + let diagnostics: Diagnostic[] = [] let ranges: Range[] = [] if (isCssDoc(state, document)) { @@ -443,7 +449,6 @@ 1 + // open paren match.groups.quote.length diagnostics.push({ - code: DiagnosticKind.InvalidConfigPath, range: absoluteRange( { start: indexToPosition(text, startIndex), @@ -467,14 +472,13 @@ function getInvalidTailwindDirectiveDiagnostics( state: State, document: TextDocument, settings: Settings + settings: Settings import { State, Settings } from '../../util/state' - let severity = settings.lint.utilityConflicts let severity = settings.lint.invalidTailwindDirective if (severity === 'ignore') return [] -import { State, Settings } from '../../util/state' + let severity = settings.lint.invalidApply findAll, -import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' let ranges: Range[] = [] if (isCssDoc(state, document)) { @@ -512,7 +516,6 @@ } } diagnostics.push({ - code: DiagnosticKind.InvalidTailwindDirective, range: absoluteRange( { start: indexToPosition( @@ -535,73 +538,47 @@ return diagnostics } -import { State, Settings } from '../../util/state' + let severity = settings.lint.invalidApply indexToPosition, - findClassListsInDocument, state: State, import { isCssDoc } from '../../util/css' -import { - only: DiagnosticKind[] = [ - AugmentedDiagnostic, findAll, - DiagnosticKind.InvalidApply, -} from './types' import { isCssDoc } from '../../util/css' + findAll, import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' - DiagnosticKind.InvalidConfigPath, - DiagnosticKind.InvalidTailwindDirective, - ] -): Promise { const settings = await getDocumentSettings(state, document) import { isCssDoc } from '../../util/css' - getClassNamesInClassList, + classLists.forEach((classList) => { ? [ import { isCssDoc } from '../../util/css' - indexToPosition, + findAll, import { isCssDoc } from '../../util/css' -} from '../../util/find' import { isCssDoc } from '../../util/css' -import { getClassNameMeta } from '../../util/getClassNameMeta' - ...(only.includes(DiagnosticKind.InvalidApply) - ? getInvalidApplyDiagnostics(state, document, settings) - : []), - + findAll, import { import { isCssDoc } from '../../util/css' -import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' + findAll, findClassNamesInRange, import { isCssDoc } from '../../util/css' -import { getClassNameMeta } from '../../util/getClassNameMeta' - + findAll, findClassListsInDocument, import { isCssDoc } from '../../util/css' -import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' + findAll, getClassNamesInClassList, import { isCssDoc } from '../../util/css' -import { getClassNameMeta } from '../../util/getClassNameMeta' - findAll, - ? getInvalidConfigPathDiagnostics(state, document, settings) - : []), + findAll, function getInvalidApplyDiagnostics( -import { isCssDoc } from '../../util/css' import { State, Settings } from '../../util/state' -import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver' - : []), function getInvalidApplyDiagnostics( -import { State, Settings } from '../../util/state' import { isCssDoc } from '../../util/css' - DiagnosticKind, -} function getInvalidApplyDiagnostics( -import { -function getInvalidApplyDiagnostics( findClassNamesInRange, uri: document.uri, import { isCssDoc } from '../../util/css' - InvalidConfigPathDiagnostic, + let otherDecls = getClassNameDecls(state, otherClassName.className) }) } diff --git a/src/lsp/providers/diagnostics/types.ts b/src/lsp/providers/diagnostics/types.ts deleted file mode 100644 index 684cda7c824aa7cc382c6ffed6b30010d31ddc97..0000000000000000000000000000000000000000 --- a/src/lsp/providers/diagnostics/types.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { Diagnostic } from 'vscode-languageserver' -import { DocumentClassName, DocumentClassList } from '../../util/state' - -export enum DiagnosticKind { - UtilityConflicts = 'utilityConflicts', - InvalidApply = 'invalidApply', - InvalidScreen = 'invalidScreen', - InvalidVariant = 'invalidVariant', - InvalidConfigPath = 'invalidConfigPath', - InvalidTailwindDirective = 'invalidTailwindDirective', -} - -export type UtilityConflictsDiagnostic = Diagnostic & { - code: DiagnosticKind.UtilityConflicts - className: DocumentClassName - otherClassName: DocumentClassName -} - -export function isUtilityConflictsDiagnostic( - diagnostic: AugmentedDiagnostic -): diagnostic is UtilityConflictsDiagnostic { - return diagnostic.code === DiagnosticKind.UtilityConflicts -} - -export type InvalidApplyDiagnostic = Diagnostic & { - code: DiagnosticKind.InvalidApply - className: DocumentClassName -} - -export function isInvalidApplyDiagnostic( - diagnostic: AugmentedDiagnostic -): diagnostic is InvalidApplyDiagnostic { - return diagnostic.code === DiagnosticKind.InvalidApply -} - -export type InvalidScreenDiagnostic = Diagnostic & { - code: DiagnosticKind.InvalidScreen -} - -export function isInvalidScreenDiagnostic( - diagnostic: AugmentedDiagnostic -): diagnostic is InvalidScreenDiagnostic { - return diagnostic.code === DiagnosticKind.InvalidScreen -} - -export type InvalidVariantDiagnostic = Diagnostic & { - code: DiagnosticKind.InvalidVariant -} - -export function isInvalidVariantDiagnostic( - diagnostic: AugmentedDiagnostic -): diagnostic is InvalidVariantDiagnostic { - return diagnostic.code === DiagnosticKind.InvalidVariant -} - -export type InvalidConfigPathDiagnostic = Diagnostic & { - code: DiagnosticKind.InvalidConfigPath -} - -export function isInvalidConfigPathDiagnostic( - diagnostic: AugmentedDiagnostic -): diagnostic is InvalidConfigPathDiagnostic { - return diagnostic.code === DiagnosticKind.InvalidConfigPath -} - -export type InvalidTailwindDirectiveDiagnostic = Diagnostic & { - code: DiagnosticKind.InvalidTailwindDirective -} - -export function isInvalidTailwindDirectiveDiagnostic( - diagnostic: AugmentedDiagnostic -): diagnostic is InvalidTailwindDirectiveDiagnostic { - return diagnostic.code === DiagnosticKind.InvalidTailwindDirective -} - -export type AugmentedDiagnostic = - | UtilityConflictsDiagnostic - | InvalidApplyDiagnostic - | InvalidScreenDiagnostic - | InvalidVariantDiagnostic - | InvalidConfigPathDiagnostic - | InvalidTailwindDirectiveDiagnostic diff --git a/src/lsp/server.ts b/src/lsp/server.ts index f4b8013534ea0de51cbb9c67f30c90d3187afb76..6c928e68b9df731b3b77b24aa82e85621eb5f7f1 100644 --- a/src/lsp/server.ts +++ b/src/lsp/server.ts @@ -32,7 +32,7 @@ import { provideDiagnostics, updateAllDiagnostics, clearAllDiagnostics, -} from './providers/diagnostics/diagnosticsProvider' +} from './providers/diagnosticsProvider' import { createEmitter } from '../lib/emitter' import { provideCodeActions } from './providers/codeActionProvider' diff --git a/src/lsp/util/rangesEqual.ts b/src/lsp/util/rangesEqual.ts deleted file mode 100644 index 220cebd50e242933d666ee7581d68e4030dd321b..0000000000000000000000000000000000000000 --- a/src/lsp/util/rangesEqual.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Range } from 'vscode-languageserver' - -export function rangesEqual(a: Range, b: Range): boolean { - return ( - a.start.line === b.start.line && - a.start.character === b.start.character && - a.end.line === b.end.line && - a.end.character === b.end.character - ) -}