4
4
Diagnostic as TSDiagnostic ,
5
5
SourceFile
6
6
} from '@tsd/typescript' ;
7
- import { extractAssertions , parseErrorAssertionToLocation } from './parser' ;
7
+ import { ExpectedError , extractAssertions , parseErrorAssertionToLocation } from './parser' ;
8
8
import { Diagnostic , DiagnosticCode , Context , Location } from './interfaces' ;
9
9
import { handle } from './assertions' ;
10
10
@@ -30,21 +30,28 @@ const expectErrordiagnosticCodesToIgnore = new Set<DiagnosticCode>([
30
30
DiagnosticCode . ThisContextOfTypeNotAssignableToMethodOfThisType
31
31
] ) ;
32
32
33
+ type IgnoreDiagnosticResult = 'preserve' | 'ignore' | Location ;
34
+
33
35
/**
34
36
* Check if the provided diagnostic should be ignored.
35
37
*
36
38
* @param diagnostic - The diagnostic to validate.
37
39
* @param expectedErrors - Map of the expected errors.
38
- * @returns Boolean indicating if the diagnostic should be ignored or not.
40
+ * @returns Whether the diagnostic should be `'preserve'`d, `'ignore'`d or, in case that
41
+ * the diagnostic is reported from inside of an `expectError` assertion, the `Location`
42
+ * of the assertion.
39
43
*/
40
- const ignoreDiagnostic = ( diagnostic : TSDiagnostic , expectedErrors : Map < Location , any > ) : boolean => {
44
+ const ignoreDiagnostic = (
45
+ diagnostic : TSDiagnostic ,
46
+ expectedErrors : Map < Location , ExpectedError >
47
+ ) : IgnoreDiagnosticResult => {
41
48
if ( ignoredDiagnostics . has ( diagnostic . code ) ) {
42
49
// Filter out diagnostics which are present in the `ignoredDiagnostics` set
43
- return true ;
50
+ return 'ignore' ;
44
51
}
45
52
46
53
if ( ! expectErrordiagnosticCodesToIgnore . has ( diagnostic . code ) ) {
47
- return false ;
54
+ return 'preserve' ;
48
55
}
49
56
50
57
const diagnosticFileName = ( diagnostic . file as SourceFile ) . fileName ;
@@ -53,13 +60,11 @@ const ignoreDiagnostic = (diagnostic: TSDiagnostic, expectedErrors: Map<Location
53
60
const start = diagnostic . start as number ;
54
61
55
62
if ( diagnosticFileName === location . fileName && start > location . start && start < location . end ) {
56
- // Remove the expected error from the Map so it's not being reported as failure
57
- expectedErrors . delete ( location ) ;
58
- return true ;
63
+ return location ;
59
64
}
60
65
}
61
66
62
- return false ;
67
+ return 'preserve' ;
63
68
} ;
64
69
65
70
/**
@@ -82,9 +87,20 @@ export const getDiagnostics = (context: Context): Diagnostic[] => {
82
87
diagnostics . push ( ...handle ( program . getTypeChecker ( ) , assertions ) ) ;
83
88
84
89
const expectedErrors = parseErrorAssertionToLocation ( assertions ) ;
90
+ const expectedErrorsLocationsWithFoundDiagnostics : Location [ ] = [ ] ;
85
91
86
92
for ( const diagnostic of tsDiagnostics ) {
87
- if ( ! diagnostic . file || ignoreDiagnostic ( diagnostic , expectedErrors ) ) {
93
+ if ( ! diagnostic . file ) {
94
+ continue ;
95
+ }
96
+
97
+ const ignoreDiagnosticResult = ignoreDiagnostic ( diagnostic , expectedErrors ) ;
98
+
99
+ if ( ignoreDiagnosticResult !== 'preserve' ) {
100
+ if ( ignoreDiagnosticResult !== 'ignore' ) {
101
+ expectedErrorsLocationsWithFoundDiagnostics . push ( ignoreDiagnosticResult ) ;
102
+ }
103
+
88
104
continue ;
89
105
}
90
106
@@ -99,6 +115,10 @@ export const getDiagnostics = (context: Context): Diagnostic[] => {
99
115
} ) ;
100
116
}
101
117
118
+ for ( const errorLocationToRemove of expectedErrorsLocationsWithFoundDiagnostics ) {
119
+ expectedErrors . delete ( errorLocationToRemove ) ;
120
+ }
121
+
102
122
for ( const [ , diagnostic ] of expectedErrors ) {
103
123
diagnostics . push ( {
104
124
...diagnostic ,
0 commit comments