1
1
import type { State } from './util/state'
2
- import type { Hover , Position } from 'vscode-languageserver'
2
+ import type { Hover , MarkupContent , Position , Range } from 'vscode-languageserver'
3
3
import { stringifyCss , stringifyConfigValue } from './util/stringify'
4
4
import dlv from 'dlv'
5
5
import { isCssContext } from './util/css'
6
- import { findClassNameAtPosition , findHelperFunctionsInRange } from './util/find'
6
+ import {
7
+ findAll ,
8
+ findClassNameAtPosition ,
9
+ findHelperFunctionsInRange ,
10
+ indexToPosition ,
11
+ } from './util/find'
7
12
import { validateApply } from './util/validateApply'
8
13
import { getClassNameParts } from './util/getClassNameAtPosition'
9
14
import * as jit from './util/jit'
10
15
import { validateConfigPath } from './diagnostics/getInvalidConfigPathDiagnostics'
11
16
import { isWithinRange } from './util/isWithinRange'
12
17
import type { TextDocument } from 'vscode-languageserver-textdocument'
13
18
import { addPixelEquivalentsToValue } from './util/pixelEquivalents'
19
+ import { getTextWithoutComments } from './util/doc'
20
+ import braces from 'braces'
21
+ import { absoluteRange } from './util/absoluteRange'
14
22
15
23
export async function doHover (
16
24
state : State ,
@@ -19,7 +27,8 @@ export async function doHover(
19
27
) : Promise < Hover > {
20
28
return (
21
29
( await provideClassNameHover ( state , document , position ) ) ||
22
- ( await provideCssHelperHover ( state , document , position ) )
30
+ ( await provideCssHelperHover ( state , document , position ) ) ||
31
+ ( await provideSourceGlobHover ( state , document , position ) )
23
32
)
24
33
}
25
34
@@ -133,3 +142,64 @@ async function provideClassNameHover(
133
142
range : className . range ,
134
143
}
135
144
}
145
+
146
+ function markdown ( lines : string [ ] ) : MarkupContent {
147
+ return {
148
+ kind : 'markdown' ,
149
+ value : lines . join ( '\n' ) ,
150
+ }
151
+ }
152
+
153
+ async function provideSourceGlobHover (
154
+ state : State ,
155
+ document : TextDocument ,
156
+ position : Position ,
157
+ ) : Promise < Hover > {
158
+ if ( ! isCssContext ( state , document , position ) ) {
159
+ return null
160
+ }
161
+
162
+ let range = {
163
+ start : { line : position . line , character : 0 } ,
164
+ end : { line : position . line + 1 , character : 0 } ,
165
+ }
166
+
167
+ let text = getTextWithoutComments ( document , 'css' , range )
168
+
169
+ let pattern = / @ s o u r c e \s * (?< path > ' [ ^ ' ] + ' | " [ ^ " ] + " ) / dg
170
+
171
+ for ( let match of findAll ( pattern , text ) ) {
172
+ let path = match . groups . path . slice ( 1 , - 1 )
173
+
174
+ // Ignore paths that don't need brace expansion
175
+ if ( ! path . includes ( '{' ) || ! path . includes ( '}' ) ) continue
176
+
177
+ // Ignore paths that don't contain the current position
178
+ let slice : Range = absoluteRange (
179
+ {
180
+ start : indexToPosition ( text , match . indices . groups . path [ 0 ] ) ,
181
+ end : indexToPosition ( text , match . indices . groups . path [ 1 ] ) ,
182
+ } ,
183
+ range ,
184
+ )
185
+
186
+ if ( ! isWithinRange ( position , slice ) ) continue
187
+
188
+ // Perform brace expansion
189
+ let paths = new Set ( braces . expand ( path ) )
190
+ if ( paths . size < 2 ) continue
191
+
192
+ return {
193
+ range : slice ,
194
+ contents : markdown ( [
195
+ //
196
+ '**Expansion**' ,
197
+ '```plaintext' ,
198
+ ...Array . from ( paths , ( path ) => `- ${ path } ` ) ,
199
+ '```' ,
200
+ ] ) ,
201
+ }
202
+ }
203
+
204
+ return null
205
+ }
0 commit comments