Skip to content

Commit b2d47d2

Browse files
committed
add hover, color decorator, linting support for classRegex setting (#129)
1 parent 5bd0978 commit b2d47d2

File tree

9 files changed

+178
-88
lines changed

9 files changed

+178
-88
lines changed

packages/tailwindcss-intellisense/src/lsp/providers/documentColorProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export function registerDocumentColorProvider(state: State) {
1010
let doc = state.editor.documents.get(document)
1111
if (!doc) return { colors: [] }
1212

13-
return { colors: getDocumentColors(state, doc) }
13+
return { colors: await getDocumentColors(state, doc) }
1414
}
1515
)
1616
}

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

Lines changed: 1 addition & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ import {
3131
} from './util/lexers'
3232
import { validateApply } from './util/validateApply'
3333
import { flagEnabled } from './util/flagEnabled'
34-
import MultiRegexp from 'multi-regexp2'
3534
import { remToPx } from './util/remToPx'
35+
import { createMultiRegexp } from './util/createMultiRegexp'
3636

3737
export function completionsFromClassList(
3838
state: State,
@@ -197,62 +197,6 @@ function provideClassAttributeCompletions(
197197
return null
198198
}
199199

200-
function createMultiRegexp(regexString: string) {
201-
let insideCharClass = false
202-
let captureGroupIndex = -1
203-
204-
for (let i = 0; i < regexString.length; i++) {
205-
if (
206-
!insideCharClass &&
207-
regexString[i] === '[' &&
208-
regexString[i - 1] !== '\\'
209-
) {
210-
insideCharClass = true
211-
} else if (
212-
insideCharClass &&
213-
regexString[i] === ']' &&
214-
regexString[i - 1] !== '\\'
215-
) {
216-
insideCharClass = false
217-
} else if (
218-
!insideCharClass &&
219-
regexString[i] === '(' &&
220-
regexString.substr(i + 1, 2) !== '?:'
221-
) {
222-
captureGroupIndex = i
223-
break
224-
}
225-
}
226-
227-
const re = /(?:[^\\]|^)\(\?:/g
228-
let match: RegExpExecArray
229-
let nonCaptureGroupIndexes: number[] = []
230-
231-
while ((match = re.exec(regexString)) !== null) {
232-
if (match[0].startsWith('(')) {
233-
nonCaptureGroupIndexes.push(match.index)
234-
} else {
235-
nonCaptureGroupIndexes.push(match.index + 1)
236-
}
237-
}
238-
239-
const regex = new MultiRegexp(
240-
new RegExp(
241-
regexString.replace(re, (m) => m.substr(0, m.length - 2)),
242-
'g'
243-
)
244-
)
245-
246-
let groupIndex =
247-
1 + nonCaptureGroupIndexes.filter((i) => i < captureGroupIndex).length
248-
249-
return {
250-
exec: (str: string) => {
251-
return regex.execForGroup(str, groupIndex)
252-
},
253-
}
254-
}
255-
256200
async function provideCustomClassNameCompletions(
257201
state: State,
258202
document: TextDocument,

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ export async function doValidate(
2626
return settings.validate
2727
? [
2828
...(only.includes(DiagnosticKind.CssConflict)
29-
? getCssConflictDiagnostics(state, document, settings)
29+
? await getCssConflictDiagnostics(state, document, settings)
3030
: []),
3131
...(only.includes(DiagnosticKind.InvalidApply)
32-
? getInvalidApplyDiagnostics(state, document, settings)
32+
? await getInvalidApplyDiagnostics(state, document, settings)
3333
: []),
3434
...(only.includes(DiagnosticKind.InvalidScreen)
3535
? getInvalidScreenDiagnostics(state, document, settings)

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@ import { getClassNameDecls } from '../util/getClassNameDecls'
1010
import { getClassNameMeta } from '../util/getClassNameMeta'
1111
import { equal } from '../util/array'
1212

13-
export function getCssConflictDiagnostics(
13+
export async function getCssConflictDiagnostics(
1414
state: State,
1515
document: TextDocument,
1616
settings: Settings
17-
): CssConflictDiagnostic[] {
17+
): Promise<CssConflictDiagnostic[]> {
1818
let severity = settings.lint.cssConflict
1919
if (severity === 'ignore') return []
2020

2121
let diagnostics: CssConflictDiagnostic[] = []
22-
const classLists = findClassListsInDocument(state, document)
22+
const classLists = await findClassListsInDocument(state, document)
2323

2424
classLists.forEach((classList) => {
2525
const classNames = getClassNamesInClassList(classList)

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,21 @@ import { Settings, State } from '../util/state'
44
import type { TextDocument, DiagnosticSeverity } from 'vscode-languageserver'
55
import { validateApply } from '../util/validateApply'
66

7-
export function getInvalidApplyDiagnostics(
7+
export async function getInvalidApplyDiagnostics(
88
state: State,
99
document: TextDocument,
1010
settings: Settings
11-
): InvalidApplyDiagnostic[] {
11+
): Promise<InvalidApplyDiagnostic[]> {
1212
let severity = settings.lint.invalidApply
1313
if (severity === 'ignore') return []
1414

15-
const classNames = findClassNamesInRange(document, undefined, 'css')
15+
const classNames = await findClassNamesInRange(
16+
state,
17+
document,
18+
undefined,
19+
'css',
20+
false
21+
)
1622

1723
let diagnostics: InvalidApplyDiagnostic[] = classNames.map((className) => {
1824
let result = validateApply(state, className.className)

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ import { stringToPath } from './util/stringToPath'
1010
import type { TextDocument } from 'vscode-languageserver'
1111
const dlv = require('dlv')
1212

13-
export function getDocumentColors(state: State, document: TextDocument) {
13+
export async function getDocumentColors(state: State, document: TextDocument) {
1414
let colors = []
1515
if (!state.enabled) return colors
1616

17-
let classLists = findClassListsInDocument(state, document)
17+
let classLists = await findClassListsInDocument(state, document)
1818
classLists.forEach((classList) => {
1919
let classNames = getClassNamesInClassList(classList)
2020
classNames.forEach((className) => {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ async function provideClassNameHover(
7777
document: TextDocument,
7878
position: Position
7979
): Promise<Hover> {
80-
let className = findClassNameAtPosition(state, document, position)
80+
let className = await findClassNameAtPosition(state, document, position)
8181
if (className === null) return null
8282

8383
const parts = getClassNameParts(state, className.className)
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
export function createMultiRegexp(regexString: string) {
2+
let insideCharClass = false
3+
let captureGroupIndex = -1
4+
5+
for (let i = 0; i < regexString.length; i++) {
6+
if (
7+
!insideCharClass &&
8+
regexString[i] === '[' &&
9+
regexString[i - 1] !== '\\'
10+
) {
11+
insideCharClass = true
12+
} else if (
13+
insideCharClass &&
14+
regexString[i] === ']' &&
15+
regexString[i - 1] !== '\\'
16+
) {
17+
insideCharClass = false
18+
} else if (
19+
!insideCharClass &&
20+
regexString[i] === '(' &&
21+
regexString.substr(i + 1, 2) !== '?:'
22+
) {
23+
captureGroupIndex = i
24+
break
25+
}
26+
}
27+
28+
const re = /(?:[^\\]|^)\(\?:/g
29+
let match: RegExpExecArray
30+
let nonCaptureGroupIndexes: number[] = []
31+
32+
while ((match = re.exec(regexString)) !== null) {
33+
if (match[0].startsWith('(')) {
34+
nonCaptureGroupIndexes.push(match.index)
35+
} else {
36+
nonCaptureGroupIndexes.push(match.index + 1)
37+
}
38+
}
39+
40+
const regex = new MultiRegexp(
41+
new RegExp(
42+
regexString.replace(re, (m) => m.substr(0, m.length - 2)),
43+
'g'
44+
)
45+
)
46+
47+
let groupIndex =
48+
1 + nonCaptureGroupIndexes.filter((i) => i < captureGroupIndex).length
49+
50+
return {
51+
exec: (str: string) => {
52+
return regex.execForGroup(str, groupIndex)
53+
},
54+
}
55+
}

0 commit comments

Comments
 (0)