11use std:: {
22 fs,
3- path:: Path ,
4- rc:: Rc ,
5- sync:: { Arc , OnceLock } ,
3+ path:: { Path , PathBuf } ,
4+ sync:: { Arc , OnceLock , mpsc} ,
65} ;
76
87use log:: debug;
98use rustc_hash:: FxHashSet ;
10- use tower_lsp:: lsp_types:: { self , DiagnosticRelatedInformation , DiagnosticSeverity , Range } ;
9+ use tower_lsp:: lsp_types:: { self , DiagnosticRelatedInformation , DiagnosticSeverity } ;
1110
12- use oxc_allocator:: Allocator ;
1311use oxc_diagnostics:: { Error , NamedSource } ;
14- use oxc_linter:: {
15- LINTABLE_EXTENSIONS , Linter , ModuleRecord ,
16- loader:: { JavaScriptSource , Loader } ,
17- } ;
18- use oxc_parser:: { ParseOptions , Parser } ;
19- use oxc_semantic:: SemanticBuilder ;
12+ use oxc_linter:: { LINTABLE_EXTENSIONS , LintService , LintServiceOptions , Linter , loader:: Loader } ;
2013
2114use crate :: DiagnosticReport ;
22- use crate :: linter:: error_with_position:: { ErrorReport , ErrorWithPosition , FixedContent } ;
23- use crate :: linter:: offset_to_position;
15+ use crate :: linter:: error_with_position:: { ErrorReport , ErrorWithPosition } ;
16+
17+ /// smaller subset of LintServiceOptions, which is used by IsolatedLintHandler
18+ #[ derive( Debug , Clone ) ]
19+ pub struct IsolatedLintHandlerOptions {
20+ pub use_cross_module : bool ,
21+ pub root_path : PathBuf ,
22+ }
2423
2524pub struct IsolatedLintHandler {
2625 linter : Arc < Linter > ,
27- loader : Loader ,
26+ options : Arc < IsolatedLintHandlerOptions > ,
2827}
2928
3029impl IsolatedLintHandler {
31- pub fn new ( linter : Arc < Linter > ) -> Self {
32- Self { linter, loader : Loader }
30+ pub fn new ( linter : Arc < Linter > , options : Arc < IsolatedLintHandlerOptions > ) -> Self {
31+ Self { linter, options }
3332 }
3433
3534 pub fn run_single (
@@ -100,89 +99,31 @@ impl IsolatedLintHandler {
10099 return None ;
101100 }
102101 let source_text = source_text. or_else ( || fs:: read_to_string ( path) . ok ( ) ) ?;
103- let javascript_sources = match self . loader . load_str ( path, & source_text) {
104- Ok ( s) => s,
105- Err ( e) => {
106- debug ! ( "failed to load {path:?}: {e}" ) ;
107- return None ;
108- }
109- } ;
110102
111103 debug ! ( "lint {path:?}" ) ;
112- let mut diagnostics = vec ! [ ] ;
113- for source in javascript_sources {
114- let JavaScriptSource {
115- source_text : javascript_source_text, source_type, start, ..
116- } = source;
117- let allocator = Allocator :: default ( ) ;
118- let ret = Parser :: new ( & allocator, javascript_source_text, source_type)
119- . with_options ( ParseOptions {
120- allow_return_outside_function : true ,
121- parse_regular_expression : true ,
122- ..ParseOptions :: default ( )
123- } )
124- . parse ( ) ;
125-
126- if !ret. errors . is_empty ( ) {
127- let reports = ret
128- . errors
129- . into_iter ( )
130- . map ( |diagnostic| ErrorReport {
131- error : Error :: from ( diagnostic) ,
132- fixed_content : None ,
133- } )
134- . collect ( ) ;
135- return Some ( Self :: wrap_diagnostics ( path, & source_text, reports, start) ) ;
104+ let mut diagnostics_result = vec ! [ ] ;
105+
106+ let ( sender, receiver) = mpsc:: channel ( ) ;
107+ let lint_service_options = LintServiceOptions :: new (
108+ self . options . root_path . clone ( ) ,
109+ vec ! [ Arc :: from( path. as_os_str( ) ) ] ,
110+ )
111+ . with_cross_module ( self . options . use_cross_module ) ;
112+ // ToDo: do not clone the linter
113+ let mut lint_service = LintService :: new ( ( * self . linter ) . clone ( ) , lint_service_options) ;
114+ tokio:: task:: block_in_place ( move || {
115+ lint_service. run ( & sender) ;
116+ } ) ;
117+
118+ while let Ok ( Some ( ( path, diagnostics) ) ) = receiver. recv ( ) {
119+ for diagnostic in diagnostics {
120+ // ToDo: reimplement fixed_content
121+ let report = ErrorReport { error : Error :: from ( diagnostic) , fixed_content : None } ;
122+ diagnostics_result. push ( Self :: wrap_diagnostics ( & path, & source_text, report) ) ;
136123 }
137-
138- let semantic_ret = SemanticBuilder :: new ( )
139- . with_cfg ( true )
140- . with_scope_tree_child_ids ( true )
141- . with_check_syntax_error ( true )
142- . build ( & ret. program ) ;
143-
144- if !semantic_ret. errors . is_empty ( ) {
145- let reports = semantic_ret
146- . errors
147- . into_iter ( )
148- . map ( |diagnostic| ErrorReport {
149- error : Error :: from ( diagnostic) ,
150- fixed_content : None ,
151- } )
152- . collect ( ) ;
153- return Some ( Self :: wrap_diagnostics ( path, & source_text, reports, start) ) ;
154- }
155-
156- let mut semantic = semantic_ret. semantic ;
157- semantic. set_irregular_whitespaces ( ret. irregular_whitespaces ) ;
158- let module_record = Arc :: new ( ModuleRecord :: new ( path, & ret. module_record , & semantic) ) ;
159- let result = self . linter . run ( path, Rc :: new ( semantic) , module_record) ;
160-
161- let reports = result
162- . into_iter ( )
163- . map ( |msg| {
164- let fixed_content = msg. fix . map ( |f| FixedContent {
165- message : f. message . map ( |m| m. to_string ( ) ) ,
166- code : f. content . to_string ( ) ,
167- range : Range {
168- start : offset_to_position (
169- ( f. span . start + start) as usize ,
170- source_text. as_str ( ) ,
171- ) ,
172- end : offset_to_position (
173- ( f. span . end + start) as usize ,
174- source_text. as_str ( ) ,
175- ) ,
176- } ,
177- } ) ;
178-
179- ErrorReport { error : Error :: from ( msg. error ) , fixed_content }
180- } )
181- . collect :: < Vec < ErrorReport > > ( ) ;
182- diagnostics. extend ( Self :: wrap_diagnostics ( path, & source_text, reports, start) ) ;
183124 }
184125
185- Some ( diagnostics )
126+ Some ( diagnostics_result )
186127 }
187128
188129 fn should_lint_path ( path : & Path ) -> bool {
@@ -195,24 +136,14 @@ impl IsolatedLintHandler {
195136 . is_some_and ( |ext| wanted_exts. contains ( ext) )
196137 }
197138
198- fn wrap_diagnostics (
199- path : & Path ,
200- source_text : & str ,
201- reports : Vec < ErrorReport > ,
202- start : u32 ,
203- ) -> Vec < ErrorWithPosition > {
139+ fn wrap_diagnostics ( path : & Path , source_text : & str , report : ErrorReport ) -> ErrorWithPosition {
204140 let source = Arc :: new ( NamedSource :: new ( path. to_string_lossy ( ) , source_text. to_owned ( ) ) ) ;
205141
206- reports
207- . into_iter ( )
208- . map ( |report| {
209- ErrorWithPosition :: new (
210- report. error . with_source_code ( Arc :: clone ( & source) ) ,
211- source_text,
212- report. fixed_content ,
213- start as usize ,
214- )
215- } )
216- . collect ( )
142+ ErrorWithPosition :: new (
143+ report. error . with_source_code ( Arc :: clone ( & source) ) ,
144+ source_text,
145+ report. fixed_content ,
146+ 0 ,
147+ )
217148 }
218149}
0 commit comments