Skip to content

Commit

Permalink
Report index status via $/progress
Browse files Browse the repository at this point in the history
Add WorkDoneProgress to represent WorkDoneProgressBegin/WorkDoneProgressReport/WorkDoneProgressEnd.
  • Loading branch information
MaskRay committed Jul 4, 2020
1 parent 468258d commit 5108cfa
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 14 deletions.
11 changes: 11 additions & 0 deletions src/lsp.hh
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,17 @@ struct TextDocumentDidChangeParam {
std::vector<TextDocumentContentChangeEvent> contentChanges;
};

struct WorkDoneProgress {
const char *kind;
std::optional<std::string> title;
std::optional<std::string> message;
std::optional<double> percentage;
};
struct WorkDoneProgressParam {
const char *token;
WorkDoneProgress value;
};

struct WorkspaceFolder {
DocumentUri uri;
std::string name;
Expand Down
2 changes: 2 additions & 0 deletions src/message_handler.hh
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ REFLECT_UNDERLYING_B(SymbolKind);
REFLECT_STRUCT(TextDocumentIdentifier, uri);
REFLECT_STRUCT(TextDocumentItem, uri, languageId, version, text);
REFLECT_STRUCT(TextEdit, range, newText);
REFLECT_STRUCT(WorkDoneProgress, kind, title, message, percentage);
REFLECT_STRUCT(WorkDoneProgressParam, token, value);
REFLECT_STRUCT(DiagnosticRelatedInformation, location, message);
REFLECT_STRUCT(Diagnostic, range, severity, code, source, message,
relatedInformation);
Expand Down
8 changes: 5 additions & 3 deletions src/messages/ccls_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ struct Out_cclsInfo {
int files, funcs, types, vars;
} db;
struct Pipeline {
int pendingIndexRequests;
int64_t lastIdle, completed, enqueued;
} pipeline;
struct Project {
int entries;
} project;
};
REFLECT_STRUCT(Out_cclsInfo::DB, files, funcs, types, vars);
REFLECT_STRUCT(Out_cclsInfo::Pipeline, pendingIndexRequests);
REFLECT_STRUCT(Out_cclsInfo::Pipeline, lastIdle, completed, enqueued);
REFLECT_STRUCT(Out_cclsInfo::Project, entries);
REFLECT_STRUCT(Out_cclsInfo, db, pipeline, project);
} // namespace
Expand All @@ -35,7 +35,9 @@ void MessageHandler::ccls_info(EmptyParam &, ReplyOnce &reply) {
result.db.funcs = db->funcs.size();
result.db.types = db->types.size();
result.db.vars = db->vars.size();
result.pipeline.pendingIndexRequests = pipeline::pending_index_requests;
result.pipeline.lastIdle = pipeline::stats.last_idle;
result.pipeline.completed = pipeline::stats.completed;
result.pipeline.enqueued = pipeline::stats.enqueued;
result.project.entries = 0;
for (auto &[_, folder] : project->root2folder)
result.project.entries += folder.entries.size();
Expand Down
2 changes: 1 addition & 1 deletion src/messages/textDocument_did.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void MessageHandler::textDocument_didOpen(DidOpenTextDocumentParam &param) {
// pending index request.
auto [lang, header] = lookupExtension(path);
if ((lang != LanguageId::Unknown && !header) ||
!pipeline::pending_index_requests)
pipeline::stats.completed == pipeline::stats.enqueued)
pipeline::index(path, {}, IndexMode::Normal, false);
if (header)
project->indexRelated(path);
Expand Down
68 changes: 59 additions & 9 deletions src/pipeline.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <llvm/Support/Threading.h>

#include <chrono>
#include <inttypes.h>
#include <mutex>
#include <shared_mutex>
#include <thread>
Expand All @@ -38,6 +39,12 @@ struct PublishDiagnosticParam {
std::vector<Diagnostic> diagnostics;
};
REFLECT_STRUCT(PublishDiagnosticParam, uri, diagnostics);

constexpr char index_progress_token[] = "index";
struct WorkDoneProgressCreateParam {
const char *token = index_progress_token;
};
REFLECT_STRUCT(WorkDoneProgressCreateParam, token);
} // namespace

