1
1
var eslint = require ( "eslint" )
2
2
var assign = require ( "object-assign" )
3
3
var loaderUtils = require ( "loader-utils" )
4
- var crypto = require ( "crypto" )
5
- var fs = require ( "fs" )
6
- var findCacheDir = require ( "find-cache-dir" )
7
4
var objectHash = require ( "object-hash" )
8
- var os = require ( "os" )
5
+ var pkg = require ( "./package.json" )
6
+ var createCache = require ( "loader-fs-cache" )
7
+ var cache = createCache ( "eslint-loader" )
9
8
10
9
var engines = { }
11
- var rules = { }
12
- var cache = null
13
- var cachePath = null
14
10
15
11
/**
16
- * linter
12
+ * printLinterOutput
17
13
*
18
- * @param {String|Buffer } input JavaScript string
14
+ * @param {Object } eslint.executeOnText return value
19
15
* @param {Object } config eslint configuration
20
16
* @param {Object } webpack webpack instance
21
17
* @return {void }
22
18
*/
23
- function lint ( input , config , webpack ) {
24
- var resourcePath = webpack . resourcePath
25
- var cwd = process . cwd ( )
26
-
27
- // remove cwd from resource path in case webpack has been started from project
28
- // root, to allow having relative paths in .eslintignore
29
- if ( resourcePath . indexOf ( cwd ) === 0 ) {
30
- resourcePath = resourcePath . substr ( cwd . length + 1 )
31
- }
32
-
33
- // get engine
34
- var configHash = objectHash ( config )
35
- var engine = engines [ configHash ]
36
- var rulesHash = rules [ configHash ]
37
-
38
- var res
39
- // If cache is enable and the data are the same as in the cache, just
40
- // use them
41
- if ( config . cache ) {
42
- // just get rules hash once per engine for performance reasons
43
- if ( ! rulesHash ) {
44
- rulesHash = objectHash ( engine . getConfigForFile ( resourcePath ) )
45
- rules [ configHash ] = rulesHash
46
- }
47
- var inputMD5 = crypto . createHash ( "md5" ) . update ( input ) . digest ( "hex" )
48
- if (
49
- cache [ resourcePath ] &&
50
- cache [ resourcePath ] . hash === inputMD5 &&
51
- cache [ resourcePath ] . rules === rulesHash
52
- ) {
53
- res = cache [ resourcePath ] . res
54
- }
55
- }
56
-
57
- // Re-lint the text if the cache off or miss
58
- if ( ! res ) {
59
- res = engine . executeOnText ( input , resourcePath , true )
60
-
61
- // Save new results in the cache
62
- if ( config . cache ) {
63
- cache [ resourcePath ] = {
64
- hash : inputMD5 ,
65
- rules : rulesHash ,
66
- res : res ,
67
- }
68
- fs . writeFileSync ( cachePath , JSON . stringify ( cache ) )
69
- }
70
- }
71
-
72
- // executeOnText ensure we will have res.results[0] only
73
-
19
+ function printLinterOutput ( res , config , webpack ) {
74
20
// skip ignored file warning
75
- if ( ! (
76
- res . warningCount === 1 &&
77
- res . results [ 0 ] . messages [ 0 ] &&
78
- res . results [ 0 ] . messages [ 0 ] . message &&
79
- res . results [ 0 ] . messages [ 0 ] . message . indexOf ( "ignore" ) > 1
80
- ) ) {
21
+ if (
22
+ ! ( res . warningCount === 1 &&
23
+ res . results [ 0 ] . messages [ 0 ] &&
24
+ res . results [ 0 ] . messages [ 0 ] . message &&
25
+ res . results [ 0 ] . messages [ 0 ] . message . indexOf ( "ignore" ) > 1 )
26
+ ) {
81
27
// quiet filter done now
82
28
// eslint allow rules to be specified in the input between comments
83
29
// so we can found warnings defined in the input itself
84
30
if ( res . warningCount && config . quiet ) {
85
31
res . warningCount = 0
86
32
res . results [ 0 ] . warningCount = 0
87
- res . results [ 0 ] . messages = res . results [ 0 ] . messages
88
- . filter ( function ( message ) {
89
- return message . severity !== 1
90
- } )
33
+ res . results [ 0 ] . messages = res . results [ 0 ] . messages . filter ( function (
34
+ message
35
+ ) {
36
+ return message . severity !== 1
37
+ } )
91
38
}
92
39
93
40
// if enabled, use eslint auto-fixing where possible
@@ -128,19 +75,21 @@ function lint(input, config, webpack) {
128
75
if ( emitter ) {
129
76
emitter ( messages )
130
77
if ( config . failOnError && res . errorCount ) {
131
- throw new Error ( "Module failed because of a eslint error.\n"
132
- + messages )
78
+ throw new Error (
79
+ "Module failed because of a eslint error.\n" + messages
80
+ )
133
81
}
134
82
else if ( config . failOnWarning && res . warningCount ) {
135
- throw new Error ( "Module failed because of a eslint warning.\n"
136
- + messages )
83
+ throw new Error (
84
+ "Module failed because of a eslint warning.\n" + messages
85
+ )
137
86
}
138
87
}
139
88
else {
140
89
throw new Error (
141
90
"Your module system doesn't support emitWarning. " +
142
- "Update available? \n" +
143
- messages
91
+ "Update available? \n" +
92
+ messages
144
93
)
145
94
}
146
95
}
@@ -155,45 +104,78 @@ function lint(input, config, webpack) {
155
104
* @return {void }
156
105
*/
157
106
module . exports = function ( input , map ) {
107
+ var webpack = this
108
+
158
109
var config = assign (
159
110
// loader defaults
160
111
{
161
112
formatter : require ( "eslint/lib/formatters/stylish" ) ,
113
+ cacheIdentifier : JSON . stringify ( {
114
+ "eslint-loader" : pkg . version ,
115
+ eslint : eslint . version ,
116
+ config : configHash ,
117
+ } ) ,
162
118
} ,
163
119
// user defaults
164
- this . options . eslint || { } ,
120
+ webpack . options . eslint || { } ,
165
121
// loader query string
166
- loaderUtils . getOptions ( this )
122
+ loaderUtils . getOptions ( webpack )
167
123
)
168
- this . cacheable ( )
169
-
170
124
// Create the engine only once per config
171
125
var configHash = objectHash ( config )
172
126
if ( ! engines [ configHash ] ) {
173
127
engines [ configHash ] = new eslint . CLIEngine ( config )
174
128
}
175
129
176
- // Read the cached information only once and if enable
177
- if ( cache === null ) {
178
- if ( config . cache ) {
179
- var thunk = findCacheDir ( {
180
- name : "eslint-loader" ,
181
- thunk : true ,
182
- create : true ,
183
- } )
184
- cachePath = thunk ( "data.json" ) || os . tmpdir ( ) + "/data.json"
185
- try {
186
- cache = require ( cachePath )
187
- }
188
- catch ( e ) {
189
- cache = { }
130
+ var cacheDirectory = config . cacheDirectory
131
+ var cacheIdentifier = config . cacheIdentifier
132
+
133
+ delete config . cacheDirectory
134
+ delete config . cacheIdentifier
135
+
136
+ webpack . cacheable ( )
137
+
138
+ var resourcePath = webpack . resourcePath
139
+ var cwd = process . cwd ( )
140
+
141
+ // remove cwd from resource path in case webpack has been started from project
142
+ // root, to allow having relative paths in .eslintignore
143
+ if ( resourcePath . indexOf ( cwd ) === 0 ) {
144
+ resourcePath = resourcePath . substr ( cwd . length + 1 )
145
+ }
146
+
147
+ var engine = engines [ configHash ]
148
+ // return early if cached
149
+ if ( config . cache ) {
150
+ var callback = webpack . async ( )
151
+ return cache (
152
+ {
153
+ directory : cacheDirectory ,
154
+ identifier : cacheIdentifier ,
155
+ options : config ,
156
+ transform : function ( ) {
157
+ return lint ( engine , input , resourcePath )
158
+ } ,
159
+ } ,
160
+ function ( err , res ) {
161
+ if ( err ) {
162
+ return callback ( err )
163
+ }
164
+ //eslint-disable-next-line
165
+ console . log ( lint ( engine , input , resourcePath ) ) ;
166
+ printLinterOutput (
167
+ res || lint ( engine , input , resourcePath ) ,
168
+ config ,
169
+ webpack
170
+ )
171
+ return callback ( null , input , map )
190
172
}
191
- }
192
- else {
193
- cache = false
194
- }
173
+ )
195
174
}
175
+ printLinterOutput ( lint ( engine , input , resourcePath ) , config , webpack )
176
+ webpack . callback ( input , map )
177
+ }
196
178
197
- lint ( input , config , this )
198
- this . callback ( null , input , map )
179
+ function lint ( engine , input , resourcePath ) {
180
+ return engine . executeOnText ( input , resourcePath , true )
199
181
}
0 commit comments