refactor diagnostics and add types
parent
e79f72bda8
commit
b79dbfc9f9
|
@ -4,10 +4,9 @@ import {
|
||||||
CodeActionKind,
|
CodeActionKind,
|
||||||
Range,
|
Range,
|
||||||
TextEdit,
|
TextEdit,
|
||||||
Diagnostic,
|
|
||||||
} from 'vscode-languageserver'
|
} from 'vscode-languageserver'
|
||||||
import { State } from '../../util/state'
|
import { State } from '../../util/state'
|
||||||
import { findLast, findClassNamesInRange } from '../../util/find'
|
import { findLast } from '../../util/find'
|
||||||
import { isWithinRange } from '../../util/isWithinRange'
|
import { isWithinRange } from '../../util/isWithinRange'
|
||||||
import { getClassNameParts } from '../../util/getClassNameAtPosition'
|
import { getClassNameParts } from '../../util/getClassNameAtPosition'
|
||||||
const dlv = require('dlv')
|
const dlv = require('dlv')
|
||||||
|
@ -16,19 +15,50 @@ import { removeRangeFromString } from '../../util/removeRangeFromString'
|
||||||
import detectIndent from 'detect-indent'
|
import detectIndent from 'detect-indent'
|
||||||
import { cssObjToAst } from '../../util/cssObjToAst'
|
import { cssObjToAst } from '../../util/cssObjToAst'
|
||||||
import isObject from '../../../util/isObject'
|
import isObject from '../../../util/isObject'
|
||||||
|
import { getDiagnostics } from '../diagnostics/diagnosticsProvider'
|
||||||
|
import { rangesEqual } from '../../util/rangesEqual'
|
||||||
|
import {
|
||||||
|
DiagnosticKind,
|
||||||
|
isInvalidApplyDiagnostic,
|
||||||
|
AugmentedDiagnostic,
|
||||||
|
InvalidApplyDiagnostic,
|
||||||
|
} from '../diagnostics/types'
|
||||||
|
|
||||||
export function provideCodeActions(
|
async function getDiagnosticsFromCodeActionParams(
|
||||||
|
state: State,
|
||||||
|
params: CodeActionParams,
|
||||||
|
only?: DiagnosticKind[]
|
||||||
|
): Promise<AugmentedDiagnostic[]> {
|
||||||
|
let document = state.editor.documents.get(params.textDocument.uri)
|
||||||
|
let diagnostics = await getDiagnostics(state, document, only)
|
||||||
|
|
||||||
|
return params.context.diagnostics
|
||||||
|
.map((diagnostic) => {
|
||||||
|
return diagnostics.find((d) => {
|
||||||
|
return rangesEqual(d.range, diagnostic.range)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.filter(Boolean)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function provideCodeActions(
|
||||||
state: State,
|
state: State,
|
||||||
params: CodeActionParams
|
params: CodeActionParams
|
||||||
): Promise<CodeAction[]> {
|
): Promise<CodeAction[]> {
|
||||||
if (params.context.diagnostics.length === 0) {
|
let codes = params.context.diagnostics
|
||||||
return null
|
.map((diagnostic) => diagnostic.code)
|
||||||
}
|
.filter(Boolean) as DiagnosticKind[]
|
||||||
|
|
||||||
|
let diagnostics = await getDiagnosticsFromCodeActionParams(
|
||||||
|
state,
|
||||||
|
params,
|
||||||
|
codes
|
||||||
|
)
|
||||||
|
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
params.context.diagnostics
|
diagnostics
|
||||||
.map((diagnostic) => {
|
.map((diagnostic) => {
|
||||||
if (diagnostic.code === 'invalidApply') {
|
if (isInvalidApplyDiagnostic(diagnostic)) {
|
||||||
return provideInvalidApplyCodeAction(state, params, diagnostic)
|
return provideInvalidApplyCodeAction(state, params, diagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,31 +157,14 @@ function classNameToAst(
|
||||||
async function provideInvalidApplyCodeAction(
|
async function provideInvalidApplyCodeAction(
|
||||||
state: State,
|
state: State,
|
||||||
params: CodeActionParams,
|
params: CodeActionParams,
|
||||||
diagnostic: Diagnostic
|
diagnostic: InvalidApplyDiagnostic
|
||||||
): Promise<CodeAction> {
|
): Promise<CodeAction> {
|
||||||
let document = state.editor.documents.get(params.textDocument.uri)
|
let document = state.editor.documents.get(params.textDocument.uri)
|
||||||
let documentText = document.getText()
|
let documentText = document.getText()
|
||||||
const { postcss } = state.modules
|
const { postcss } = state.modules
|
||||||
let change: TextEdit
|
let change: TextEdit
|
||||||
|
|
||||||
let documentClassNames = findClassNamesInRange(
|
let totalClassNamesInClassList = diagnostic.className.classList.classList.split(
|
||||||
document,
|
|
||||||
{
|
|
||||||
start: {
|
|
||||||
line: Math.max(0, diagnostic.range.start.line - 10),
|
|
||||||
character: 0,
|
|
||||||
},
|
|
||||||
end: { line: diagnostic.range.start.line + 10, character: 0 },
|
|
||||||
},
|
|
||||||
'css'
|
|
||||||
)
|
|
||||||
let documentClassName = documentClassNames.find((className) =>
|
|
||||||
isWithinRange(diagnostic.range.start, className.range)
|
|
||||||
)
|
|
||||||
if (!documentClassName) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
let totalClassNamesInClassList = documentClassName.classList.classList.split(
|
|
||||||
/\s+/
|
/\s+/
|
||||||
).length
|
).length
|
||||||
|
|
||||||
|
@ -184,7 +197,7 @@ async function provideInvalidApplyCodeAction(
|
||||||
state,
|
state,
|
||||||
className,
|
className,
|
||||||
rule.selector,
|
rule.selector,
|
||||||
documentClassName.classList.important
|
diagnostic.className.classList.important
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!ast) {
|
if (!ast) {
|
||||||
|
@ -250,10 +263,10 @@ async function provideInvalidApplyCodeAction(
|
||||||
...(totalClassNamesInClassList > 1
|
...(totalClassNamesInClassList > 1
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
range: documentClassName.classList.range,
|
range: diagnostic.className.classList.range,
|
||||||
newText: removeRangeFromString(
|
newText: removeRangeFromString(
|
||||||
documentClassName.classList.classList,
|
diagnostic.className.classList.classList,
|
||||||
documentClassName.relativeRange
|
diagnostic.className.relativeRange
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,95 +1,103 @@
|
||||||
import {
|
import { TextDocument, DiagnosticSeverity, Range } from 'vscode-languageserver'
|
||||||
TextDocument,
|
import { State, Settings } from '../../util/state'
|
||||||
Diagnostic,
|
import { isCssDoc } from '../../util/css'
|
||||||
DiagnosticSeverity,
|
|
||||||
Range,
|
|
||||||
} from 'vscode-languageserver'
|
|
||||||
import { State, Settings } from '../util/state'
|
|
||||||
import { isCssDoc } from '../util/css'
|
|
||||||
import {
|
import {
|
||||||
findClassNamesInRange,
|
findClassNamesInRange,
|
||||||
findClassListsInDocument,
|
findClassListsInDocument,
|
||||||
getClassNamesInClassList,
|
getClassNamesInClassList,
|
||||||
findAll,
|
findAll,
|
||||||
indexToPosition,
|
indexToPosition,
|
||||||
} from '../util/find'
|
} from '../../util/find'
|
||||||
import { getClassNameMeta } from '../util/getClassNameMeta'
|
import { getClassNameMeta } from '../../util/getClassNameMeta'
|
||||||
import { getClassNameDecls } from '../util/getClassNameDecls'
|
import { getClassNameDecls } from '../../util/getClassNameDecls'
|
||||||
import { equal } from '../../util/array'
|
import { equal } from '../../../util/array'
|
||||||
import { getDocumentSettings } from '../util/getDocumentSettings'
|
import { getDocumentSettings } from '../../util/getDocumentSettings'
|
||||||
const dlv = require('dlv')
|
const dlv = require('dlv')
|
||||||
import semver from 'semver'
|
import semver from 'semver'
|
||||||
import { getLanguageBoundaries } from '../util/getLanguageBoundaries'
|
import { getLanguageBoundaries } from '../../util/getLanguageBoundaries'
|
||||||
import { absoluteRange } from '../util/absoluteRange'
|
import { absoluteRange } from '../../util/absoluteRange'
|
||||||
import { isObject } from '../../class-names/isObject'
|
import { isObject } from '../../../class-names/isObject'
|
||||||
import { stringToPath } from '../util/stringToPath'
|
import { stringToPath } from '../../util/stringToPath'
|
||||||
import { closest } from '../util/closest'
|
import { closest } from '../../util/closest'
|
||||||
|
import {
|
||||||
|
InvalidApplyDiagnostic,
|
||||||
|
DiagnosticKind,
|
||||||
|
UtilityConflictsDiagnostic,
|
||||||
|
InvalidScreenDiagnostic,
|
||||||
|
InvalidVariantDiagnostic,
|
||||||
|
InvalidConfigPathDiagnostic,
|
||||||
|
InvalidTailwindDirectiveDiagnostic,
|
||||||
|
AugmentedDiagnostic,
|
||||||
|
} from './types'
|
||||||
|
|
||||||
function getInvalidApplyDiagnostics(
|
function getInvalidApplyDiagnostics(
|
||||||
state: State,
|
state: State,
|
||||||
document: TextDocument,
|
document: TextDocument,
|
||||||
settings: Settings
|
settings: Settings
|
||||||
): Diagnostic[] {
|
): InvalidApplyDiagnostic[] {
|
||||||
let severity = settings.lint.invalidApply
|
let severity = settings.lint.invalidApply
|
||||||
if (severity === 'ignore') return []
|
if (severity === 'ignore') return []
|
||||||
|
|
||||||
const classNames = findClassNamesInRange(document, undefined, 'css')
|
const classNames = findClassNamesInRange(document, undefined, 'css')
|
||||||
|
|
||||||
let diagnostics: Diagnostic[] = classNames
|
let diagnostics: InvalidApplyDiagnostic[] = classNames.map((className) => {
|
||||||
.map(({ className, range }) => {
|
const meta = getClassNameMeta(state, className.className)
|
||||||
const meta = getClassNameMeta(state, className)
|
if (!meta) return null
|
||||||
if (!meta) return null
|
|
||||||
|
|
||||||
let message: string
|
let message: string
|
||||||
|
|
||||||
if (Array.isArray(meta)) {
|
if (Array.isArray(meta)) {
|
||||||
message = `'@apply' cannot be used with '${className}' because it is included in multiple rulesets.`
|
message = `'@apply' cannot be used with '${className.className}' because it is included in multiple rulesets.`
|
||||||
} else if (meta.source !== 'utilities') {
|
} else if (meta.source !== 'utilities') {
|
||||||
message = `'@apply' cannot be used with '${className}' because it is not a utility.`
|
message = `'@apply' cannot be used with '${className.className}' because it is not a utility.`
|
||||||
} else if (meta.context && meta.context.length > 0) {
|
} else if (meta.context && meta.context.length > 0) {
|
||||||
if (meta.context.length === 1) {
|
if (meta.context.length === 1) {
|
||||||
message = `'@apply' cannot be used with '${className}' because it is nested inside of an at-rule ('${meta.context[0]}').`
|
message = `'@apply' cannot be used with '${className.className}' because it is nested inside of an at-rule ('${meta.context[0]}').`
|
||||||
} else {
|
} else {
|
||||||
message = `'@apply' cannot be used with '${className}' because it is nested inside of at-rules (${meta.context
|
message = `'@apply' cannot be used with '${
|
||||||
.map((c) => `'${c}'`)
|
className.className
|
||||||
.join(', ')}).`
|
}' because it is nested inside of at-rules (${meta.context
|
||||||
}
|
.map((c) => `'${c}'`)
|
||||||
} else if (meta.pseudo && meta.pseudo.length > 0) {
|
.join(', ')}).`
|
||||||
if (meta.pseudo.length === 1) {
|
|
||||||
message = `'@apply' cannot be used with '${className}' because its definition includes a pseudo-selector ('${meta.pseudo[0]}')`
|
|
||||||
} else {
|
|
||||||
message = `'@apply' cannot be used with '${className}' because its definition includes pseudo-selectors (${meta.pseudo
|
|
||||||
.map((p) => `'${p}'`)
|
|
||||||
.join(', ')}).`
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else if (meta.pseudo && meta.pseudo.length > 0) {
|
||||||
if (!message) return null
|
if (meta.pseudo.length === 1) {
|
||||||
|
message = `'@apply' cannot be used with '${className.className}' because its definition includes a pseudo-selector ('${meta.pseudo[0]}')`
|
||||||
return {
|
} else {
|
||||||
severity:
|
message = `'@apply' cannot be used with '${
|
||||||
severity === 'error'
|
className.className
|
||||||
? DiagnosticSeverity.Error
|
}' because its definition includes pseudo-selectors (${meta.pseudo
|
||||||
: DiagnosticSeverity.Warning,
|
.map((p) => `'${p}'`)
|
||||||
range,
|
.join(', ')}).`
|
||||||
message,
|
|
||||||
code: 'invalidApply',
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.filter(Boolean)
|
|
||||||
|
|
||||||
return diagnostics
|
if (!message) return null
|
||||||
|
|
||||||
|
return {
|
||||||
|
code: DiagnosticKind.InvalidApply,
|
||||||
|
severity:
|
||||||
|
severity === 'error'
|
||||||
|
? DiagnosticSeverity.Error
|
||||||
|
: DiagnosticSeverity.Warning,
|
||||||
|
range: className.range,
|
||||||
|
message,
|
||||||
|
className,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return diagnostics.filter(Boolean)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUtilityConflictDiagnostics(
|
function getUtilityConflictDiagnostics(
|
||||||
state: State,
|
state: State,
|
||||||
document: TextDocument,
|
document: TextDocument,
|
||||||
settings: Settings
|
settings: Settings
|
||||||
): Diagnostic[] {
|
): UtilityConflictsDiagnostic[] {
|
||||||
let severity = settings.lint.utilityConflicts
|
let severity = settings.lint.utilityConflicts
|
||||||
if (severity === 'ignore') return []
|
if (severity === 'ignore') return []
|
||||||
|
|
||||||
let diagnostics: Diagnostic[] = []
|
let diagnostics: UtilityConflictsDiagnostic[] = []
|
||||||
const classLists = findClassListsInDocument(state, document)
|
const classLists = findClassListsInDocument(state, document)
|
||||||
|
|
||||||
classLists.forEach((classList) => {
|
classLists.forEach((classList) => {
|
||||||
|
@ -115,6 +123,9 @@ function getUtilityConflictDiagnostics(
|
||||||
equal(meta.pseudo, otherMeta.pseudo)
|
equal(meta.pseudo, otherMeta.pseudo)
|
||||||
) {
|
) {
|
||||||
diagnostics.push({
|
diagnostics.push({
|
||||||
|
code: DiagnosticKind.UtilityConflicts,
|
||||||
|
className,
|
||||||
|
otherClassName,
|
||||||
range: className.range,
|
range: className.range,
|
||||||
severity:
|
severity:
|
||||||
severity === 'error'
|
severity === 'error'
|
||||||
|
@ -143,11 +154,11 @@ function getInvalidScreenDiagnostics(
|
||||||
state: State,
|
state: State,
|
||||||
document: TextDocument,
|
document: TextDocument,
|
||||||
settings: Settings
|
settings: Settings
|
||||||
): Diagnostic[] {
|
): InvalidScreenDiagnostic[] {
|
||||||
let severity = settings.lint.invalidScreen
|
let severity = settings.lint.invalidScreen
|
||||||
if (severity === 'ignore') return []
|
if (severity === 'ignore') return []
|
||||||
|
|
||||||
let diagnostics: Diagnostic[] = []
|
let diagnostics: InvalidScreenDiagnostic[] = []
|
||||||
let ranges: Range[] = []
|
let ranges: Range[] = []
|
||||||
|
|
||||||
if (isCssDoc(state, document)) {
|
if (isCssDoc(state, document)) {
|
||||||
|
@ -178,6 +189,7 @@ function getInvalidScreenDiagnostics(
|
||||||
}
|
}
|
||||||
|
|
||||||
diagnostics.push({
|
diagnostics.push({
|
||||||
|
code: DiagnosticKind.InvalidScreen,
|
||||||
range: absoluteRange(
|
range: absoluteRange(
|
||||||
{
|
{
|
||||||
start: indexToPosition(
|
start: indexToPosition(
|
||||||
|
@ -204,11 +216,11 @@ function getInvalidVariantDiagnostics(
|
||||||
state: State,
|
state: State,
|
||||||
document: TextDocument,
|
document: TextDocument,
|
||||||
settings: Settings
|
settings: Settings
|
||||||
): Diagnostic[] {
|
): InvalidVariantDiagnostic[] {
|
||||||
let severity = settings.lint.invalidVariant
|
let severity = settings.lint.invalidVariant
|
||||||
if (severity === 'ignore') return []
|
if (severity === 'ignore') return []
|
||||||
|
|
||||||
let diagnostics: Diagnostic[] = []
|
let diagnostics: InvalidVariantDiagnostic[] = []
|
||||||
let ranges: Range[] = []
|
let ranges: Range[] = []
|
||||||
|
|
||||||
if (isCssDoc(state, document)) {
|
if (isCssDoc(state, document)) {
|
||||||
|
@ -244,6 +256,7 @@ function getInvalidVariantDiagnostics(
|
||||||
listStartIndex + variants.slice(0, i).join('').length
|
listStartIndex + variants.slice(0, i).join('').length
|
||||||
|
|
||||||
diagnostics.push({
|
diagnostics.push({
|
||||||
|
code: DiagnosticKind.InvalidVariant,
|
||||||
range: absoluteRange(
|
range: absoluteRange(
|
||||||
{
|
{
|
||||||
start: indexToPosition(text, variantStartIndex),
|
start: indexToPosition(text, variantStartIndex),
|
||||||
|
@ -268,11 +281,11 @@ function getInvalidConfigPathDiagnostics(
|
||||||
state: State,
|
state: State,
|
||||||
document: TextDocument,
|
document: TextDocument,
|
||||||
settings: Settings
|
settings: Settings
|
||||||
): Diagnostic[] {
|
): InvalidConfigPathDiagnostic[] {
|
||||||
let severity = settings.lint.invalidConfigPath
|
let severity = settings.lint.invalidConfigPath
|
||||||
if (severity === 'ignore') return []
|
if (severity === 'ignore') return []
|
||||||
|
|
||||||
let diagnostics: Diagnostic[] = []
|
let diagnostics: InvalidConfigPathDiagnostic[] = []
|
||||||
let ranges: Range[] = []
|
let ranges: Range[] = []
|
||||||
|
|
||||||
if (isCssDoc(state, document)) {
|
if (isCssDoc(state, document)) {
|
||||||
|
@ -381,6 +394,7 @@ function getInvalidConfigPathDiagnostics(
|
||||||
match.groups.quote.length
|
match.groups.quote.length
|
||||||
|
|
||||||
diagnostics.push({
|
diagnostics.push({
|
||||||
|
code: DiagnosticKind.InvalidConfigPath,
|
||||||
range: absoluteRange(
|
range: absoluteRange(
|
||||||
{
|
{
|
||||||
start: indexToPosition(text, startIndex),
|
start: indexToPosition(text, startIndex),
|
||||||
|
@ -404,11 +418,11 @@ function getInvalidTailwindDirectiveDiagnostics(
|
||||||
state: State,
|
state: State,
|
||||||
document: TextDocument,
|
document: TextDocument,
|
||||||
settings: Settings
|
settings: Settings
|
||||||
): Diagnostic[] {
|
): InvalidTailwindDirectiveDiagnostic[] {
|
||||||
let severity = settings.lint.invalidTailwindDirective
|
let severity = settings.lint.invalidTailwindDirective
|
||||||
if (severity === 'ignore') return []
|
if (severity === 'ignore') return []
|
||||||
|
|
||||||
let diagnostics: Diagnostic[] = []
|
let diagnostics: InvalidTailwindDirectiveDiagnostic[] = []
|
||||||
let ranges: Range[] = []
|
let ranges: Range[] = []
|
||||||
|
|
||||||
if (isCssDoc(state, document)) {
|
if (isCssDoc(state, document)) {
|
||||||
|
@ -446,6 +460,7 @@ function getInvalidTailwindDirectiveDiagnostics(
|
||||||
}
|
}
|
||||||
|
|
||||||
diagnostics.push({
|
diagnostics.push({
|
||||||
|
code: DiagnosticKind.InvalidTailwindDirective,
|
||||||
range: absoluteRange(
|
range: absoluteRange(
|
||||||
{
|
{
|
||||||
start: indexToPosition(
|
start: indexToPosition(
|
||||||
|
@ -468,26 +483,48 @@ function getInvalidTailwindDirectiveDiagnostics(
|
||||||
return diagnostics
|
return diagnostics
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function provideDiagnostics(
|
export async function getDiagnostics(
|
||||||
state: State,
|
state: State,
|
||||||
document: TextDocument
|
document: TextDocument,
|
||||||
): Promise<void> {
|
only: DiagnosticKind[] = [
|
||||||
|
DiagnosticKind.UtilityConflicts,
|
||||||
|
DiagnosticKind.InvalidApply,
|
||||||
|
DiagnosticKind.InvalidScreen,
|
||||||
|
DiagnosticKind.InvalidVariant,
|
||||||
|
DiagnosticKind.InvalidConfigPath,
|
||||||
|
DiagnosticKind.InvalidTailwindDirective,
|
||||||
|
]
|
||||||
|
): Promise<AugmentedDiagnostic[]> {
|
||||||
const settings = await getDocumentSettings(state, document)
|
const settings = await getDocumentSettings(state, document)
|
||||||
|
|
||||||
const diagnostics: Diagnostic[] = settings.validate
|
return settings.validate
|
||||||
? [
|
? [
|
||||||
...getUtilityConflictDiagnostics(state, document, settings),
|
...(only.includes(DiagnosticKind.UtilityConflicts)
|
||||||
...getInvalidApplyDiagnostics(state, document, settings),
|
? getUtilityConflictDiagnostics(state, document, settings)
|
||||||
...getInvalidScreenDiagnostics(state, document, settings),
|
: []),
|
||||||
...getInvalidVariantDiagnostics(state, document, settings),
|
...(only.includes(DiagnosticKind.InvalidApply)
|
||||||
...getInvalidConfigPathDiagnostics(state, document, settings),
|
? getInvalidApplyDiagnostics(state, document, settings)
|
||||||
...getInvalidTailwindDirectiveDiagnostics(state, document, settings),
|
: []),
|
||||||
|
...(only.includes(DiagnosticKind.InvalidScreen)
|
||||||
|
? getInvalidScreenDiagnostics(state, document, settings)
|
||||||
|
: []),
|
||||||
|
...(only.includes(DiagnosticKind.InvalidVariant)
|
||||||
|
? getInvalidVariantDiagnostics(state, document, settings)
|
||||||
|
: []),
|
||||||
|
...(only.includes(DiagnosticKind.InvalidConfigPath)
|
||||||
|
? getInvalidConfigPathDiagnostics(state, document, settings)
|
||||||
|
: []),
|
||||||
|
...(only.includes(DiagnosticKind.InvalidTailwindDirective)
|
||||||
|
? getInvalidTailwindDirectiveDiagnostics(state, document, settings)
|
||||||
|
: []),
|
||||||
]
|
]
|
||||||
: []
|
: []
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function provideDiagnostics(state: State, document: TextDocument) {
|
||||||
state.editor.connection.sendDiagnostics({
|
state.editor.connection.sendDiagnostics({
|
||||||
uri: document.uri,
|
uri: document.uri,
|
||||||
diagnostics,
|
diagnostics: await getDiagnostics(state, document),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
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
|
|
@ -32,7 +32,7 @@ import {
|
||||||
provideDiagnostics,
|
provideDiagnostics,
|
||||||
updateAllDiagnostics,
|
updateAllDiagnostics,
|
||||||
clearAllDiagnostics,
|
clearAllDiagnostics,
|
||||||
} from './providers/diagnosticsProvider'
|
} from './providers/diagnostics/diagnosticsProvider'
|
||||||
import { createEmitter } from '../lib/emitter'
|
import { createEmitter } from '../lib/emitter'
|
||||||
import { provideCodeActions } from './providers/codeActionProvider'
|
import { provideCodeActions } from './providers/codeActionProvider'
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
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
|
||||||
|
)
|
||||||
|
}
|
Loading…
Reference in New Issue