mirror of
https://github.com/MaskRay/ccls.git
synced 2025-06-07 16:54:54 +00:00
stdin stdout logging, debug level logging
This commit is contained in:
parent
da360d2466
commit
a3709737ad
@ -29,6 +29,13 @@ static std::mutex mtx;
|
||||
FILE *file;
|
||||
Verbosity verbosity;
|
||||
|
||||
bool SetVerbosity(int value) {
|
||||
verbosity = static_cast<Verbosity>(value);
|
||||
if (value > Verbosity_DEBUG || value < Verbosity_FATAL)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Message::Message(Verbosity verbosity, const char *file, int line)
|
||||
: verbosity_(verbosity) {
|
||||
using namespace llvm;
|
||||
@ -60,6 +67,7 @@ Message::Message(Verbosity verbosity, const char *file, int line)
|
||||
case Verbosity_ERROR: stream_ << 'E'; break;
|
||||
case Verbosity_WARNING: stream_ << 'W'; break;
|
||||
case Verbosity_INFO: stream_ << 'I'; break;
|
||||
case Verbosity_DEBUG: stream_ << 'D'; break;
|
||||
default: stream_ << "V(" << int(verbosity_) << ')';
|
||||
}
|
||||
// clang-format on
|
||||
|
@ -15,8 +15,11 @@ enum Verbosity {
|
||||
Verbosity_ERROR = -2,
|
||||
Verbosity_WARNING = -1,
|
||||
Verbosity_INFO = 0,
|
||||
Verbosity_DEBUG = 1,
|
||||
};
|
||||
|
||||
extern Verbosity verbosity;
|
||||
bool SetVerbosity(int value);
|
||||
|
||||
struct Message {
|
||||
std::stringstream stream_;
|
||||
|
@ -49,7 +49,7 @@ namespace {
|
||||
OptionCategory C("ccls options");
|
||||
|
||||
opt<bool> opt_help("h", desc("Alias for -help"), cat(C));
|
||||
opt<int> opt_verbose("v", desc("verbosity"), init(0), cat(C));
|
||||
opt<int> opt_verbose("v", desc("verbosity, 0 default. From 1 (debug) to -3 (critical)"), init(0), cat(C));
|
||||
opt<std::string> opt_test_index("test-index", ValueOptional, init("!"),
|
||||
desc("run index tests"), cat(C));
|
||||
|
||||
@ -86,7 +86,11 @@ int main(int argc, char **argv) {
|
||||
PrintHelpMessage();
|
||||
return 0;
|
||||
}
|
||||
ccls::log::verbosity = ccls::log::Verbosity(opt_verbose.getValue());
|
||||
|
||||
if (!ccls::log::SetVerbosity(opt_verbose.getValue())) {
|
||||
fprintf(stderr, "Unsupported verbosity level set\n");
|
||||
}
|
||||
|
||||
|
||||
pipeline::Init();
|
||||
const char *env = getenv("CCLS_CRASH_RECOVERY");
|
||||
|
@ -35,6 +35,7 @@ limitations under the License.
|
||||
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
#include <charconv>
|
||||
#include <shared_mutex>
|
||||
#include <thread>
|
||||
#ifndef _WIN32
|
||||
@ -413,6 +414,42 @@ void Quit(SemaManager &manager) {
|
||||
no_active_threads.wait(lock, [] { return !active_threads; });
|
||||
}
|
||||
|
||||
struct HeadersData {
|
||||
std::size_t content_length;
|
||||
};
|
||||
|
||||
void ReadHeaders(bool* eof, HeadersData* headers) {
|
||||
static const std::string_view kContentLength("Content-Length: ");
|
||||
std::string buf;
|
||||
while (true) {
|
||||
int c = getchar();
|
||||
if (c == EOF) {
|
||||
*eof = true;
|
||||
return;
|
||||
}
|
||||
if (c == '\n') {
|
||||
if (buf.empty()) {
|
||||
if (headers->content_length == 0)
|
||||
LOG_S(WARNING) << "Content-Length was not defined in header";
|
||||
return;
|
||||
}
|
||||
if (!buf.compare(0, kContentLength.size(), kContentLength)) {
|
||||
std::from_chars_result result = std::from_chars(
|
||||
buf.c_str() + kContentLength.size(),
|
||||
buf.c_str() + buf.size(),
|
||||
headers->content_length);
|
||||
if (result.ec != std::errc() || headers->content_length == 0) {
|
||||
LOG_S(WARNING) << "Content-Length parse error / invalid value";
|
||||
return;
|
||||
}
|
||||
}
|
||||
buf.clear();
|
||||
} else if (c != '\r') {
|
||||
buf.push_back(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void ThreadEnter() {
|
||||
@ -483,52 +520,53 @@ void LaunchStdin() {
|
||||
ThreadEnter();
|
||||
std::thread([]() {
|
||||
set_thread_name("stdin");
|
||||
bool eof = false;
|
||||
std::string str;
|
||||
const std::string_view kContentLength("Content-Length: ");
|
||||
while (true) {
|
||||
int len = 0;
|
||||
while (!eof) {
|
||||
HeadersData headers{};
|
||||
ReadHeaders(&eof, &headers);
|
||||
if (eof)
|
||||
return;
|
||||
if (headers.content_length == 0)
|
||||
continue;
|
||||
|
||||
str.clear();
|
||||
while (true) {
|
||||
str.reserve(headers.content_length);
|
||||
for (std::size_t i = 0; i < headers.content_length; ++i) {
|
||||
int c = getchar();
|
||||
if (c == EOF)
|
||||
if (c == EOF) {
|
||||
eof = true;
|
||||
return;
|
||||
if (c == '\n') {
|
||||
if (str.empty())
|
||||
break;
|
||||
if (!str.compare(0, kContentLength.size(), kContentLength))
|
||||
len = atoi(str.c_str() + kContentLength.size());
|
||||
str.clear();
|
||||
} else if (c != '\r') {
|
||||
str += c;
|
||||
}
|
||||
str.push_back(c);
|
||||
}
|
||||
|
||||
str.resize(len);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
int c = getchar();
|
||||
if (c == EOF)
|
||||
return;
|
||||
str[i] = c;
|
||||
}
|
||||
|
||||
auto message = std::make_unique<char[]>(len);
|
||||
auto message = std::make_unique<char[]>(headers.content_length);
|
||||
std::copy(str.begin(), str.end(), message.get());
|
||||
auto document = std::make_unique<rapidjson::Document>();
|
||||
document->Parse(message.get(), len);
|
||||
assert(!document->HasParseError());
|
||||
document->Parse(message.get(), headers.content_length);
|
||||
if (document->HasParseError()) {
|
||||
LOG_S(WARNING) << "Json parse error";
|
||||
continue;
|
||||
}
|
||||
|
||||
JsonReader reader{document.get()};
|
||||
if (!reader.m->HasMember("jsonrpc") ||
|
||||
std::string((*reader.m)["jsonrpc"].GetString()) != "2.0")
|
||||
break;
|
||||
std::string((*reader.m)["jsonrpc"].GetString()) != "2.0") {
|
||||
LOG_S(WARNING) << "Bad jsonrpc member";
|
||||
continue;
|
||||
}
|
||||
RequestId id;
|
||||
std::string method;
|
||||
ReflectMember(reader, "id", id);
|
||||
ReflectMember(reader, "method", method);
|
||||
if (method.empty())
|
||||
if (method.empty()) {
|
||||
LOG_S(WARNING) << "Empty method";
|
||||
continue;
|
||||
}
|
||||
bool should_exit = method == "exit";
|
||||
// g_config is not available before "initialize". Use 0 in that case.
|
||||
LOG_S(DEBUG) << "Received method: " << method;
|
||||
on_request->PushBack(
|
||||
{id, std::move(method), std::move(message), std::move(document),
|
||||
chrono::steady_clock::now() +
|
||||
@ -738,6 +776,7 @@ void NotifyOrRequest(const char *method, bool request,
|
||||
JsonWriter writer(&w);
|
||||
fn(writer);
|
||||
w.EndObject();
|
||||
LOG_S(DEBUG) << "Notify/Request sent " << method;
|
||||
for_stdout->PushBack(output.GetString());
|
||||
}
|
||||
|
||||
@ -765,6 +804,7 @@ static void Reply(RequestId id, const char *key,
|
||||
JsonWriter writer(&w);
|
||||
fn(writer);
|
||||
w.EndObject();
|
||||
LOG_S(DEBUG) << "Reply sent: " << id.value;
|
||||
for_stdout->PushBack(output.GetString());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user