void VFS::clear() {
Expand Down Expand Up @@ -67,7 +74,8 @@ void standaloneInitialize(MessageHandler &, const std::string &root);
namespace pipeline {

std::atomic<bool> g_quit;
std::atomic<int64_t> loaded_ts{0}, pending_index_requests{0}, request_id{0};
std::atomic<int64_t> loaded_ts{0}, request_id{0};
IndexStats stats;
int64_t tick = 0;

namespace {
Expand Down Expand Up @@ -195,9 +203,6 @@ bool indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
return false;
auto &request = *opt_request;
bool loud = request.mode != IndexMode::OnChange;
struct RAII {
~RAII() { pending_index_requests--; }
} raii;

// Dummy one to trigger refresh semantic highlight.
if (request.path.empty()) {
Expand All @@ -207,6 +212,9 @@ bool indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
return false;
}

struct RAII {
~RAII() { stats.completed++; }
} raii;
if (!matcher.matches(request.path)) {
LOG_IF_S(INFO, loud) << "skip " << request.path;
return false;
Expand Down Expand Up @@ -643,7 +651,9 @@ void mainLoop() {
handler.manager = &manager;
handler.include_complete = &include_complete;

bool work_done_created = false, in_progress = false;
bool has_indexed = false;
int64_t last_completed = 0;
std::deque<InMessage> backlog;
StringMap<std::deque<InMessage *>> path2backlog;
while (true) {
Expand Down Expand Up @@ -693,6 +703,45 @@ void mainLoop() {
}
}

int64_t completed = stats.completed.load(std::memory_order_relaxed);
if (completed != last_completed) {
if (!work_done_created) {
WorkDoneProgressCreateParam param;
request("window/workDoneProgress/create", param);
work_done_created = true;
}

int64_t enqueued = stats.enqueued.load(std::memory_order_relaxed);
if (completed != enqueued) {
if (!in_progress) {
WorkDoneProgressParam param;
param.token = index_progress_token;
param.value.kind = "begin";
param.value.title = "indexing";
notify("$/progress", param);
in_progress = true;
}
int64_t last_idle = stats.last_idle.load(std::memory_order_relaxed);
WorkDoneProgressParam param;
param.token = index_progress_token;
param.value.kind = "report";
param.value.message =
(Twine(completed - last_idle) + "/" + Twine(enqueued - last_idle))
.str();
param.value.percentage =
100.0 * (completed - last_idle) / (enqueued - last_idle);
notify("$/progress", param);
} else if (in_progress) {
stats.last_idle.store(enqueued, std::memory_order_relaxed);
WorkDoneProgressParam param;
param.token = index_progress_token;
param.value.kind = "end";
notify("$/progress", param);
in_progress = false;
}
last_completed = completed;
}

if (did_work) {
has_indexed |= indexed;
if (g_quit.load(std::memory_order_relaxed))
Expand Down Expand Up @@ -736,16 +785,16 @@ void standalone(const std::string &root) {
int entries = 0;
for (auto &[_, folder] : project.root2folder)
entries += folder.entries.size();
printf("entries: %5d\n", entries);
printf("entries: %4d\n", entries);
}
while (1) {
(void)on_indexed->dequeueAll();
int pending = pending_index_requests;
int64_t enqueued = stats.enqueued, completed = stats.completed;
if (tty) {
printf("\rpending: %5d", pending);
printf("\rcompleted: %4" PRId64 "/%" PRId64, completed, enqueued);
fflush(stdout);
}
if (!pending)
if (completed == enqueued)
break;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
Expand All @@ -756,7 +805,8 @@ void standalone(const std::string &root) {

void index(const std::string &path, const std::vector<const char *> &args,
IndexMode mode, bool must_exist, RequestId id) {
pending_index_requests++;
if (!path.empty())
stats.enqueued++;
index_request->pushBack({path, args, mode, must_exist, std::move(id)},
mode != IndexMode::Background);
}
Expand Down
7 changes: 6 additions & 1 deletion src/pipeline.hh
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,14 @@ enum class IndexMode {
Normal,
};

struct IndexStats {
std::atomic<int64_t> last_idle, completed, enqueued;
};

namespace pipeline {
extern std::atomic<bool> g_quit;
extern std::atomic<int64_t> loaded_ts, pending_index_requests;
extern std::atomic<int64_t> loaded_ts;
extern IndexStats stats;
extern int64_t tick;

void threadEnter();
Expand Down

0 comments on commit 5108cfa

Please sign in to comment.