char/avril
(wip) why'd you have to go and make things so complicaaaaated?
git clone https://git.t4t.associates/char/avril
51266f9
main
1use std:: path:: PathBuf ; 2use std:: process:: ExitCode ; 3 4use crate :: cli:: ParseError ; 5use crate :: fragments::{ Arg , Entry , Parser , reject}; 6 7pub struct Args { 8pub typescript : PathBuf , 9pub entry : Entry , 10} 11 12/// `avril check` argument parsing failed. 13# [ derive ( Debug , thiserror :: Error )] 14pub enum CheckParseError { 15# [ error ( transparent )] 16Generic ( # [ from ] ParseError ), 17# [ error ( "check requires --typescript=PATH to the native backend" )] 18MissingBackend , 19} 20 21pub fn parse ( args : & [ String ]) ->Result < Args , CheckParseError > { 22let cwd =crate :: fragments:: working_dir () ?; 23let mut parser =Parser :: new ( "check" , args. to_vec (), & cwd) ?; 24let ( mut typescript, mut raw) =( None , None ); 25while let Some ( arg) = parser. next () ?{ 26match arg{ 27Arg :: Positional ( arg) if raw. is_none () => raw =Some ( arg), 28Arg :: Positional ( _) =>return Err ( parser. usage (). into ()), 29Arg :: Flag ( arg) if parser. path_once ( & arg, "--typescript" , & mut typescript) ? =>{} 30Arg :: Flag ( arg) =>return Err ( reject ( & arg, & []). into ()), 31} 32} 33let typescript = typescript. ok_or ( CheckParseError :: MissingBackend ) ?; 34let raw = raw. ok_or_else ( || parser. usage ()) ?; 35let entry = parser. entry ( & raw) ?; 36Ok ( Args { 37typescript : PathBuf :: from ( typescript), 38 entry, 39}) 40} 41 42fn display_uri ( uri : & str ) ->String { 43if let Some ( path) = url:: Url :: parse ( uri) 44. ok () 45. and_then ( |url| url. to_file_path (). ok ()) 46{ 47return path. display (). to_string (); 48} 49for ( editor, original) in [ 50( "avril-https:" , "https:" ), 51( "avril-http:" , "http:" ), 52( "avril-builtin:" , "avril:" ), 53] { 54if let Some ( rest) = uri. strip_prefix ( editor) { 55return format! ( "{original}{rest}" ); 56} 57} 58 uri. to_owned () 59} 60 61pub fn run ( args : Args ) ->Result < ExitCode , Box < dyn std:: error:: Error >> { 62let Args { typescript, entry} = args; 63let ( _authority, root, packages) = entry. project ( false ) ?; 64let runtime = tokio:: runtime:: Builder :: new_multi_thread () 65. worker_threads ( 2 ) 66. enable_all () 67. build () ?; 68let caps = entry. caps ; 69let explicit_lock = entry. explicit_lock ; 70let module = entry. module ; 71let diagnostics = runtime. block_on ( async move { 72let input =crate :: lsp:: check_input ( 73 root, 74 caps, 75 packages, 76 explicit_lock, 77 entry. automatic_types , 78& module, 79) 80. await ?; 81 avril_lsp:: check ( & typescript, input). await 82}); 83let diagnostics =match diagnostics{ 84Ok ( diagnostics) => diagnostics, 85Err ( error) =>{ 86 runtime. shutdown_background (); 87return Err ( error); 88} 89}; 90 runtime. shutdown_background (); 91let mut failed =false ; 92for diagnosticin & diagnostics{ 93let severity =if diagnostic. severity ==1 { 94 failed =true ; 95"error" 96} else { 97"warning" 98}; 99let code = diagnostic 100. code 101. map ( |code|format! ( " TS{code}" )) 102. unwrap_or_default (); 103println! ( 104"{}:{}:{}: {severity}{code}: {}" , 105display_uri ( & diagnostic. uri ), 106 diagnostic. line +1 , 107 diagnostic. character +1 , 108 diagnostic. message 109); 110} 111Ok ( if failed{ 112ExitCode :: FAILURE 113} else { 114ExitCode :: SUCCESS 115}) 116}