Use `itemDefaults` to reduce size of completion lists (#706)
* Use completion list `itemDefaults` * more defaultsmaster
parent
7235aeab48
commit
637f838725
|
@ -378,8 +378,21 @@ async function createProjectService(
|
|||
const disposables: Array<Disposable | Promise<Disposable>> = []
|
||||
let documentSelector = projectConfig.documentSelector
|
||||
|
||||
let itemDefaults =
|
||||
params.capabilities.textDocument?.completion?.completionList?.itemDefaults ?? []
|
||||
|
||||
// VS Code _does_ support `itemDefaults.data` since at least 1.67.0 (this extension's min version)
|
||||
// but it doesn't advertise it in its capabilities. So we manually add it here.
|
||||
// See also: https://github.com/microsoft/vscode-languageserver-node/issues/1181
|
||||
if (params.clientInfo?.name === 'Visual Studio Code' && !itemDefaults.includes('data')) {
|
||||
itemDefaults.push('data')
|
||||
}
|
||||
|
||||
let state: State = {
|
||||
enabled: false,
|
||||
completionItemData: {
|
||||
_projectKey: projectKey,
|
||||
},
|
||||
editor: {
|
||||
connection,
|
||||
folder,
|
||||
|
@ -390,6 +403,7 @@ async function createProjectService(
|
|||
capabilities: {
|
||||
configuration: true,
|
||||
diagnosticRelatedInformation: true,
|
||||
itemDefaults,
|
||||
},
|
||||
documents: documentService.documents,
|
||||
getConfiguration,
|
||||
|
@ -1114,21 +1128,13 @@ async function createProjectService(
|
|||
let settings = await state.editor.getConfiguration(document.uri)
|
||||
if (!settings.tailwindCSS.suggestions) return null
|
||||
if (await isExcluded(state, document)) return null
|
||||
let result = await doComplete(state, document, params.position, params.context)
|
||||
if (!result) return result
|
||||
return {
|
||||
isIncomplete: result.isIncomplete,
|
||||
items: result.items.map((item) => ({
|
||||
...item,
|
||||
data: { projectKey, originalData: item.data },
|
||||
})),
|
||||
}
|
||||
return doComplete(state, document, params.position, params.context)
|
||||
}, null)
|
||||
},
|
||||
onCompletionResolve(item: CompletionItem): Promise<CompletionItem> {
|
||||
return withFallback(() => {
|
||||
if (!state.enabled) return null
|
||||
return resolveCompletionItem(state, { ...item, data: item.data?.originalData })
|
||||
return resolveCompletionItem(state, item)
|
||||
}, null)
|
||||
},
|
||||
async onCodeAction(params: CodeActionParams): Promise<CodeAction[]> {
|
||||
|
@ -2162,7 +2168,7 @@ class TW {
|
|||
}
|
||||
|
||||
async onCompletionResolve(item: CompletionItem): Promise<CompletionItem> {
|
||||
return this.projects.get(item.data.projectKey)?.onCompletionResolve(item) ?? null
|
||||
return this.projects.get(item.data?._projectKey)?.onCompletionResolve(item) ?? null
|
||||
}
|
||||
|
||||
onCodeAction(params: CodeActionParams): Promise<CodeAction[]> {
|
||||
|
|
|
@ -97,12 +97,13 @@ export function completionsFromClassList(
|
|||
}
|
||||
|
||||
if (modifiers) {
|
||||
return {
|
||||
return withDefaults(
|
||||
{
|
||||
isIncomplete: false,
|
||||
items: modifiers.map((modifier, index) => {
|
||||
let className = `${beforeSlash}/${modifier}`
|
||||
let kind: CompletionItemKind = 21
|
||||
let documentation: string = null
|
||||
let documentation: string | undefined
|
||||
|
||||
const color = getColor(state, className)
|
||||
if (color !== null) {
|
||||
|
@ -114,17 +115,18 @@ export function completionsFromClassList(
|
|||
|
||||
return {
|
||||
label: className,
|
||||
documentation,
|
||||
...(documentation ? { documentation } : {}),
|
||||
kind,
|
||||
sortText: naturalExpand(index),
|
||||
data: [className],
|
||||
textEdit: {
|
||||
newText: className,
|
||||
range: replacementRange,
|
||||
},
|
||||
}
|
||||
}),
|
||||
}
|
||||
},
|
||||
{
|
||||
range: replacementRange,
|
||||
data: state.completionItemData,
|
||||
},
|
||||
state.editor.capabilities.itemDefaults
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,13 +143,14 @@ export function completionsFromClassList(
|
|||
let variantOrder = 0
|
||||
|
||||
function variantItem(
|
||||
item: Omit<CompletionItem, 'kind' | 'data' | 'sortText' | 'textEdit'> & {
|
||||
textEdit?: { newText: string; range?: Range }
|
||||
}
|
||||
item: Omit<CompletionItem, 'kind' | 'data' | 'command' | 'sortText' | 'textEdit'>
|
||||
): CompletionItem {
|
||||
return {
|
||||
kind: 9,
|
||||
data: 'variant',
|
||||
data: {
|
||||
...(state.completionItemData ?? {}),
|
||||
_type: 'variant',
|
||||
},
|
||||
command:
|
||||
item.insertTextFormat === 2 // Snippet
|
||||
? undefined
|
||||
|
@ -157,11 +160,6 @@ export function completionsFromClassList(
|
|||
},
|
||||
sortText: '-' + naturalExpand(variantOrder++),
|
||||
...item,
|
||||
textEdit: {
|
||||
newText: item.label,
|
||||
range: replacementRange,
|
||||
...item.textEdit,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,9 +172,7 @@ export function completionsFromClassList(
|
|||
variantItem({
|
||||
label: `${variant.name}${variant.hasDash ? '-' : ''}[]${sep}`,
|
||||
insertTextFormat: 2,
|
||||
textEdit: {
|
||||
newText: `${variant.name}${variant.hasDash ? '-' : ''}[\${1}]${sep}\${0}`,
|
||||
},
|
||||
textEditText: `${variant.name}${variant.hasDash ? '-' : ''}[\${1}]${sep}\${0}`,
|
||||
// command: {
|
||||
// title: '',
|
||||
// command: 'tailwindCSS.onInsertArbitraryVariantSnippet',
|
||||
|
@ -199,9 +195,7 @@ export function completionsFromClassList(
|
|||
variantItem({
|
||||
label: `${variant.name}${sep}`,
|
||||
detail: variant.selectors().join(', '),
|
||||
textEdit: {
|
||||
newText: resultingVariants[resultingVariants.length - 1] + sep,
|
||||
},
|
||||
textEditText: resultingVariants[resultingVariants.length - 1] + sep,
|
||||
additionalTextEdits:
|
||||
shouldSortVariants && resultingVariants.length > 1
|
||||
? [
|
||||
|
@ -248,12 +242,13 @@ export function completionsFromClassList(
|
|||
}
|
||||
|
||||
if (state.classList) {
|
||||
return {
|
||||
return withDefaults(
|
||||
{
|
||||
isIncomplete: false,
|
||||
items: items.concat(
|
||||
state.classList.map(([className, { color }], index) => {
|
||||
let kind: CompletionItemKind = color ? 16 : 21
|
||||
let documentation = null
|
||||
let documentation: string | undefined
|
||||
|
||||
if (color && typeof color !== 'string') {
|
||||
documentation = culori.formatRgb(color)
|
||||
|
@ -262,20 +257,26 @@ export function completionsFromClassList(
|
|||
return {
|
||||
label: className,
|
||||
kind,
|
||||
documentation,
|
||||
sortText: naturalExpand(index),
|
||||
data: [...existingVariants, important ? `!${className}` : className],
|
||||
textEdit: {
|
||||
newText: className,
|
||||
range: replacementRange,
|
||||
},
|
||||
...(documentation ? { documentation } : {}),
|
||||
sortText: naturalExpand(index, state.classList.length),
|
||||
} as CompletionItem
|
||||
})
|
||||
),
|
||||
}
|
||||
},
|
||||
{
|
||||
data: {
|
||||
...(state.completionItemData ?? {}),
|
||||
...(important ? { important } : {}),
|
||||
variants: existingVariants,
|
||||
},
|
||||
range: replacementRange,
|
||||
},
|
||||
state.editor.capabilities.itemDefaults
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
return withDefaults(
|
||||
{
|
||||
isIncomplete: false,
|
||||
items: items
|
||||
.concat(
|
||||
|
@ -287,9 +288,9 @@ export function completionsFromClassList(
|
|||
}
|
||||
return item.__info && isUtil(item)
|
||||
})
|
||||
.map((className, index) => {
|
||||
.map((className, index, classNames) => {
|
||||
let kind: CompletionItemKind = 21
|
||||
let documentation: string = null
|
||||
let documentation: string | undefined
|
||||
|
||||
const color = getColor(state, className)
|
||||
if (color !== null) {
|
||||
|
@ -302,13 +303,8 @@ export function completionsFromClassList(
|
|||
return {
|
||||
label: className,
|
||||
kind,
|
||||
documentation,
|
||||
sortText: naturalExpand(index),
|
||||
data: [...existingVariants, important ? `!${className}` : className],
|
||||
textEdit: {
|
||||
newText: className,
|
||||
range: replacementRange,
|
||||
},
|
||||
...(documentation ? { documentation } : {}),
|
||||
sortText: naturalExpand(index, classNames.length),
|
||||
} as CompletionItem
|
||||
})
|
||||
)
|
||||
|
@ -321,7 +317,17 @@ export function completionsFromClassList(
|
|||
}
|
||||
return true
|
||||
}),
|
||||
}
|
||||
},
|
||||
{
|
||||
range: replacementRange,
|
||||
data: {
|
||||
...(state.completionItemData ?? {}),
|
||||
variants: existingVariants,
|
||||
...(important ? { important } : {}),
|
||||
},
|
||||
},
|
||||
state.editor.capabilities.itemDefaults
|
||||
)
|
||||
}
|
||||
|
||||
for (let i = parts.length - 1; i > 0; i--) {
|
||||
|
@ -341,25 +347,25 @@ export function completionsFromClassList(
|
|||
}
|
||||
}
|
||||
|
||||
return {
|
||||
return withDefaults(
|
||||
{
|
||||
isIncomplete: false,
|
||||
items: Object.keys(isSubset ? subset : state.classNames.classNames)
|
||||
.filter((k) => k !== '__info')
|
||||
.filter((className) => isContextItem(state, [...subsetKey, className]))
|
||||
.map((className, index): CompletionItem => {
|
||||
.map((className, index, classNames): CompletionItem => {
|
||||
return {
|
||||
label: className + sep,
|
||||
kind: 9,
|
||||
documentation: null,
|
||||
command: {
|
||||
title: '',
|
||||
command: 'editor.action.triggerSuggest',
|
||||
},
|
||||
sortText: '-' + naturalExpand(index),
|
||||
data: [...subsetKey, className],
|
||||
textEdit: {
|
||||
newText: className + sep,
|
||||
range: replacementRange,
|
||||
sortText: '-' + naturalExpand(index, classNames.length),
|
||||
data: {
|
||||
...(state.completionItemData ?? {}),
|
||||
className,
|
||||
variants: subsetKey,
|
||||
},
|
||||
}
|
||||
})
|
||||
|
@ -368,9 +374,9 @@ export function completionsFromClassList(
|
|||
.filter((className) =>
|
||||
dlv(state.classNames.classNames, [...subsetKey, className, '__info'])
|
||||
)
|
||||
.map((className, index) => {
|
||||
.map((className, index, classNames) => {
|
||||
let kind: CompletionItemKind = 21
|
||||
let documentation: string = null
|
||||
let documentation: string | undefined
|
||||
|
||||
const color = getColor(state, className)
|
||||
if (color !== null) {
|
||||
|
@ -383,13 +389,8 @@ export function completionsFromClassList(
|
|||
return {
|
||||
label: className,
|
||||
kind,
|
||||
documentation,
|
||||
sortText: naturalExpand(index),
|
||||
data: [...subsetKey, className],
|
||||
textEdit: {
|
||||
newText: className,
|
||||
range: replacementRange,
|
||||
},
|
||||
...(documentation ? { documentation } : {}),
|
||||
sortText: naturalExpand(index, classNames.length),
|
||||
}
|
||||
})
|
||||
)
|
||||
|
@ -402,7 +403,16 @@ export function completionsFromClassList(
|
|||
}
|
||||
return true
|
||||
}),
|
||||
}
|
||||
},
|
||||
{
|
||||
range: replacementRange,
|
||||
data: {
|
||||
...(state.completionItemData ?? {}),
|
||||
variants: subsetKey,
|
||||
},
|
||||
},
|
||||
state.editor.capabilities.itemDefaults
|
||||
)
|
||||
}
|
||||
|
||||
async function provideClassAttributeCompletions(
|
||||
|
@ -569,7 +579,9 @@ function provideAtApplyCompletions(
|
|||
semver.gte(state.version, '2.0.0-alpha.1') || flagEnabled(state, 'applyComplexClasses')
|
||||
)
|
||||
}
|
||||
let validated = validateApply(state, item.data)
|
||||
let variants = item.data?.variants ?? []
|
||||
let className = item.data?.className ?? item.label
|
||||
let validated = validateApply(state, [...variants, className])
|
||||
return validated !== null && validated.isApplyable === true
|
||||
}
|
||||
)
|
||||
|
@ -673,7 +685,8 @@ function provideCssHelperCompletions(
|
|||
end: position,
|
||||
}
|
||||
|
||||
return {
|
||||
return withDefaults(
|
||||
{
|
||||
isIncomplete: false,
|
||||
items: Object.keys(obj)
|
||||
.sort((a, z) => {
|
||||
|
@ -690,9 +703,10 @@ function provideCssHelperCompletions(
|
|||
}
|
||||
return 0
|
||||
})
|
||||
.map((item, index) => {
|
||||
.map((item, index, items) => {
|
||||
let color = getColorFromValue(obj[item])
|
||||
const replaceDot: boolean = item.indexOf('.') !== -1 && separator && separator.endsWith('.')
|
||||
const replaceDot: boolean =
|
||||
item.indexOf('.') !== -1 && separator && separator.endsWith('.')
|
||||
const insertClosingBrace: boolean =
|
||||
text.charAt(text.length - 1) !== ']' &&
|
||||
(replaceDot || (separator && separator.endsWith('[')))
|
||||
|
@ -700,21 +714,17 @@ function provideCssHelperCompletions(
|
|||
|
||||
return {
|
||||
label: item,
|
||||
sortText: naturalExpand(index),
|
||||
sortText: naturalExpand(index, items.length),
|
||||
commitCharacters: [!item.includes('.') && '.', !item.includes('[') && '['].filter(
|
||||
Boolean
|
||||
),
|
||||
kind: color ? 16 : isObject(obj[item]) ? 9 : 10,
|
||||
// VS Code bug causes some values to not display in some cases
|
||||
detail: detail === '0' || detail === 'transparent' ? `${detail} ` : detail,
|
||||
documentation:
|
||||
color && typeof color !== 'string' && (color.alpha ?? 1) !== 0
|
||||
? culori.formatRgb(color)
|
||||
: null,
|
||||
textEdit: {
|
||||
newText: `${item}${insertClosingBrace ? ']' : ''}`,
|
||||
range: editRange,
|
||||
},
|
||||
...(color && typeof color !== 'string' && (color.alpha ?? 1) !== 0
|
||||
? { documentation: culori.formatRgb(color) }
|
||||
: {}),
|
||||
...(insertClosingBrace ? { textEditText: `${item}]` } : {}),
|
||||
additionalTextEdits: replaceDot
|
||||
? [
|
||||
{
|
||||
|
@ -729,10 +739,18 @@ function provideCssHelperCompletions(
|
|||
},
|
||||
]
|
||||
: [],
|
||||
data: 'helper',
|
||||
}
|
||||
}),
|
||||
}
|
||||
},
|
||||
{
|
||||
range: editRange,
|
||||
data: {
|
||||
...(state.completionItemData ?? {}),
|
||||
_type: 'helper',
|
||||
},
|
||||
},
|
||||
state.editor.capabilities.itemDefaults
|
||||
)
|
||||
}
|
||||
|
||||
function provideTailwindDirectiveCompletions(
|
||||
|
@ -753,9 +771,7 @@ function provideTailwindDirectiveCompletions(
|
|||
|
||||
if (match === null) return null
|
||||
|
||||
return {
|
||||
isIncomplete: false,
|
||||
items: [
|
||||
let items = [
|
||||
semver.gte(state.version, '1.0.0-beta.1')
|
||||
? {
|
||||
label: 'base',
|
||||
|
@ -818,12 +834,21 @@ function provideTailwindDirectiveCompletions(
|
|||
)})`,
|
||||
},
|
||||
},
|
||||
].map((item) => ({
|
||||
]
|
||||
|
||||
return withDefaults(
|
||||
{
|
||||
isIncomplete: false,
|
||||
items: items.map((item) => ({
|
||||
...item,
|
||||
kind: 21,
|
||||
data: '@tailwind',
|
||||
textEdit: {
|
||||
newText: item.label,
|
||||
})),
|
||||
},
|
||||
{
|
||||
data: {
|
||||
...(state.completionItemData ?? {}),
|
||||
_type: '@tailwind',
|
||||
},
|
||||
range: {
|
||||
start: {
|
||||
line: position.line,
|
||||
|
@ -832,8 +857,8 @@ function provideTailwindDirectiveCompletions(
|
|||
end: position,
|
||||
},
|
||||
},
|
||||
})),
|
||||
}
|
||||
state.editor.capabilities.itemDefaults
|
||||
)
|
||||
}
|
||||
|
||||
function provideVariantsDirectiveCompletions(
|
||||
|
@ -877,19 +902,23 @@ function provideVariantsDirectiveCompletions(
|
|||
possibleVariants = possibleVariants.filter((v) => !state.screens.includes(v))
|
||||
}
|
||||
|
||||
return {
|
||||
return withDefaults(
|
||||
{
|
||||
isIncomplete: false,
|
||||
items: possibleVariants
|
||||
.filter((v) => existingVariants.indexOf(v) === -1)
|
||||
.map((variant, index) => ({
|
||||
.map((variant, index, variants) => ({
|
||||
// TODO: detail
|
||||
label: variant,
|
||||
detail: state.variants[variant],
|
||||
kind: 21,
|
||||
data: 'variant',
|
||||
sortText: naturalExpand(index),
|
||||
textEdit: {
|
||||
newText: variant,
|
||||
sortText: naturalExpand(index, variants.length),
|
||||
})),
|
||||
},
|
||||
{
|
||||
data: {
|
||||
...(state.completionItemData ?? {}),
|
||||
_type: 'variant',
|
||||
},
|
||||
range: {
|
||||
start: {
|
||||
line: position.line,
|
||||
|
@ -898,8 +927,8 @@ function provideVariantsDirectiveCompletions(
|
|||
end: position,
|
||||
},
|
||||
},
|
||||
})),
|
||||
}
|
||||
state.editor.capabilities.itemDefaults
|
||||
)
|
||||
}
|
||||
|
||||
function provideLayerDirectiveCompletions(
|
||||
|
@ -920,15 +949,20 @@ function provideLayerDirectiveCompletions(
|
|||
|
||||
if (match === null) return null
|
||||
|
||||
return {
|
||||
return withDefaults(
|
||||
{
|
||||
isIncomplete: false,
|
||||
items: ['base', 'components', 'utilities'].map((layer, index) => ({
|
||||
items: ['base', 'components', 'utilities'].map((layer, index, layers) => ({
|
||||
label: layer,
|
||||
kind: 21,
|
||||
data: 'layer',
|
||||
sortText: naturalExpand(index),
|
||||
textEdit: {
|
||||
newText: layer,
|
||||
sortText: naturalExpand(index, layers.length),
|
||||
})),
|
||||
},
|
||||
{
|
||||
data: {
|
||||
...(state.completionItemData ?? {}),
|
||||
_type: 'layer',
|
||||
},
|
||||
range: {
|
||||
start: {
|
||||
line: position.line,
|
||||
|
@ -937,6 +971,44 @@ function provideLayerDirectiveCompletions(
|
|||
end: position,
|
||||
},
|
||||
},
|
||||
state.editor.capabilities.itemDefaults
|
||||
)
|
||||
}
|
||||
|
||||
function withDefaults(
|
||||
completionList: CompletionList,
|
||||
defaults: Partial<{ data: any; range: Range }>,
|
||||
supportedDefaults: string[]
|
||||
): CompletionList {
|
||||
let defaultData = supportedDefaults.includes('data')
|
||||
let defaultRange = supportedDefaults.includes('editRange')
|
||||
|
||||
return {
|
||||
...completionList,
|
||||
...(defaultData || defaultRange
|
||||
? {
|
||||
itemDefaults: {
|
||||
...(defaultData && defaults.data ? { data: defaults.data } : {}),
|
||||
...(defaultRange && defaults.range ? { editRange: defaults.range } : {}),
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
items:
|
||||
defaultData && defaultRange
|
||||
? completionList.items
|
||||
: completionList.items.map(({ textEditText, ...item }) => ({
|
||||
...item,
|
||||
...(defaultData || !defaults.data || item.data ? {} : { data: defaults.data }),
|
||||
...(defaultRange || !defaults.range
|
||||
? textEditText
|
||||
? { textEditText }
|
||||
: {}
|
||||
: {
|
||||
textEdit: {
|
||||
newText: textEditText ?? item.label,
|
||||
range: defaults.range,
|
||||
},
|
||||
}),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
@ -963,15 +1035,20 @@ function provideScreenDirectiveCompletions(
|
|||
|
||||
if (!isObject(screens)) return null
|
||||
|
||||
return {
|
||||
return withDefaults(
|
||||
{
|
||||
isIncomplete: false,
|
||||
items: Object.keys(screens).map((screen, index) => ({
|
||||
label: screen,
|
||||
kind: 21,
|
||||
data: 'screen',
|
||||
sortText: naturalExpand(index),
|
||||
textEdit: {
|
||||
newText: screen,
|
||||
})),
|
||||
},
|
||||
{
|
||||
data: {
|
||||
...(state.completionItemData ?? {}),
|
||||
_type: 'screen',
|
||||
},
|
||||
range: {
|
||||
start: {
|
||||
line: position.line,
|
||||
|
@ -980,8 +1057,8 @@ function provideScreenDirectiveCompletions(
|
|||
end: position,
|
||||
},
|
||||
},
|
||||
})),
|
||||
}
|
||||
state.editor.capabilities.itemDefaults
|
||||
)
|
||||
}
|
||||
|
||||
function provideCssDirectiveCompletions(
|
||||
|
@ -1089,14 +1166,19 @@ function provideCssDirectiveCompletions(
|
|||
: []),
|
||||
]
|
||||
|
||||
return {
|
||||
return withDefaults(
|
||||
{
|
||||
isIncomplete: false,
|
||||
items: items.map((item) => ({
|
||||
...item,
|
||||
kind: 14,
|
||||
data: 'directive',
|
||||
textEdit: {
|
||||
newText: item.label,
|
||||
})),
|
||||
},
|
||||
{
|
||||
data: {
|
||||
...(state.completionItemData ?? {}),
|
||||
_type: 'directive',
|
||||
},
|
||||
range: {
|
||||
start: {
|
||||
line: position.line,
|
||||
|
@ -1105,8 +1187,8 @@ function provideCssDirectiveCompletions(
|
|||
end: position,
|
||||
},
|
||||
},
|
||||
})),
|
||||
}
|
||||
state.editor.capabilities.itemDefaults
|
||||
)
|
||||
}
|
||||
|
||||
async function provideConfigDirectiveCompletions(
|
||||
|
@ -1131,15 +1213,24 @@ async function provideConfigDirectiveCompletions(
|
|||
let valueBeforeLastSlash = partial.substring(0, partial.lastIndexOf('/'))
|
||||
let valueAfterLastSlash = partial.substring(partial.lastIndexOf('/') + 1)
|
||||
|
||||
return {
|
||||
return withDefaults(
|
||||
{
|
||||
isIncomplete: false,
|
||||
items: (await state.editor.readDirectory(document, valueBeforeLastSlash || '.'))
|
||||
.filter(([name, type]) => type.isDirectory || /\.c?js$/.test(name))
|
||||
.map(([name, type]) => ({
|
||||
label: type.isDirectory ? name + '/' : name,
|
||||
kind: type.isDirectory ? 19 : 17,
|
||||
textEdit: {
|
||||
newText: type.isDirectory ? name + '/' : name,
|
||||
command: type.isDirectory
|
||||
? { command: 'editor.action.triggerSuggest', title: '' }
|
||||
: undefined,
|
||||
})),
|
||||
},
|
||||
{
|
||||
data: {
|
||||
...(state.completionItemData ?? {}),
|
||||
_type: 'filesystem',
|
||||
},
|
||||
range: {
|
||||
start: {
|
||||
line: position.line,
|
||||
|
@ -1148,11 +1239,8 @@ async function provideConfigDirectiveCompletions(
|
|||
end: position,
|
||||
},
|
||||
},
|
||||
command: type.isDirectory
|
||||
? { command: 'editor.action.triggerSuggest', title: '' }
|
||||
: undefined,
|
||||
})),
|
||||
}
|
||||
state.editor.capabilities.itemDefaults
|
||||
)
|
||||
}
|
||||
|
||||
async function provideEmmetCompletions(
|
||||
|
@ -1255,25 +1343,31 @@ export async function resolveCompletionItem(
|
|||
state: State,
|
||||
item: CompletionItem
|
||||
): Promise<CompletionItem> {
|
||||
if (['helper', 'directive', 'variant', 'layer', '@tailwind'].includes(item.data)) {
|
||||
if (
|
||||
['helper', 'directive', 'variant', 'layer', '@tailwind', 'filesystem'].includes(
|
||||
item.data?._type
|
||||
)
|
||||
) {
|
||||
return item
|
||||
}
|
||||
|
||||
if (item.data === 'screen') {
|
||||
if (item.data?._type === 'screen') {
|
||||
let screens = dlv(state.config, ['theme', 'screens'], dlv(state.config, ['screens'], {}))
|
||||
if (!isObject(screens)) screens = {}
|
||||
item.detail = stringifyScreen(screens[item.label] as Screen)
|
||||
return item
|
||||
}
|
||||
|
||||
if (!Array.isArray(item.data)) {
|
||||
return item
|
||||
let className = item.data?.className ?? item.label
|
||||
if (item.data?.important) {
|
||||
className = `!${className}`
|
||||
}
|
||||
let variants = item.data?.variants ?? []
|
||||
|
||||
if (state.jit) {
|
||||
if (item.kind === 9) return item
|
||||
if (item.detail && item.documentation) return item
|
||||
let { root, rules } = jit.generateRules(state, [item.data.join(state.separator)])
|
||||
let { root, rules } = jit.generateRules(state, [[...variants, className].join(state.separator)])
|
||||
if (rules.length === 0) return item
|
||||
if (!item.detail) {
|
||||
if (rules.length === 1) {
|
||||
|
@ -1291,14 +1385,14 @@ export async function resolveCompletionItem(
|
|||
return item
|
||||
}
|
||||
|
||||
const className = dlv(state.classNames.classNames, [...item.data, '__info'])
|
||||
const rules = dlv(state.classNames.classNames, [...variants, className, '__info'])
|
||||
if (item.kind === 9) {
|
||||
item.detail = state.classNames.context[item.data[item.data.length - 1]].join(', ')
|
||||
item.detail = state.classNames.context[className].join(', ')
|
||||
} else {
|
||||
item.detail = await getCssDetail(state, className)
|
||||
item.detail = await getCssDetail(state, rules)
|
||||
if (!item.documentation) {
|
||||
const settings = await state.editor.getConfiguration()
|
||||
const css = stringifyCss(item.data.join(':'), className, settings)
|
||||
const css = stringifyCss([...variants, className].join(':'), rules, settings)
|
||||
if (css) {
|
||||
item.documentation = {
|
||||
kind: 'markdown' as typeof MarkupKind.Markdown,
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
function pad(n: string): string {
|
||||
return ('00000000' + n).substr(-8)
|
||||
}
|
||||
|
||||
export function naturalExpand(value: number | string): string {
|
||||
let str = typeof value === 'string' ? value : value.toString()
|
||||
return str.replace(/\d+/g, pad)
|
||||
export function naturalExpand(value: number, total?: number): string {
|
||||
let length = typeof total === 'number' ? total.toString().length : 8
|
||||
return ('0'.repeat(length) + value).slice(-length)
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ export type EditorState = {
|
|||
capabilities: {
|
||||
configuration: boolean
|
||||
diagnosticRelatedInformation: boolean
|
||||
itemDefaults: string[]
|
||||
}
|
||||
getConfiguration: (uri?: string) => Promise<Settings>
|
||||
getDocumentSymbols: (uri: string) => Promise<SymbolInformation[]>
|
||||
|
@ -118,6 +119,7 @@ export interface State {
|
|||
jitContext?: any
|
||||
classList?: Array<[string, { color: culori.Color | KeywordColor | null; modifiers?: string[] }]>
|
||||
pluginVersions?: string
|
||||
completionItemData?: Record<string, any>
|
||||
// postcssPlugins?: { before: any[]; after: any[] }
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"vscode"
|
||||
],
|
||||
"engines": {
|
||||
"vscode": "^1.65.0"
|
||||
"vscode": "^1.67.0"
|
||||
},
|
||||
"categories": [
|
||||
"Linters",
|
||||
|
|
Loading…
Reference in New Issue