@@ -29,16 +29,17 @@ export type Mapper = {
29
29
*/
30
30
rangeForNode : ( node : AST . Node , span ?: AST . Node [ 'loc' ] ) => Range ;
31
31
32
+ /**
33
+ * Given a 0-based line number, returns the corresponding start and
34
+ * end offsets for that line.
35
+ */
36
+ rangeForLine : ( line : number ) => Range ;
37
+
32
38
/**
33
39
* Captures the existence of a directive specified by the given source
34
40
* node and affecting the given range of text.
35
41
*/
36
- directive : (
37
- commentNode : AST . CommentStatement | AST . MustacheCommentStatement ,
38
- type : DirectiveKind ,
39
- ) => void ;
40
-
41
- // directiveTerminatingExpression: (location: Range) => void;
42
+ directive : ( type : DirectiveKind , location : Range , areaOfEffect : Range ) => void ;
42
43
43
44
/**
44
45
* Records an error at the given location.
@@ -87,14 +88,6 @@ export type Mapper = {
87
88
callback : ( ) => void ,
88
89
codeFeaturesForNode ?: CodeInformation ,
89
90
) : void ;
90
-
91
- /**
92
- * This needs to be called after any node that "consumes" a `glint-expect-error` directive.
93
- * This essentially marks the end of the area of effect for the directive; this helps us
94
- * filter out the "unused ts-expect-error" placeholder diagnostic if, in fact, an error
95
- * diagnostic was reported within the directive's area of effect.
96
- */
97
- terminateDirectiveAreaOfEffect ( endStr : string ) : void ;
98
91
} ;
99
92
100
93
type LocalDirective = Omit < Directive , 'source' > ;
@@ -184,13 +177,6 @@ export function mapTemplateContents(
184
177
} ) ;
185
178
186
179
let ignoreErrors = false ;
187
- let isNoCheckDirectivePresent = false ;
188
- let expectErrorToken :
189
- | {
190
- numErrors : number ;
191
- commentNode : AST . CommentStatement | AST . MustacheCommentStatement ;
192
- }
193
- | undefined ;
194
180
195
181
// Associates all content emitted during the given callback with the
196
182
// given range in the template source and corresponding AST node.
@@ -269,23 +255,6 @@ export function mapTemplateContents(
269
255
verification : false ,
270
256
} ;
271
257
}
272
-
273
- if ( expectErrorToken ) {
274
- // We are currently in a region of code covered by a @glint -expect-error directive. We need to
275
- // keep track of the number of errors encountered within this region so that we can know whether
276
- // we will need to propagate an "unused ts-expect-error" diagnostic back to the original
277
- // .gts file or not.
278
- const token = expectErrorToken ;
279
- return {
280
- ...features ,
281
- verification : {
282
- shouldReport : ( ) => {
283
- token . numErrors ++ ;
284
- return false ;
285
- } ,
286
- } ,
287
- } ;
288
- }
289
258
}
290
259
return features ;
291
260
}
@@ -335,112 +304,16 @@ export function mapTemplateContents(
335
304
errors . push ( { message, location } ) ;
336
305
} ,
337
306
338
- directive (
339
- commentNode : AST . CommentStatement | AST . MustacheCommentStatement ,
340
- kind : DirectiveKind ,
341
- ) {
342
- if ( kind === 'expect-error' ) {
343
- if ( ! expectErrorToken ) {
344
- mapper . text ( `// @glint-expect-error BEGIN AREA_OF_EFFECT` ) ;
345
- mapper . newline ( ) ;
346
- }
347
-
348
- expectErrorToken = {
349
- numErrors : 0 ,
350
- commentNode,
351
- } ;
352
- }
353
-
354
- if ( kind === 'ignore' ) {
355
- ignoreErrors = true ;
356
- mapper . text ( `// @glint-ignore BEGIN AREA_OF_EFFECT` ) ;
357
- mapper . newline ( ) ;
358
- }
359
-
360
- if ( kind === 'nocheck' ) {
361
- ignoreErrors = true ;
362
- isNoCheckDirectivePresent = true ;
363
- mapper . text ( `// @glint-nocheck` ) ;
364
- mapper . newline ( ) ;
365
- }
366
-
367
- directives . push ( { kind } ) ;
368
- } ,
369
-
370
- terminateDirectiveAreaOfEffect ( endStr : string ) {
371
- if ( expectErrorToken ) {
372
- // There is an active "@glint-expect-error" directive whose
373
- // are of effect we need to terminate.
374
- //
375
- // There is a somewhat delicate order in which everything below needs to happen,
376
- // but here is an outline:
377
- //
378
- // 1. Volar will call the `shouldReport` function of the `verification` object
379
- // of the `CodeInformation` object that we pass along with each mapping for
380
- // every diagnostic reported by TS within the transformed region of code.
381
- //
382
- // 2. This callback's main job is to return a boolean indicating whether we
383
- // should propagate TS diagnostics within the transformed region of code
384
- // back to search (e.g. the original .gts file). But in addition to that we are somewhat
385
- // hackishly using `shouldReport` to track the number of errors encountered
386
- // within the directive's area of effect so that we can later determine
387
- // whether to filter out the "unused ts-expect-error" placeholder diagnostic
388
- // that we emit below.
389
- //
390
- // 3. The first `shouldReport` that gets called by Volar is in `resolveCodeFeatures`;
391
- // this implementation of `shouldReport` increments `numErrors` for each diagnostic
392
- // found in the region.
393
- //
394
- // 4. The second `shouldReport` that gets called is below: we emit a
395
- // `// @ts-expect-error GLINT_PLACEHOLDER` diagnostic that is always triggering
396
- // within the transformed code, and we use `shouldReport` to decide whether
397
- // to filter out that diagnostic or not.
398
- //
399
- // This approach was taken from Vue tooling; it is complicated but it solves the problem
400
- // of keeping the code transform static while keeping all of the dynamic/stateful
401
- // error tracking and filtering logic in `shouldReport` callbacks.
402
- const token = expectErrorToken ;
403
-
404
- mapper . newline ( ) ;
405
-
406
- // 1. Emit a ts-expect-error this is guaranteed to trigger within the generated TS code
407
- // because we immediately follow it up with an empty semi-colon statement.
408
- // 2. Map it back to the original `{{ @glint -expect-error }}` comment node in the source.
409
- mapper . forNode (
410
- token . commentNode ,
411
- ( ) => {
412
- mapper . text ( `// @ts-expect-error GLINT_PLACEHOLDER` ) ;
413
- } ,
414
- {
415
- verification : {
416
- // If no diagnostic errors were encountered within the area of effect,
417
- // then filter out the "unused ts-expect-error" diagnostic triggered by our
418
- // placeholder @ts -expect-error
419
- shouldReport : ( ) => token . numErrors === 0 ,
420
- } ,
421
- } ,
422
- ) ;
423
-
424
- // Make the above placeholder diagnostic trigger an "unused ts-expect-error" diagnostic
425
- // by introducing an error-less empty semi-colon statement.
426
- mapper . newline ( ) ;
427
- mapper . text ( ';' ) ;
428
- mapper . newline ( ) ;
429
-
430
- expectErrorToken = undefined ;
431
-
432
- mapper . text ( `// @glint-expect-error END AREA_OF_EFFECT for ${ endStr } ` ) ;
433
- mapper . newline ( ) ;
434
- }
435
-
436
- if ( ignoreErrors && ! isNoCheckDirectivePresent ) {
437
- ignoreErrors = false ;
438
- mapper . text ( `// @glint-ignore END AREA_OF_EFFECT for ${ endStr } ` ) ;
439
- mapper . newline ( ) ;
440
- }
307
+ directive ( kind : DirectiveKind , location : Range , areaOfEffect : Range ) {
308
+ directives . push ( { kind, location, areaOfEffect } ) ;
441
309
} ,
442
310
443
311
rangeForNode : buildRangeForNode ( lineOffsets ) ,
312
+
313
+ rangeForLine : ( line : number ) : Range => ( {
314
+ start : lineOffsets [ line ] ,
315
+ end : lineOffsets [ line + 1 ] ?? template . length ,
316
+ } ) ,
444
317
} ;
445
318
446
319
callback ( ast , mapper ) ;
0 commit comments