Skip to content

Commit 5fe7b89

Browse files
author
Brad Cornes
committed
add initial definition provider
1 parent cfa6f12 commit 5fe7b89

File tree

4 files changed

+87
-12
lines changed

4 files changed

+87
-12
lines changed

packages/tailwindcss-class-names/src/getUtilityConfigMap.js

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,33 @@ export async function getUtilityConfigMap({ cwd, resolvedConfig, postcss }) {
3333
postcss,
3434
config: proxiedConfig,
3535
addUtilities: (utilities) => {
36-
Object.keys(utilities).forEach((util) => {
37-
let props = Object.keys(utilities[util])
38-
if (
39-
props.length === 1 &&
40-
/^\.[^\s]+$/.test(util) &&
41-
typeof utilities[util][props[0]] === 'string' &&
42-
utilities[util][props[0]].substr(0, 5) === '$dep$'
43-
) {
44-
classNameConfigMap[util.substr(1)] = utilities[util][
45-
props[0]
46-
].substr(5)
36+
;(Array.isArray(utilities) ? utilities : [utilities]).forEach(
37+
(utils) => {
38+
Object.keys(utils).forEach((util) => {
39+
if (!/^\.[^\s]+$/.test(util)) {
40+
return
41+
}
42+
let props = Object.keys(utils[util])
43+
let values = props.map((prop) => utils[util][prop])
44+
if (values.some((val) => typeof val !== 'string')) {
45+
return
46+
}
47+
let deps = values
48+
.filter((val) => val.substr(0, 5) === '$dep$')
49+
// unique
50+
.filter((val, index, self) => self.indexOf(val) === index)
51+
.map((dep) => dep.substr(5))
52+
if (deps.length === 1) {
53+
let className = util.substr(1)
54+
let match = className.match(/[^\\]::?/)
55+
if (match !== null) {
56+
className = className.substr(0, match.index + 1)
57+
}
58+
classNameConfigMap[className] = deps[0]
59+
}
60+
})
4761
}
48-
})
62+
)
4963
},
5064
})
5165
})
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { State, DocumentClassName } from '../util/state'
2+
import {
3+
TextDocumentPositionParams,
4+
DefinitionLink,
5+
} from 'vscode-languageserver'
6+
import { isHtmlContext } from '../util/html'
7+
import { isJsContext } from '../util/js'
8+
import {
9+
getClassNameAtPosition,
10+
getClassNameParts,
11+
} from '../util/getClassNameAtPosition'
12+
import getConfigLocation from '../util/getConfigLocation'
13+
14+
export function provideDefinition(
15+
state: State,
16+
{ textDocument, position }: TextDocumentPositionParams
17+
): Promise<DefinitionLink[]> {
18+
let doc = state.editor.documents.get(textDocument.uri)
19+
20+
if (!isHtmlContext(doc, position) && !isJsContext(doc, position)) return null
21+
22+
let hovered = getClassNameAtPosition(doc, position)
23+
if (!hovered) return null
24+
25+
return classNameToDefinition(state, hovered)
26+
}
27+
28+
async function classNameToDefinition(
29+
state: State,
30+
{ className, range }: DocumentClassName
31+
): Promise<DefinitionLink[]> {
32+
const parts = getClassNameParts(state, className)
33+
if (!parts) return null
34+
35+
const configKey = state.utilityConfigMap[parts[parts.length - 1]]
36+
if (!configKey) return null
37+
38+
const location = await getConfigLocation(state, configKey.split('.'))
39+
if (!location) return null
40+
41+
return [
42+
{
43+
originSelectionRange: range,
44+
targetUri: location.file,
45+
// TODO: figure out why this doesn't work properly
46+
targetRange: location.range,
47+
targetSelectionRange: location.range
48+
},
49+
]
50+
}

packages/tailwindcss-language-server/src/server.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
Hover,
1717
TextDocumentPositionParams,
1818
DidChangeConfigurationNotification,
19+
DefinitionLink,
1920
} from 'vscode-languageserver'
2021
import getTailwindState from 'tailwindcss-class-names'
2122
import { State, Settings, EditorState } from './util/state'
@@ -27,6 +28,7 @@ import { provideHover } from './providers/hoverProvider'
2728
import { URI } from 'vscode-uri'
2829
import { getDocumentSettings } from './util/getDocumentSettings'
2930
import getConfigLocation from './util/getConfigLocation'
31+
import { provideDefinition } from './providers/definitionProvider'
3032

3133
let state: State = { enabled: false }
3234
let connection = createConnection(ProposedFeatures.all)
@@ -125,6 +127,7 @@ connection.onInitialize(
125127
],
126128
},
127129
hoverProvider: true,
130+
definitionProvider: true,
128131
},
129132
}
130133
}
@@ -188,4 +191,11 @@ connection.onHover(
188191
}
189192
)
190193

194+
connection.onDefinition(
195+
(params: TextDocumentPositionParams): Promise<DefinitionLink[]> => {
196+
if (!state.enabled) return null
197+
return provideDefinition(state, params)
198+
}
199+
)
200+
191201
connection.listen()

packages/tailwindcss-language-server/src/util/state.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export type State = null | {
3636
variants?: string[]
3737
classNames?: ClassNames
3838
dependencies?: string[]
39+
utilityConfigMap?: Record<string, string>
3940
editor?: EditorState
4041
error?: Error
4142
}

0 commit comments

Comments
 (0)