diff --git a/src/class-names/index.js b/src/class-names/index.js index 88dd419..83a15b1 100644 --- a/src/class-names/index.js +++ b/src/class-names/index.js @@ -47,6 +47,7 @@ export default async function getClassNames( let tailwindcss let browserslistModule let version + let featureFlags = { future: [], experimental: [] } const configPaths = ( await glob(CONFIG_GLOB, { @@ -75,6 +76,10 @@ export default async function getClassNames( browserslistModule = importFrom(tailwindBase, 'browserslist') } catch (_) {} + try { + featureFlags = importFrom(tailwindBase, './lib/featureFlags.js').default + } catch (_) {} + const sepLocation = semver.gte(version, '0.99.0') ? ['separator'] : ['options', 'separator'] @@ -152,6 +157,7 @@ export default async function getClassNames( tailwindcss, postcss, }, + featureFlags, } } diff --git a/src/lsp/providers/completionProvider.ts b/src/lsp/providers/completionProvider.ts index ec93d44..795127c 100644 --- a/src/lsp/providers/completionProvider.ts +++ b/src/lsp/providers/completionProvider.ts @@ -28,6 +28,8 @@ import { getClassAttributeLexer, getComputedClassAttributeLexer, } from '../util/lexers' +import { validateApply } from '../util/validateApply' +import { flagEnabled } from '../util/flagEnabled' function completionsFromClassList( state: State, @@ -193,16 +195,11 @@ function provideAtApplyCompletions( end: position, }, (item) => { - // TODO: first line excludes all subtrees but there could _technically_ be - // valid apply-able class names in there. Will be correct in 99% of cases - if (item.kind === CompletionItemKind.Module) return false - let info = dlv(state.classNames.classNames, item.data) - return ( - !Array.isArray(info) && - info.__source === 'utilities' && - info.__context.length === 0 && - info.__pseudo.length === 0 - ) + if (item.kind === CompletionItemKind.Module) { + return flagEnabled(state, 'applyComplexClasses') + } + let validated = validateApply(state, item.data) + return validated !== null && validated.isApplyable === true } ) } diff --git a/src/lsp/providers/diagnostics/getInvalidApplyDiagnostics.ts b/src/lsp/providers/diagnostics/getInvalidApplyDiagnostics.ts index e829b57..0f11ca4 100644 --- a/src/lsp/providers/diagnostics/getInvalidApplyDiagnostics.ts +++ b/src/lsp/providers/diagnostics/getInvalidApplyDiagnostics.ts @@ -3,6 +3,7 @@ import { InvalidApplyDiagnostic, DiagnosticKind } from './types' import { Settings, State } from '../../util/state' import { TextDocument, DiagnosticSeverity } from 'vscode-languageserver' import { validateApply } from '../../util/validateApply' +import { flagEnabled } from '../../util/flagEnabled' export function getInvalidApplyDiagnostics( state: State, @@ -11,6 +12,7 @@ export function getInvalidApplyDiagnostics( ): InvalidApplyDiagnostic[] { let severity = settings.lint.invalidApply if (severity === 'ignore') return [] + if (flagEnabled(state, 'applyComplexClasses')) return [] const classNames = findClassNamesInRange(document, undefined, 'css') diff --git a/src/lsp/util/flagEnabled.ts b/src/lsp/util/flagEnabled.ts new file mode 100644 index 0000000..51332c1 --- /dev/null +++ b/src/lsp/util/flagEnabled.ts @@ -0,0 +1,20 @@ +import { State } from './state' +const dlv = require('dlv') + +export function flagEnabled(state: State, flag: string) { + if (state.featureFlags.future.includes(flag)) { + return ( + state.config.future === 'all' || + dlv(state.config, ['future', flag], false) + ) + } + + if (state.featureFlags.experimental.includes(flag)) { + return ( + state.config.experimental === 'all' || + dlv(state.config, ['experimental', flag], false) + ) + } + + return false +} diff --git a/src/lsp/util/state.ts b/src/lsp/util/state.ts index 09a0200..47b976d 100644 --- a/src/lsp/util/state.ts +++ b/src/lsp/util/state.ts @@ -57,6 +57,7 @@ export type State = null | { variants?: string[] classNames?: ClassNames dependencies?: string[] + featureFlags?: { future: string[]; experimental: string[] } editor?: EditorState error?: Error } diff --git a/src/lsp/util/validateApply.ts b/src/lsp/util/validateApply.ts index 52f2b2c..5a17956 100644 --- a/src/lsp/util/validateApply.ts +++ b/src/lsp/util/validateApply.ts @@ -1,5 +1,6 @@ import { State } from './state' import { getClassNameMeta } from './getClassNameMeta' +import { flagEnabled } from './flagEnabled' export function validateApply( state: State, @@ -8,6 +9,10 @@ export function validateApply( const meta = getClassNameMeta(state, classNameOrParts) if (!meta) return null + if (flagEnabled(state, 'applyComplexClasses')) { + return { isApplyable: true } + } + const className = Array.isArray(classNameOrParts) ? classNameOrParts.join(state.separator) : classNameOrParts