22
22
#include < llvm/Support/Threading.h>
23
23
24
24
#include < chrono>
25
+ #include < inttypes.h>
25
26
#include < mutex>
26
27
#include < shared_mutex>
27
28
#include < thread>
@@ -38,6 +39,12 @@ struct PublishDiagnosticParam {
38
39
std::vector<Diagnostic> diagnostics;
39
40
};
40
41
REFLECT_STRUCT (PublishDiagnosticParam, uri, diagnostics);
42
+
43
+ constexpr char index_progress_token[] = " index" ;
44
+ struct WorkDoneProgressCreateParam {
45
+ const char *token = index_progress_token;
46
+ };
47
+ REFLECT_STRUCT (WorkDoneProgressCreateParam, token);
41
48
} // namespace
42
49
43
50
void VFS::clear () {
@@ -67,7 +74,8 @@ void standaloneInitialize(MessageHandler &, const std::string &root);
67
74
namespace pipeline {
68
75
69
76
std::atomic<bool > g_quit;
70
- std::atomic<int64_t > loaded_ts{0 }, pending_index_requests{0 }, request_id{0 };
77
+ std::atomic<int64_t > loaded_ts{0 }, request_id{0 };
78
+ IndexStats stats;
71
79
int64_t tick = 0 ;
72
80
73
81
namespace {
@@ -195,9 +203,6 @@ bool indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
195
203
return false ;
196
204
auto &request = *opt_request;
197
205
bool loud = request.mode != IndexMode::OnChange;
198
- struct RAII {
199
- ~RAII () { pending_index_requests--; }
200
- } raii;
201
206
202
207
// Dummy one to trigger refresh semantic highlight.
203
208
if (request.path .empty ()) {
@@ -207,6 +212,9 @@ bool indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
207
212
return false ;
208
213
}
209
214
215
+ struct RAII {
216
+ ~RAII () { stats.completed ++; }
217
+ } raii;
210
218
if (!matcher.matches (request.path )) {
211
219
LOG_IF_S (INFO, loud) << " skip " << request.path ;
212
220
return false ;
@@ -643,7 +651,9 @@ void mainLoop() {
643
651
handler.manager = &manager;
644
652
handler.include_complete = &include_complete;
645
653
654
+ bool work_done_created = false , in_progress = false ;
646
655
bool has_indexed = false ;
656
+ int64_t last_completed = 0 ;
647
657
std::deque<InMessage> backlog;
648
658
StringMap<std::deque<InMessage *>> path2backlog;
649
659
while (true ) {
@@ -693,6 +703,44 @@ void mainLoop() {
693
703
}
694
704
}
695
705
706
+ int64_t completed = stats.completed .load (std::memory_order_relaxed);
707
+ if (completed != last_completed) {
708
+ if (!work_done_created) {
709
+ WorkDoneProgressCreateParam param;
710
+ request (" window/workDoneProgress/create" , param);
711
+ work_done_created = true ;
712
+ }
713
+
714
+ int64_t enqueued = stats.enqueued .load (std::memory_order_relaxed);
715
+ if (completed != enqueued) {
716
+ if (!in_progress) {
717
+ WorkDoneProgressParam param;
718
+ param.token = index_progress_token;
719
+ param.value .kind = " begin" ;
720
+ param.value .title = " indexing" ;
721
+ notify (" $/progress" , param);
722
+ in_progress = true ;
723
+ }
724
+ int64_t last_idle = stats.last_idle .load (std::memory_order_relaxed);
725
+ WorkDoneProgressParam param;
726
+ param.token = index_progress_token;
727
+ param.value .kind = " report" ;
728
+ param.value .message =
729
+ (Twine (completed - last_idle) + " /" + Twine (enqueued - last_idle))
730
+ .str ();
731
+ param.value .percentage =
732
+ 100.0 * (completed - last_idle) / (enqueued - last_idle);
733
+ notify (" $/progress" , param);
734
+ } else if (in_progress) {
735
+ stats.last_idle .store (enqueued, std::memory_order_relaxed);
736
+ WorkDoneProgressParam param;
737
+ param.token = index_progress_token;
738
+ param.value .kind = " end" ;
739
+ notify (" $/progress" , param);
740
+ in_progress = false ;
741
+ }
742
+ }
743
+
696
744
if (did_work) {
697
745
has_indexed |= indexed;
698
746
if (g_quit.load (std::memory_order_relaxed))
@@ -736,16 +784,16 @@ void standalone(const std::string &root) {
736
784
int entries = 0 ;
737
785
for (auto &[_, folder] : project.root2folder )
738
786
entries += folder.entries .size ();
739
- printf (" entries: %5d \n " , entries);
787
+ printf (" entries: %4d \n " , entries);
740
788
}
741
789
while (1 ) {
742
790
(void )on_indexed->dequeueAll ();
743
- int pending = pending_index_requests ;
791
+ int64_t enqueued = stats. enqueued , completed = stats. completed ;
744
792
if (tty) {
745
- printf (" \r pending : %5d " , pending );
793
+ printf (" \r completed : %4 " PRId64 " /% " PRId64, completed, enqueued );
746
794
fflush (stdout);
747
795
}
748
- if (!pending )
796
+ if (completed == enqueued )
749
797
break ;
750
798
std::this_thread::sleep_for (std::chrono::milliseconds (100 ));
751
799
}
@@ -756,7 +804,8 @@ void standalone(const std::string &root) {
756
804
757
805
void index (const std::string &path, const std::vector<const char *> &args,
758
806
IndexMode mode, bool must_exist, RequestId id) {
759
- pending_index_requests++;
807
+ if (!path.empty ())
808
+ stats.enqueued ++;
760
809
index_request->pushBack ({path, args, mode, must_exist, std::move (id)},
761
810
mode != IndexMode::Background);
762
811
}
0 commit comments