@@ -5,11 +5,11 @@ use std::process::ExitCode;
55use std:: time:: { SystemTime , UNIX_EPOCH } ;
66
77use rsscript:: {
8- Diagnostic , analyze_source, check_generated_rust_package , explain_diagnostic_code ,
9- format_diagnostic_explanation , format_diagnostics_human , format_diagnostics_json ,
10- format_review_human, format_review_json, format_review_map_human, format_review_map_json ,
11- lower_source_to_rust , lower_source_to_rust_package , parse_source_map_json ,
12- remap_rustc_diagnostic_json_lines, review_map_sources, review_sources,
8+ Diagnostic , analyze_source, analyze_source_with_interfaces , check_generated_rust_package ,
9+ explain_diagnostic_code , format_diagnostic_explanation , format_diagnostics_human ,
10+ format_diagnostics_json , format_review_human, format_review_json, format_review_map_human,
11+ format_review_map_json , lower_source_to_rust , lower_source_to_rust_package ,
12+ parse_source_map_json , remap_rustc_diagnostic_json_lines, review_map_sources, review_sources,
1313 write_generated_rust_package,
1414} ;
1515
@@ -44,8 +44,8 @@ fn run_check(args: &[String]) -> ExitCode {
4444 return ExitCode :: SUCCESS ;
4545 }
4646
47- let ( json , path ) = parse_path_args ( args) ;
48- let Some ( path) = path else {
47+ let options = parse_check_args ( args) ;
48+ let Some ( path) = options . path else {
4949 print_usage ( ) ;
5050 return ExitCode :: from ( 2 ) ;
5151 } ;
@@ -58,8 +58,23 @@ fn run_check(args: &[String]) -> ExitCode {
5858 }
5959 } ;
6060
61- let diagnostics = analyze_source ( path, & source) ;
62- if json {
61+ let interfaces = match read_interface_sources ( & options. interfaces ) {
62+ Ok ( interfaces) => interfaces,
63+ Err ( error) => {
64+ eprintln ! ( "{error}" ) ;
65+ return ExitCode :: from ( 2 ) ;
66+ }
67+ } ;
68+ let interface_refs = interfaces
69+ . iter ( )
70+ . map ( |interface| ( interface. path . as_str ( ) , interface. contents . as_str ( ) ) )
71+ . collect :: < Vec < _ > > ( ) ;
72+ let diagnostics = if interface_refs. is_empty ( ) {
73+ analyze_source ( path, & source)
74+ } else {
75+ analyze_source_with_interfaces ( path, & source, & interface_refs)
76+ } ;
77+ if options. json {
6378 println ! ( "{}" , format_diagnostics_json( & diagnostics) ) ;
6479 } else if diagnostics. is_empty ( ) {
6580 println ! ( "{path}: ok" ) ;
@@ -376,6 +391,39 @@ struct LowerOptions<'a> {
376391 out_dir : Option < & ' a str > ,
377392}
378393
394+ struct CheckOptions < ' a > {
395+ json : bool ,
396+ path : Option < & ' a str > ,
397+ interfaces : Vec < & ' a str > ,
398+ }
399+
400+ fn parse_check_args ( args : & [ String ] ) -> CheckOptions < ' _ > {
401+ let mut json = false ;
402+ let mut path = None ;
403+ let mut interfaces = Vec :: new ( ) ;
404+ let mut index = 0 ;
405+
406+ while let Some ( arg) = args. get ( index) {
407+ if arg == "--json" {
408+ json = true ;
409+ } else if arg == "--interface" {
410+ index += 1 ;
411+ if let Some ( interface) = args. get ( index) {
412+ interfaces. push ( interface. as_str ( ) ) ;
413+ }
414+ } else if path. is_none ( ) {
415+ path = Some ( arg. as_str ( ) ) ;
416+ }
417+ index += 1 ;
418+ }
419+
420+ CheckOptions {
421+ json,
422+ path,
423+ interfaces,
424+ }
425+ }
426+
379427fn parse_lower_args ( args : & [ String ] ) -> LowerOptions < ' _ > {
380428 let mut emit_rust = false ;
381429 let mut path = None ;
@@ -401,6 +449,25 @@ fn parse_lower_args(args: &[String]) -> LowerOptions<'_> {
401449 }
402450}
403451
452+ struct InterfaceSource {
453+ path : String ,
454+ contents : String ,
455+ }
456+
457+ fn read_interface_sources ( paths : & [ & str ] ) -> Result < Vec < InterfaceSource > , String > {
458+ paths
459+ . iter ( )
460+ . map ( |path| {
461+ fs:: read_to_string ( path)
462+ . map ( |contents| InterfaceSource {
463+ path : ( * path) . to_string ( ) ,
464+ contents,
465+ } )
466+ . map_err ( |error| format ! ( "failed to read interface {path}: {error}" ) )
467+ } )
468+ . collect ( )
469+ }
470+
404471fn default_runtime_path ( ) -> Result < PathBuf , String > {
405472 let path = env:: current_dir ( )
406473 . map_err ( |error| format ! ( "failed to read current directory: {error}" ) ) ?
@@ -600,7 +667,7 @@ fn read_review_map_file(path: &Path) -> Result<ReviewMapSource, String> {
600667
601668fn print_usage ( ) {
602669 eprintln ! ( "usage:" ) ;
603- eprintln ! ( " rsscript check [--json] <file.rss>" ) ;
670+ eprintln ! ( " rsscript check [--json] [--interface <file.rssi> ...] <file.rss>" ) ;
604671 eprintln ! ( " rsscript check --explain <code>" ) ;
605672 eprintln ! ( " rsscript fmt <file.rss>" ) ;
606673 eprintln ! ( " rsscript lower --rust <file.rss>" ) ;
0 commit comments