@@ -3,12 +3,19 @@ extern crate napi;
3
3
#[ macro_use]
4
4
extern crate napi_derive;
5
5
6
- use deno_lint:: diagnostic:: LintDiagnostic ;
7
- use deno_lint:: linter:: LinterBuilder ;
8
- use napi:: { CallContext , Error , JsBuffer , JsObject , JsString , Module , Result , Status } ;
6
+ use napi:: JsBoolean ;
7
+ use std:: env;
9
8
use std:: fmt;
9
+ use std:: fs;
10
10
use std:: io:: Write ;
11
11
use std:: str;
12
+
13
+ use deno_lint:: diagnostic:: LintDiagnostic ;
14
+ use deno_lint:: linter:: LinterBuilder ;
15
+ use ignore:: overrides:: OverrideBuilder ;
16
+ use ignore:: types:: TypesBuilder ;
17
+ use ignore:: WalkBuilder ;
18
+ use napi:: { CallContext , Error , JsBuffer , JsObject , JsString , Module , Result , Status } ;
12
19
use termcolor:: Color :: { Ansi256 , Red } ;
13
20
use termcolor:: { Ansi , ColorSpec , WriteColor } ;
14
21
@@ -102,6 +109,7 @@ pub fn format_diagnostic(diagnostic: &LintDiagnostic) -> String {
102
109
103
110
fn init ( js_module : & mut Module ) -> Result < ( ) > {
104
111
js_module. create_named_method ( "lint" , lint) ?;
112
+ js_module. create_named_method ( "denolint" , lint_command) ?;
105
113
106
114
Ok ( ( ) )
107
115
}
@@ -117,11 +125,13 @@ fn lint(ctx: CallContext) -> Result<JsObject> {
117
125
reason : format ! ( "Input source is not valid utf8 string {}" , e) ,
118
126
} ) ?;
119
127
128
+ let file_name_ref = file_name. as_str ( ) ?;
129
+
120
130
let file_diagnostics = linter
121
- . lint ( file_name . as_str ( ) ? . to_owned ( ) , source_string. to_owned ( ) )
131
+ . lint ( file_name_ref . to_owned ( ) , source_string. to_owned ( ) )
122
132
. map_err ( |e| Error {
123
133
status : Status :: GenericFailure ,
124
- reason : format ! ( "Lint failed: {}" , e) ,
134
+ reason : format ! ( "Lint failed: {}, at: {} " , e, file_name_ref ) ,
125
135
} ) ?;
126
136
127
137
let mut result = ctx. env . create_array_with_length ( file_diagnostics. len ( ) ) ?;
@@ -137,3 +147,93 @@ fn lint(ctx: CallContext) -> Result<JsObject> {
137
147
138
148
Ok ( result)
139
149
}
150
+
151
+ #[ js_function( 1 ) ]
152
+ fn lint_command ( ctx : CallContext ) -> Result < JsBoolean > {
153
+ let __dirname = ctx. get :: < JsString > ( 0 ) ?;
154
+ let mut has_error = false ;
155
+ let cwd = env:: current_dir ( ) . map_err ( |e| {
156
+ Error :: new (
157
+ Status :: GenericFailure ,
158
+ format ! ( "Get current_dir failed {}" , e) ,
159
+ )
160
+ } ) ?;
161
+
162
+ let mut eslint_ignore_file = cwd. clone ( ) ;
163
+
164
+ eslint_ignore_file. push ( ".eslintignore" ) ;
165
+
166
+ let mut type_builder = TypesBuilder :: new ( ) ;
167
+
168
+ type_builder
169
+ . add ( "typescript" , "*.ts" )
170
+ . map_err ( |e| Error :: from_reason ( format ! ( "{}" , e) ) ) ?;
171
+ type_builder
172
+ . add ( "typescript" , "*.tsx" )
173
+ . map_err ( |e| Error :: from_reason ( format ! ( "{}" , e) ) ) ?;
174
+
175
+ let types = type_builder
176
+ . add_defaults ( )
177
+ . select ( "typescript" )
178
+ . select ( "js" )
179
+ . build ( )
180
+ . map_err ( |e| Error :: from_reason ( format ! ( "{}" , e) ) ) ?;
181
+
182
+ let override_ignore = match fs:: File :: open ( & eslint_ignore_file) {
183
+ Ok ( _) => OverrideBuilder :: new ( eslint_ignore_file)
184
+ . build ( )
185
+ . map_err ( |e| {
186
+ Error :: from_reason ( format ! (
187
+ "Create ignore rules from .eslintignore file failed {}" ,
188
+ e
189
+ ) )
190
+ } ) ?,
191
+ Err ( _) => OverrideBuilder :: new ( __dirname. as_str ( ) ?)
192
+ . build ( )
193
+ . map_err ( |e| {
194
+ Error :: from_reason ( format ! (
195
+ "Create ignore rules from .defaultignore file failed {}" ,
196
+ e
197
+ ) )
198
+ } ) ?,
199
+ } ;
200
+
201
+ for result in WalkBuilder :: new ( cwd)
202
+ . overrides ( override_ignore)
203
+ . types ( types)
204
+ . follow_links ( true )
205
+ . build ( )
206
+ {
207
+ match result {
208
+ Ok ( entry) => {
209
+ let p = entry. path ( ) ;
210
+ if !p. is_dir ( ) {
211
+ let file_content = fs:: read_to_string ( & p)
212
+ . map_err ( |e| Error :: from_reason ( format ! ( "Read file {:?} failed: {}" , p, e) ) ) ?;
213
+ let mut linter = LinterBuilder :: default ( ) . build ( ) ;
214
+ let file_diagnostics = linter
215
+ . lint (
216
+ ( & p. to_str ( ) )
217
+ . ok_or ( Error :: from_reason ( format ! (
218
+ "Convert path to string failed: {:?}" ,
219
+ & p
220
+ ) ) ) ?
221
+ . to_owned ( ) ,
222
+ file_content,
223
+ )
224
+ . map_err ( |e| Error {
225
+ status : Status :: GenericFailure ,
226
+ reason : format ! ( "Lint failed: {}, at: {:?}" , e, & p) ,
227
+ } ) ?;
228
+ for diagnostic in file_diagnostics {
229
+ has_error = true ;
230
+ println ! ( "{:?}" , diagnostic) ;
231
+ }
232
+ }
233
+ }
234
+ Err ( _) => { }
235
+ } ;
236
+ }
237
+
238
+ ctx. env . get_boolean ( has_error)
239
+ }
0 commit comments