6
6
TextEdit ,
7
7
} from 'vscode-languageserver'
8
8
import { State } from '../../util/state'
9
- import { findLast } from '../../util/find'
10
9
import { isWithinRange } from '../../util/isWithinRange'
11
10
import { getClassNameParts } from '../../util/getClassNameAtPosition'
12
11
const dlv = require ( 'dlv' )
@@ -31,6 +30,9 @@ import {
31
30
} from '../diagnostics/types'
32
31
import { flatten , dedupeBy } from '../../../util/array'
33
32
import { joinWithAnd } from '../../util/joinWithAnd'
33
+ import { getLanguageBoundaries } from '../../util/getLanguageBoundaries'
34
+ import { isCssDoc } from '../../util/css'
35
+ import { absoluteRange } from '../../util/absoluteRange'
34
36
35
37
async function getDiagnosticsFromCodeActionParams (
36
38
state : State ,
@@ -210,61 +212,76 @@ async function provideInvalidApplyCodeActions(
210
212
) : Promise < CodeAction [ ] > {
211
213
let document = state . editor . documents . get ( params . textDocument . uri )
212
214
let documentText = document . getText ( )
215
+ let cssRange : Range
216
+ let cssText = documentText
213
217
const { postcss } = state . modules
214
218
let change : TextEdit
215
219
216
220
let totalClassNamesInClassList = diagnostic . className . classList . classList . split (
217
221
/ \s + /
218
222
) . length
219
223
220
- await postcss ( [
221
- postcss . plugin ( '' , ( _options = { } ) => {
222
- return ( root ) => {
223
- root . walkRules ( ( rule ) => {
224
- if ( change ) return false
224
+ if ( ! isCssDoc ( state , document ) ) {
225
+ let languageBoundaries = getLanguageBoundaries ( state , document )
226
+ if ( ! languageBoundaries ) return [ ]
227
+ cssRange = languageBoundaries . css . find ( ( range ) =>
228
+ isWithinRange ( diagnostic . range . start , range )
229
+ )
230
+ if ( ! cssRange ) return [ ]
231
+ cssText = document . getText ( cssRange )
232
+ }
225
233
226
- rule . walkAtRules ( 'apply' , ( atRule ) => {
227
- let { start, end } = atRule . source
228
- let range : Range = {
229
- start : {
230
- line : start . line - 1 ,
231
- character : start . column - 1 ,
232
- } ,
233
- end : {
234
- line : end . line - 1 ,
235
- character : end . column - 1 ,
236
- } ,
237
- }
234
+ try {
235
+ await postcss ( [
236
+ postcss . plugin ( '' , ( _options = { } ) => {
237
+ return ( root ) => {
238
+ root . walkRules ( ( rule ) => {
239
+ if ( change ) return false
240
+
241
+ rule . walkAtRules ( 'apply' , ( atRule ) => {
242
+ let { start, end } = atRule . source
243
+ let atRuleRange : Range = {
244
+ start : {
245
+ line : start . line - 1 ,
246
+ character : start . column - 1 ,
247
+ } ,
248
+ end : {
249
+ line : end . line - 1 ,
250
+ character : end . column - 1 ,
251
+ } ,
252
+ }
253
+ if ( cssRange ) {
254
+ atRuleRange = absoluteRange ( atRuleRange , cssRange )
255
+ }
238
256
239
- if ( ! isWithinRange ( diagnostic . range . start , range ) ) {
240
- // keep looking
241
- return true
242
- }
257
+ if ( ! isWithinRange ( diagnostic . range . start , atRuleRange ) ) {
258
+ // keep looking
259
+ return true
260
+ }
243
261
244
- let className = document . getText ( diagnostic . range )
245
- let ast = classNameToAst (
246
- state ,
247
- className ,
248
- rule . selector ,
249
- diagnostic . className . classList . important
250
- )
262
+ let className = diagnostic . className . className
263
+ let ast = classNameToAst (
264
+ state ,
265
+ className ,
266
+ rule . selector ,
267
+ diagnostic . className . classList . important
268
+ )
251
269
252
- if ( ! ast ) {
253
- return false
254
- }
270
+ if ( ! ast ) {
271
+ return false
272
+ }
255
273
256
- rule . after ( ast . nodes )
257
- let insertedRule = rule . next ( )
274
+ rule . after ( ast . nodes )
275
+ let insertedRule = rule . next ( )
258
276
259
- if ( totalClassNamesInClassList === 1 ) {
260
- atRule . remove ( )
261
- }
277
+ if ( totalClassNamesInClassList === 1 ) {
278
+ atRule . remove ( )
279
+ }
262
280
263
- let outputIndent : string
264
- let documentIndent = detectIndent ( documentText )
281
+ let outputIndent : string
282
+ let documentIndent = detectIndent ( documentText )
265
283
266
- change = {
267
- range : {
284
+ let ruleRange : Range = {
268
285
start : {
269
286
line : rule . source . start . line - 1 ,
270
287
character : rule . source . start . column - 1 ,
@@ -273,30 +290,39 @@ async function provideInvalidApplyCodeActions(
273
290
line : rule . source . end . line - 1 ,
274
291
character : rule . source . end . column ,
275
292
} ,
276
- } ,
277
- newText :
278
- rule . toString ( ) +
279
- ( insertedRule . raws . before || '\n\n' ) +
280
- insertedRule
281
- . toString ( )
282
- . replace ( / \n \s * \n / g, '\n' )
283
- . replace ( / ( @ a p p l y [ ^ ; \n ] + ) $ / gm, '$1;' )
284
- . replace ( / ( [ ^ \s ^ ] ) { $ / gm, '$1 {' )
285
- . replace ( / ^ \s + / gm, ( m : string ) => {
286
- if ( typeof outputIndent === 'undefined' ) outputIndent = m
287
- return m . replace (
288
- new RegExp ( outputIndent , 'g' ) ,
289
- documentIndent . indent
290
- )
291
- } ) ,
292
- }
293
+ }
294
+ if ( cssRange ) {
295
+ ruleRange = absoluteRange ( ruleRange , cssRange )
296
+ }
297
+
298
+ change = {
299
+ range : ruleRange ,
300
+ newText :
301
+ rule . toString ( ) +
302
+ ( insertedRule . raws . before || '\n\n' ) +
303
+ insertedRule
304
+ . toString ( )
305
+ . replace ( / \n \s * \n / g, '\n' )
306
+ . replace ( / ( @ a p p l y [ ^ ; \n ] + ) $ / gm, '$1;' )
307
+ . replace ( / ( [ ^ \s ^ ] ) { $ / gm, '$1 {' )
308
+ . replace ( / ^ \s + / gm, ( m : string ) => {
309
+ if ( typeof outputIndent === 'undefined' ) outputIndent = m
310
+ return m . replace (
311
+ new RegExp ( outputIndent , 'g' ) ,
312
+ documentIndent . indent
313
+ )
314
+ } ) ,
315
+ }
293
316
294
- return false
317
+ return false
318
+ } )
295
319
} )
296
- } )
297
- }
298
- } ) ,
299
- ] ) . process ( documentText , { from : undefined } )
320
+ }
321
+ } ) ,
322
+ ] ) . process ( cssText , { from : undefined } )
323
+ } catch ( _ ) {
324
+ return [ ]
325
+ }
300
326
301
327
if ( ! change ) {
302
328
return [ ]
0 commit comments