refactor "suggestion" quick fixes

master
Brad Cornes 2020-06-18 14:49:50 +01:00
parent 7b916ab3c6
commit 6cbd49a74a
3 changed files with 46 additions and 25 deletions

View File

@ -24,6 +24,10 @@ import {
InvalidApplyDiagnostic, InvalidApplyDiagnostic,
isUtilityConflictsDiagnostic, isUtilityConflictsDiagnostic,
UtilityConflictsDiagnostic, UtilityConflictsDiagnostic,
isInvalidConfigPathDiagnostic,
isInvalidTailwindDirectiveDiagnostic,
isInvalidScreenDiagnostic,
isInvalidVariantDiagnostic,
} from '../diagnostics/types' } from '../diagnostics/types'
import { flatten, dedupeBy } from '../../../util/array' import { flatten, dedupeBy } from '../../../util/array'
import { joinWithAnd } from '../../util/joinWithAnd' import { joinWithAnd } from '../../util/joinWithAnd'
@ -72,18 +76,14 @@ export async function provideCodeActions(
return provideUtilityConflictsCodeActions(state, params, diagnostic) return provideUtilityConflictsCodeActions(state, params, diagnostic)
} }
let match = findLast( if (
/ Did you mean (?:something like )?'(?<replacement>[^']+)'\?$/g, isInvalidConfigPathDiagnostic(diagnostic) ||
diagnostic.message isInvalidTailwindDirectiveDiagnostic(diagnostic) ||
) isInvalidScreenDiagnostic(diagnostic) ||
isInvalidVariantDiagnostic(diagnostic)
if (!match) { ) {
return [] return diagnostic.suggestions.map((suggestion) => ({
} title: `Replace with '${suggestion}'`,
return [
{
title: `Replace with '${match.groups.replacement}'`,
kind: CodeActionKind.QuickFix, kind: CodeActionKind.QuickFix,
diagnostics: [diagnostic], diagnostics: [diagnostic],
edit: { edit: {
@ -91,13 +91,15 @@ export async function provideCodeActions(
[params.textDocument.uri]: [ [params.textDocument.uri]: [
{ {
range: diagnostic.range, range: diagnostic.range,
newText: match.groups.replacement, newText: suggestion,
}, },
], ],
}, },
}, },
}, }))
] }
return []
}) })
return Promise.all(actions) return Promise.all(actions)

View File

