@@ -2,17 +2,16 @@ use std::collections::HashSet;
2
2
use std:: iter;
3
3
use std:: iter:: zip;
4
4
use std:: num:: NonZero ;
5
- use std:: panic:: { catch_unwind, AssertUnwindSafe } ;
6
- use std:: sync:: { Arc , Mutex } ;
5
+ use std:: panic:: { AssertUnwindSafe , catch_unwind} ;
7
6
8
7
use cairo_lang_filesystem:: ids:: FileId ;
9
- use lsp_types:: notification:: Notification ;
10
8
use lsp_types:: Url ;
11
9
use tracing:: { error, trace} ;
12
10
13
11
use self :: project_diagnostics:: ProjectDiagnostics ;
14
12
use self :: refresh:: { clear_old_diagnostics, refresh_diagnostics} ;
15
13
use self :: trigger:: trigger;
14
+ use crate :: ide:: analysis_progress:: AnalysisProgressController ;
16
15
use crate :: lang:: diagnostics:: file_batches:: { batches, find_primary_files, find_secondary_files} ;
17
16
use crate :: lang:: lsp:: LsProtoGroup ;
18
17
use crate :: server:: client:: Notifier ;
@@ -39,87 +38,41 @@ pub struct DiagnosticsController {
39
38
trigger : trigger:: Sender < StateSnapshots > ,
40
39
_thread : JoinHandle ,
41
40
state_snapshots_props : StateSnapshotsProps ,
42
- active_snapshots : Arc < Mutex < HashSet < usize > > > ,
43
- notifier : Notifier ,
44
41
}
45
42
46
43
impl DiagnosticsController {
47
44
/// Creates a new diagnostics controller.
48
- pub fn new ( notifier : Notifier ) -> Self {
45
+ pub fn new (
46
+ notifier : Notifier ,
47
+ analysis_progress_controller : AnalysisProgressController ,
48
+ ) -> Self {
49
49
let ( trigger, receiver) = trigger ( ) ;
50
- let ( thread, parallelism) = DiagnosticsControllerThread :: spawn ( receiver, notifier. clone ( ) ) ;
50
+ let ( thread, parallelism) = DiagnosticsControllerThread :: spawn (
51
+ receiver,
52
+ notifier. clone ( ) ,
53
+ analysis_progress_controller,
54
+ ) ;
55
+
51
56
Self {
52
57
trigger,
53
58
_thread : thread,
54
59
state_snapshots_props : StateSnapshotsProps { parallelism } ,
55
- active_snapshots : Arc :: new ( Mutex :: new ( HashSet :: default ( ) ) ) ,
56
- notifier,
57
60
}
58
61
}
59
62
60
63
/// Schedules diagnostics refreshing on snapshot(s) of the current state.
61
64
pub fn refresh ( & self , state : & State ) {
62
- let mut state_snapshots = StateSnapshots :: new ( state, & self . state_snapshots_props ) ;
63
- self . register_beacons ( & mut state_snapshots) ;
64
-
65
- DiagnosticsController :: notify_start_analysis ( self . notifier . clone ( ) ) ;
66
- self . trigger . activate ( state_snapshots) ;
67
- }
68
-
69
- fn register_beacons ( & self , state_snapshots : & mut StateSnapshots ) {
70
- let active_snapshots_ref = self . active_snapshots . clone ( ) ;
71
- ( active_snapshots_ref. lock ( ) . unwrap ( ) ) . clear ( ) ;
72
-
73
- state_snapshots. 0 . iter_mut ( ) . enumerate ( ) . for_each ( |( i, beacon) | {
74
- let mut active_snapshots = active_snapshots_ref. lock ( ) . unwrap ( ) ;
75
- active_snapshots. insert ( i) ;
76
-
77
- let active_snapshots_ref_2 = self . active_snapshots . clone ( ) ;
78
- let notifer_ref = self . notifier . clone ( ) ;
79
- beacon. on_drop ( move || {
80
- let mut active_snapshots = active_snapshots_ref_2. lock ( ) . unwrap ( ) ;
81
-
82
- active_snapshots. remove ( & i) ;
83
- if active_snapshots. is_empty ( ) {
84
- DiagnosticsController :: notify_stop_analysis ( notifer_ref) ;
85
- }
86
- } ) ;
87
- } ) ;
88
- }
89
-
90
- fn notify_stop_analysis ( notifier : Notifier ) {
91
- notifier. notify :: < DiagnosticsCalculationFinish > ( ( ) ) ;
92
- }
93
-
94
- fn notify_start_analysis ( notifier : Notifier ) {
95
- notifier. notify :: < DiagnosticsCalculationStart > ( ( ) ) ;
65
+ self . trigger . activate ( StateSnapshots :: new ( state, & self . state_snapshots_props ) ) ;
96
66
}
97
67
}
98
68
99
- /// Notifies about diagnostics round which is beginning to calculate
100
- #[ derive( Debug ) ]
101
- pub struct DiagnosticsCalculationStart ;
102
-
103
- impl Notification for DiagnosticsCalculationStart {
104
- type Params = ( ) ;
105
- const METHOD : & ' static str = "cairo/diagnosticsCalculationStart" ;
106
- }
107
-
108
- /// Notifies about diagnostics round which ended calulating
109
- #[ derive( Debug ) ]
110
- pub struct DiagnosticsCalculationFinish ;
111
-
112
- impl Notification for DiagnosticsCalculationFinish {
113
- type Params = ( ) ;
114
- const METHOD : & ' static str = "cairo/diagnosticsCalculationFinish" ;
115
- }
116
-
117
69
/// Stores entire state of diagnostics controller's worker thread.
118
70
struct DiagnosticsControllerThread {
119
71
receiver : trigger:: Receiver < StateSnapshots > ,
120
72
notifier : Notifier ,
121
73
pool : thread:: Pool ,
122
74
project_diagnostics : ProjectDiagnostics ,
75
+ analysis_progress_controller : AnalysisProgressController ,
123
76
}
124
77
125
78
impl DiagnosticsControllerThread {
@@ -128,10 +81,12 @@ impl DiagnosticsControllerThread {
128
81
fn spawn (
129
82
receiver : trigger:: Receiver < StateSnapshots > ,
130
83
notifier : Notifier ,
84
+ analysis_progress_controller : AnalysisProgressController ,
131
85
) -> ( JoinHandle , NonZero < usize > ) {
132
86
let this = Self {
133
87
receiver,
134
88
notifier,
89
+ analysis_progress_controller,
135
90
pool : thread:: Pool :: new ( ) ,
136
91
project_diagnostics : ProjectDiagnostics :: new ( ) ,
137
92
} ;
@@ -148,7 +103,8 @@ impl DiagnosticsControllerThread {
148
103
149
104
/// Runs diagnostics controller's event loop.
150
105
fn event_loop ( & self ) {
151
- while let Some ( state_snapshots) = self . receiver . wait ( ) {
106
+ while let Some ( mut state_snapshots) = self . receiver . wait ( ) {
107
+ self . analysis_progress_controller . track_analysis ( & mut state_snapshots. 0 ) ;
152
108
if let Err ( err) = catch_unwind ( AssertUnwindSafe ( || {
153
109
self . diagnostics_controller_tick ( state_snapshots) ;
154
110
} ) ) {
@@ -165,7 +121,7 @@ impl DiagnosticsControllerThread {
165
121
/// Runs a single tick of the diagnostics controller's event loop.
166
122
#[ tracing:: instrument( skip_all) ]
167
123
fn diagnostics_controller_tick ( & self , state_snapshots : StateSnapshots ) {
168
- let ( state, primary_snapshots, secondary_snapshots) = state_snapshots. split ( ) ;
124
+ let ( mut state, primary_snapshots, secondary_snapshots) = state_snapshots. split ( ) ;
169
125
170
126
let primary_set = find_primary_files ( & state. db , & state. open_files ) ;
171
127
let primary: Vec < _ > = primary_set. iter ( ) . copied ( ) . collect ( ) ;
@@ -182,6 +138,7 @@ impl DiagnosticsControllerThread {
182
138
183
139
self . spawn_worker ( move |project_diagnostics, notifier| {
184
140
clear_old_diagnostics ( files_to_preserve, project_diagnostics, notifier) ;
141
+ state. signal ( ) ;
185
142
} ) ;
186
143
}
187
144
@@ -206,7 +163,7 @@ impl DiagnosticsControllerThread {
206
163
fn spawn_refresh_worker ( & self , files : & [ FileId ] , state_snapshots : Vec < StateSnapshot > ) {
207
164
let files_batches = batches ( files, self . pool . parallelism ( ) ) ;
208
165
assert_eq ! ( files_batches. len( ) , state_snapshots. len( ) ) ;
209
- for ( batch, state) in zip ( files_batches, state_snapshots) {
166
+ for ( batch, mut state) in zip ( files_batches, state_snapshots) {
210
167
self . spawn_worker ( move |project_diagnostics, notifier| {
211
168
refresh_diagnostics (
212
169
& state. db ,
@@ -215,6 +172,7 @@ impl DiagnosticsControllerThread {
215
172
project_diagnostics,
216
173
notifier,
217
174
) ;
175
+ state. signal ( ) ;
218
176
} ) ;
219
177
}
220
178
}
0 commit comments