From 1ccdabfea48359cdee3506bd171b14ce1ded5f2e Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 27 Mar 2025 16:18:44 -0400 Subject: [PATCH 1/5] Add css `var()` hovers in v4 --- .../tests/hover/hover.test.js | 59 ++++++++++++++++++- .../getInvalidConfigPathDiagnostics.ts | 5 ++ .../src/hoverProvider.ts | 2 + .../src/util/find.ts | 6 +- .../src/util/state.ts | 2 +- 5 files changed, 70 insertions(+), 4 deletions(-) diff --git a/packages/tailwindcss-language-server/tests/hover/hover.test.js b/packages/tailwindcss-language-server/tests/hover/hover.test.js index ac97e414..beabf92b 100644 --- a/packages/tailwindcss-language-server/tests/hover/hover.test.js +++ b/packages/tailwindcss-language-server/tests/hover/hover.test.js @@ -1,5 +1,7 @@ -import { test } from 'vitest' +import { expect, test } from 'vitest' import { withFixture } from '../common' +import { css, defineTest } from '../../src/testing' +import { createClient } from '../utils/client' withFixture('basic', (c) => { async function testHover( @@ -545,3 +547,58 @@ withFixture('v4/path-mappings', (c) => { }, }) }) + +defineTest({ + name: 'wip', + fs: { + 'app.css': css` + @import 'tailwindcss'; + `, + }, + + prepare: async ({ root }) => ({ client: await createClient({ root }) }), + + handle: async ({ client }) => { + let doc = await client.open({ + lang: 'css', + text: css` + .foo { + color: theme(--color-black); + } + .bar { + color: var(--color-black); + } + `, + }) + + // color: theme(--color-black); + // ^ + let hoverTheme = await doc.hover({ line: 1, character: 18 }) + + // color: var(--color-black); + // ^ + let hoverVar = await doc.hover({ line: 4, character: 16 }) + + expect(hoverTheme).toEqual({ + contents: { + kind: 'markdown', + value: ['```plaintext', '#000', '```'].join('\n'), + }, + range: { + start: { line: 1, character: 15 }, + end: { line: 1, character: 28 }, + }, + }) + + expect(hoverVar).toEqual({ + contents: { + kind: 'markdown', + value: ['```plaintext', '#000', '```'].join('\n'), + }, + range: { + start: { line: 4, character: 13 }, + end: { line: 4, character: 26 }, + }, + }) + }, +}) diff --git a/packages/tailwindcss-language-service/src/diagnostics/getInvalidConfigPathDiagnostics.ts b/packages/tailwindcss-language-service/src/diagnostics/getInvalidConfigPathDiagnostics.ts index d20655e3..76864281 100644 --- a/packages/tailwindcss-language-service/src/diagnostics/getInvalidConfigPathDiagnostics.ts +++ b/packages/tailwindcss-language-service/src/diagnostics/getInvalidConfigPathDiagnostics.ts @@ -186,6 +186,11 @@ export function getInvalidConfigPathDiagnostics( findHelperFunctionsInDocument(state, document).forEach((helperFn) => { let base = helperFn.helper === 'theme' ? ['theme'] : [] + + // var(…) may not refer to theme values but other values in the cascade + // so they can't be unconditionally validated + if (helperFn.helper === 'var') return + let result = validateConfigPath(state, helperFn.path, base) if (result.isValid === true) { diff --git a/packages/tailwindcss-language-service/src/hoverProvider.ts b/packages/tailwindcss-language-service/src/hoverProvider.ts index 1db68bed..12adae01 100644 --- a/packages/tailwindcss-language-service/src/hoverProvider.ts +++ b/packages/tailwindcss-language-service/src/hoverProvider.ts @@ -53,6 +53,8 @@ async function provideCssHelperHover( for (let helperFn of helperFns) { if (!isWithinRange(position, helperFn.ranges.path)) continue + if (helperFn.helper === 'var' && !state.v4) continue + let validated = validateConfigPath( state, helperFn.path, diff --git a/packages/tailwindcss-language-service/src/util/find.ts b/packages/tailwindcss-language-service/src/util/find.ts index 03218798..9118403d 100644 --- a/packages/tailwindcss-language-service/src/util/find.ts +++ b/packages/tailwindcss-language-service/src/util/find.ts @@ -405,7 +405,7 @@ export function findHelperFunctionsInRange( ): DocumentHelperFunction[] { const text = getTextWithoutComments(doc, 'css', range) let matches = findAll( - /(?[\W])(?config|theme|--theme)(?\(\s*)(?[^)]*?)\s*\)/g, + /(?[\W])(?config|theme|--theme|var)(?\(\s*)(?[^)]*?)\s*\)/g, text, ) @@ -450,10 +450,12 @@ export function findHelperFunctionsInRange( match.groups.helper.length + match.groups.innerPrefix.length - let helper: 'config' | 'theme' = 'config' + let helper: 'config' | 'theme' | 'var' = 'config' if (match.groups.helper === 'theme' || match.groups.helper === '--theme') { helper = 'theme' + } else if (match.groups.helper === 'var') { + helper = 'var' } return { diff --git a/packages/tailwindcss-language-service/src/util/state.ts b/packages/tailwindcss-language-service/src/util/state.ts index 119e5f59..8c819eb8 100644 --- a/packages/tailwindcss-language-service/src/util/state.ts +++ b/packages/tailwindcss-language-service/src/util/state.ts @@ -161,7 +161,7 @@ export type DocumentClassName = { } export type DocumentHelperFunction = { - helper: 'theme' | 'config' + helper: 'theme' | 'config' | 'var' path: string ranges: { full: Range From 22368d68279699b3f77effa1b0ed8ebe7cf4b844 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 31 Mar 2025 12:46:39 -0400 Subject: [PATCH 2/5] Refactor --- packages/tailwindcss-language-service/src/hoverProvider.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/tailwindcss-language-service/src/hoverProvider.ts b/packages/tailwindcss-language-service/src/hoverProvider.ts index 12adae01..be18b784 100644 --- a/packages/tailwindcss-language-service/src/hoverProvider.ts +++ b/packages/tailwindcss-language-service/src/hoverProvider.ts @@ -69,8 +69,10 @@ async function provideCssHelperHover( value = addPixelEquivalentsToValue(value, settings.tailwindCSS.rootFontSize) } + let lines = ['```plaintext', value, '```'] + return { - contents: { kind: 'markdown', value: ['```plaintext', value, '```'].join('\n') }, + contents: { kind: 'markdown', value: lines.join('\n') }, range: helperFn.ranges.path, } } From 6905c6f7d8ecc7dbda3fada86fa587a23c8c3209 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 31 Mar 2025 12:47:01 -0400 Subject: [PATCH 3/5] Make v4 theme key hovers nicer --- .../tests/hover/hover.test.js | 27 ++++++++++++++++--- .../src/hoverProvider.ts | 11 ++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/packages/tailwindcss-language-server/tests/hover/hover.test.js b/packages/tailwindcss-language-server/tests/hover/hover.test.js index beabf92b..569cee4e 100644 --- a/packages/tailwindcss-language-server/tests/hover/hover.test.js +++ b/packages/tailwindcss-language-server/tests/hover/hover.test.js @@ -399,7 +399,14 @@ withFixture('v4/basic', (c) => { expected: { contents: { kind: 'markdown', - value: ['```plaintext', '80rem /* 1280px */', '```'].join('\n'), + value: [ + // + '```css', + '@theme {', + ' --breakpoint-xl: 80rem /* 1280px */;', + '}', + '```', + ].join('\n'), }, range: { start: { line: 0, character: 23 }, @@ -582,7 +589,14 @@ defineTest({ expect(hoverTheme).toEqual({ contents: { kind: 'markdown', - value: ['```plaintext', '#000', '```'].join('\n'), + value: [ + // + '```css', + '@theme {', + ' --color-black: #000;', + '}', + '```', + ].join('\n'), }, range: { start: { line: 1, character: 15 }, @@ -593,7 +607,14 @@ defineTest({ expect(hoverVar).toEqual({ contents: { kind: 'markdown', - value: ['```plaintext', '#000', '```'].join('\n'), + value: [ + // + '```css', + '@theme {', + ' --color-black: #000;', + '}', + '```', + ].join('\n'), }, range: { start: { line: 4, character: 13 }, diff --git a/packages/tailwindcss-language-service/src/hoverProvider.ts b/packages/tailwindcss-language-service/src/hoverProvider.ts index be18b784..583cc80f 100644 --- a/packages/tailwindcss-language-service/src/hoverProvider.ts +++ b/packages/tailwindcss-language-service/src/hoverProvider.ts @@ -71,6 +71,17 @@ async function provideCssHelperHover( let lines = ['```plaintext', value, '```'] + if (state.v4 && helperFn.path.startsWith('--')) { + lines = [ + // + '```css', + '@theme {', + ` ${helperFn.path}: ${value};`, + '}', + '```', + ] + } + return { contents: { kind: 'markdown', value: lines.join('\n') }, range: helperFn.ranges.path, From 197092b7203eaf962413fd28258a2ddb107ae8f9 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 31 Mar 2025 13:04:04 -0400 Subject: [PATCH 4/5] Update changelog --- packages/vscode-tailwindcss/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/vscode-tailwindcss/CHANGELOG.md b/packages/vscode-tailwindcss/CHANGELOG.md index 31a8ca66..d298b73f 100644 --- a/packages/vscode-tailwindcss/CHANGELOG.md +++ b/packages/vscode-tailwindcss/CHANGELOG.md @@ -2,7 +2,8 @@ ## Prerelease -- Nothing yet! +- Support theme key hovers in the CSS `var()` function ([#1289](https://github.com/tailwindlabs/tailwindcss-intellisense/pull/1289)) +- Show theme key hovers inside `@theme` for better context and syntax highlighting ([#1289](https://github.com/tailwindlabs/tailwindcss-intellisense/pull/1289)) # 0.14.12 From bf8582f352affce9942e80b1913da8c6b02c9d3d Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 31 Mar 2025 13:10:09 -0400 Subject: [PATCH 5/5] Update test name --- packages/tailwindcss-language-server/tests/hover/hover.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tailwindcss-language-server/tests/hover/hover.test.js b/packages/tailwindcss-language-server/tests/hover/hover.test.js index 569cee4e..e4cb9324 100644 --- a/packages/tailwindcss-language-server/tests/hover/hover.test.js +++ b/packages/tailwindcss-language-server/tests/hover/hover.test.js @@ -556,7 +556,7 @@ withFixture('v4/path-mappings', (c) => { }) defineTest({ - name: 'wip', + name: 'Can hover showing theme values used in var(…) and theme(…) functions', fs: { 'app.css': css` @import 'tailwindcss';