Skip to content

Commit 0e16829

Browse files
Fix infinite loop when resolving completion details (#1400)
Fixes #1399
1 parent b6fbe32 commit 0e16829

File tree

3 files changed

+50
-0
lines changed

3 files changed

+50
-0
lines changed

packages/tailwindcss-language-service/src/util/rewriting/index.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { expect, test } from 'vitest'
22
import {
33
addThemeValues,
44
evaluateExpression,
5+
inlineThemeValues,
56
replaceCssCalc,
67
replaceCssVarsWithFallbacks,
78
} from './index'
@@ -124,6 +125,42 @@ test('recursive theme replacements', () => {
124125
)
125126
})
126127

128+
test('recursive theme replacements (inlined)', () => {
129+
let map = new Map<string, string>([
130+
['--color-a', 'var(--color-a)'],
131+
['--color-b', 'rgb(var(--color-b))'],
132+
['--color-c', 'rgb(var(--channel) var(--channel) var(--channel))'],
133+
['--channel', '255'],
134+
135+
['--color-d', 'rgb(var(--indirect) var(--indirect) var(--indirect))'],
136+
['--indirect', 'var(--channel)'],
137+
['--channel', '255'],
138+
139+
['--mutual-a', 'calc(var(--mutual-b) * 1)'],
140+
['--mutual-b', 'calc(var(--mutual-a) + 1)'],
141+
])
142+
143+
let state: State = {
144+
enabled: true,
145+
designSystem: {
146+
theme: { prefix: null } as any,
147+
resolveThemeValue: (name) => map.get(name) ?? null,
148+
} as DesignSystem,
149+
}
150+
151+
expect(inlineThemeValues('var(--color-a)', state)).toBe('var(--color-a)')
152+
expect(inlineThemeValues('var(--color-b)', state)).toBe('rgb(var(--color-b))')
153+
expect(inlineThemeValues('var(--color-c)', state)).toBe('rgb(255 255 255)')
154+
155+
// This one is wrong but fixing it without breaking the infinite recursion guard is complex
156+
expect(inlineThemeValues('var(--color-d)', state)).toBe(
157+
'rgb(255 var(--indirect) var(--indirect))',
158+
)
159+
160+
expect(inlineThemeValues('var(--mutual-a)', state)).toBe('calc(calc(var(--mutual-a) + 1) * 1)')
161+
expect(inlineThemeValues('var(--mutual-b)', state)).toBe('calc(calc(var(--mutual-b) * 1) + 1)')
162+
})
163+
127164
test('Evaluating CSS calc expressions', () => {
128165
expect(replaceCssCalc('calc(1px + 1px)', (node) => evaluateExpression(node.value))).toBe('2px')
129166
expect(replaceCssCalc('calc(1px * 4)', (node) => evaluateExpression(node.value))).toBe('4px')

packages/tailwindcss-language-service/src/util/rewriting/inline-theme-values.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,20 @@ import { replaceCssVars, replaceCssCalc } from './replacements'
77
export function inlineThemeValues(css: string, state: State): string {
88
if (!state.designSystem) return css
99

10+
let seen = new Set<string>()
11+
1012
css = replaceCssCalc(css, (expr) => {
1113
let inlined = replaceCssVars(expr.value, {
1214
replace({ name, fallback }) {
1315
if (!name.startsWith('--')) return null
1416

17+
// TODO: This isn't quite right as we might skip expanding a variable
18+
// that should be expanded
19+
if (seen.has(name)) return null
20+
1521
let value = resolveVariableValue(state.designSystem, name)
1622
if (value === null) return fallback
23+
if (value.includes('var(')) seen.add(name)
1724

1825
return value
1926
},
@@ -26,8 +33,13 @@ export function inlineThemeValues(css: string, state: State): string {
2633
replace({ name, fallback }) {
2734
if (!name.startsWith('--')) return null
2835

36+
// TODO: This isn't quite right as we might skip expanding a variable
37+
// that should be expanded
38+
if (seen.has(name)) return null
39+
2940
let value = resolveVariableValue(state.designSystem, name)
3041
if (value === null) return fallback
42+
if (value.includes('var(')) seen.add(name)
3143

3244
return value
3345
},

packages/vscode-tailwindcss/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Prerelease
44

55
- Bump bundled CSS language service ([#1395](https://github.com/tailwindlabs/tailwindcss-intellisense/pull/1395))
6+
- Fix infinite loop when resolving completion details with recursive theme keys ([#1400](https://github.com/tailwindlabs/tailwindcss-intellisense/pull/1400))
67

78
## 0.14.20
89

0 commit comments

Comments
 (0)