diff --git a/packages/tailwindcss-language-server/tests/completions/completions.test.js b/packages/tailwindcss-language-server/tests/completions/completions.test.js index f4d88622..090ec872 100644 --- a/packages/tailwindcss-language-server/tests/completions/completions.test.js +++ b/packages/tailwindcss-language-server/tests/completions/completions.test.js @@ -983,7 +983,7 @@ defineTest({ }) defineTest({ - name: 'Completions for outline and border utilities have simplified details', + name: 'Completions for several utilities have simplified details', fs: { 'app.css': css` @import 'tailwindcss'; @@ -993,24 +993,59 @@ defineTest({ handle: async ({ client }) => { let document = await client.open({ lang: 'html', - text: html`
`, + text: html``, }) - // - // ^ - let completionA = await document.completions({ line: 0, character: 20 }) + // + // ^ + let list = await document.completions({ line: 0, character: 12 }) + let items = list?.items ?? [] + + let map = { + 'border-0': 'border-width: 0px;', + 'outline-0': 'outline-width: 0px;', + 'leading-0': 'line-height: 0rem /* 0px */;', + 'duration-1000': 'transition-duration: 1000ms;', + 'font-bold': 'font-weight: 700;', + 'ease-linear': 'transition-timing-function: linear;', + 'ease-initial': '--tw-ease: initial;', + + 'space-x-0': + 'margin-inline-start: calc(0rem /* 0px */ * var(--tw-space-x-reverse)); margin-inline-end: calc(0rem /* 0px */ * calc(1 - var(--tw-space-x-reverse)));', + 'space-y-0': + 'margin-block-start: calc(0rem /* 0px */ * var(--tw-space-y-reverse)); margin-block-end: calc(0rem /* 0px */ * calc(1 - var(--tw-space-y-reverse)));', + 'divide-x-0': + 'border-inline-start-width: calc(0px * var(--tw-divide-x-reverse)); border-inline-end-width: calc(0px * calc(1 - var(--tw-divide-x-reverse)));', + 'divide-y-0': + 'border-top-width: calc(0px * var(--tw-divide-y-reverse)); border-bottom-width: calc(0px * calc(1 - var(--tw-divide-y-reverse)));', + + 'tracking-wide': 'letter-spacing: 0.025em;', + + 'from-red-500': '--tw-gradient-from: oklch(63.7% 0.237 25.331);', + 'via-red-500': '--tw-gradient-via: oklch(63.7% 0.237 25.331);', + 'to-red-500': '--tw-gradient-to: oklch(63.7% 0.237 25.331);', + + 'scale-100': '--tw-scale-x: 100%; --tw-scale-y: 100%; --tw-scale-z: 100%;', + 'scale-z-100': '--tw-scale-z: 100%;', + + 'translate-1': '--tw-translate-x: 0.25rem /* 4px */; --tw-translate-y: 0.25rem /* 4px */;', + 'translate-z-1': '--tw-translate-z: 0.25rem /* 4px */;', + + 'bg-conic-0': + '--tw-gradient-position: from 0deg in oklab; background-image: conic-gradient(var(--tw-gradient-stops));', + } - // - // ^ - let completionB = await document.completions({ line: 0, character: 30 }) + let requests = await Promise.all( + Object.keys(map).map(async (label) => { + let item = items.find((item) => item.label === label) + if (!item) throw new Error(`Item not found for label: ${label}`) - let border = completionA?.items.find((item) => item.label === 'border-0') - let outline = completionB?.items.find((item) => item.label === 'outline-0') + let resolved = await client.conn.sendRequest('completionItem/resolve', item) - let borderResolved = await client.conn.sendRequest('completionItem/resolve', border) - let outlineResolved = await client.conn.sendRequest('completionItem/resolve', outline) + return [label, resolved.detail] + }), + ) - expect(borderResolved).toMatchObject({ detail: 'border-width: 0px;' }) - expect(outlineResolved).toMatchObject({ detail: 'outline-width: 0px;' }) + expect(Object.fromEntries(requests)).toEqual(map) }, }) diff --git a/packages/tailwindcss-language-service/src/completionProvider.ts b/packages/tailwindcss-language-service/src/completionProvider.ts index 48ff6093..36e7676b 100644 --- a/packages/tailwindcss-language-service/src/completionProvider.ts +++ b/packages/tailwindcss-language-service/src/completionProvider.ts @@ -2304,15 +2304,53 @@ export async function resolveCompletionItem( if (rule.name === 'supports' && rule.params === '(-moz-orient: inline)') { rule.remove() } + + if ( + rule.name === 'supports' && + rule.params === '(background-image: linear-gradient(in lab, red, red))' + ) { + rule.remove() + } }) + let ignoredValues = new Set([ + 'var(--tw-border-style)', + 'var(--tw-outline-style)', + 'var(--tw-translate-x) var(--tw-translate-y)', + 'var(--tw-translate-x) var(--tw-translate-y) var(--tw-translate-z)', + 'var(--tw-scale-x) var(--tw-scale-y)', + 'var(--tw-scale-x) var(--tw-scale-y) var(--tw-scale-z)', + ]) + base.walkDecls((node) => { - if (node.value === 'var(--tw-border-style)') return - if (node.value === 'var(--tw-outline-style)') return + if (ignoredValues.has(node.value)) return decls.push(node) }) + // TODO: Hardcoding this list is really unfortunate. We should be able + // to handle this in Tailwind CSS itself. + function isOtherDecl(node: postcss.Declaration) { + if (node.prop === '--tw-leading') return false + if (node.prop === '--tw-duration') return false + if (node.prop === '--tw-ease') return false + if (node.prop === '--tw-font-weight') return false + if (node.prop === '--tw-gradient-via-stops') return false + if (node.prop === '--tw-gradient-stops') return false + if (node.prop === '--tw-tracking') return false + if (node.prop === '--tw-space-x-reverse' && node.value === '0') return false + if (node.prop === '--tw-space-y-reverse' && node.value === '0') return false + if (node.prop === '--tw-divide-x-reverse' && node.value === '0') return false + if (node.prop === '--tw-divide-y-reverse' && node.value === '0') return false + + return true + } + + // We want to remove these decls from details *as long as they're not the only one* + if (decls.some(isOtherDecl)) { + decls = decls.filter(isOtherDecl) + } + item.detail = await jit.stringifyDecls(state, postcss.rule({ selectors: [], nodes: decls })) } else { item.detail = `${rules.length} rules` diff --git a/packages/vscode-tailwindcss/CHANGELOG.md b/packages/vscode-tailwindcss/CHANGELOG.md index 5cdd4db7..1bbdff03 100644 --- a/packages/vscode-tailwindcss/CHANGELOG.md +++ b/packages/vscode-tailwindcss/CHANGELOG.md @@ -4,6 +4,7 @@ - Bump bundled CSS language service ([#1395](https://github.com/tailwindlabs/tailwindcss-intellisense/pull/1395)) - Fix infinite loop when resolving completion details with recursive theme keys ([#1400](https://github.com/tailwindlabs/tailwindcss-intellisense/pull/1400)) +- Simplify completion details for more utilities ([#1397](https://github.com/tailwindlabs/tailwindcss-intellisense/pull/1397)) ## 0.14.20