@@ -16,7 +16,7 @@ use vfs::{Vfs, Change, FileContents};
16
16
use racer;
17
17
use rustfmt:: { Input as FmtInput , format_input} ;
18
18
use rustfmt:: file_lines:: { Range as RustfmtRange , FileLines } ;
19
- use config:: FmtConfig ;
19
+ use config:: { Config , FmtConfig } ;
20
20
use serde_json;
21
21
use span;
22
22
use Span ;
@@ -42,19 +42,22 @@ pub struct ActionHandler {
42
42
build_queue : Arc < BuildQueue > ,
43
43
current_project : Mutex < Option < PathBuf > > ,
44
44
previous_build_results : Arc < Mutex < BuildResults > > ,
45
+ config : Arc < Mutex < Config > > ,
45
46
fmt_config : Mutex < FmtConfig > ,
46
47
}
47
48
48
49
impl ActionHandler {
49
50
pub fn new ( analysis : Arc < AnalysisHost > ,
50
- vfs : Arc < Vfs > ,
51
- build_queue : Arc < BuildQueue > ) -> ActionHandler {
51
+ vfs : Arc < Vfs > ) -> ActionHandler {
52
+ let config = Arc :: new ( Mutex :: new ( Config :: default ( ) ) ) ;
53
+ let build_queue = Arc :: new ( BuildQueue :: new ( vfs. clone ( ) , config. clone ( ) ) ) ;
52
54
ActionHandler {
53
55
analysis,
54
56
vfs : vfs. clone ( ) ,
55
57
build_queue,
56
58
current_project : Mutex :: new ( None ) ,
57
59
previous_build_results : Arc :: new ( Mutex :: new ( HashMap :: new ( ) ) ) ,
60
+ config,
58
61
fmt_config : Mutex :: new ( FmtConfig :: default ( ) ) ,
59
62
}
60
63
}
@@ -77,10 +80,10 @@ impl ActionHandler {
77
80
* current_project = Some ( new_path) ;
78
81
}
79
82
}
80
- self . build ( & root_path, BuildPriority :: Immediate , out) ;
83
+ self . build ( & root_path, BuildPriority :: Immediate , true , out) ;
81
84
}
82
85
83
- pub fn build < O : Output > ( & self , project_path : & Path , priority : BuildPriority , out : O ) {
86
+ pub fn build < O : Output > ( & self , project_path : & Path , priority : BuildPriority , force_clean : bool , out : O ) {
84
87
fn clear_build_results ( results : & mut BuildResults ) {
85
88
// We must not clear the hashmap, just the values in each list.
86
89
// This allows us to save allocated before memory.
@@ -138,14 +141,20 @@ impl ActionHandler {
138
141
let previous_build_results = self . previous_build_results . clone ( ) ;
139
142
let project_path = project_path. to_owned ( ) ;
140
143
let out = out. clone ( ) ;
144
+ let show_warnings = {
145
+ let config = self . config . lock ( ) . unwrap ( ) ;
146
+ config. show_warnings
147
+ } ;
148
+
149
+
141
150
thread:: spawn ( move || {
142
151
// We use `rustDocument` document here since these notifications are
143
152
// custom to the RLS and not part of the LS protocol.
144
153
out. notify ( "rustDocument/diagnosticsBegin" ) ;
145
154
// let start_time = ::std::time::Instant::now();
146
155
147
156
debug ! ( "build {:?}" , project_path) ;
148
- let result = build_queue. request_build ( & project_path, priority) ;
157
+ let result = build_queue. request_build ( & project_path, priority, force_clean ) ;
149
158
match result {
150
159
BuildResult :: Success ( messages, new_analysis) | BuildResult :: Failure ( messages, new_analysis) => {
151
160
// eprintln!("built {:?}", start_time.elapsed());
@@ -155,11 +164,6 @@ impl ActionHandler {
155
164
// which had errors, but now don't. This instructs the IDE to clear
156
165
// errors for those files.
157
166
let notifications = {
158
- let show_warnings = {
159
- let config = build_queue. config . lock ( ) . unwrap ( ) ;
160
- config. show_warnings
161
- } ;
162
-
163
167
let mut results = previous_build_results. lock ( ) . unwrap ( ) ;
164
168
clear_build_results ( & mut results) ;
165
169
parse_compiler_messages ( & messages, & mut results) ;
@@ -223,21 +227,21 @@ impl ActionHandler {
223
227
} ) . collect ( ) ;
224
228
self . vfs . on_changes ( & changes) . expect ( "error committing to VFS" ) ;
225
229
226
- self . build_current_project ( BuildPriority :: Normal , out) ;
230
+ self . build_current_project ( BuildPriority :: Normal , false , out) ;
227
231
}
228
232
229
233
pub fn on_save < O : Output > ( & self , save : DidSaveTextDocumentParams , _out : O ) {
230
234
let fname = parse_file_path ( & save. text_document . uri ) . unwrap ( ) ;
231
235
self . vfs . file_saved ( & fname) . unwrap ( ) ;
232
236
}
233
237
234
- fn build_current_project < O : Output > ( & self , priority : BuildPriority , out : O ) {
238
+ fn build_current_project < O : Output > ( & self , priority : BuildPriority , force_clean : bool , out : O ) {
235
239
let current_project = {
236
240
let current_project = self . current_project . lock ( ) . unwrap ( ) ;
237
241
current_project. clone ( )
238
242
} ;
239
243
match current_project {
240
- Some ( ref current_project) => self . build ( current_project, priority, out) ,
244
+ Some ( ref current_project) => self . build ( current_project, priority, force_clean , out) ,
241
245
None => debug ! ( "build_current_project - no project path" ) ,
242
246
}
243
247
}
@@ -619,18 +623,59 @@ impl ActionHandler {
619
623
range : range_whole_file,
620
624
new_text : text,
621
625
} ] ;
622
- out. success ( id, ResponseData :: TextEdit ( result) )
626
+ out. success ( id, ResponseData :: TextEdit ( result) ) ;
623
627
} else {
624
628
debug ! ( "reformat: format_input failed: has errors, summary = {:?}" , summary) ;
625
629
626
- out. failure ( id, "Reformat failed to complete successfully" )
630
+ out. failure ( id, "Reformat failed to complete successfully" ) ;
627
631
}
628
632
}
629
633
Err ( e) => {
630
634
debug ! ( "Reformat failed: {:?}" , e) ;
631
- out. failure ( id, "Reformat failed to complete successfully" )
635
+ out. failure ( id, "Reformat failed to complete successfully" ) ;
636
+ }
637
+ }
638
+ }
639
+
640
+ pub fn on_change_config< O : Output > ( & self , params : DidChangeConfigurationParams , out : O ) {
641
+ trace ! ( "config change: {:?}" , params. settings) ;
642
+ if let Some ( config) = params. settings . get ( "rust" ) {
643
+ if let Ok ( new_config) = serde_json:: from_value ( config. clone ( ) ) : Result <Config , _> {
644
+ let unstable_features = new_config. unstable_features ;
645
+
646
+ {
647
+ let mut config = self . config . lock ( ) . unwrap ( ) ;
648
+ * config = new_config;
649
+ }
650
+ // We do a clean build so that if we've changed any relevant options
651
+ // for Cargo, we'll notice them. But if nothing relevant changes
652
+ // then we don't do unnecessary building (i.e., we don't delete
653
+ // artifacts on disk).
654
+ self . build_current_project ( BuildPriority :: Immediate , true , out. clone ( ) ) ;
655
+
656
+ const RANGE_FORMATTING_ID : & ' static str = "rls-range-formatting" ;
657
+ const RENAME_ID : & ' static str = "rls-rename" ;
658
+ // FIXME should handle the response
659
+ if unstable_features {
660
+ let output = serde_json:: to_string (
661
+ & RequestMessage :: new ( NOTIFICATION__RegisterCapability . to_owned ( ) ,
662
+ RegistrationParams { registrations : vec ! [ Registration { id: RANGE_FORMATTING_ID . to_owned( ) , method: REQUEST__RangeFormatting . to_owned( ) , register_options: serde_json:: Value :: Null } ,
663
+ Registration { id: RENAME_ID . to_owned( ) , method: REQUEST__Rename . to_owned( ) , register_options: serde_json:: Value :: Null } ] } )
664
+ ) . unwrap ( ) ;
665
+ out. response ( output) ;
666
+ } else {
667
+ let output = serde_json:: to_string (
668
+ & RequestMessage :: new ( NOTIFICATION__UnregisterCapability . to_owned ( ) ,
669
+ UnregistrationParams { unregisterations : vec ! [ Unregistration { id: RANGE_FORMATTING_ID . to_owned( ) , method: REQUEST__RangeFormatting . to_owned( ) } ,
670
+ Unregistration { id: RENAME_ID . to_owned( ) , method: REQUEST__Rename . to_owned( ) } ] } )
671
+ ) . unwrap ( ) ;
672
+ out. response ( output) ;
673
+ }
674
+
675
+ return ;
632
676
}
633
677
}
678
+ debug!( "Received unactionable config: {:?}" , params. settings ) ;
634
679
}
635
680
636
681
fn convert_pos_to_span( & self , doc: & TextDocumentIdentifier , pos: Position ) -> Span {
0 commit comments