reuse @apply validation in hover provider
parent
2df85449a4
commit
8c6ba84417
|
@ -2,7 +2,7 @@ import { findClassNamesInRange } from '../../util/find'
|
||||||
import { InvalidApplyDiagnostic, DiagnosticKind } from './types'
|
import { InvalidApplyDiagnostic, DiagnosticKind } from './types'
|
||||||
import { Settings, State } from '../../util/state'
|
import { Settings, State } from '../../util/state'
|
||||||
import { TextDocument, DiagnosticSeverity } from 'vscode-languageserver'
|
import { TextDocument, DiagnosticSeverity } from 'vscode-languageserver'
|
||||||
import { getClassNameMeta } from '../../util/getClassNameMeta'
|
import { validateApply } from '../../util/validateApply'
|
||||||
|
|
||||||
export function getInvalidApplyDiagnostics(
|
export function getInvalidApplyDiagnostics(
|
||||||
state: State,
|
state: State,
|
||||||
|
@ -15,39 +15,12 @@ export function getInvalidApplyDiagnostics(
|
||||||
const classNames = findClassNamesInRange(document, undefined, 'css')
|
const classNames = findClassNamesInRange(document, undefined, 'css')
|
||||||
|
|
||||||
let diagnostics: InvalidApplyDiagnostic[] = classNames.map((className) => {
|
let diagnostics: InvalidApplyDiagnostic[] = classNames.map((className) => {
|
||||||
const meta = getClassNameMeta(state, className.className)
|
let result = validateApply(state, className.className)
|
||||||
if (!meta) return null
|
|
||||||
|
|
||||||
let message: string
|
if (result === null || result.isApplyable === true) {
|
||||||
|
return null
|
||||||
if (Array.isArray(meta)) {
|
|
||||||
message = `'@apply' cannot be used with '${className.className}' because it is included in multiple rulesets.`
|
|
||||||
} else if (meta.source !== 'utilities') {
|
|
||||||
message = `'@apply' cannot be used with '${className.className}' because it is not a utility.`
|
|
||||||
} else if (meta.context && meta.context.length > 0) {
|
|
||||||
if (meta.context.length === 1) {
|
|
||||||
message = `'@apply' cannot be used with '${className.className}' because it is nested inside of an at-rule ('${meta.context[0]}').`
|
|
||||||
} else {
|
|
||||||
message = `'@apply' cannot be used with '${
|
|
||||||
className.className
|
|
||||||
}' because it is nested inside of at-rules (${meta.context
|
|
||||||
.map((c) => `'${c}'`)
|
|
||||||
.join(', ')}).`
|
|
||||||
}
|
|
||||||
} else if (meta.pseudo && meta.pseudo.length > 0) {
|
|
||||||
if (meta.pseudo.length === 1) {
|
|
||||||
message = `'@apply' cannot be used with '${className.className}' because its definition includes a pseudo-selector ('${meta.pseudo[0]}')`
|
|
||||||
} else {
|
|
||||||
message = `'@apply' cannot be used with '${
|
|
||||||
className.className
|
|
||||||
}' because its definition includes pseudo-selectors (${meta.pseudo
|
|
||||||
.map((p) => `'${p}'`)
|
|
||||||
.join(', ')}).`
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!message) return null
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
code: DiagnosticKind.InvalidApply,
|
code: DiagnosticKind.InvalidApply,
|
||||||
severity:
|
severity:
|
||||||
|
@ -55,7 +28,7 @@ export function getInvalidApplyDiagnostics(
|
||||||
? DiagnosticSeverity.Error
|
? DiagnosticSeverity.Error
|
||||||
: DiagnosticSeverity.Warning,
|
: DiagnosticSeverity.Warning,
|
||||||
range: className.range,
|
range: className.range,
|
||||||
message,
|
message: result.reason,
|
||||||
className,
|
className,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import { State } from '../util/state'
|
import { State } from '../util/state'
|
||||||
import { Hover, TextDocumentPositionParams } from 'vscode-languageserver'
|
import { Hover, TextDocumentPositionParams } from 'vscode-languageserver'
|
||||||
import { getClassNameParts } from '../util/getClassNameAtPosition'
|
|
||||||
import { stringifyCss, stringifyConfigValue } from '../util/stringify'
|
import { stringifyCss, stringifyConfigValue } from '../util/stringify'
|
||||||
const dlv = require('dlv')
|
const dlv = require('dlv')
|
||||||
import { isCssContext } from '../util/css'
|
import { isCssContext } from '../util/css'
|
||||||
import { findClassNameAtPosition } from '../util/find'
|
import { findClassNameAtPosition } from '../util/find'
|
||||||
|
import { validateApply } from '../util/validateApply'
|
||||||
|
import { getClassNameParts } from '../util/getClassNameAtPosition'
|
||||||
|
|
||||||
export function provideHover(
|
export function provideHover(
|
||||||
state: State,
|
state: State,
|
||||||
|
@ -81,6 +82,13 @@ function provideClassNameHover(
|
||||||
const parts = getClassNameParts(state, className.className)
|
const parts = getClassNameParts(state, className.className)
|
||||||
if (!parts) return null
|
if (!parts) return null
|
||||||
|
|
||||||
|
if (isCssContext(state, doc, position)) {
|
||||||
|
let validated = validateApply(state, parts)
|
||||||
|
if (validated === null || validated.isApplyable === false) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
contents: {
|
contents: {
|
||||||
language: 'css',
|
language: 'css',
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { State } from './state'
|
||||||
|
import { getClassNameMeta } from './getClassNameMeta'
|
||||||
|
|
||||||
|
export function validateApply(
|
||||||
|
state: State,
|
||||||
|
classNameOrParts: string | string[]
|
||||||
|
): { isApplyable: true } | { isApplyable: false; reason: string } | null {
|
||||||
|
const meta = getClassNameMeta(state, classNameOrParts)
|
||||||
|
if (!meta) return null
|
||||||
|
|
||||||
|
const className = Array.isArray(classNameOrParts)
|
||||||
|
? classNameOrParts.join(state.separator)
|
||||||
|
: classNameOrParts
|
||||||
|
|
||||||
|
let reason: string
|
||||||
|
|
||||||
|
if (Array.isArray(meta)) {
|
||||||
|
reason = `'@apply' cannot be used with '${className}' because it is included in multiple rulesets.`
|
||||||
|
} else if (meta.source !== 'utilities') {
|
||||||
|
reason = `'@apply' cannot be used with '${className}' because it is not a utility.`
|
||||||
|
} else if (meta.context && meta.context.length > 0) {
|
||||||
|
if (meta.context.length === 1) {
|
||||||
|
reason = `'@apply' cannot be used with '${className}' because it is nested inside of an at-rule ('${meta.context[0]}').`
|
||||||
|
} else {
|
||||||
|
reason = `'@apply' cannot be used with '${className}' because it is nested inside of at-rules (${meta.context
|
||||||
|
.map((c) => `'${c}'`)
|
||||||
|
.join(', ')}).`
|
||||||
|
}
|
||||||
|
} else if (meta.pseudo && meta.pseudo.length > 0) {
|
||||||
|
if (meta.pseudo.length === 1) {
|
||||||
|
reason = `'@apply' cannot be used with '${className}' because its definition includes a pseudo-selector ('${meta.pseudo[0]}')`
|
||||||
|
} else {
|
||||||
|
reason = `'@apply' cannot be used with '${className}' because its definition includes pseudo-selectors (${meta.pseudo
|
||||||
|
.map((p) => `'${p}'`)
|
||||||
|
.join(', ')}).`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reason) {
|
||||||
|
return { isApplyable: false, reason }
|
||||||
|
}
|
||||||
|
|
||||||
|
return { isApplyable: true }
|
||||||
|
}
|
Loading…
Reference in New Issue