@ -197,8 +197,11 @@ function getInvalidScreenDiagnostics(
} }
let message = `The screen '${match.groups.screen}' does not exist in your theme config.` let message = `The screen '${match.groups.screen}' does not exist in your theme config.`
let suggestions: string[] = []
let suggestion = closest(match.groups.screen, screens) let suggestion = closest(match.groups.screen, screens)
if (suggestion) { if (suggestion) {
suggestions.push(suggestion)
message += ` Did you mean '${suggestion}'?` message += ` Did you mean '${suggestion}'?`
} }
@ -219,6 +222,7 @@ function getInvalidScreenDiagnostics(
? DiagnosticSeverity.Error ? DiagnosticSeverity.Error
: DiagnosticSeverity.Warning, : DiagnosticSeverity.Warning,
message, message,
suggestions,
}) })
}) })
}) })
@ -261,8 +265,11 @@ function getInvalidVariantDiagnostics(
} }
let message = `The variant '${variant}' does not exist.` let message = `The variant '${variant}' does not exist.`
let suggestions: string[] = []
let suggestion = closest(variant, state.variants) let suggestion = closest(variant, state.variants)
if (suggestion) { if (suggestion) {
suggestions.push(suggestion)
message += ` Did you mean '${suggestion}'?` message += ` Did you mean '${suggestion}'?`
} }
@ -283,6 +290,7 @@ function getInvalidVariantDiagnostics(
? DiagnosticSeverity.Error ? DiagnosticSeverity.Error
: DiagnosticSeverity.Warning, : DiagnosticSeverity.Warning,
message, message,
suggestions,
}) })
} }
}) })
@ -337,6 +345,7 @@ function getInvalidConfigPathDiagnostics(
}, '') }, '')
let message: string let message: string
let suggestions: string[] = []
if (isValid(value)) { if (isValid(value)) {
// The value resolves successfully, but we need to check that there // 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])) Object.keys(parentValue).filter((key) => isValid(parentValue[key]))
) )
if (closestValidKey) { if (closestValidKey) {
message += ` Did you mean '${stitch([ suggestions.push(
...keys.slice(0, keys.length - 1), stitch([...keys.slice(0, keys.length - 1), closestValidKey])
closestValidKey, )
])}'?` message += ` Did you mean '${suggestions[0]}'?`
} }
} }
} else { } else {
message = `'${match.groups.key}' was found but does not resolve to a string.` message = `'${match.groups.key}' was found but does not resolve to a string.`
if (isObject(value)) { if (isObject(value)) {
let firstValidKey = Object.keys(value).find((key) => let validKeys = Object.keys(value).filter((key) =>
isValid(value[key]) isValid(value[key])
) )
if (firstValidKey) { if (validKeys.length) {
message += ` Did you mean something like '${stitch([ suggestions.push(
...keys, ...validKeys.map((validKey) => stitch([...keys, validKey]))
firstValidKey, )
])}'?` message += ` Did you mean something like '${suggestions[0]}'?`
} }
} }
} }
@ -421,6 +430,7 @@ function getInvalidConfigPathDiagnostics(
? DiagnosticSeverity.Error ? DiagnosticSeverity.Error
: DiagnosticSeverity.Warning, : DiagnosticSeverity.Warning,
message, message,
suggestions,
}) })
}) })
}) })
@ -464,11 +474,15 @@ function getInvalidTailwindDirectiveDiagnostics(
} }
let message = `'${match.groups.value}' is not a valid group.` let message = `'${match.groups.value}' is not a valid group.`
let suggestions: string[] = []
if (match.groups.value === 'preflight') { if (match.groups.value === 'preflight') {
suggestions.push('base')
message += ` Did you mean 'base'?` message += ` Did you mean 'base'?`
} else { } else {
let suggestion = closest(match.groups.value, valid) let suggestion = closest(match.groups.value, valid)
if (suggestion) { if (suggestion) {
suggestions.push(suggestion)
message += ` Did you mean '${suggestion}'?` message += ` Did you mean '${suggestion}'?`
} }
} }
@ -490,6 +504,7 @@ function getInvalidTailwindDirectiveDiagnostics(
? DiagnosticSeverity.Error ? DiagnosticSeverity.Error
: DiagnosticSeverity.Warning, : DiagnosticSeverity.Warning,
message, message,
suggestions,
}) })
}) })
}) })

View File

@ -35,6 +35,7 @@ export function isInvalidApplyDiagnostic(
export type InvalidScreenDiagnostic = Diagnostic & { export type InvalidScreenDiagnostic = Diagnostic & {
code: DiagnosticKind.InvalidScreen code: DiagnosticKind.InvalidScreen
suggestions: string[]
} }
export function isInvalidScreenDiagnostic( export function isInvalidScreenDiagnostic(
@ -45,6 +46,7 @@ export function isInvalidScreenDiagnostic(
export type InvalidVariantDiagnostic = Diagnostic & { export type InvalidVariantDiagnostic = Diagnostic & {
code: DiagnosticKind.InvalidVariant code: DiagnosticKind.InvalidVariant
suggestions: string[]
} }
export function isInvalidVariantDiagnostic( export function isInvalidVariantDiagnostic(
@ -55,6 +57,7 @@ export function isInvalidVariantDiagnostic(
export type InvalidConfigPathDiagnostic = Diagnostic & { export type InvalidConfigPathDiagnostic = Diagnostic & {
code: DiagnosticKind.InvalidConfigPath code: DiagnosticKind.InvalidConfigPath
suggestions: string[]
} }
export function isInvalidConfigPathDiagnostic( export function isInvalidConfigPathDiagnostic(
@ -65,6 +68,7 @@ export function isInvalidConfigPathDiagnostic(
export type InvalidTailwindDirectiveDiagnostic = Diagnostic & { export type InvalidTailwindDirectiveDiagnostic = Diagnostic & {
code: DiagnosticKind.InvalidTailwindDirective code: DiagnosticKind.InvalidTailwindDirective
suggestions: string[]
} }
export function isInvalidTailwindDirectiveDiagnostic( export function isInvalidTailwindDirectiveDiagnostic(