diff --git a/src/lsp/providers/codeActionProvider/index.ts b/src/lsp/providers/codeActionProvider/index.ts index 5bced1d..6ae4bf9 100644 --- a/src/lsp/providers/codeActionProvider/index.ts +++ b/src/lsp/providers/codeActionProvider/index.ts @@ -24,6 +24,10 @@ import { InvalidApplyDiagnostic, isUtilityConflictsDiagnostic, UtilityConflictsDiagnostic, + isInvalidConfigPathDiagnostic, + isInvalidTailwindDirectiveDiagnostic, + isInvalidScreenDiagnostic, + isInvalidVariantDiagnostic, } from '../diagnostics/types' import { flatten, dedupeBy } from '../../../util/array' import { joinWithAnd } from '../../util/joinWithAnd' @@ -72,18 +76,14 @@ export async function provideCodeActions( return provideUtilityConflictsCodeActions(state, params, diagnostic) } - let match = findLast( - / Did you mean (?:something like )?'(?[^']+)'\?$/g, - diagnostic.message - ) - - if (!match) { - return [] - } - - return [ - { - title: `Replace with '${match.groups.replacement}'`, + if ( + isInvalidConfigPathDiagnostic(diagnostic) || + isInvalidTailwindDirectiveDiagnostic(diagnostic) || + isInvalidScreenDiagnostic(diagnostic) || + isInvalidVariantDiagnostic(diagnostic) + ) { + return diagnostic.suggestions.map((suggestion) => ({ + title: `Replace with '${suggestion}'`, kind: CodeActionKind.QuickFix, diagnostics: [diagnostic], edit: { @@ -91,13 +91,15 @@ export async function provideCodeActions( [params.textDocument.uri]: [ { range: diagnostic.range, - newText: match.groups.replacement, + newText: suggestion, }, ], }, }, - }, - ] + })) + } + + return [] }) return Promise.all(actions) diff --git a/src/lsp/providers/diagnostics/diagnosticsProvider.ts b/src/lsp/providers/diagnostics/diagnosticsProvider.ts index 1c98a39..91ca0e3 100644 --- a/src/lsp/providers/diagnostics/diagnosticsProvider.ts +++ b/src/lsp/providers/diagnostics/diagnosticsProvider.ts @@ -197,8 +197,11 @@ function getInvalidScreenDiagnostics( } let message = `The screen '${match.groups.screen}' does not exist in your theme config.` + let suggestions: string[] = [] let suggestion = closest(match.groups.screen, screens) + if (suggestion) { + suggestions.push(suggestion) message += ` Did you mean '${suggestion}'?` } @@ -219,6 +222,7 @@ function getInvalidScreenDiagnostics( ? DiagnosticSeverity.Error : DiagnosticSeverity.Warning, message, + suggestions, }) }) }) @@ -261,8 +265,11 @@ function getInvalidVariantDiagnostics( } let message = `The variant '${variant}' does not exist.` + let suggestions: string[] = [] let suggestion = closest(variant, state.variants) + if (suggestion) { + suggestions.push(suggestion) message += ` Did you mean '${suggestion}'?` } @@ -283,6 +290,7 @@ function getInvalidVariantDiagnostics( ? DiagnosticSeverity.Error : DiagnosticSeverity.Warning, message, + suggestions, }) } }) @@ -337,6 +345,7 @@ function getInvalidConfigPathDiagnostics( }, '') let message: string + let suggestions: string[] = [] if (isValid(value)) { // The value resolves successfully, but we need to check that there @@ -374,24 +383,24 @@ function getInvalidConfigPathDiagnostics( Object.keys(parentValue).filter((key) => isValid(parentValue[key])) ) if (closestValidKey) { - message += ` Did you mean '${stitch([ - ...keys.slice(0, keys.length - 1), - closestValidKey, - ])}'?` + suggestions.push( + stitch([...keys.slice(0, keys.length - 1), closestValidKey]) + ) + message += ` Did you mean '${suggestions[0]}'?` } } } else { message = `'${match.groups.key}' was found but does not resolve to a string.` if (isObject(value)) { - let firstValidKey = Object.keys(value).find((key) => + let validKeys = Object.keys(value).filter((key) => isValid(value[key]) ) - if (firstValidKey) { - message += ` Did you mean something like '${stitch([ - ...keys, - firstValidKey, - ])}'?` + if (validKeys.length) { + suggestions.push( + ...validKeys.map((validKey) => stitch([...keys, validKey])) + ) + message += ` Did you mean something like '${suggestions[0]}'?` } } } @@ -421,6 +430,7 @@ function getInvalidConfigPathDiagnostics( ? DiagnosticSeverity.Error : DiagnosticSeverity.Warning, message, + suggestions, }) }) }) @@ -464,11 +474,15 @@ function getInvalidTailwindDirectiveDiagnostics( } let message = `'${match.groups.value}' is not a valid group.` + let suggestions: string[] = [] + if (match.groups.value === 'preflight') { + suggestions.push('base') message += ` Did you mean 'base'?` } else { let suggestion = closest(match.groups.value, valid) if (suggestion) { + suggestions.push(suggestion) message += ` Did you mean '${suggestion}'?` } } @@ -490,6 +504,7 @@ function getInvalidTailwindDirectiveDiagnostics( ? DiagnosticSeverity.Error : DiagnosticSeverity.Warning, message, + suggestions, }) }) }) diff --git a/src/lsp/providers/diagnostics/types.ts b/src/lsp/providers/diagnostics/types.ts index 00fc979..385aac5 100644 --- a/src/lsp/providers/diagnostics/types.ts +++ b/src/lsp/providers/diagnostics/types.ts @@ -35,6 +35,7 @@ export function isInvalidApplyDiagnostic( export type InvalidScreenDiagnostic = Diagnostic & { code: DiagnosticKind.InvalidScreen + suggestions: string[] } export function isInvalidScreenDiagnostic( @@ -45,6 +46,7 @@ export function isInvalidScreenDiagnostic( export type InvalidVariantDiagnostic = Diagnostic & { code: DiagnosticKind.InvalidVariant + suggestions: string[] } export function isInvalidVariantDiagnostic( @@ -55,6 +57,7 @@ export function isInvalidVariantDiagnostic( export type InvalidConfigPathDiagnostic = Diagnostic & { code: DiagnosticKind.InvalidConfigPath + suggestions: string[] } export function isInvalidConfigPathDiagnostic( @@ -65,6 +68,7 @@ export function isInvalidConfigPathDiagnostic( export type InvalidTailwindDirectiveDiagnostic = Diagnostic & { code: DiagnosticKind.InvalidTailwindDirective + suggestions: string[] } export function isInvalidTailwindDirectiveDiagnostic(