Skip to content

Commit 86497bb

Browse files
authored
Rework language boundary detection (#502)
* Fix `classRegex` error * Rework language boundary detection
1 parent a082bb3 commit 86497bb

13 files changed

+24067
-8306
lines changed

package-lock.json

Lines changed: 23893 additions & 8186 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/tailwindcss-language-service/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"semver": "7.3.2",
3030
"sift-string": "0.0.2",
3131
"stringify-object": "3.3.0",
32+
"tmp-cache": "1.1.0",
3233
"vscode-emmet-helper-bundled": "0.0.1",
3334
"vscode-languageclient": "7.0.0",
3435
"vscode-languageserver": "7.0.0",

packages/tailwindcss-language-service/src/codeActions/provideInvalidApplyCodeActions.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ export async function provideInvalidApplyCodeActions(
4343
if (!isCssDoc(state, document)) {
4444
let languageBoundaries = getLanguageBoundaries(state, document)
4545
if (!languageBoundaries) return []
46-
cssRange = languageBoundaries.css.find((range) => isWithinRange(diagnostic.range.start, range))
46+
cssRange = languageBoundaries
47+
.filter((b) => b.type === 'css')
48+
.find(({ range }) => isWithinRange(diagnostic.range.start, range))?.range
4749
if (!cssRange) return []
4850
cssText = document.getText(cssRange)
4951
}

packages/tailwindcss-language-service/src/completionProvider.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { stringifyScreen, Screen } from './util/screens'
2020
import isObject from './util/isObject'
2121
import * as emmetHelper from 'vscode-emmet-helper-bundled'
2222
import { isValidLocationForEmmetAbbreviation } from './util/isValidLocationForEmmetAbbreviation'
23-
import { isJsContext } from './util/js'
23+
import { isJsDoc, isJsxContext } from './util/js'
2424
import { naturalExpand } from './util/naturalExpand'
2525
import semver from 'semver'
2626
import { docsUrl } from './util/docsUrl'
@@ -511,7 +511,7 @@ async function provideClassNameCompletions(
511511
return provideAtApplyCompletions(state, document, position)
512512
}
513513

514-
if (isHtmlContext(state, document, position) || isJsContext(state, document, position)) {
514+
if (isHtmlContext(state, document, position) || isJsxContext(state, document, position)) {
515515
return provideClassAttributeCompletions(state, document, position, context)
516516
}
517517

@@ -973,8 +973,8 @@ async function provideEmmetCompletions(
973973
let settings = await state.editor.getConfiguration(document.uri)
974974
if (settings.tailwindCSS.emmetCompletions !== true) return null
975975

976-
const isHtml = isHtmlContext(state, document, position)
977-
const isJs = !isHtml && isJsContext(state, document, position)
976+
const isHtml = !isJsDoc(state, document) && isHtmlContext(state, document, position)
977+
const isJs = isJsDoc(state, document) || isJsxContext(state, document, position)
978978

979979
const syntax = isHtml ? 'html' : isJs ? 'jsx' : null
980980

packages/tailwindcss-language-service/src/diagnostics/getInvalidConfigPathDiagnostics.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ export function getInvalidConfigPathDiagnostics(
173173
} else {
174174
let boundaries = getLanguageBoundaries(state, document)
175175
if (!boundaries) return []
176-
ranges.push(...boundaries.css)
176+
ranges.push(...boundaries.filter((b) => b.type === 'css').map(({ range }) => range))
177177
}
178178

179179
ranges.forEach((range) => {

packages/tailwindcss-language-service/src/diagnostics/getInvalidScreenDiagnostics.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export function getInvalidScreenDiagnostics(
2424
} else {
2525
let boundaries = getLanguageBoundaries(state, document)
2626
if (!boundaries) return []
27-
ranges.push(...boundaries.css)
27+
ranges.push(...boundaries.filter((b) => b.type === 'css').map(({ range }) => range))
2828
}
2929

3030
ranges.forEach((range) => {

packages/tailwindcss-language-service/src/diagnostics/getInvalidTailwindDirectiveDiagnostics.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export function getInvalidTailwindDirectiveDiagnostics(
2424
} else {
2525
let boundaries = getLanguageBoundaries(state, document)
2626
if (!boundaries) return []
27-
ranges.push(...boundaries.css)
27+
ranges.push(...boundaries.filter((b) => b.type === 'css').map(({ range }) => range))
2828
}
2929

3030
let notSemicolonLanguages = ['sass', 'sugarss', 'stylus']

packages/tailwindcss-language-service/src/diagnostics/getInvalidVariantDiagnostics.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export function getInvalidVariantDiagnostics(
2828
} else {
2929
let boundaries = getLanguageBoundaries(state, document)
3030
if (!boundaries) return []
31-
ranges.push(...boundaries.css)
31+
ranges.push(...boundaries.filter((b) => b.type === 'css').map(({ range }) => range))
3232
}
3333

3434
let possibleVariants = Object.keys(state.variants)

packages/tailwindcss-language-service/src/util/css.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import type { TextDocument, Position } from 'vscode-languageserver'
2-
import { isInsideTag, isVueDoc, isSvelteDoc, isHtmlDoc } from './html'
2+
import { isVueDoc, isSvelteDoc, isHtmlDoc } from './html'
33
import { isJsDoc } from './js'
44
import { State } from './state'
55
import { cssLanguages } from './languages'
6+
import { getLanguageBoundaries } from './getLanguageBoundaries'
67

78
export function isCssDoc(state: State, doc: TextDocument): boolean {
89
const userCssLanguages = Object.keys(state.editor.userLanguages).filter((lang) =>
@@ -23,7 +24,9 @@ export function isCssContext(state: State, doc: TextDocument, position: Position
2324
end: position,
2425
})
2526

26-
return isInsideTag(str, ['style'])
27+
let boundaries = getLanguageBoundaries(state, doc, str)
28+
29+
return boundaries ? boundaries[boundaries.length - 1].type === 'css' : false
2730
}
2831

2932
return false

packages/tailwindcss-language-service/src/util/find.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import lineColumn from 'line-column'
44
import { isCssContext, isCssDoc } from './css'
55
import { isHtmlContext } from './html'
66
import { isWithinRange } from './isWithinRange'
7-
import { isJsContext } from './js'
7+
import { isJsxContext } from './js'
88
import { flatten } from './array'
99
import { getClassAttributeLexer, getComputedClassAttributeLexer } from './lexers'
1010
import { getLanguageBoundaries } from './getLanguageBoundaries'
@@ -306,9 +306,13 @@ export async function findClassListsInDocument(
306306

307307
return flatten([
308308
...(await Promise.all(
309-
boundaries.html.map((range) => findClassListsInHtmlRange(state, doc, range))
309+
boundaries
310+
.filter((b) => b.type === 'html' || b.type === 'jsx')
311+
.map(({ range }) => findClassListsInHtmlRange(state, doc, range))
310312
)),
311-
...boundaries.css.map((range) => findClassListsInCssRange(doc, range)),
313+
...boundaries
314+
.filter((b) => b.type === 'css')
315+
.map(({ range }) => findClassListsInCssRange(doc, range)),
312316
await findCustomClassLists(state, doc),
313317
])
314318
}
@@ -324,7 +328,11 @@ export function findHelperFunctionsInDocument(
324328
let boundaries = getLanguageBoundaries(state, doc)
325329
if (!boundaries) return []
326330

327-
return flatten(boundaries.css.map((range) => findHelperFunctionsInRange(doc, range)))
331+
return flatten(
332+
boundaries
333+
.filter((b) => b.type === 'css')
334+
.map(({ range }) => findHelperFunctionsInRange(doc, range))
335+
)
328336
}
329337

330338
export function findHelperFunctionsInRange(
@@ -385,7 +393,7 @@ export async function findClassNameAtPosition(
385393

386394
if (isCssContext(state, doc, position)) {
387395
classNames = await findClassNamesInRange(state, doc, searchRange, 'css')
388-
} else if (isHtmlContext(state, doc, position) || isJsContext(state, doc, position)) {
396+
} else if (isHtmlContext(state, doc, position) || isJsxContext(state, doc, position)) {
389397
classNames = await findClassNamesInRange(state, doc, searchRange, 'html')
390398
}
391399

0 commit comments

Comments
 (0)