7
7
mod logger;
8
8
mod rustc_wrapper;
9
9
10
- use std:: {
11
- env, fs,
12
- path:: { Path , PathBuf } ,
13
- process,
14
- } ;
10
+ use std:: { env, fs, path:: PathBuf , process} ;
15
11
12
+ use anyhow:: Context ;
16
13
use lsp_server:: Connection ;
17
- use rust_analyzer:: { cli:: flags, config:: Config , from_json, Result } ;
14
+ use rust_analyzer:: { cli:: flags, config:: Config , from_json} ;
18
15
use vfs:: AbsPathBuf ;
19
16
20
17
#[ cfg( all( feature = "mimalloc" ) ) ]
@@ -25,7 +22,7 @@ static ALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc;
25
22
#[ global_allocator]
26
23
static ALLOC : jemallocator:: Jemalloc = jemallocator:: Jemalloc ;
27
24
28
- fn main ( ) {
25
+ fn main ( ) -> anyhow :: Result < ( ) > {
29
26
if std:: env:: var ( "RA_RUSTC_WRAPPER" ) . is_ok ( ) {
30
27
let mut args = std:: env:: args_os ( ) ;
31
28
let _me = args. next ( ) . unwrap ( ) ;
@@ -41,14 +38,7 @@ fn main() {
41
38
}
42
39
43
40
let flags = flags:: RustAnalyzer :: from_env_or_exit ( ) ;
44
- if let Err ( err) = try_main ( flags) {
45
- tracing:: error!( "Unexpected error: {}" , err) ;
46
- eprintln ! ( "{err}" ) ;
47
- process:: exit ( 101 ) ;
48
- }
49
- }
50
41
51
- fn try_main ( flags : flags:: RustAnalyzer ) -> Result < ( ) > {
52
42
#[ cfg( debug_assertions) ]
53
43
if flags. wait_dbg || env:: var ( "RA_WAIT_DBG" ) . is_ok ( ) {
54
44
#[ allow( unused_mut) ]
@@ -58,14 +48,8 @@ fn try_main(flags: flags::RustAnalyzer) -> Result<()> {
58
48
}
59
49
}
60
50
61
- let mut log_file = flags. log_file . as_deref ( ) ;
62
-
63
- let env_log_file = env:: var ( "RA_LOG_FILE" ) . ok ( ) ;
64
- if let Some ( env_log_file) = env_log_file. as_deref ( ) {
65
- log_file = Some ( Path :: new ( env_log_file) ) ;
66
- }
51
+ setup_logging ( flags. log_file . clone ( ) ) ?;
67
52
68
- setup_logging ( log_file) ?;
69
53
let verbosity = flags. verbosity ( ) ;
70
54
71
55
match flags. subcommand {
@@ -102,7 +86,7 @@ fn try_main(flags: flags::RustAnalyzer) -> Result<()> {
102
86
Ok ( ( ) )
103
87
}
104
88
105
- fn setup_logging ( log_file : Option < & Path > ) -> Result < ( ) > {
89
+ fn setup_logging ( log_file_flag : Option < PathBuf > ) -> anyhow :: Result < ( ) > {
106
90
if cfg ! ( windows) {
107
91
// This is required so that windows finds our pdb that is placed right beside the exe.
108
92
// By default it doesn't look at the folder the exe resides in, only in the current working
@@ -115,23 +99,42 @@ fn setup_logging(log_file: Option<&Path>) -> Result<()> {
115
99
}
116
100
}
117
101
}
102
+
118
103
if env:: var ( "RUST_BACKTRACE" ) . is_err ( ) {
119
104
env:: set_var ( "RUST_BACKTRACE" , "short" ) ;
120
105
}
121
106
107
+ let log_file = env:: var ( "RA_LOG_FILE" ) . ok ( ) . map ( PathBuf :: from) . or ( log_file_flag) ;
122
108
let log_file = match log_file {
123
109
Some ( path) => {
124
110
if let Some ( parent) = path. parent ( ) {
125
111
let _ = fs:: create_dir_all ( parent) ;
126
112
}
127
- Some ( fs:: File :: create ( path) ?)
113
+ Some (
114
+ fs:: File :: create ( & path)
115
+ . with_context ( || format ! ( "can't create log file at {}" , path. display( ) ) ) ?,
116
+ )
128
117
}
129
118
None => None ,
130
119
} ;
131
- let filter = env:: var ( "RA_LOG" ) . ok ( ) ;
132
- // deliberately enable all `error` logs if the user has not set RA_LOG, as there is usually useful
133
- // information in there for debugging
134
- logger:: Logger :: new ( log_file, filter. as_deref ( ) . or ( Some ( "error" ) ) ) . install ( ) ?;
120
+
121
+ logger:: LoggerConfig {
122
+ log_file,
123
+ // Deliberately enable all `error` logs if the user has not set RA_LOG, as there is usually
124
+ // useful information in there for debugging.
125
+ filter : env:: var ( "RA_LOG" ) . ok ( ) . unwrap_or_else ( || "error" . to_string ( ) ) ,
126
+ // The meaning of CHALK_DEBUG I suspected is to tell chalk crates
127
+ // (i.e. chalk-solve, chalk-ir, chalk-recursive) how to filter tracing
128
+ // logs. But now we can only have just one filter, which means we have to
129
+ // merge chalk filter to our main filter (from RA_LOG env).
130
+ //
131
+ // The acceptable syntax of CHALK_DEBUG is `target[span{field=value}]=level`.
132
+ // As the value should only affect chalk crates, we'd better manually
133
+ // specify the target. And for simplicity, CHALK_DEBUG only accept the value
134
+ // that specify level.
135
+ chalk_filter : env:: var ( "CHALK_DEBUG" ) . ok ( ) ,
136
+ }
137
+ . init ( ) ?;
135
138
136
139
profile:: init ( ) ;
137
140
@@ -146,8 +149,8 @@ const STACK_SIZE: usize = 1024 * 1024 * 8;
146
149
fn with_extra_thread (
147
150
thread_name : impl Into < String > ,
148
151
thread_intent : stdx:: thread:: ThreadIntent ,
149
- f : impl FnOnce ( ) -> Result < ( ) > + Send + ' static ,
150
- ) -> Result < ( ) > {
152
+ f : impl FnOnce ( ) -> anyhow :: Result < ( ) > + Send + ' static ,
153
+ ) -> anyhow :: Result < ( ) > {
151
154
let handle = stdx:: thread:: Builder :: new ( thread_intent)
152
155
. name ( thread_name. into ( ) )
153
156
. stack_size ( STACK_SIZE )
@@ -158,7 +161,7 @@ fn with_extra_thread(
158
161
Ok ( ( ) )
159
162
}
160
163
161
- fn run_server ( ) -> Result < ( ) > {
164
+ fn run_server ( ) -> anyhow :: Result < ( ) > {
162
165
tracing:: info!( "server version {} will start" , rust_analyzer:: version( ) ) ;
163
166
164
167
let ( connection, io_threads) = Connection :: stdio ( ) ;
0 commit comments