1
1
import * as path from 'path' ;
2
- import * as pkgConf from 'pkg-conf' ;
3
- import {
4
- ScriptTarget ,
5
- ModuleResolutionKind ,
6
- flattenDiagnosticMessageText ,
7
- CompilerOptions ,
8
- createProgram ,
9
- JsxEmit ,
10
- SyntaxKind ,
11
- SourceFile ,
12
- Diagnostic as TSDiagnostic
13
- } from 'typescript' ;
14
- import { Diagnostic , DiagnosticCode , Context , Position } from './interfaces' ;
2
+ import { flattenDiagnosticMessageText , createProgram , SyntaxKind , Diagnostic as TSDiagnostic , Program , SourceFile } from 'typescript' ;
3
+ import { Diagnostic , DiagnosticCode , Context , Location } from './interfaces' ;
15
4
16
5
// List of diagnostic codes that should be ignored
17
6
const ignoredDiagnostics = new Set < number > ( [
18
7
DiagnosticCode . AwaitIsOnlyAllowedInAsyncFunction
19
8
] ) ;
20
9
21
- const loadConfig = ( cwd : string ) : CompilerOptions => {
22
- const config = pkgConf . sync ( 'tsd-check' , {
23
- cwd,
24
- defaults : {
25
- compilerOptions : {
26
- strict : true ,
27
- jsx : JsxEmit . React ,
28
- target : ScriptTarget . ES2017
29
- }
30
- }
31
- } ) ;
32
-
33
- return {
34
- ...config . compilerOptions ,
35
- ...{
36
- moduleResolution : ModuleResolutionKind . NodeJs ,
37
- skipLibCheck : true
38
- }
39
- } ;
40
- } ;
10
+ const diagnosticCodesToIgnore = new Set < DiagnosticCode > ( [
11
+ DiagnosticCode . ArgumentTypeIsNotAssignableToParameterType ,
12
+ DiagnosticCode . PropertyDoesNotExistOnType ,
13
+ DiagnosticCode . CannotAssignToReadOnlyProperty
14
+ ] ) ;
41
15
42
16
/**
43
17
* Extract all the `expectError` statements and convert it to a range map.
44
18
*
45
- * @param sourceFile - File to extract the statements from .
19
+ * @param program - The TypeScript program .
46
20
*/
47
- const extractExpectErrorRanges = ( sourceFile : SourceFile ) => {
48
- const expectedErrors = new Map < Position , Pick < Diagnostic , 'fileName' | 'line' | 'column' > > ( ) ;
21
+ const extractExpectErrorRanges = ( program : Program ) => {
22
+ const expectedErrors = new Map < Location , Pick < Diagnostic , 'fileName' | 'line' | 'column' > > ( ) ;
49
23
50
- for ( const statement of sourceFile . statements ) {
51
- if ( statement . kind !== SyntaxKind . ExpressionStatement || ! statement . getText ( ) . startsWith ( 'expectError' ) ) {
52
- continue ;
53
- }
24
+ for ( const sourceFile of program . getSourceFiles ( ) ) {
25
+ for ( const statement of sourceFile . statements ) {
26
+ if ( statement . kind !== SyntaxKind . ExpressionStatement || ! statement . getText ( ) . startsWith ( 'expectError' ) ) {
27
+ continue ;
28
+ }
54
29
55
- const position = {
56
- start : statement . getStart ( ) ,
57
- end : statement . getEnd ( )
58
- } ;
30
+ const location = {
31
+ fileName : statement . getSourceFile ( ) . fileName ,
32
+ start : statement . getStart ( ) ,
33
+ end : statement . getEnd ( )
34
+ } ;
59
35
60
- const pos = statement . getSourceFile ( ) . getLineAndCharacterOfPosition ( statement . getStart ( ) ) ;
36
+ const pos = statement . getSourceFile ( ) . getLineAndCharacterOfPosition ( statement . getStart ( ) ) ;
61
37
62
- expectedErrors . set ( position , {
63
- fileName : statement . getSourceFile ( ) . fileName ,
64
- line : pos . line + 1 ,
65
- column : pos . character
66
- } ) ;
38
+ expectedErrors . set ( location , {
39
+ fileName : location . fileName ,
40
+ line : pos . line + 1 ,
41
+ column : pos . character
42
+ } ) ;
43
+ }
67
44
}
68
45
69
46
return expectedErrors ;
70
47
} ;
71
48
72
- const diagnosticCodesToIgnore = [
73
- DiagnosticCode . ArgumentTypeIsNotAssignableToParameterType ,
74
- DiagnosticCode . PropertyDoesNotExistOnType ,
75
- DiagnosticCode . CannotAssignToReadOnlyProperty
76
- ] ;
77
-
78
49
/**
79
50
* Check if the provided diagnostic should be ignored.
80
51
*
81
52
* @param diagnostic - The diagnostic to validate.
82
53
* @param expectedErrors - Map of the expected errors.
83
54
* @return Boolean indicating if the diagnostic should be ignored or not.
84
55
*/
85
- const ignoreDiagnostic = ( diagnostic : TSDiagnostic , expectedErrors : Map < Position , any > ) : boolean => {
56
+ const ignoreDiagnostic = ( diagnostic : TSDiagnostic , expectedErrors : Map < Location , any > ) : boolean => {
86
57
if ( ignoredDiagnostics . has ( diagnostic . code ) ) {
87
58
// Filter out diagnostics which are present in the `ignoredDiagnostics` set
88
59
return true ;
89
60
}
90
61
91
- if ( ! diagnosticCodesToIgnore . includes ( diagnostic . code ) ) {
62
+ if ( ! diagnosticCodesToIgnore . has ( diagnostic . code ) ) {
92
63
return false ;
93
64
}
94
65
95
- for ( const [ range ] of expectedErrors ) {
66
+ const diagnosticFileName = ( diagnostic . file as SourceFile ) . fileName ;
67
+
68
+ for ( const [ location ] of expectedErrors ) {
96
69
const start = diagnostic . start as number ;
97
70
98
- if ( start > range . start && start < range . end ) {
71
+ if ( diagnosticFileName === location . fileName && start > location . start && start < location . end ) {
99
72
// Remove the expected error from the Map so it's not being reported as failure
100
- expectedErrors . delete ( range ) ;
73
+ expectedErrors . delete ( location ) ;
101
74
return true ;
102
75
}
103
76
}
@@ -112,19 +85,17 @@ const ignoreDiagnostic = (diagnostic: TSDiagnostic, expectedErrors: Map<Position
112
85
* @returns List of diagnostics
113
86
*/
114
87
export const getDiagnostics = ( context : Context ) : Diagnostic [ ] => {
115
- const compilerOptions = loadConfig ( context . cwd ) ;
116
-
117
- const fileName = path . join ( context . cwd , context . testFile ) ;
88
+ const fileNames = context . testFiles . map ( fileName => path . join ( context . cwd , fileName ) ) ;
118
89
119
90
const result : Diagnostic [ ] = [ ] ;
120
91
121
- const program = createProgram ( [ fileName ] , compilerOptions ) ;
92
+ const program = createProgram ( fileNames , context . config . compilerOptions ) ;
122
93
123
94
const diagnostics = program
124
95
. getSemanticDiagnostics ( )
125
96
. concat ( program . getSyntacticDiagnostics ( ) ) ;
126
97
127
- const expectedErrors = extractExpectErrorRanges ( program . getSourceFile ( fileName ) as SourceFile ) ;
98
+ const expectedErrors = extractExpectErrorRanges ( program ) ;
128
99
129
100
for ( const diagnostic of diagnostics ) {
130
101
if ( ! diagnostic . file || ignoreDiagnostic ( diagnostic , expectedErrors ) ) {
0 commit comments