vscode-css-languageservice 5.4.1 → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -1
- package/README.md +1 -0
- package/lib/esm/beautify/beautify-css.js +50 -8
- package/lib/esm/cssLanguageService.d.ts +37 -37
- package/lib/esm/cssLanguageService.js +72 -75
- package/lib/esm/cssLanguageTypes.d.ts +238 -238
- package/lib/esm/cssLanguageTypes.js +42 -42
- package/lib/esm/data/webCustomData.js +21959 -21965
- package/lib/esm/languageFacts/builtinData.js +142 -142
- package/lib/esm/languageFacts/colors.js +469 -472
- package/lib/esm/languageFacts/dataManager.js +88 -92
- package/lib/esm/languageFacts/dataProvider.js +73 -79
- package/lib/esm/languageFacts/entry.js +137 -138
- package/lib/esm/languageFacts/facts.js +8 -8
- package/lib/esm/parser/cssErrors.js +48 -50
- package/lib/esm/parser/cssNodes.js +1502 -2019
- package/lib/esm/parser/cssParser.js +1534 -1566
- package/lib/esm/parser/cssScanner.js +592 -599
- package/lib/esm/parser/cssSymbolScope.js +311 -341
- package/lib/esm/parser/lessParser.js +714 -740
- package/lib/esm/parser/lessScanner.js +57 -78
- package/lib/esm/parser/scssErrors.js +18 -20
- package/lib/esm/parser/scssParser.js +796 -818
- package/lib/esm/parser/scssScanner.js +95 -116
- package/lib/esm/services/cssCodeActions.js +77 -81
- package/lib/esm/services/cssCompletion.js +1054 -1149
- package/lib/esm/services/cssFolding.js +190 -193
- package/lib/esm/services/cssFormatter.js +136 -136
- package/lib/esm/services/cssHover.js +148 -151
- package/lib/esm/services/cssNavigation.js +378 -470
- package/lib/esm/services/cssSelectionRange.js +47 -47
- package/lib/esm/services/cssValidation.js +41 -44
- package/lib/esm/services/lessCompletion.js +378 -397
- package/lib/esm/services/lint.js +518 -532
- package/lib/esm/services/lintRules.js +76 -83
- package/lib/esm/services/lintUtil.js +196 -205
- package/lib/esm/services/pathCompletion.js +157 -231
- package/lib/esm/services/scssCompletion.js +354 -378
- package/lib/esm/services/scssNavigation.js +82 -154
- package/lib/esm/services/selectorPrinting.js +492 -536
- package/lib/esm/utils/arrays.js +40 -46
- package/lib/esm/utils/objects.js +11 -11
- package/lib/esm/utils/resources.js +11 -24
- package/lib/esm/utils/strings.js +102 -104
- package/lib/umd/beautify/beautify-css.js +50 -8
- package/lib/umd/cssLanguageService.d.ts +37 -37
- package/lib/umd/cssLanguageService.js +99 -102
- package/lib/umd/cssLanguageTypes.d.ts +238 -238
- package/lib/umd/cssLanguageTypes.js +89 -88
- package/lib/umd/data/webCustomData.js +21972 -21978
- package/lib/umd/languageFacts/builtinData.js +154 -154
- package/lib/umd/languageFacts/colors.js +492 -495
- package/lib/umd/languageFacts/dataManager.js +101 -104
- package/lib/umd/languageFacts/dataProvider.js +86 -91
- package/lib/umd/languageFacts/entry.js +152 -153
- package/lib/umd/languageFacts/facts.js +29 -29
- package/lib/umd/parser/cssErrors.js +61 -62
- package/lib/umd/parser/cssNodes.js +1587 -2034
- package/lib/umd/parser/cssParser.js +1547 -1578
- package/lib/umd/parser/cssScanner.js +606 -611
- package/lib/umd/parser/cssSymbolScope.js +328 -353
- package/lib/umd/parser/lessParser.js +727 -752
- package/lib/umd/parser/lessScanner.js +70 -90
- package/lib/umd/parser/scssErrors.js +31 -32
- package/lib/umd/parser/scssParser.js +809 -830
- package/lib/umd/parser/scssScanner.js +108 -128
- package/lib/umd/services/cssCodeActions.js +90 -93
- package/lib/umd/services/cssCompletion.js +1067 -1161
- package/lib/umd/services/cssFolding.js +203 -206
- package/lib/umd/services/cssFormatter.js +150 -150
- package/lib/umd/services/cssHover.js +161 -163
- package/lib/umd/services/cssNavigation.js +391 -482
- package/lib/umd/services/cssSelectionRange.js +60 -60
- package/lib/umd/services/cssValidation.js +54 -56
- package/lib/umd/services/lessCompletion.js +391 -409
- package/lib/umd/services/lint.js +531 -544
- package/lib/umd/services/lintRules.js +91 -95
- package/lib/umd/services/lintUtil.js +210 -218
- package/lib/umd/services/pathCompletion.js +171 -244
- package/lib/umd/services/scssCompletion.js +367 -390
- package/lib/umd/services/scssNavigation.js +95 -166
- package/lib/umd/services/selectorPrinting.js +510 -550
- package/lib/umd/utils/arrays.js +55 -61
- package/lib/umd/utils/objects.js +25 -25
- package/lib/umd/utils/resources.js +26 -39
- package/lib/umd/utils/strings.js +120 -122
- package/package.json +11 -11
|
@@ -1,1149 +1,1054 @@
|
|
|
1
|
-
/*---------------------------------------------------------------------------------------------
|
|
2
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
-
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
4
|
-
*--------------------------------------------------------------------------------------------*/
|
|
5
|
-
'use strict';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
this.
|
|
69
|
-
this.
|
|
70
|
-
this.
|
|
71
|
-
this.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
this.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
this.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (node instanceof nodes.
|
|
131
|
-
this.
|
|
132
|
-
}
|
|
133
|
-
else if (node instanceof nodes.
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
this.
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
if (
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
};
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
if (this.
|
|
452
|
-
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
for (
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
return
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
for (
|
|
560
|
-
result.items.push({
|
|
561
|
-
label:
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
});
|
|
613
|
-
}
|
|
614
|
-
return result;
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
for (
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
return
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
if (!
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
this.
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
if (
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
return result;
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
}
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
range
|
|
930
|
-
});
|
|
931
|
-
}
|
|
932
|
-
});
|
|
933
|
-
return result;
|
|
934
|
-
}
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
return
|
|
994
|
-
}
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
if (
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
}());
|
|
1054
|
-
|
|
1055
|
-
function isDeprecated(entry) {
|
|
1056
|
-
if (entry.status && (entry.status === 'nonstandard' || entry.status === 'obsolete')) {
|
|
1057
|
-
return true;
|
|
1058
|
-
}
|
|
1059
|
-
return false;
|
|
1060
|
-
}
|
|
1061
|
-
var Set = /** @class */ (function () {
|
|
1062
|
-
function Set() {
|
|
1063
|
-
this.entries = {};
|
|
1064
|
-
}
|
|
1065
|
-
Set.prototype.add = function (entry) {
|
|
1066
|
-
this.entries[entry] = true;
|
|
1067
|
-
};
|
|
1068
|
-
Set.prototype.remove = function (entry) {
|
|
1069
|
-
delete this.entries[entry];
|
|
1070
|
-
};
|
|
1071
|
-
Set.prototype.getEntries = function () {
|
|
1072
|
-
return Object.keys(this.entries);
|
|
1073
|
-
};
|
|
1074
|
-
return Set;
|
|
1075
|
-
}());
|
|
1076
|
-
function moveCursorInsideParenthesis(text) {
|
|
1077
|
-
return text.replace(/\(\)$/, "($1)");
|
|
1078
|
-
}
|
|
1079
|
-
function collectValues(styleSheet, declaration) {
|
|
1080
|
-
var fullPropertyName = declaration.getFullPropertyName();
|
|
1081
|
-
var entries = new Set();
|
|
1082
|
-
function visitValue(node) {
|
|
1083
|
-
if (node instanceof nodes.Identifier || node instanceof nodes.NumericValue || node instanceof nodes.HexColorValue) {
|
|
1084
|
-
entries.add(node.getText());
|
|
1085
|
-
}
|
|
1086
|
-
return true;
|
|
1087
|
-
}
|
|
1088
|
-
function matchesProperty(decl) {
|
|
1089
|
-
var propertyName = decl.getFullPropertyName();
|
|
1090
|
-
return fullPropertyName === propertyName;
|
|
1091
|
-
}
|
|
1092
|
-
function vistNode(node) {
|
|
1093
|
-
if (node instanceof nodes.Declaration && node !== declaration) {
|
|
1094
|
-
if (matchesProperty(node)) {
|
|
1095
|
-
var value = node.getValue();
|
|
1096
|
-
if (value) {
|
|
1097
|
-
value.accept(visitValue);
|
|
1098
|
-
}
|
|
1099
|
-
}
|
|
1100
|
-
}
|
|
1101
|
-
return true;
|
|
1102
|
-
}
|
|
1103
|
-
styleSheet.accept(vistNode);
|
|
1104
|
-
return entries;
|
|
1105
|
-
}
|
|
1106
|
-
var ColorValueCollector = /** @class */ (function () {
|
|
1107
|
-
function ColorValueCollector(entries, currentOffset) {
|
|
1108
|
-
this.entries = entries;
|
|
1109
|
-
this.currentOffset = currentOffset;
|
|
1110
|
-
// nothing to do
|
|
1111
|
-
}
|
|
1112
|
-
ColorValueCollector.prototype.visitNode = function (node) {
|
|
1113
|
-
if (node instanceof nodes.HexColorValue || (node instanceof nodes.Function && languageFacts.isColorConstructor(node))) {
|
|
1114
|
-
if (this.currentOffset < node.offset || node.end < this.currentOffset) {
|
|
1115
|
-
this.entries.add(node.getText());
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
return true;
|
|
1119
|
-
};
|
|
1120
|
-
return ColorValueCollector;
|
|
1121
|
-
}());
|
|
1122
|
-
var VariableCollector = /** @class */ (function () {
|
|
1123
|
-
function VariableCollector(entries, currentOffset) {
|
|
1124
|
-
this.entries = entries;
|
|
1125
|
-
this.currentOffset = currentOffset;
|
|
1126
|
-
// nothing to do
|
|
1127
|
-
}
|
|
1128
|
-
VariableCollector.prototype.visitNode = function (node) {
|
|
1129
|
-
if (node instanceof nodes.Identifier && node.isCustomProperty) {
|
|
1130
|
-
if (this.currentOffset < node.offset || node.end < this.currentOffset) {
|
|
1131
|
-
this.entries.add(node.getText());
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
return true;
|
|
1135
|
-
};
|
|
1136
|
-
return VariableCollector;
|
|
1137
|
-
}());
|
|
1138
|
-
function getCurrentWord(document, offset) {
|
|
1139
|
-
var i = offset - 1;
|
|
1140
|
-
var text = document.getText();
|
|
1141
|
-
while (i >= 0 && ' \t\n\r":{[()]},*>+'.indexOf(text.charAt(i)) === -1) {
|
|
1142
|
-
i--;
|
|
1143
|
-
}
|
|
1144
|
-
return text.substring(i + 1, offset);
|
|
1145
|
-
}
|
|
1146
|
-
function isColorString(s) {
|
|
1147
|
-
// From https://stackoverflow.com/questions/8027423/how-to-check-if-a-string-is-a-valid-hex-color-representation/8027444
|
|
1148
|
-
return (s.toLowerCase() in languageFacts.colors) || /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(s);
|
|
1149
|
-
}
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
'use strict';
|
|
6
|
+
import * as nodes from '../parser/cssNodes';
|
|
7
|
+
import { Symbols } from '../parser/cssSymbolScope';
|
|
8
|
+
import * as languageFacts from '../languageFacts/facts';
|
|
9
|
+
import * as strings from '../utils/strings';
|
|
10
|
+
import { Position, CompletionItemKind, Range, TextEdit, InsertTextFormat, MarkupKind, CompletionItemTag } from '../cssLanguageTypes';
|
|
11
|
+
import * as nls from 'vscode-nls';
|
|
12
|
+
import { isDefined } from '../utils/objects';
|
|
13
|
+
import { PathCompletionParticipant } from './pathCompletion';
|
|
14
|
+
const localize = nls.loadMessageBundle();
|
|
15
|
+
const SnippetFormat = InsertTextFormat.Snippet;
|
|
16
|
+
const retriggerCommand = {
|
|
17
|
+
title: 'Suggest',
|
|
18
|
+
command: 'editor.action.triggerSuggest'
|
|
19
|
+
};
|
|
20
|
+
var SortTexts;
|
|
21
|
+
(function (SortTexts) {
|
|
22
|
+
// char code 32, comes before everything
|
|
23
|
+
SortTexts["Enums"] = " ";
|
|
24
|
+
SortTexts["Normal"] = "d";
|
|
25
|
+
SortTexts["VendorPrefixed"] = "x";
|
|
26
|
+
SortTexts["Term"] = "y";
|
|
27
|
+
SortTexts["Variable"] = "z";
|
|
28
|
+
})(SortTexts || (SortTexts = {}));
|
|
29
|
+
export class CSSCompletion {
|
|
30
|
+
constructor(variablePrefix = null, lsOptions, cssDataManager) {
|
|
31
|
+
this.variablePrefix = variablePrefix;
|
|
32
|
+
this.lsOptions = lsOptions;
|
|
33
|
+
this.cssDataManager = cssDataManager;
|
|
34
|
+
this.completionParticipants = [];
|
|
35
|
+
}
|
|
36
|
+
configure(settings) {
|
|
37
|
+
this.defaultSettings = settings;
|
|
38
|
+
}
|
|
39
|
+
getSymbolContext() {
|
|
40
|
+
if (!this.symbolContext) {
|
|
41
|
+
this.symbolContext = new Symbols(this.styleSheet);
|
|
42
|
+
}
|
|
43
|
+
return this.symbolContext;
|
|
44
|
+
}
|
|
45
|
+
setCompletionParticipants(registeredCompletionParticipants) {
|
|
46
|
+
this.completionParticipants = registeredCompletionParticipants || [];
|
|
47
|
+
}
|
|
48
|
+
async doComplete2(document, position, styleSheet, documentContext, completionSettings = this.defaultSettings) {
|
|
49
|
+
if (!this.lsOptions.fileSystemProvider || !this.lsOptions.fileSystemProvider.readDirectory) {
|
|
50
|
+
return this.doComplete(document, position, styleSheet, completionSettings);
|
|
51
|
+
}
|
|
52
|
+
const participant = new PathCompletionParticipant(this.lsOptions.fileSystemProvider.readDirectory);
|
|
53
|
+
const contributedParticipants = this.completionParticipants;
|
|
54
|
+
this.completionParticipants = [participant].concat(contributedParticipants);
|
|
55
|
+
const result = this.doComplete(document, position, styleSheet, completionSettings);
|
|
56
|
+
try {
|
|
57
|
+
const pathCompletionResult = await participant.computeCompletions(document, documentContext);
|
|
58
|
+
return {
|
|
59
|
+
isIncomplete: result.isIncomplete || pathCompletionResult.isIncomplete,
|
|
60
|
+
items: pathCompletionResult.items.concat(result.items)
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
this.completionParticipants = contributedParticipants;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
doComplete(document, position, styleSheet, documentSettings) {
|
|
68
|
+
this.offset = document.offsetAt(position);
|
|
69
|
+
this.position = position;
|
|
70
|
+
this.currentWord = getCurrentWord(document, this.offset);
|
|
71
|
+
this.defaultReplaceRange = Range.create(Position.create(this.position.line, this.position.character - this.currentWord.length), this.position);
|
|
72
|
+
this.textDocument = document;
|
|
73
|
+
this.styleSheet = styleSheet;
|
|
74
|
+
this.documentSettings = documentSettings;
|
|
75
|
+
try {
|
|
76
|
+
const result = { isIncomplete: false, items: [] };
|
|
77
|
+
this.nodePath = nodes.getNodePath(this.styleSheet, this.offset);
|
|
78
|
+
for (let i = this.nodePath.length - 1; i >= 0; i--) {
|
|
79
|
+
const node = this.nodePath[i];
|
|
80
|
+
if (node instanceof nodes.Property) {
|
|
81
|
+
this.getCompletionsForDeclarationProperty(node.getParent(), result);
|
|
82
|
+
}
|
|
83
|
+
else if (node instanceof nodes.Expression) {
|
|
84
|
+
if (node.parent instanceof nodes.Interpolation) {
|
|
85
|
+
this.getVariableProposals(null, result);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
this.getCompletionsForExpression(node, result);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
else if (node instanceof nodes.SimpleSelector) {
|
|
92
|
+
const parentRef = node.findAParent(nodes.NodeType.ExtendsReference, nodes.NodeType.Ruleset);
|
|
93
|
+
if (parentRef) {
|
|
94
|
+
if (parentRef.type === nodes.NodeType.ExtendsReference) {
|
|
95
|
+
this.getCompletionsForExtendsReference(parentRef, node, result);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
const parentRuleSet = parentRef;
|
|
99
|
+
this.getCompletionsForSelector(parentRuleSet, parentRuleSet && parentRuleSet.isNested(), result);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else if (node instanceof nodes.FunctionArgument) {
|
|
104
|
+
this.getCompletionsForFunctionArgument(node, node.getParent(), result);
|
|
105
|
+
}
|
|
106
|
+
else if (node instanceof nodes.Declarations) {
|
|
107
|
+
this.getCompletionsForDeclarations(node, result);
|
|
108
|
+
}
|
|
109
|
+
else if (node instanceof nodes.VariableDeclaration) {
|
|
110
|
+
this.getCompletionsForVariableDeclaration(node, result);
|
|
111
|
+
}
|
|
112
|
+
else if (node instanceof nodes.RuleSet) {
|
|
113
|
+
this.getCompletionsForRuleSet(node, result);
|
|
114
|
+
}
|
|
115
|
+
else if (node instanceof nodes.Interpolation) {
|
|
116
|
+
this.getCompletionsForInterpolation(node, result);
|
|
117
|
+
}
|
|
118
|
+
else if (node instanceof nodes.FunctionDeclaration) {
|
|
119
|
+
this.getCompletionsForFunctionDeclaration(node, result);
|
|
120
|
+
}
|
|
121
|
+
else if (node instanceof nodes.MixinReference) {
|
|
122
|
+
this.getCompletionsForMixinReference(node, result);
|
|
123
|
+
}
|
|
124
|
+
else if (node instanceof nodes.Function) {
|
|
125
|
+
this.getCompletionsForFunctionArgument(null, node, result);
|
|
126
|
+
}
|
|
127
|
+
else if (node instanceof nodes.Supports) {
|
|
128
|
+
this.getCompletionsForSupports(node, result);
|
|
129
|
+
}
|
|
130
|
+
else if (node instanceof nodes.SupportsCondition) {
|
|
131
|
+
this.getCompletionsForSupportsCondition(node, result);
|
|
132
|
+
}
|
|
133
|
+
else if (node instanceof nodes.ExtendsReference) {
|
|
134
|
+
this.getCompletionsForExtendsReference(node, null, result);
|
|
135
|
+
}
|
|
136
|
+
else if (node.type === nodes.NodeType.URILiteral) {
|
|
137
|
+
this.getCompletionForUriLiteralValue(node, result);
|
|
138
|
+
}
|
|
139
|
+
else if (node.parent === null) {
|
|
140
|
+
this.getCompletionForTopLevel(result);
|
|
141
|
+
}
|
|
142
|
+
else if (node.type === nodes.NodeType.StringLiteral && this.isImportPathParent(node.parent.type)) {
|
|
143
|
+
this.getCompletionForImportPath(node, result);
|
|
144
|
+
// } else if (node instanceof nodes.Variable) {
|
|
145
|
+
// this.getCompletionsForVariableDeclaration()
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
if (result.items.length > 0 || this.offset > node.offset) {
|
|
151
|
+
return this.finalize(result);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
this.getCompletionsForStylesheet(result);
|
|
155
|
+
if (result.items.length === 0) {
|
|
156
|
+
if (this.variablePrefix && this.currentWord.indexOf(this.variablePrefix) === 0) {
|
|
157
|
+
this.getVariableProposals(null, result);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return this.finalize(result);
|
|
161
|
+
}
|
|
162
|
+
finally {
|
|
163
|
+
// don't hold on any state, clear symbolContext
|
|
164
|
+
this.position = null;
|
|
165
|
+
this.currentWord = null;
|
|
166
|
+
this.textDocument = null;
|
|
167
|
+
this.styleSheet = null;
|
|
168
|
+
this.symbolContext = null;
|
|
169
|
+
this.defaultReplaceRange = null;
|
|
170
|
+
this.nodePath = null;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
isImportPathParent(type) {
|
|
174
|
+
return type === nodes.NodeType.Import;
|
|
175
|
+
}
|
|
176
|
+
finalize(result) {
|
|
177
|
+
return result;
|
|
178
|
+
}
|
|
179
|
+
findInNodePath(...types) {
|
|
180
|
+
for (let i = this.nodePath.length - 1; i >= 0; i--) {
|
|
181
|
+
const node = this.nodePath[i];
|
|
182
|
+
if (types.indexOf(node.type) !== -1) {
|
|
183
|
+
return node;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
getCompletionsForDeclarationProperty(declaration, result) {
|
|
189
|
+
return this.getPropertyProposals(declaration, result);
|
|
190
|
+
}
|
|
191
|
+
getPropertyProposals(declaration, result) {
|
|
192
|
+
const triggerPropertyValueCompletion = this.isTriggerPropertyValueCompletionEnabled;
|
|
193
|
+
const completePropertyWithSemicolon = this.isCompletePropertyWithSemicolonEnabled;
|
|
194
|
+
const properties = this.cssDataManager.getProperties();
|
|
195
|
+
properties.forEach(entry => {
|
|
196
|
+
let range;
|
|
197
|
+
let insertText;
|
|
198
|
+
let retrigger = false;
|
|
199
|
+
if (declaration) {
|
|
200
|
+
range = this.getCompletionRange(declaration.getProperty());
|
|
201
|
+
insertText = entry.name;
|
|
202
|
+
if (!isDefined(declaration.colonPosition)) {
|
|
203
|
+
insertText += ': ';
|
|
204
|
+
retrigger = true;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
range = this.getCompletionRange(null);
|
|
209
|
+
insertText = entry.name + ': ';
|
|
210
|
+
retrigger = true;
|
|
211
|
+
}
|
|
212
|
+
// Empty .selector { | } case
|
|
213
|
+
if (!declaration && completePropertyWithSemicolon) {
|
|
214
|
+
insertText += '$0;';
|
|
215
|
+
}
|
|
216
|
+
// Cases such as .selector { p; } or .selector { p:; }
|
|
217
|
+
if (declaration && !declaration.semicolonPosition) {
|
|
218
|
+
if (completePropertyWithSemicolon && this.offset >= this.textDocument.offsetAt(range.end)) {
|
|
219
|
+
insertText += '$0;';
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
const item = {
|
|
223
|
+
label: entry.name,
|
|
224
|
+
documentation: languageFacts.getEntryDescription(entry, this.doesSupportMarkdown()),
|
|
225
|
+
tags: isDeprecated(entry) ? [CompletionItemTag.Deprecated] : [],
|
|
226
|
+
textEdit: TextEdit.replace(range, insertText),
|
|
227
|
+
insertTextFormat: InsertTextFormat.Snippet,
|
|
228
|
+
kind: CompletionItemKind.Property
|
|
229
|
+
};
|
|
230
|
+
if (!entry.restrictions) {
|
|
231
|
+
retrigger = false;
|
|
232
|
+
}
|
|
233
|
+
if (triggerPropertyValueCompletion && retrigger) {
|
|
234
|
+
item.command = retriggerCommand;
|
|
235
|
+
}
|
|
236
|
+
const relevance = typeof entry.relevance === 'number' ? Math.min(Math.max(entry.relevance, 0), 99) : 50;
|
|
237
|
+
const sortTextSuffix = (255 - relevance).toString(16);
|
|
238
|
+
const sortTextPrefix = strings.startsWith(entry.name, '-') ? SortTexts.VendorPrefixed : SortTexts.Normal;
|
|
239
|
+
item.sortText = sortTextPrefix + '_' + sortTextSuffix;
|
|
240
|
+
result.items.push(item);
|
|
241
|
+
});
|
|
242
|
+
this.completionParticipants.forEach(participant => {
|
|
243
|
+
if (participant.onCssProperty) {
|
|
244
|
+
participant.onCssProperty({
|
|
245
|
+
propertyName: this.currentWord,
|
|
246
|
+
range: this.defaultReplaceRange
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
return result;
|
|
251
|
+
}
|
|
252
|
+
get isTriggerPropertyValueCompletionEnabled() {
|
|
253
|
+
return this.documentSettings?.triggerPropertyValueCompletion ?? true;
|
|
254
|
+
}
|
|
255
|
+
get isCompletePropertyWithSemicolonEnabled() {
|
|
256
|
+
return this.documentSettings?.completePropertyWithSemicolon ?? true;
|
|
257
|
+
}
|
|
258
|
+
getCompletionsForDeclarationValue(node, result) {
|
|
259
|
+
const propertyName = node.getFullPropertyName();
|
|
260
|
+
const entry = this.cssDataManager.getProperty(propertyName);
|
|
261
|
+
let existingNode = node.getValue() || null;
|
|
262
|
+
while (existingNode && existingNode.hasChildren()) {
|
|
263
|
+
existingNode = existingNode.findChildAtOffset(this.offset, false);
|
|
264
|
+
}
|
|
265
|
+
this.completionParticipants.forEach(participant => {
|
|
266
|
+
if (participant.onCssPropertyValue) {
|
|
267
|
+
participant.onCssPropertyValue({
|
|
268
|
+
propertyName,
|
|
269
|
+
propertyValue: this.currentWord,
|
|
270
|
+
range: this.getCompletionRange(existingNode)
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
if (entry) {
|
|
275
|
+
if (entry.restrictions) {
|
|
276
|
+
for (const restriction of entry.restrictions) {
|
|
277
|
+
switch (restriction) {
|
|
278
|
+
case 'color':
|
|
279
|
+
this.getColorProposals(entry, existingNode, result);
|
|
280
|
+
break;
|
|
281
|
+
case 'position':
|
|
282
|
+
this.getPositionProposals(entry, existingNode, result);
|
|
283
|
+
break;
|
|
284
|
+
case 'repeat':
|
|
285
|
+
this.getRepeatStyleProposals(entry, existingNode, result);
|
|
286
|
+
break;
|
|
287
|
+
case 'line-style':
|
|
288
|
+
this.getLineStyleProposals(entry, existingNode, result);
|
|
289
|
+
break;
|
|
290
|
+
case 'line-width':
|
|
291
|
+
this.getLineWidthProposals(entry, existingNode, result);
|
|
292
|
+
break;
|
|
293
|
+
case 'geometry-box':
|
|
294
|
+
this.getGeometryBoxProposals(entry, existingNode, result);
|
|
295
|
+
break;
|
|
296
|
+
case 'box':
|
|
297
|
+
this.getBoxProposals(entry, existingNode, result);
|
|
298
|
+
break;
|
|
299
|
+
case 'image':
|
|
300
|
+
this.getImageProposals(entry, existingNode, result);
|
|
301
|
+
break;
|
|
302
|
+
case 'timing-function':
|
|
303
|
+
this.getTimingFunctionProposals(entry, existingNode, result);
|
|
304
|
+
break;
|
|
305
|
+
case 'shape':
|
|
306
|
+
this.getBasicShapeProposals(entry, existingNode, result);
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
this.getValueEnumProposals(entry, existingNode, result);
|
|
312
|
+
this.getCSSWideKeywordProposals(entry, existingNode, result);
|
|
313
|
+
this.getUnitProposals(entry, existingNode, result);
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
const existingValues = collectValues(this.styleSheet, node);
|
|
317
|
+
for (const existingValue of existingValues.getEntries()) {
|
|
318
|
+
result.items.push({
|
|
319
|
+
label: existingValue,
|
|
320
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), existingValue),
|
|
321
|
+
kind: CompletionItemKind.Value
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
this.getVariableProposals(existingNode, result);
|
|
326
|
+
this.getTermProposals(entry, existingNode, result);
|
|
327
|
+
return result;
|
|
328
|
+
}
|
|
329
|
+
getValueEnumProposals(entry, existingNode, result) {
|
|
330
|
+
if (entry.values) {
|
|
331
|
+
for (const value of entry.values) {
|
|
332
|
+
let insertString = value.name;
|
|
333
|
+
let insertTextFormat;
|
|
334
|
+
if (strings.endsWith(insertString, ')')) {
|
|
335
|
+
const from = insertString.lastIndexOf('(');
|
|
336
|
+
if (from !== -1) {
|
|
337
|
+
insertString = insertString.substr(0, from) + '($1)';
|
|
338
|
+
insertTextFormat = SnippetFormat;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
let sortText = SortTexts.Enums;
|
|
342
|
+
if (strings.startsWith(value.name, '-')) {
|
|
343
|
+
sortText += SortTexts.VendorPrefixed;
|
|
344
|
+
}
|
|
345
|
+
const item = {
|
|
346
|
+
label: value.name,
|
|
347
|
+
documentation: languageFacts.getEntryDescription(value, this.doesSupportMarkdown()),
|
|
348
|
+
tags: isDeprecated(entry) ? [CompletionItemTag.Deprecated] : [],
|
|
349
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), insertString),
|
|
350
|
+
sortText,
|
|
351
|
+
kind: CompletionItemKind.Value,
|
|
352
|
+
insertTextFormat
|
|
353
|
+
};
|
|
354
|
+
result.items.push(item);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return result;
|
|
358
|
+
}
|
|
359
|
+
getCSSWideKeywordProposals(entry, existingNode, result) {
|
|
360
|
+
for (const keywords in languageFacts.cssWideKeywords) {
|
|
361
|
+
result.items.push({
|
|
362
|
+
label: keywords,
|
|
363
|
+
documentation: languageFacts.cssWideKeywords[keywords],
|
|
364
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), keywords),
|
|
365
|
+
kind: CompletionItemKind.Value
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
for (const func in languageFacts.cssWideFunctions) {
|
|
369
|
+
const insertText = moveCursorInsideParenthesis(func);
|
|
370
|
+
result.items.push({
|
|
371
|
+
label: func,
|
|
372
|
+
documentation: languageFacts.cssWideFunctions[func],
|
|
373
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), insertText),
|
|
374
|
+
kind: CompletionItemKind.Function,
|
|
375
|
+
insertTextFormat: SnippetFormat,
|
|
376
|
+
command: strings.startsWith(func, 'var') ? retriggerCommand : undefined
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
return result;
|
|
380
|
+
}
|
|
381
|
+
getCompletionsForInterpolation(node, result) {
|
|
382
|
+
if (this.offset >= node.offset + 2) {
|
|
383
|
+
this.getVariableProposals(null, result);
|
|
384
|
+
}
|
|
385
|
+
return result;
|
|
386
|
+
}
|
|
387
|
+
getVariableProposals(existingNode, result) {
|
|
388
|
+
const symbols = this.getSymbolContext().findSymbolsAtOffset(this.offset, nodes.ReferenceType.Variable);
|
|
389
|
+
for (const symbol of symbols) {
|
|
390
|
+
const insertText = strings.startsWith(symbol.name, '--') ? `var(${symbol.name})` : symbol.name;
|
|
391
|
+
const completionItem = {
|
|
392
|
+
label: symbol.name,
|
|
393
|
+
documentation: symbol.value ? strings.getLimitedString(symbol.value) : symbol.value,
|
|
394
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), insertText),
|
|
395
|
+
kind: CompletionItemKind.Variable,
|
|
396
|
+
sortText: SortTexts.Variable
|
|
397
|
+
};
|
|
398
|
+
if (typeof completionItem.documentation === 'string' && isColorString(completionItem.documentation)) {
|
|
399
|
+
completionItem.kind = CompletionItemKind.Color;
|
|
400
|
+
}
|
|
401
|
+
if (symbol.node.type === nodes.NodeType.FunctionParameter) {
|
|
402
|
+
const mixinNode = (symbol.node.getParent());
|
|
403
|
+
if (mixinNode.type === nodes.NodeType.MixinDeclaration) {
|
|
404
|
+
completionItem.detail = localize('completion.argument', 'argument from \'{0}\'', mixinNode.getName());
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
result.items.push(completionItem);
|
|
408
|
+
}
|
|
409
|
+
return result;
|
|
410
|
+
}
|
|
411
|
+
getVariableProposalsForCSSVarFunction(result) {
|
|
412
|
+
const allReferencedVariables = new Set();
|
|
413
|
+
this.styleSheet.acceptVisitor(new VariableCollector(allReferencedVariables, this.offset));
|
|
414
|
+
let symbols = this.getSymbolContext().findSymbolsAtOffset(this.offset, nodes.ReferenceType.Variable);
|
|
415
|
+
for (const symbol of symbols) {
|
|
416
|
+
if (strings.startsWith(symbol.name, '--')) {
|
|
417
|
+
const completionItem = {
|
|
418
|
+
label: symbol.name,
|
|
419
|
+
documentation: symbol.value ? strings.getLimitedString(symbol.value) : symbol.value,
|
|
420
|
+
textEdit: TextEdit.replace(this.getCompletionRange(null), symbol.name),
|
|
421
|
+
kind: CompletionItemKind.Variable
|
|
422
|
+
};
|
|
423
|
+
if (typeof completionItem.documentation === 'string' && isColorString(completionItem.documentation)) {
|
|
424
|
+
completionItem.kind = CompletionItemKind.Color;
|
|
425
|
+
}
|
|
426
|
+
result.items.push(completionItem);
|
|
427
|
+
}
|
|
428
|
+
allReferencedVariables.remove(symbol.name);
|
|
429
|
+
}
|
|
430
|
+
for (const name of allReferencedVariables.getEntries()) {
|
|
431
|
+
if (strings.startsWith(name, '--')) {
|
|
432
|
+
const completionItem = {
|
|
433
|
+
label: name,
|
|
434
|
+
textEdit: TextEdit.replace(this.getCompletionRange(null), name),
|
|
435
|
+
kind: CompletionItemKind.Variable
|
|
436
|
+
};
|
|
437
|
+
result.items.push(completionItem);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
return result;
|
|
441
|
+
}
|
|
442
|
+
getUnitProposals(entry, existingNode, result) {
|
|
443
|
+
let currentWord = '0';
|
|
444
|
+
if (this.currentWord.length > 0) {
|
|
445
|
+
const numMatch = this.currentWord.match(/^-?\d[\.\d+]*/);
|
|
446
|
+
if (numMatch) {
|
|
447
|
+
currentWord = numMatch[0];
|
|
448
|
+
result.isIncomplete = currentWord.length === this.currentWord.length;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
else if (this.currentWord.length === 0) {
|
|
452
|
+
result.isIncomplete = true;
|
|
453
|
+
}
|
|
454
|
+
if (existingNode && existingNode.parent && existingNode.parent.type === nodes.NodeType.Term) {
|
|
455
|
+
existingNode = existingNode.getParent(); // include the unary operator
|
|
456
|
+
}
|
|
457
|
+
if (entry.restrictions) {
|
|
458
|
+
for (const restriction of entry.restrictions) {
|
|
459
|
+
const units = languageFacts.units[restriction];
|
|
460
|
+
if (units) {
|
|
461
|
+
for (const unit of units) {
|
|
462
|
+
const insertText = currentWord + unit;
|
|
463
|
+
result.items.push({
|
|
464
|
+
label: insertText,
|
|
465
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), insertText),
|
|
466
|
+
kind: CompletionItemKind.Unit
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
return result;
|
|
473
|
+
}
|
|
474
|
+
getCompletionRange(existingNode) {
|
|
475
|
+
if (existingNode && existingNode.offset <= this.offset && this.offset <= existingNode.end) {
|
|
476
|
+
const end = existingNode.end !== -1 ? this.textDocument.positionAt(existingNode.end) : this.position;
|
|
477
|
+
const start = this.textDocument.positionAt(existingNode.offset);
|
|
478
|
+
if (start.line === end.line) {
|
|
479
|
+
return Range.create(start, end); // multi line edits are not allowed
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
return this.defaultReplaceRange;
|
|
483
|
+
}
|
|
484
|
+
getColorProposals(entry, existingNode, result) {
|
|
485
|
+
for (const color in languageFacts.colors) {
|
|
486
|
+
result.items.push({
|
|
487
|
+
label: color,
|
|
488
|
+
documentation: languageFacts.colors[color],
|
|
489
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), color),
|
|
490
|
+
kind: CompletionItemKind.Color
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
for (const color in languageFacts.colorKeywords) {
|
|
494
|
+
result.items.push({
|
|
495
|
+
label: color,
|
|
496
|
+
documentation: languageFacts.colorKeywords[color],
|
|
497
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), color),
|
|
498
|
+
kind: CompletionItemKind.Value
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
const colorValues = new Set();
|
|
502
|
+
this.styleSheet.acceptVisitor(new ColorValueCollector(colorValues, this.offset));
|
|
503
|
+
for (const color of colorValues.getEntries()) {
|
|
504
|
+
result.items.push({
|
|
505
|
+
label: color,
|
|
506
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), color),
|
|
507
|
+
kind: CompletionItemKind.Color
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
for (const p of languageFacts.colorFunctions) {
|
|
511
|
+
let tabStop = 1;
|
|
512
|
+
const replaceFunction = (_match, p1) => '${' + tabStop++ + ':' + p1 + '}';
|
|
513
|
+
const insertText = p.func.replace(/\[?\$(\w+)\]?/g, replaceFunction);
|
|
514
|
+
result.items.push({
|
|
515
|
+
label: p.func.substr(0, p.func.indexOf('(')),
|
|
516
|
+
detail: p.func,
|
|
517
|
+
documentation: p.desc,
|
|
518
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), insertText),
|
|
519
|
+
insertTextFormat: SnippetFormat,
|
|
520
|
+
kind: CompletionItemKind.Function
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
return result;
|
|
524
|
+
}
|
|
525
|
+
getPositionProposals(entry, existingNode, result) {
|
|
526
|
+
for (const position in languageFacts.positionKeywords) {
|
|
527
|
+
result.items.push({
|
|
528
|
+
label: position,
|
|
529
|
+
documentation: languageFacts.positionKeywords[position],
|
|
530
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), position),
|
|
531
|
+
kind: CompletionItemKind.Value
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
return result;
|
|
535
|
+
}
|
|
536
|
+
getRepeatStyleProposals(entry, existingNode, result) {
|
|
537
|
+
for (const repeat in languageFacts.repeatStyleKeywords) {
|
|
538
|
+
result.items.push({
|
|
539
|
+
label: repeat,
|
|
540
|
+
documentation: languageFacts.repeatStyleKeywords[repeat],
|
|
541
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), repeat),
|
|
542
|
+
kind: CompletionItemKind.Value
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
return result;
|
|
546
|
+
}
|
|
547
|
+
getLineStyleProposals(entry, existingNode, result) {
|
|
548
|
+
for (const lineStyle in languageFacts.lineStyleKeywords) {
|
|
549
|
+
result.items.push({
|
|
550
|
+
label: lineStyle,
|
|
551
|
+
documentation: languageFacts.lineStyleKeywords[lineStyle],
|
|
552
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), lineStyle),
|
|
553
|
+
kind: CompletionItemKind.Value
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
return result;
|
|
557
|
+
}
|
|
558
|
+
getLineWidthProposals(entry, existingNode, result) {
|
|
559
|
+
for (const lineWidth of languageFacts.lineWidthKeywords) {
|
|
560
|
+
result.items.push({
|
|
561
|
+
label: lineWidth,
|
|
562
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), lineWidth),
|
|
563
|
+
kind: CompletionItemKind.Value
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
return result;
|
|
567
|
+
}
|
|
568
|
+
getGeometryBoxProposals(entry, existingNode, result) {
|
|
569
|
+
for (const box in languageFacts.geometryBoxKeywords) {
|
|
570
|
+
result.items.push({
|
|
571
|
+
label: box,
|
|
572
|
+
documentation: languageFacts.geometryBoxKeywords[box],
|
|
573
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), box),
|
|
574
|
+
kind: CompletionItemKind.Value
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
return result;
|
|
578
|
+
}
|
|
579
|
+
getBoxProposals(entry, existingNode, result) {
|
|
580
|
+
for (const box in languageFacts.boxKeywords) {
|
|
581
|
+
result.items.push({
|
|
582
|
+
label: box,
|
|
583
|
+
documentation: languageFacts.boxKeywords[box],
|
|
584
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), box),
|
|
585
|
+
kind: CompletionItemKind.Value
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
return result;
|
|
589
|
+
}
|
|
590
|
+
getImageProposals(entry, existingNode, result) {
|
|
591
|
+
for (const image in languageFacts.imageFunctions) {
|
|
592
|
+
const insertText = moveCursorInsideParenthesis(image);
|
|
593
|
+
result.items.push({
|
|
594
|
+
label: image,
|
|
595
|
+
documentation: languageFacts.imageFunctions[image],
|
|
596
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), insertText),
|
|
597
|
+
kind: CompletionItemKind.Function,
|
|
598
|
+
insertTextFormat: image !== insertText ? SnippetFormat : void 0
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
return result;
|
|
602
|
+
}
|
|
603
|
+
getTimingFunctionProposals(entry, existingNode, result) {
|
|
604
|
+
for (const timing in languageFacts.transitionTimingFunctions) {
|
|
605
|
+
const insertText = moveCursorInsideParenthesis(timing);
|
|
606
|
+
result.items.push({
|
|
607
|
+
label: timing,
|
|
608
|
+
documentation: languageFacts.transitionTimingFunctions[timing],
|
|
609
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), insertText),
|
|
610
|
+
kind: CompletionItemKind.Function,
|
|
611
|
+
insertTextFormat: timing !== insertText ? SnippetFormat : void 0
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
return result;
|
|
615
|
+
}
|
|
616
|
+
getBasicShapeProposals(entry, existingNode, result) {
|
|
617
|
+
for (const shape in languageFacts.basicShapeFunctions) {
|
|
618
|
+
const insertText = moveCursorInsideParenthesis(shape);
|
|
619
|
+
result.items.push({
|
|
620
|
+
label: shape,
|
|
621
|
+
documentation: languageFacts.basicShapeFunctions[shape],
|
|
622
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), insertText),
|
|
623
|
+
kind: CompletionItemKind.Function,
|
|
624
|
+
insertTextFormat: shape !== insertText ? SnippetFormat : void 0
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
return result;
|
|
628
|
+
}
|
|
629
|
+
getCompletionsForStylesheet(result) {
|
|
630
|
+
const node = this.styleSheet.findFirstChildBeforeOffset(this.offset);
|
|
631
|
+
if (!node) {
|
|
632
|
+
return this.getCompletionForTopLevel(result);
|
|
633
|
+
}
|
|
634
|
+
if (node instanceof nodes.RuleSet) {
|
|
635
|
+
return this.getCompletionsForRuleSet(node, result);
|
|
636
|
+
}
|
|
637
|
+
if (node instanceof nodes.Supports) {
|
|
638
|
+
return this.getCompletionsForSupports(node, result);
|
|
639
|
+
}
|
|
640
|
+
return result;
|
|
641
|
+
}
|
|
642
|
+
getCompletionForTopLevel(result) {
|
|
643
|
+
this.cssDataManager.getAtDirectives().forEach(entry => {
|
|
644
|
+
result.items.push({
|
|
645
|
+
label: entry.name,
|
|
646
|
+
textEdit: TextEdit.replace(this.getCompletionRange(null), entry.name),
|
|
647
|
+
documentation: languageFacts.getEntryDescription(entry, this.doesSupportMarkdown()),
|
|
648
|
+
tags: isDeprecated(entry) ? [CompletionItemTag.Deprecated] : [],
|
|
649
|
+
kind: CompletionItemKind.Keyword
|
|
650
|
+
});
|
|
651
|
+
});
|
|
652
|
+
this.getCompletionsForSelector(null, false, result);
|
|
653
|
+
return result;
|
|
654
|
+
}
|
|
655
|
+
getCompletionsForRuleSet(ruleSet, result) {
|
|
656
|
+
const declarations = ruleSet.getDeclarations();
|
|
657
|
+
const isAfter = declarations && declarations.endsWith('}') && this.offset >= declarations.end;
|
|
658
|
+
if (isAfter) {
|
|
659
|
+
return this.getCompletionForTopLevel(result);
|
|
660
|
+
}
|
|
661
|
+
const isInSelectors = !declarations || this.offset <= declarations.offset;
|
|
662
|
+
if (isInSelectors) {
|
|
663
|
+
return this.getCompletionsForSelector(ruleSet, ruleSet.isNested(), result);
|
|
664
|
+
}
|
|
665
|
+
return this.getCompletionsForDeclarations(ruleSet.getDeclarations(), result);
|
|
666
|
+
}
|
|
667
|
+
getCompletionsForSelector(ruleSet, isNested, result) {
|
|
668
|
+
const existingNode = this.findInNodePath(nodes.NodeType.PseudoSelector, nodes.NodeType.IdentifierSelector, nodes.NodeType.ClassSelector, nodes.NodeType.ElementNameSelector);
|
|
669
|
+
if (!existingNode && this.hasCharacterAtPosition(this.offset - this.currentWord.length - 1, ':')) {
|
|
670
|
+
// after the ':' of a pseudo selector, no node generated for just ':'
|
|
671
|
+
this.currentWord = ':' + this.currentWord;
|
|
672
|
+
if (this.hasCharacterAtPosition(this.offset - this.currentWord.length - 1, ':')) {
|
|
673
|
+
this.currentWord = ':' + this.currentWord; // for '::'
|
|
674
|
+
}
|
|
675
|
+
this.defaultReplaceRange = Range.create(Position.create(this.position.line, this.position.character - this.currentWord.length), this.position);
|
|
676
|
+
}
|
|
677
|
+
const pseudoClasses = this.cssDataManager.getPseudoClasses();
|
|
678
|
+
pseudoClasses.forEach(entry => {
|
|
679
|
+
const insertText = moveCursorInsideParenthesis(entry.name);
|
|
680
|
+
const item = {
|
|
681
|
+
label: entry.name,
|
|
682
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), insertText),
|
|
683
|
+
documentation: languageFacts.getEntryDescription(entry, this.doesSupportMarkdown()),
|
|
684
|
+
tags: isDeprecated(entry) ? [CompletionItemTag.Deprecated] : [],
|
|
685
|
+
kind: CompletionItemKind.Function,
|
|
686
|
+
insertTextFormat: entry.name !== insertText ? SnippetFormat : void 0
|
|
687
|
+
};
|
|
688
|
+
if (strings.startsWith(entry.name, ':-')) {
|
|
689
|
+
item.sortText = SortTexts.VendorPrefixed;
|
|
690
|
+
}
|
|
691
|
+
result.items.push(item);
|
|
692
|
+
});
|
|
693
|
+
const pseudoElements = this.cssDataManager.getPseudoElements();
|
|
694
|
+
pseudoElements.forEach(entry => {
|
|
695
|
+
const insertText = moveCursorInsideParenthesis(entry.name);
|
|
696
|
+
const item = {
|
|
697
|
+
label: entry.name,
|
|
698
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), insertText),
|
|
699
|
+
documentation: languageFacts.getEntryDescription(entry, this.doesSupportMarkdown()),
|
|
700
|
+
tags: isDeprecated(entry) ? [CompletionItemTag.Deprecated] : [],
|
|
701
|
+
kind: CompletionItemKind.Function,
|
|
702
|
+
insertTextFormat: entry.name !== insertText ? SnippetFormat : void 0
|
|
703
|
+
};
|
|
704
|
+
if (strings.startsWith(entry.name, '::-')) {
|
|
705
|
+
item.sortText = SortTexts.VendorPrefixed;
|
|
706
|
+
}
|
|
707
|
+
result.items.push(item);
|
|
708
|
+
});
|
|
709
|
+
if (!isNested) { // show html tags only for top level
|
|
710
|
+
for (const entry of languageFacts.html5Tags) {
|
|
711
|
+
result.items.push({
|
|
712
|
+
label: entry,
|
|
713
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), entry),
|
|
714
|
+
kind: CompletionItemKind.Keyword
|
|
715
|
+
});
|
|
716
|
+
}
|
|
717
|
+
for (const entry of languageFacts.svgElements) {
|
|
718
|
+
result.items.push({
|
|
719
|
+
label: entry,
|
|
720
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), entry),
|
|
721
|
+
kind: CompletionItemKind.Keyword
|
|
722
|
+
});
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
const visited = {};
|
|
726
|
+
visited[this.currentWord] = true;
|
|
727
|
+
const docText = this.textDocument.getText();
|
|
728
|
+
this.styleSheet.accept(n => {
|
|
729
|
+
if (n.type === nodes.NodeType.SimpleSelector && n.length > 0) {
|
|
730
|
+
const selector = docText.substr(n.offset, n.length);
|
|
731
|
+
if (selector.charAt(0) === '.' && !visited[selector]) {
|
|
732
|
+
visited[selector] = true;
|
|
733
|
+
result.items.push({
|
|
734
|
+
label: selector,
|
|
735
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), selector),
|
|
736
|
+
kind: CompletionItemKind.Keyword
|
|
737
|
+
});
|
|
738
|
+
}
|
|
739
|
+
return false;
|
|
740
|
+
}
|
|
741
|
+
return true;
|
|
742
|
+
});
|
|
743
|
+
if (ruleSet && ruleSet.isNested()) {
|
|
744
|
+
const selector = ruleSet.getSelectors().findFirstChildBeforeOffset(this.offset);
|
|
745
|
+
if (selector && ruleSet.getSelectors().getChildren().indexOf(selector) === 0) {
|
|
746
|
+
this.getPropertyProposals(null, result);
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
return result;
|
|
750
|
+
}
|
|
751
|
+
getCompletionsForDeclarations(declarations, result) {
|
|
752
|
+
if (!declarations || this.offset === declarations.offset) { // incomplete nodes
|
|
753
|
+
return result;
|
|
754
|
+
}
|
|
755
|
+
const node = declarations.findFirstChildBeforeOffset(this.offset);
|
|
756
|
+
if (!node) {
|
|
757
|
+
return this.getCompletionsForDeclarationProperty(null, result);
|
|
758
|
+
}
|
|
759
|
+
if (node instanceof nodes.AbstractDeclaration) {
|
|
760
|
+
const declaration = node;
|
|
761
|
+
if (!isDefined(declaration.colonPosition) || this.offset <= declaration.colonPosition) {
|
|
762
|
+
// complete property
|
|
763
|
+
return this.getCompletionsForDeclarationProperty(declaration, result);
|
|
764
|
+
}
|
|
765
|
+
else if ((isDefined(declaration.semicolonPosition) && declaration.semicolonPosition < this.offset)) {
|
|
766
|
+
if (this.offset === declaration.semicolonPosition + 1) {
|
|
767
|
+
return result; // don't show new properties right after semicolon (see Bug 15421:[intellisense] [css] Be less aggressive when manually typing CSS)
|
|
768
|
+
}
|
|
769
|
+
// complete next property
|
|
770
|
+
return this.getCompletionsForDeclarationProperty(null, result);
|
|
771
|
+
}
|
|
772
|
+
if (declaration instanceof nodes.Declaration) {
|
|
773
|
+
// complete value
|
|
774
|
+
return this.getCompletionsForDeclarationValue(declaration, result);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
else if (node instanceof nodes.ExtendsReference) {
|
|
778
|
+
this.getCompletionsForExtendsReference(node, null, result);
|
|
779
|
+
}
|
|
780
|
+
else if (this.currentWord && this.currentWord[0] === '@') {
|
|
781
|
+
this.getCompletionsForDeclarationProperty(null, result);
|
|
782
|
+
}
|
|
783
|
+
else if (node instanceof nodes.RuleSet) {
|
|
784
|
+
this.getCompletionsForDeclarationProperty(null, result);
|
|
785
|
+
}
|
|
786
|
+
return result;
|
|
787
|
+
}
|
|
788
|
+
getCompletionsForVariableDeclaration(declaration, result) {
|
|
789
|
+
if (this.offset && isDefined(declaration.colonPosition) && this.offset > declaration.colonPosition) {
|
|
790
|
+
this.getVariableProposals(declaration.getValue(), result);
|
|
791
|
+
}
|
|
792
|
+
return result;
|
|
793
|
+
}
|
|
794
|
+
getCompletionsForExpression(expression, result) {
|
|
795
|
+
const parent = expression.getParent();
|
|
796
|
+
if (parent instanceof nodes.FunctionArgument) {
|
|
797
|
+
this.getCompletionsForFunctionArgument(parent, parent.getParent(), result);
|
|
798
|
+
return result;
|
|
799
|
+
}
|
|
800
|
+
const declaration = expression.findParent(nodes.NodeType.Declaration);
|
|
801
|
+
if (!declaration) {
|
|
802
|
+
this.getTermProposals(undefined, null, result);
|
|
803
|
+
return result;
|
|
804
|
+
}
|
|
805
|
+
const node = expression.findChildAtOffset(this.offset, true);
|
|
806
|
+
if (!node) {
|
|
807
|
+
return this.getCompletionsForDeclarationValue(declaration, result);
|
|
808
|
+
}
|
|
809
|
+
if (node instanceof nodes.NumericValue || node instanceof nodes.Identifier) {
|
|
810
|
+
return this.getCompletionsForDeclarationValue(declaration, result);
|
|
811
|
+
}
|
|
812
|
+
return result;
|
|
813
|
+
}
|
|
814
|
+
getCompletionsForFunctionArgument(arg, func, result) {
|
|
815
|
+
const identifier = func.getIdentifier();
|
|
816
|
+
if (identifier && identifier.matches('var')) {
|
|
817
|
+
if (!func.getArguments().hasChildren() || func.getArguments().getChild(0) === arg) {
|
|
818
|
+
this.getVariableProposalsForCSSVarFunction(result);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
return result;
|
|
822
|
+
}
|
|
823
|
+
getCompletionsForFunctionDeclaration(decl, result) {
|
|
824
|
+
const declarations = decl.getDeclarations();
|
|
825
|
+
if (declarations && this.offset > declarations.offset && this.offset < declarations.end) {
|
|
826
|
+
this.getTermProposals(undefined, null, result);
|
|
827
|
+
}
|
|
828
|
+
return result;
|
|
829
|
+
}
|
|
830
|
+
getCompletionsForMixinReference(ref, result) {
|
|
831
|
+
const allMixins = this.getSymbolContext().findSymbolsAtOffset(this.offset, nodes.ReferenceType.Mixin);
|
|
832
|
+
for (const mixinSymbol of allMixins) {
|
|
833
|
+
if (mixinSymbol.node instanceof nodes.MixinDeclaration) {
|
|
834
|
+
result.items.push(this.makeTermProposal(mixinSymbol, mixinSymbol.node.getParameters(), null));
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
const identifierNode = ref.getIdentifier() || null;
|
|
838
|
+
this.completionParticipants.forEach(participant => {
|
|
839
|
+
if (participant.onCssMixinReference) {
|
|
840
|
+
participant.onCssMixinReference({
|
|
841
|
+
mixinName: this.currentWord,
|
|
842
|
+
range: this.getCompletionRange(identifierNode)
|
|
843
|
+
});
|
|
844
|
+
}
|
|
845
|
+
});
|
|
846
|
+
return result;
|
|
847
|
+
}
|
|
848
|
+
getTermProposals(entry, existingNode, result) {
|
|
849
|
+
const allFunctions = this.getSymbolContext().findSymbolsAtOffset(this.offset, nodes.ReferenceType.Function);
|
|
850
|
+
for (const functionSymbol of allFunctions) {
|
|
851
|
+
if (functionSymbol.node instanceof nodes.FunctionDeclaration) {
|
|
852
|
+
result.items.push(this.makeTermProposal(functionSymbol, functionSymbol.node.getParameters(), existingNode));
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
return result;
|
|
856
|
+
}
|
|
857
|
+
makeTermProposal(symbol, parameters, existingNode) {
|
|
858
|
+
const decl = symbol.node;
|
|
859
|
+
const params = parameters.getChildren().map((c) => {
|
|
860
|
+
return (c instanceof nodes.FunctionParameter) ? c.getName() : c.getText();
|
|
861
|
+
});
|
|
862
|
+
const insertText = symbol.name + '(' + params.map((p, index) => '${' + (index + 1) + ':' + p + '}').join(', ') + ')';
|
|
863
|
+
return {
|
|
864
|
+
label: symbol.name,
|
|
865
|
+
detail: symbol.name + '(' + params.join(', ') + ')',
|
|
866
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), insertText),
|
|
867
|
+
insertTextFormat: SnippetFormat,
|
|
868
|
+
kind: CompletionItemKind.Function,
|
|
869
|
+
sortText: SortTexts.Term
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
getCompletionsForSupportsCondition(supportsCondition, result) {
|
|
873
|
+
const child = supportsCondition.findFirstChildBeforeOffset(this.offset);
|
|
874
|
+
if (child) {
|
|
875
|
+
if (child instanceof nodes.Declaration) {
|
|
876
|
+
if (!isDefined(child.colonPosition) || this.offset <= child.colonPosition) {
|
|
877
|
+
return this.getCompletionsForDeclarationProperty(child, result);
|
|
878
|
+
}
|
|
879
|
+
else {
|
|
880
|
+
return this.getCompletionsForDeclarationValue(child, result);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
else if (child instanceof nodes.SupportsCondition) {
|
|
884
|
+
return this.getCompletionsForSupportsCondition(child, result);
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
if (isDefined(supportsCondition.lParent) && this.offset > supportsCondition.lParent && (!isDefined(supportsCondition.rParent) || this.offset <= supportsCondition.rParent)) {
|
|
888
|
+
return this.getCompletionsForDeclarationProperty(null, result);
|
|
889
|
+
}
|
|
890
|
+
return result;
|
|
891
|
+
}
|
|
892
|
+
getCompletionsForSupports(supports, result) {
|
|
893
|
+
const declarations = supports.getDeclarations();
|
|
894
|
+
const inInCondition = !declarations || this.offset <= declarations.offset;
|
|
895
|
+
if (inInCondition) {
|
|
896
|
+
const child = supports.findFirstChildBeforeOffset(this.offset);
|
|
897
|
+
if (child instanceof nodes.SupportsCondition) {
|
|
898
|
+
return this.getCompletionsForSupportsCondition(child, result);
|
|
899
|
+
}
|
|
900
|
+
return result;
|
|
901
|
+
}
|
|
902
|
+
return this.getCompletionForTopLevel(result);
|
|
903
|
+
}
|
|
904
|
+
getCompletionsForExtendsReference(extendsRef, existingNode, result) {
|
|
905
|
+
return result;
|
|
906
|
+
}
|
|
907
|
+
getCompletionForUriLiteralValue(uriLiteralNode, result) {
|
|
908
|
+
let uriValue;
|
|
909
|
+
let position;
|
|
910
|
+
let range;
|
|
911
|
+
// No children, empty value
|
|
912
|
+
if (!uriLiteralNode.hasChildren()) {
|
|
913
|
+
uriValue = '';
|
|
914
|
+
position = this.position;
|
|
915
|
+
const emptyURIValuePosition = this.textDocument.positionAt(uriLiteralNode.offset + 'url('.length);
|
|
916
|
+
range = Range.create(emptyURIValuePosition, emptyURIValuePosition);
|
|
917
|
+
}
|
|
918
|
+
else {
|
|
919
|
+
const uriValueNode = uriLiteralNode.getChild(0);
|
|
920
|
+
uriValue = uriValueNode.getText();
|
|
921
|
+
position = this.position;
|
|
922
|
+
range = this.getCompletionRange(uriValueNode);
|
|
923
|
+
}
|
|
924
|
+
this.completionParticipants.forEach(participant => {
|
|
925
|
+
if (participant.onCssURILiteralValue) {
|
|
926
|
+
participant.onCssURILiteralValue({
|
|
927
|
+
uriValue,
|
|
928
|
+
position,
|
|
929
|
+
range
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
});
|
|
933
|
+
return result;
|
|
934
|
+
}
|
|
935
|
+
getCompletionForImportPath(importPathNode, result) {
|
|
936
|
+
this.completionParticipants.forEach(participant => {
|
|
937
|
+
if (participant.onCssImportPath) {
|
|
938
|
+
participant.onCssImportPath({
|
|
939
|
+
pathValue: importPathNode.getText(),
|
|
940
|
+
position: this.position,
|
|
941
|
+
range: this.getCompletionRange(importPathNode)
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
});
|
|
945
|
+
return result;
|
|
946
|
+
}
|
|
947
|
+
hasCharacterAtPosition(offset, char) {
|
|
948
|
+
const text = this.textDocument.getText();
|
|
949
|
+
return (offset >= 0 && offset < text.length) && text.charAt(offset) === char;
|
|
950
|
+
}
|
|
951
|
+
doesSupportMarkdown() {
|
|
952
|
+
if (!isDefined(this.supportsMarkdown)) {
|
|
953
|
+
if (!isDefined(this.lsOptions.clientCapabilities)) {
|
|
954
|
+
this.supportsMarkdown = true;
|
|
955
|
+
return this.supportsMarkdown;
|
|
956
|
+
}
|
|
957
|
+
const documentationFormat = this.lsOptions.clientCapabilities.textDocument?.completion?.completionItem?.documentationFormat;
|
|
958
|
+
this.supportsMarkdown = Array.isArray(documentationFormat) && documentationFormat.indexOf(MarkupKind.Markdown) !== -1;
|
|
959
|
+
}
|
|
960
|
+
return this.supportsMarkdown;
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
function isDeprecated(entry) {
|
|
964
|
+
if (entry.status && (entry.status === 'nonstandard' || entry.status === 'obsolete')) {
|
|
965
|
+
return true;
|
|
966
|
+
}
|
|
967
|
+
return false;
|
|
968
|
+
}
|
|
969
|
+
class Set {
|
|
970
|
+
constructor() {
|
|
971
|
+
this.entries = {};
|
|
972
|
+
}
|
|
973
|
+
add(entry) {
|
|
974
|
+
this.entries[entry] = true;
|
|
975
|
+
}
|
|
976
|
+
remove(entry) {
|
|
977
|
+
delete this.entries[entry];
|
|
978
|
+
}
|
|
979
|
+
getEntries() {
|
|
980
|
+
return Object.keys(this.entries);
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
function moveCursorInsideParenthesis(text) {
|
|
984
|
+
return text.replace(/\(\)$/, "($1)");
|
|
985
|
+
}
|
|
986
|
+
function collectValues(styleSheet, declaration) {
|
|
987
|
+
const fullPropertyName = declaration.getFullPropertyName();
|
|
988
|
+
const entries = new Set();
|
|
989
|
+
function visitValue(node) {
|
|
990
|
+
if (node instanceof nodes.Identifier || node instanceof nodes.NumericValue || node instanceof nodes.HexColorValue) {
|
|
991
|
+
entries.add(node.getText());
|
|
992
|
+
}
|
|
993
|
+
return true;
|
|
994
|
+
}
|
|
995
|
+
function matchesProperty(decl) {
|
|
996
|
+
const propertyName = decl.getFullPropertyName();
|
|
997
|
+
return fullPropertyName === propertyName;
|
|
998
|
+
}
|
|
999
|
+
function vistNode(node) {
|
|
1000
|
+
if (node instanceof nodes.Declaration && node !== declaration) {
|
|
1001
|
+
if (matchesProperty(node)) {
|
|
1002
|
+
const value = node.getValue();
|
|
1003
|
+
if (value) {
|
|
1004
|
+
value.accept(visitValue);
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
return true;
|
|
1009
|
+
}
|
|
1010
|
+
styleSheet.accept(vistNode);
|
|
1011
|
+
return entries;
|
|
1012
|
+
}
|
|
1013
|
+
class ColorValueCollector {
|
|
1014
|
+
constructor(entries, currentOffset) {
|
|
1015
|
+
this.entries = entries;
|
|
1016
|
+
this.currentOffset = currentOffset;
|
|
1017
|
+
// nothing to do
|
|
1018
|
+
}
|
|
1019
|
+
visitNode(node) {
|
|
1020
|
+
if (node instanceof nodes.HexColorValue || (node instanceof nodes.Function && languageFacts.isColorConstructor(node))) {
|
|
1021
|
+
if (this.currentOffset < node.offset || node.end < this.currentOffset) {
|
|
1022
|
+
this.entries.add(node.getText());
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
return true;
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
class VariableCollector {
|
|
1029
|
+
constructor(entries, currentOffset) {
|
|
1030
|
+
this.entries = entries;
|
|
1031
|
+
this.currentOffset = currentOffset;
|
|
1032
|
+
// nothing to do
|
|
1033
|
+
}
|
|
1034
|
+
visitNode(node) {
|
|
1035
|
+
if (node instanceof nodes.Identifier && node.isCustomProperty) {
|
|
1036
|
+
if (this.currentOffset < node.offset || node.end < this.currentOffset) {
|
|
1037
|
+
this.entries.add(node.getText());
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
return true;
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
function getCurrentWord(document, offset) {
|
|
1044
|
+
let i = offset - 1;
|
|
1045
|
+
const text = document.getText();
|
|
1046
|
+
while (i >= 0 && ' \t\n\r":{[()]},*>+'.indexOf(text.charAt(i)) === -1) {
|
|
1047
|
+
i--;
|
|
1048
|
+
}
|
|
1049
|
+
return text.substring(i + 1, offset);
|
|
1050
|
+
}
|
|
1051
|
+
function isColorString(s) {
|
|
1052
|
+
// From https://stackoverflow.com/questions/8027423/how-to-check-if-a-string-is-a-valid-hex-color-representation/8027444
|
|
1053
|
+
return (s.toLowerCase() in languageFacts.colors) || /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(s);
|
|
1054
|
+
}
|