@@ -2,7 +2,9 @@ import ts = require('typescript');
2
2
import path = require( 'path' ) ;
3
3
import type config = require( '@tsslint/config' ) ;
4
4
import core = require( '@tsslint/core' ) ;
5
+ import cache = require( './lib/cache' ) ;
5
6
import glob = require( 'glob' ) ;
7
+ import fs = require( 'fs' ) ;
6
8
7
9
( async ( ) => {
8
10
@@ -79,13 +81,16 @@ import glob = require('glob');
79
81
const tsconfig = await getTsconfigPath ( tsconfigOption ) ;
80
82
const configFile = ts . findConfigFile ( path . dirname ( tsconfig ) , ts . sys . fileExists , 'tsslint.config.ts' ) ;
81
83
82
- log . step ( `Project: ${ path . relative ( process . cwd ( ) , tsconfig ) } (${ parseCommonLine ( tsconfig ) . fileNames . length } files)` ) ;
83
-
84
84
if ( ! configFile ) {
85
+ log . step ( `Project: ${ path . relative ( process . cwd ( ) , tsconfig ) } ` ) ;
85
86
log . error ( 'No tsslint.config.ts file found!' ) ;
86
87
return ;
87
88
}
88
89
90
+ parsed = parseCommonLine ( tsconfig ) ;
91
+
92
+ log . step ( `Project: ${ path . relative ( process . cwd ( ) , tsconfig ) } (${ parsed . fileNames . length } files)` ) ;
93
+
89
94
if ( ! configs . has ( configFile ) ) {
90
95
try {
91
96
configs . set ( configFile , await core . buildConfigFile ( configFile , ts . sys . createHash , {
@@ -103,24 +108,47 @@ import glob = require('glob');
103
108
return ;
104
109
}
105
110
106
- parsed = parseCommonLine ( tsconfig ) ;
107
111
if ( ! parsed . fileNames ) {
108
112
throw new Error ( 'No input files found in tsconfig!' ) ;
109
113
}
110
114
projectVersion ++ ;
111
115
typeRootsVersion ++ ;
112
116
113
- const linter = core . createLinter ( {
117
+ const lintCache = process . argv . includes ( '--force' )
118
+ ? { }
119
+ : cache . loadCache ( configFile , ts . sys . createHash ) ;
120
+ const projectContext : config . ProjectContext = {
114
121
configFile,
115
122
languageService,
116
123
languageServiceHost,
117
124
typescript : ts ,
118
125
tsconfig : ts . server . toNormalizedPath ( tsconfig ) ,
119
- } , tsslintConfig , false ) ;
126
+ } ;
127
+ const linter = core . createLinter ( projectContext , tsslintConfig , 'cli' ) ;
120
128
121
129
let hasFix = false ;
130
+ let cached = 0 ;
122
131
123
132
for ( const fileName of parsed . fileNames ) {
133
+
134
+ const fileMtime = fs . statSync ( fileName ) . mtimeMs ;
135
+ let fileCache = lintCache [ fileName ] ;
136
+ if ( fileCache ) {
137
+ if ( fileCache [ 0 ] !== fileMtime ) {
138
+ fileCache [ 0 ] = fileMtime ;
139
+ fileCache [ 1 ] = { } ;
140
+ fileCache [ 2 ] . length = 0 ;
141
+ fileCache [ 3 ] . length = 0 ;
142
+ fileCache [ 4 ] = { } ;
143
+ }
144
+ else {
145
+ cached ++ ;
146
+ }
147
+ }
148
+ else {
149
+ lintCache [ fileName ] = fileCache = [ fileMtime , { } , [ ] , [ ] , { } ] ;
150
+ }
151
+
124
152
if ( process . argv . includes ( '--fix' ) ) {
125
153
126
154
let retry = 3 ;
@@ -130,8 +158,14 @@ import glob = require('glob');
130
158
while ( shouldRetry && retry ) {
131
159
shouldRetry = false ;
132
160
retry -- ;
133
- const diagnostics = linter . lint ( fileName ) ;
134
- const fixes = linter . getCodeFixes ( fileName , 0 , Number . MAX_VALUE , diagnostics ) ;
161
+ if ( Object . values ( fileCache [ 1 ] ) . some ( fixes => fixes > 0 ) ) {
162
+ // Reset the cache if there are any fixes applied.
163
+ fileCache [ 1 ] = { } ;
164
+ fileCache [ 2 ] . length = 0 ;
165
+ fileCache [ 3 ] . length = 0 ;
166
+ }
167
+ const diagnostics = linter . lint ( fileName , fileCache ) ;
168
+ const fixes = linter . getCodeFixes ( fileName , 0 , Number . MAX_VALUE , diagnostics , fileCache ) ;
135
169
const textChanges = core . combineCodeFixes ( fileName , fixes ) ;
136
170
if ( textChanges . length ) {
137
171
const oldSnapshot = snapshots . get ( fileName ) ! ;
@@ -145,10 +179,11 @@ import glob = require('glob');
145
179
146
180
if ( newSnapshot ) {
147
181
ts . sys . writeFile ( fileName , newSnapshot . getText ( 0 , newSnapshot . getLength ( ) ) ) ;
182
+ fileCache [ 0 ] = fs . statSync ( fileName ) . mtimeMs ;
148
183
}
149
184
}
150
185
else {
151
- const diagnostics = linter . lint ( fileName ) ;
186
+ const diagnostics = linter . lint ( fileName , fileCache ) ;
152
187
for ( const diagnostic of diagnostics ) {
153
188
if ( diagnostic . category === ts . DiagnosticCategory . Suggestion ) {
154
189
continue ;
@@ -176,6 +211,12 @@ import glob = require('glob');
176
211
}
177
212
}
178
213
214
+ cache . saveCache ( configFile , lintCache , ts . sys . createHash ) ;
215
+
216
+ if ( cached ) {
217
+ log . info ( `Linted ${ parsed . fileNames . length - cached } files. (Cached ${ cached } files result, use --force to re-lint all files.)` ) ;
218
+ }
219
+
179
220
if ( hasFix ) {
180
221
log . info ( `Use --fix to apply fixes.` ) ;
181
222
}
0 commit comments