diff --git a/src/lsp/providers/codeActionProvider/index.ts b/src/lsp/providers/codeActionProvider/index.ts
index 19d724e27e2e2fe641eceadbea635c44cf65eccd..28b51444d56fb61000f2e34b32affdfdd19e4f01 100644
--- a/src/lsp/providers/codeActionProvider/index.ts
+++ b/src/lsp/providers/codeActionProvider/index.ts
@@ -4,39 +4,92 @@ CodeActionParams,
CodeActionKind,
Range,
TextEdit,
+} from 'vscode-languageserver'
+import { State } from '../../util/state'
+import { findLast } from '../../util/find'
+import { isWithinRange } from '../../util/isWithinRange'
+import { getClassNameParts } from '../../util/getClassNameAtPosition'
+const dlv = require('dlv')
+import dset from 'dset'
+import { removeRangeFromString } from '../../util/removeRangeFromString'
+import detectIndent from 'detect-indent'
+import {
Diagnostic,
+import {
} from 'vscode-languageserver'
+export function provideCodeActions(
import { State } from '../../util/state'
+ CodeAction,
import { findLast, findClassNamesInRange } from '../../util/find'
import {
+ state: State,
import {
+ CodeAction,
import { getClassNameParts } from '../../util/getClassNameAtPosition'
+ CodeAction,
const dlv = require('dlv')
+ CodeAction,
import dset from 'dset'
+ CodeAction,
import { removeRangeFromString } from '../../util/removeRangeFromString'
import {
+import { State } from '../../util/state'
+ state: State,
TextEdit,
+ state: State,
+ params: CodeActionParams,
+ CodeAction,
import { cssObjToAst } from '../../util/cssObjToAst'
+ CodeAction,
import isObject from '../../../util/isObject'
import {
+ Diagnostic,
+ let diagnostics = await getDiagnostics(state, document, only)
+import {
import { State } from '../../util/state'
CodeAction,
+ CodeAction,
+ CodeAction,
state: State,
+ CodeAction,
params: CodeActionParams
CodeAction,
+ CodeAction,
CodeActionParams,
+ })
+ CodeAction,
if (params.context.diagnostics.length === 0) {
CodeAction,
+ CodeAction,
Range,
+}
+
+ CodeAction,
}
+ CodeAction,
import {
-import { State } from '../../util/state'
CodeAction,
+ CodeAction,
+): Promise<CodeAction[]> {
+ params: CodeActionParams
Diagnostic,
+ CodeAction,
params.context.diagnostics
CodeAction,
+ CodeAction,
import { State } from '../../util/state'
+
+ CodeAction,
if (diagnostic.code === 'invalidApply') {
+ state,
+ params,
+ codes
+ )
+
+ return Promise.all(
+ diagnostics
+ .map((diagnostic) => {
+ if (isInvalidApplyDiagnostic(diagnostic)) {
return provideInvalidApplyCodeAction(state, params, diagnostic)
}
@@ -135,36 +188,17 @@
async function provideInvalidApplyCodeAction(
state: State,
params: CodeActionParams,
- diagnostic: Diagnostic
+ diagnostic: InvalidApplyDiagnostic
): Promise<CodeAction> {
let document = state.editor.documents.get(params.textDocument.uri)
let documentText = document.getText()
const { postcss } = state.modules
let change: TextEdit
- let documentClassNames = findClassNamesInRange(
-import { isWithinRange } from '../../util/isWithinRange'
CodeAction,
-import { isWithinRange } from '../../util/isWithinRange'
CodeActionParams,
- start: {
- line: Math.max(0, diagnostic.range.start.line - 10),
- character: 0,
-import { isWithinRange } from '../../util/isWithinRange'
Diagnostic,
import {
-import isObject from '../../../util/isObject'
- },
- 'css'
- )
- let documentClassName = documentClassNames.find((className) =>
- isWithinRange(diagnostic.range.start, className.range)
- )
- if (!documentClassName) {
- return null
- }
- let totalClassNamesInClassList = documentClassName.classList.classList.split(
-import {
if (params.context.diagnostics.length === 0) {
).length
@@ -197,7 +231,7 @@ let ast = classNameToAst(
state,
className,
rule.selector,
- documentClassName.classList.important
+ diagnostic.className.classList.important
)
if (!ast) {
@@ -263,13 +297,13 @@ [params.textDocument.uri]: [
...(totalClassNamesInClassList > 1
? [
{
-
+): Promise<CodeAction[]> {
import { State } from '../../util/state'
newText: removeRangeFromString(
CodeAction,
+ CodeActionKind,
-import {
CodeAction,
- CodeAction,
+ kind: CodeActionKind.QuickFix,
),
},
]
diff --git a/src/lsp/providers/diagnosticsProvider.ts b/src/lsp/providers/diagnostics/diagnosticsProvider.ts
rename from src/lsp/providers/diagnosticsProvider.ts
rename to src/lsp/providers/diagnostics/diagnosticsProvider.ts
index f6fa9092b7d83df2bd1647b212f32527f8c843ee..56362d5488cc8776715de6feac2096c57149f255 100644
--- a/src/lsp/providers/diagnosticsProvider.ts
+++ b/src/lsp/providers/diagnostics/diagnosticsProvider.ts
@@ -1,122 +1,141 @@
+ document: TextDocument,
import {
+ document: TextDocument,
TextDocument,
+ document: TextDocument,
Diagnostic,
- DiagnosticSeverity,
- Range,
-} from 'vscode-languageserver'
-import { State, Settings } from '../util/state'
-import { isCssDoc } from '../util/css'
import {
findClassNamesInRange,
findClassListsInDocument,
getClassNamesInClassList,
findAll,
indexToPosition,
-import {
+ document: TextDocument,
DiagnosticSeverity,
-import {
+ document: TextDocument,
Range,
-import {
+ document: TextDocument,
} from 'vscode-languageserver'
-import {
+ document: TextDocument,
import { State, Settings } from '../util/state'
-import {
+ document: TextDocument,
import { isCssDoc } from '../util/css'
const dlv = require('dlv')
import semver from 'semver'
TextDocument,
+ message: `'${className.className}' and '${otherClassName.className}' apply the same CSS properties.`,
+import { absoluteRange } from '../../util/absoluteRange'
+ settings: Settings
import {
- TextDocument,
+ settings: Settings
TextDocument,
- TextDocument,
+ settings: Settings
Diagnostic,
- TextDocument,
+import {
+ settings: Settings
DiagnosticSeverity,
+ DiagnosticKind,
+ UtilityConflictsDiagnostic,
+ InvalidScreenDiagnostic,
+ InvalidVariantDiagnostic,
+ InvalidConfigPathDiagnostic,
+ InvalidTailwindDirectiveDiagnostic,
+ AugmentedDiagnostic,
+): Diagnostic[] {
TextDocument,
- Range,
function getInvalidApplyDiagnostics(
state: State,
document: TextDocument,
settings: Settings
): Diagnostic[] {
+ Diagnostic,
let severity = settings.lint.invalidApply
if (severity === 'ignore') return []
const classNames = findClassNamesInRange(document, undefined, 'css')
Diagnostic,
+} from '../util/find'
+): Diagnostic[] {
Range,
Diagnostic,
+import {
} from 'vscode-languageserver'
- const meta = getClassNameMeta(state, className)
+
Diagnostic,
-import { isCssDoc } from '../util/css'
+import { equal } from '../../util/array'
Diagnostic,
+import { getDocumentSettings } from '../util/getDocumentSettings'
+): Diagnostic[] {
findClassNamesInRange,
+ Diagnostic,
TextDocument,
-} from 'vscode-languageserver'
- DiagnosticSeverity,
- DiagnosticSeverity,
+ let severity = settings.lint.invalidApply
import {
- DiagnosticSeverity,
+ let severity = settings.lint.invalidApply
TextDocument,
- DiagnosticSeverity,
+ let severity = settings.lint.invalidApply
Diagnostic,
- DiagnosticSeverity,
+ let severity = settings.lint.invalidApply
DiagnosticSeverity,
+import { isObject } from '../../class-names/isObject'
DiagnosticSeverity,
+ let severity = settings.lint.invalidApply
Range,
- DiagnosticSeverity,
+ let severity = settings.lint.invalidApply
} from 'vscode-languageserver'
- DiagnosticSeverity,
+ let severity = settings.lint.invalidApply
import { State, Settings } from '../util/state'
- DiagnosticSeverity,
+ let severity = settings.lint.invalidApply
import { isCssDoc } from '../util/css'
- DiagnosticSeverity,
+ let severity = settings.lint.invalidApply
findClassNamesInRange,
Range,
+import { State, Settings } from '../util/state'
+ if (severity === 'ignore') return []
- Range,
+ if (severity === 'ignore') return []
import {
- Range,
+ if (severity === 'ignore') return []
TextDocument,
- Range,
+ TextDocument,
Diagnostic,
+ DiagnosticSeverity,
+ let severity = settings.lint.invalidApply
Range,
- DiagnosticSeverity,
- } else {
+ className.className
- message = `'@apply' cannot be used with '${className}' because its definition includes pseudo-selectors (${meta.pseudo
+ }' because its definition includes pseudo-selectors (${meta.pseudo
- .map((p) => `'${p}'`)
+ .map((p) => `'${p}'`)
- .join(', ')}).`
+ .join(', ')}).`
Range,
-import {
+import { State, Settings } from '../util/state'
+ if (severity === 'ignore') return []
Range,
-import { State, Settings } from '../util/state'
- if (!message) return null
+ if (!message) return null
- Range,
+ return {
+ code: DiagnosticKind.InvalidApply,
+ if (severity === 'ignore') return []
findClassNamesInRange,
-} from 'vscode-languageserver'
+ const classNames = findClassNamesInRange(document, undefined, 'css')
-} from 'vscode-languageserver'
+ const classNames = findClassNamesInRange(document, undefined, 'css')
import {
-} from 'vscode-languageserver'
+ const classNames = findClassNamesInRange(document, undefined, 'css')
TextDocument,
-} from 'vscode-languageserver'
+ const classNames = findClassNamesInRange(document, undefined, 'css')
Diagnostic,
-} from 'vscode-languageserver'
+ const classNames = findClassNamesInRange(document, undefined, 'css')
DiagnosticSeverity,
-} from 'vscode-languageserver'
+ const classNames = findClassNamesInRange(document, undefined, 'css')
Range,
- code: 'invalidApply',
+ if (severity === 'ignore') return []
Range,
-import { State, Settings } from '../util/state'
- })
- .filter(Boolean)
+ })
+ const classNames = findClassNamesInRange(document, undefined, 'css')
} from 'vscode-languageserver'
- findClassNamesInRange,
}
function getUtilityConflictDiagnostics(
@@ -124,12 +143,12 @@ state: State,
document: TextDocument,
settings: Settings
Diagnostic,
-import {
+ } else {
let severity = settings.lint.utilityConflicts
if (severity === 'ignore') return []
-import { State, Settings } from '../util/state'
Diagnostic,
+ message = `'@apply' cannot be used with '${className}' because it is nested inside of at-rules (${meta.context
const classLists = findClassListsInDocument(state, document)
classLists.forEach((classList) => {
@@ -155,6 +174,9 @@ equal(meta.context, otherMeta.context) &&
equal(meta.pseudo, otherMeta.pseudo)
) {
diagnostics.push({
+ code: DiagnosticKind.UtilityConflicts,
+ className,
+ otherClassName,
range: className.range,
severity:
severity === 'error'
@@ -184,11 +206,11 @@ state: State,
document: TextDocument,
settings: Settings
Diagnostic,
-import {
+ } else if (meta.pseudo && meta.pseudo.length > 0) {
let severity = settings.lint.invalidScreen
if (severity === 'ignore') return []
-import { State, Settings } from '../util/state'
+ let diagnostics: Diagnostic[] = classNames
Diagnostic,
let ranges: Range[] = []
@@ -220,6 +242,7 @@ message += ` Did you mean '${suggestion}'?`
}
diagnostics.push({
+ code: DiagnosticKind.InvalidScreen,
range: absoluteRange(
{
start: indexToPosition(
@@ -247,12 +270,12 @@ state: State,
document: TextDocument,
settings: Settings
Diagnostic,
-import {
+ message = `'@apply' cannot be used with '${className}' because its definition includes pseudo-selectors (${meta.pseudo
let severity = settings.lint.invalidVariant
if (severity === 'ignore') return []
-import { State, Settings } from '../util/state'
Diagnostic,
+ .map((p) => `'${p}'`)
let ranges: Range[] = []
if (isCssDoc(state, document)) {
@@ -288,6 +311,7 @@ let variantStartIndex =
listStartIndex + variants.slice(0, i).join('').length
diagnostics.push({
+ code: DiagnosticKind.InvalidVariant,
range: absoluteRange(
{
start: indexToPosition(text, variantStartIndex),
@@ -313,12 +337,12 @@ state: State,
document: TextDocument,
settings: Settings
Diagnostic,
-import {
+ if (!message) return null
let severity = settings.lint.invalidConfigPath
if (severity === 'ignore') return []
-import { State, Settings } from '../util/state'
Diagnostic,
+ return {
let ranges: Range[] = []
if (isCssDoc(state, document)) {
@@ -427,6 +451,7 @@ 1 + // open paren
match.groups.quote.length
diagnostics.push({
+ code: DiagnosticKind.InvalidConfigPath,
range: absoluteRange(
{
start: indexToPosition(text, startIndex),
@@ -451,12 +476,13 @@ state: State,
document: TextDocument,
settings: Settings
Diagnostic,
+} from 'vscode-languageserver'
import {
let severity = settings.lint.invalidTailwindDirective
if (severity === 'ignore') return []
-import { State, Settings } from '../util/state'
Diagnostic,
+ ? DiagnosticSeverity.Error
let ranges: Range[] = []
if (isCssDoc(state, document)) {
@@ -494,6 +520,7 @@ }
}
diagnostics.push({
+ code: DiagnosticKind.InvalidTailwindDirective,
range: absoluteRange(
{
start: indexToPosition(
@@ -516,41 +543,67 @@
return diagnostics
}
- TextDocument,
+ Diagnostic,
} from 'vscode-languageserver'
-import { State, Settings } from '../util/state'
+ DiagnosticSeverity,
state: State,
TextDocument,
+ findClassNamesInRange,
+ only: DiagnosticKind[] = [
+ DiagnosticKind.UtilityConflicts,
+ DiagnosticKind.InvalidApply,
+ Diagnostic,
.filter(Boolean)
- TextDocument,
+ Diagnostic,
return diagnostics
- TextDocument,
+ Diagnostic,
}
-
- TextDocument,
+ Diagnostic,
function getUtilityConflictDiagnostics(
- TextDocument,
+ Diagnostic,
let severity = settings.lint.utilityConflicts
- TextDocument,
+ Diagnostic,
let diagnostics: Diagnostic[] = []
function getInvalidApplyDiagnostics(
+
+ const meta = getClassNameMeta(state, className)
DiagnosticSeverity,
function getInvalidApplyDiagnostics(
+ TextDocument,
+ const meta = getClassNameMeta(state, className)
Range,
- TextDocument,
+ Diagnostic,
const classNames = getClassNamesInClassList(classList)
+ : []),
+ ...(only.includes(DiagnosticKind.InvalidApply)
+ ? getInvalidApplyDiagnostics(state, document, settings)
+ : []),
+ ...(only.includes(DiagnosticKind.InvalidScreen)
+ ? getInvalidScreenDiagnostics(state, document, settings)
+ : []),
+ if (!meta) return null
TextDocument,
+ ? getInvalidVariantDiagnostics(state, document, settings)
+ Diagnostic,
classNames.forEach((className, index) => {
- TextDocument,
+ ...(only.includes(DiagnosticKind.InvalidConfigPath)
+ ? getInvalidConfigPathDiagnostics(state, document, settings)
+ const meta = getClassNameMeta(state, className)
import { State, Settings } from '../util/state'
+ Diagnostic,
import { isCssDoc } from '../util/css'
+} from 'vscode-languageserver'
+ ? getInvalidTailwindDirectiveDiagnostics(state, document, settings)
+ : []),
]
: []
+}
+export async function provideDiagnostics(state: State, document: TextDocument) {
state.editor.connection.sendDiagnostics({
uri: document.uri,
- state: State,
Diagnostic,
+ !Array.isArray(otherMeta) &&
})
}