diff --git a/src/lsp/providers/diagnosticsProvider.ts b/src/lsp/providers/diagnosticsProvider.ts index bb59ff571ca903793d4eb34a45d4775e9e9beaca..866c07d56dabc00b1759e3d154f43154c872931c 100644 --- a/src/lsp/providers/diagnosticsProvider.ts +++ b/src/lsp/providers/diagnosticsProvider.ts @@ -2,7 +2,6 @@ import { TextDocument, Diagnostic, DiagnosticSeverity, - Range, } from 'vscode-languageserver' import { State, Settings } from '../util/state' import { isCssDoc } from '../util/css' @@ -19,8 +18,6 @@ import { equal, flatten } from '../../util/array' import { getDocumentSettings } from '../util/getDocumentSettings' const dlv = require('dlv') import semver from 'semver' -import { getLanguageBoundaries } from '../util/getLanguageBoundaries' -import { absoluteRange } from '../util/absoluteRange' function getUnsupportedApplyDiagnostics( state: State, @@ -143,71 +140,50 @@ ): Diagnostic[] { let severity = settings.lint.unknownScreen if (severity === 'ignore') return [] - let diagnostics: Diagnostic[] = [] - let ranges: Range[] = [] TextDocument, - Diagnostic, - if (isCssDoc(state, document)) { - ranges.push(undefined) - } else { - let boundaries = getLanguageBoundaries(state, document) - if (!boundaries) return [] - ranges.push(...boundaries.css) - } - - ranges.forEach((range) => { -import { const dlv = require('dlv') -import { + TextDocument, import semver from 'semver' -import { + TextDocument, import { getLanguageBoundaries } from '../util/getLanguageBoundaries' -import { import { absoluteRange } from '../util/absoluteRange' + TextDocument, -import { + TextDocument, -import { + TextDocument, function getUnsupportedApplyDiagnostics( + .map((match) => { if (screens.includes(match.groups.screen)) { return null } -import { + return { + range: { + TextDocument, settings: Settings -import { + TextDocument, ): Diagnostic[] { -import { + TextDocument, let severity = settings.lint.unsupportedApply import { - if (severity === 'ignore') return [] + severity === 'error' -import { + TextDocument, Diagnostic, -import { - indexToPosition, TextDocument, -import { Diagnostic, - Diagnostic, import { - const meta = getClassNameMeta(state, className) - }, - range - ), severity: severity === 'error' ? DiagnosticSeverity.Error : DiagnosticSeverity.Warning, message: 'Unknown screen', - }) + } } from 'vscode-languageserver' - Diagnostic, - }) - TextDocument, Diagnostic, } from 'vscode-languageserver' - Range, + DiagnosticSeverity, } function getUnknownVariantDiagnostics( @@ -218,79 +193,70 @@ ): Diagnostic[] { let severity = settings.lint.unknownVariant if (severity === 'ignore') return [] -} from 'vscode-languageserver' +import { getLanguageBoundaries } from '../util/getLanguageBoundaries' findClassNamesInRange, - let ranges: Range[] = [] + TextDocument, - if (isCssDoc(state, document)) { - getClassNamesInClassList, TextDocument, + Diagnostic, - getClassNamesInClassList, + Diagnostic, - getClassNamesInClassList, + DiagnosticSeverity, - getClassNamesInClassList, + Range, - getClassNamesInClassList, + } from 'vscode-languageserver' - getClassNamesInClassList, + import { State, Settings } from '../util/state' - getClassNamesInClassList, import { isCssDoc } from '../util/css' - getClassNamesInClassList, + findClassNamesInRange, - let matches = findAll(/(?:\s|^)@variants\s+(?[^{]+)/g, text) -import { function getUnsupportedApplyDiagnostics( +function getUnsupportedApplyDiagnostics( import { + TextDocument, if (meta.context.length === 1) { -import { + TextDocument, message = `\`@apply\` cannot be used with \`.${className}\` because it is nested inside of an at-rule (${meta.context[0]}).` -import { + TextDocument, } else { -import { + TextDocument, message = `\`@apply\` cannot be used with \`.${className}\` because it is nested inside of at-rules (${meta.context.join( -import { + TextDocument, ', ' - if (state.variants.includes(variant)) { - continue - } -} from '../util/find' +import { isCssDoc } from '../util/css' findClassNamesInRange, - listStartIndex + variants.slice(0, i).join('').length TextDocument, - Diagnostic, - diagnostics.push({ - range: absoluteRange( - { + )}).` start: indexToPosition(text, variantStartIndex), end: indexToPosition(text, variantStartIndex + variant.length), }, + findClassNamesInRange, import { - severity: - ), + severity === 'error' -import { getClassNameMeta } from '../util/getClassNameMeta' findClassNamesInRange, + Diagnostic, - severity === 'error' + : DiagnosticSeverity.Warning, - ? DiagnosticSeverity.Error -import { getClassNameDecls } from '../util/getClassNameDecls' TextDocument, + } import { - }) + Range, -import { getClassNameDecls } from '../util/getClassNameDecls' DiagnosticSeverity, +import { isCssDoc } from '../util/css' - Range, + + TextDocument, DiagnosticSeverity, + findClassNamesInRange, + findClassListsInDocument, } from 'vscode-languageserver' - Diagnostic, -import { + state: State, -import { State, Settings } from '../util/state' + TextDocument, - return diagnostics } function getUnknownConfigKeyDiagnostics( @@ -301,33 +266,23 @@ ): Diagnostic[] { let severity = settings.lint.unknownConfigKey if (severity === 'ignore') return [] -} from 'vscode-languageserver' +import { getLanguageBoundaries } from '../util/getLanguageBoundaries' findClassNamesInRange, - let ranges: Range[] = [] TextDocument, - Diagnostic, - getClassNamesInClassList, + Range, import { - getClassNamesInClassList, TextDocument, - } else { - let boundaries = getLanguageBoundaries(state, document) - getClassNamesInClassList, Range, - ranges.push(...boundaries.css) - } + TextDocument, TextDocument, + Range, Diagnostic, - ranges.forEach((range) => { - let text = document.getText(range) - let matches = findAll( - /(?\s|^)(?config|theme)\((?['"])(?[^)]+)\k\)/g, - text -import { + TextDocument, -import { + TextDocument, function getUnsupportedApplyDiagnostics( + .map((match) => { let base = match.groups.helper === 'theme' ? ['theme'] : [] let keys = match.groups.key.split(/[.\[\]]/).filter(Boolean) let value = dlv(state.config, [...base, ...keys]) @@ -345,34 +300,26 @@ match.groups.helper.length + 1 + // open paren match.groups.quote.length - diagnostics.push({ + return { -import { TextDocument, -import { isCssDoc } from '../util/css' -import { TextDocument, - findClassNamesInRange, +} from 'vscode-languageserver' -import { getDocumentSettings } from '../util/getDocumentSettings' TextDocument, - end: indexToPosition(text, startIndex + match.groups.key.length), + } - indexToPosition, + state: State, Range, -import { + TextDocument, Diagnostic, -} from 'vscode-languageserver' import { - if (Array.isArray(meta)) { severity: severity === 'error' ? DiagnosticSeverity.Error : DiagnosticSeverity.Warning, message: `Unknown ${match.groups.helper} key: ${match.groups.key}`, - }) + } }) - }) - } from 'vscode-languageserver' - Range, + DiagnosticSeverity, } function getUnsupportedTailwindDirectiveDiagnostics( @@ -383,67 +330,49 @@ ): Diagnostic[] { let severity = settings.lint.unsupportedTailwindDirective if (severity === 'ignore') return [] - let diagnostics: Diagnostic[] = [] - let ranges: Range[] = [] TextDocument, - Diagnostic, import { - getClassNamesInClassList, + findClassNamesInRange, - getClassNamesInClassList, TextDocument, - } else { - let boundaries = getLanguageBoundaries(state, document) - getClassNamesInClassList, Range, - getClassNamesInClassList, } from 'vscode-languageserver' - } - ranges.forEach((range) => { - let text = document.getText(range) -import { getDocumentSettings } from '../util/getDocumentSettings' + state: State, import { State, Settings } from '../util/state' TextDocument, - Diagnostic, -import { getDocumentSettings } from '../util/getDocumentSettings' + Range, import { isCssDoc } from '../util/css' -import { getDocumentSettings } from '../util/getDocumentSettings' + state: State, findClassNamesInRange, -const dlv = require('dlv') + document: TextDocument, -const dlv = require('dlv') + document: TextDocument, import { -const dlv = require('dlv') + document: TextDocument, TextDocument, - ] -import { + TextDocument, function getUnsupportedApplyDiagnostics( - if (valid.includes(match.groups.value)) { + .map((match) => { + if (allowed.includes(match.groups.value)) { return null } -import { + return { + range: { + TextDocument, settings: Settings -import { + TextDocument, ): Diagnostic[] { -import { TextDocument, - findClassNamesInRange, + .filter(Boolean) import { - if (severity === 'ignore') return [] - text, -const dlv = require('dlv') Range, +import { isCssDoc } from '../util/css' -import { + TextDocument, Diagnostic, - Diagnostic, -import { + TextDocument, Diagnostic, - DiagnosticSeverity, import { - if (!meta) return null - range - ), severity: severity === 'error' ? DiagnosticSeverity.Error @@ -451,12 +379,10 @@ : DiagnosticSeverity.Warning, message: `Unsupported value: ${match.groups.value}${ match.groups.value === 'preflight' ? '. Use base instead.' : '' }`, - }) + } }) - }) - } from 'vscode-languageserver' - Range, + DiagnosticSeverity, } export async function provideDiagnostics( @@ -468,25 +395,33 @@ const diagnostics: Diagnostic[] = settings.validate ? [ ...getUtilityConflictDiagnostics(state, document, settings), TextDocument, + return diagnostics + document: TextDocument, } from 'vscode-languageserver' TextDocument, +} from 'vscode-languageserver' import { State, Settings } from '../util/state' TextDocument, +} from 'vscode-languageserver' import { isCssDoc } from '../util/css' TextDocument, +} from 'vscode-languageserver' findClassNamesInRange, TextDocument, -import { +import { State, Settings } from '../util/state' TextDocument, -import { +import { State, Settings } from '../util/state' import { TextDocument, -import { +import { State, Settings } from '../util/state' TextDocument, TextDocument, -import { +import { State, Settings } from '../util/state' Diagnostic, - indexToPosition, + settings + ), + ] + settings: Settings import { State, Settings } from '../util/state' ] : [] diff --git a/src/lsp/util/absoluteRange.ts b/src/lsp/util/absoluteRange.ts deleted file mode 100644 index 9250e4fb9ec9b13ff3124072808f2013ef5009a0..0000000000000000000000000000000000000000 --- a/src/lsp/util/absoluteRange.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Range } from 'vscode-languageserver' - -export function absoluteRange(range: Range, reference?: Range) { - return { - start: { - line: (reference?.start.line || 0) + range.start.line, - character: - (range.end.line === 0 ? reference?.start.character || 0 : 0) + - range.start.character, - }, - end: { - line: (reference?.start.line || 0) + range.end.line, - character: - (range.end.line === 0 ? reference?.start.character || 0 : 0) + - range.end.character, - }, - } -} diff --git a/src/lsp/util/find.ts b/src/lsp/util/find.ts index 609de6207d066862bb645e4d9ca199c915010b61..0f996a43f914e393b546ae08a4410908687126b3 100644 --- a/src/lsp/util/find.ts +++ b/src/lsp/util/find.ts @@ -11,8 +11,6 @@ getClassAttributeLexer, getComputedClassAttributeLexer, } from './lexers' import { TextDocument, Range, Position } from 'vscode-languageserver' -import lineColumn from 'line-column' -import { TextDocument, Range, Position } from 'vscode-languageserver' import { isCssContext, isCssDoc } from './css' export function findAll(re: RegExp, str: string): RegExpMatchArray[] { let match: RegExpMatchArray @@ -234,22 +232,86 @@ return findClassListsInCssRange(doc) } import { TextDocument, Range, Position } from 'vscode-languageserver' + lexer.reset(subtext) + let text = doc.getText() + let blocks = findAll( + /<(?template|style|script)\b[^>]*>.*?(<\/\k>|$)/gis, + text import { isJsContext, isJsDoc } from './js' +import { isJsContext, isJsDoc } from './js' +import { DocumentClassName, DocumentClassList, State } from './state' +import { isCssContext, isCssDoc } from './css' + let cssRanges: Range[] = [] + for (let i = 0; i < blocks.length; i++) { + let range = { + start: indexToPosition(text, blocks[i].index), + end: indexToPosition(text, blocks[i].index + blocks[i][0].length), import { TextDocument, Range, Position } from 'vscode-languageserver' -import { isJsContext, isJsDoc } from './js' + return matches + if (blocks[i].groups.type === 'style') { + return matches import { TextDocument, Range, Position } from 'vscode-languageserver' + } else { + htmlRanges.push(range) + } + } +import { DocumentClassName, DocumentClassList, State } from './state' + [], + [ +import { DocumentClassName, DocumentClassList, State } from './state' let matches: RegExpMatchArray[] = [] import { DocumentClassName, DocumentClassList, State } from './state' + while ((match = re.exec(str)) !== null) { +import { DocumentClassName, DocumentClassList, State } from './state' import { TextDocument, Range, Position } from 'vscode-languageserver' +import { import { isJsContext, isJsDoc } from './js' +import { isJsContext, isJsDoc } from './js' + } + + if (isHtmlDoc(state, doc) || isJsDoc(state, doc) || isSvelteDoc(doc)) { + let text = doc.getText() + let styleBlocks = findAll(/]*>|>).*?(<\/style>|$)/gis, text) + let htmlRanges: Range[] = [] + let cssRanges: Range[] = [] + let currentIndex = 0 + +} import lineColumn from 'line-column' + htmlRanges.push({ + start: indexToPosition(text, currentIndex), + end: indexToPosition(text, styleBlocks[i].index), +import { isHtmlContext, isHtmlDoc, isSvelteDoc, isVueDoc } from './html' import { TextDocument, Range, Position } from 'vscode-languageserver' +} import { isJsContext, isJsDoc } from './js' -import { isCssContext, isCssDoc } from './css' + start: indexToPosition(text, styleBlocks[i].index), + end: indexToPosition( + text, + styleBlocks[i].index + styleBlocks[i][0].length + ), +import { isHtmlContext, isHtmlDoc, isSvelteDoc, isVueDoc } from './html' import { TextDocument, Range, Position } from 'vscode-languageserver' + currentIndex = styleBlocks[i].index + styleBlocks[i][0].length + } + htmlRanges.push({ + start: indexToPosition(text, currentIndex), + end: indexToPosition(text, text.length), +export function findLast(re: RegExp, str: string): RegExpMatchArray { import { isJsContext, isJsDoc } from './js' + + return [].concat.apply( + return matches import { isHtmlContext, isHtmlDoc, isSvelteDoc, isVueDoc } from './html' + [ + ...htmlRanges.map((range) => findClassListsInHtmlRange(doc, range)), + ...cssRanges.map((range) => findClassListsInCssRange(doc, range)), + ] + ) + } + + return [] } export function indexToPosition(str: string, index: number): Position { diff --git a/src/lsp/util/getLanguageBoundaries.ts b/src/lsp/util/getLanguageBoundaries.ts deleted file mode 100644 index dfef2300d3a9052cb3f60970538858b81d8af39b..0000000000000000000000000000000000000000 --- a/src/lsp/util/getLanguageBoundaries.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { TextDocument, Range } from 'vscode-languageserver' -import { isVueDoc, isHtmlDoc, isSvelteDoc } from './html' -import { State } from './state' -import { findAll, indexToPosition } from './find' -import { isJsDoc } from './js' - -export interface LanguageBoundaries { - html: Range[] - css: Range[] -} - -export function getLanguageBoundaries( - state: State, - doc: TextDocument -): LanguageBoundaries | null { - if (isVueDoc(doc)) { - let text = doc.getText() - let blocks = findAll( - /<(?template|style|script)\b[^>]*>.*?(<\/\k>|$)/gis, - text - ) - let htmlRanges: Range[] = [] - let cssRanges: Range[] = [] - for (let i = 0; i < blocks.length; i++) { - let range = { - start: indexToPosition(text, blocks[i].index), - end: indexToPosition(text, blocks[i].index + blocks[i][0].length), - } - if (blocks[i].groups.type === 'style') { - cssRanges.push(range) - } else { - htmlRanges.push(range) - } - } - - return { - html: htmlRanges, - css: cssRanges, - } - } - - if (isHtmlDoc(state, doc) || isJsDoc(state, doc) || isSvelteDoc(doc)) { - let text = doc.getText() - let styleBlocks = findAll(/]*>|>).*?(<\/style>|$)/gis, text) - let htmlRanges: Range[] = [] - let cssRanges: Range[] = [] - let currentIndex = 0 - - for (let i = 0; i < styleBlocks.length; i++) { - htmlRanges.push({ - start: indexToPosition(text, currentIndex), - end: indexToPosition(text, styleBlocks[i].index), - }) - cssRanges.push({ - start: indexToPosition(text, styleBlocks[i].index), - end: indexToPosition( - text, - styleBlocks[i].index + styleBlocks[i][0].length - ), - }) - currentIndex = styleBlocks[i].index + styleBlocks[i][0].length - } - htmlRanges.push({ - start: indexToPosition(text, currentIndex), - end: indexToPosition(text, text.length), - }) - - return { - html: htmlRanges, - css: cssRanges, - } - } - - return null -}