Refactor serializer

Delete virtual bases Reader & Writer
Delete unused MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY
Merge serializers/{json,binary}.hh into serializer.{hh,cc}
MAKE_REFLECT_STRUCT => REFLECT_STRUCT
MAKE_REFLECT_TYPE_PROXY => REFLECT_UNDERLYING
This commit is contained in:
Fangrui Song 2018-12-02 15:53:33 -08:00
parent 1a7e463553
commit cc11d30dad
34 changed files with 875 additions and 952 deletions

View File

@ -247,28 +247,28 @@ struct Config {
int maxNum = 2000; int maxNum = 2000;
} xref; } xref;
}; };
MAKE_REFLECT_STRUCT(Config::Clang, excludeArgs, extraArgs, pathMappings, REFLECT_STRUCT(Config::Clang, excludeArgs, extraArgs, pathMappings,
resourceDir); resourceDir);
MAKE_REFLECT_STRUCT(Config::ClientCapability, hierarchicalDocumentSymbolSupport, REFLECT_STRUCT(Config::ClientCapability, hierarchicalDocumentSymbolSupport,
snippetSupport); snippetSupport);
MAKE_REFLECT_STRUCT(Config::CodeLens, localVariables); REFLECT_STRUCT(Config::CodeLens, localVariables);
MAKE_REFLECT_STRUCT(Config::Completion::Include, blacklist, maxPathSize, REFLECT_STRUCT(Config::Completion::Include, blacklist, maxPathSize,
suffixWhitelist, whitelist); suffixWhitelist, whitelist);
MAKE_REFLECT_STRUCT(Config::Completion, caseSensitivity, detailedLabel, REFLECT_STRUCT(Config::Completion, caseSensitivity, detailedLabel,
dropOldRequests, duplicateOptional, filterAndSort, include, dropOldRequests, duplicateOptional, filterAndSort, include,
maxNum); maxNum);
MAKE_REFLECT_STRUCT(Config::Diagnostics, blacklist, onChange, onOpen, onSave, REFLECT_STRUCT(Config::Diagnostics, blacklist, onChange, onOpen, onSave,
spellChecking, whitelist) spellChecking, whitelist)
MAKE_REFLECT_STRUCT(Config::Highlight, largeFileSize, lsRanges, blacklist, REFLECT_STRUCT(Config::Highlight, largeFileSize, lsRanges, blacklist,
whitelist) whitelist)
MAKE_REFLECT_STRUCT(Config::Index, blacklist, comments, initialBlacklist, REFLECT_STRUCT(Config::Index, blacklist, comments, initialBlacklist,
initialWhitelist, multiVersion, multiVersionBlacklist, initialWhitelist, multiVersion, multiVersionBlacklist,
multiVersionWhitelist, onChange, threads, trackDependency, multiVersionWhitelist, onChange, threads, trackDependency,
whitelist); whitelist);
MAKE_REFLECT_STRUCT(Config::Session, maxNum); REFLECT_STRUCT(Config::Session, maxNum);
MAKE_REFLECT_STRUCT(Config::WorkspaceSymbol, caseSensitivity, maxNum, sort); REFLECT_STRUCT(Config::WorkspaceSymbol, caseSensitivity, maxNum, sort);
MAKE_REFLECT_STRUCT(Config::Xref, maxNum); REFLECT_STRUCT(Config::Xref, maxNum);
MAKE_REFLECT_STRUCT(Config, compilationDatabaseCommand, REFLECT_STRUCT(Config, compilationDatabaseCommand,
compilationDatabaseDirectory, cacheDirectory, cacheFormat, compilationDatabaseDirectory, cacheDirectory, cacheFormat,
clang, client, codeLens, completion, diagnostics, highlight, clang, client, codeLens, completion, diagnostics, highlight,
index, session, workspaceSymbol, xref); index, session, workspaceSymbol, xref);

View File

@ -8,7 +8,6 @@
#include "pipeline.hh" #include "pipeline.hh"
#include "platform.hh" #include "platform.hh"
#include "sema_manager.hh" #include "sema_manager.hh"
#include "serializer.hh"
#include <clang/AST/AST.h> #include <clang/AST/AST.h>
#include <clang/Frontend/FrontendAction.h> #include <clang/Frontend/FrontendAction.h>
@ -1172,7 +1171,7 @@ public:
} // namespace } // namespace
const int IndexFile::kMajorVersion = 19; const int IndexFile::kMajorVersion = 19;
const int IndexFile::kMinorVersion = 0; const int IndexFile::kMinorVersion = 1;
IndexFile::IndexFile(llvm::sys::fs::UniqueID UniqueID, const std::string &path, IndexFile::IndexFile(llvm::sys::fs::UniqueID UniqueID, const std::string &path,
const std::string &contents) const std::string &contents)
@ -1354,90 +1353,85 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs,
} }
} // namespace idx } // namespace idx
void Reflect(Reader &vis, SymbolRef &v) { void Reflect(JsonReader &vis, SymbolRef &v) {
if (vis.Format() == SerializeFormat::Json) { std::string t = vis.GetString();
std::string t = vis.GetString(); char *s = const_cast<char *>(t.c_str());
char *s = const_cast<char *>(t.c_str()); v.range = Range::FromString(s);
v.range = Range::FromString(s); s = strchr(s, '|');
s = strchr(s, '|'); v.usr = strtoull(s + 1, &s, 10);
v.usr = strtoull(s + 1, &s, 10); v.kind = static_cast<Kind>(strtol(s + 1, &s, 10));
v.kind = static_cast<Kind>(strtol(s + 1, &s, 10)); v.role = static_cast<Role>(strtol(s + 1, &s, 10));
v.role = static_cast<Role>(strtol(s + 1, &s, 10));
} else {
Reflect(vis, v.range);
Reflect(vis, v.usr);
Reflect(vis, v.kind);
Reflect(vis, v.role);
}
} }
void Reflect(Writer &vis, SymbolRef &v) { void Reflect(JsonReader &vis, Use &v) {
if (vis.Format() == SerializeFormat::Json) { std::string t = vis.GetString();
char buf[99]; char *s = const_cast<char *>(t.c_str());
snprintf(buf, sizeof buf, "%s|%" PRIu64 "|%d|%d", v.range = Range::FromString(s);
v.range.ToString().c_str(), v.usr, int(v.kind), int(v.role)); s = strchr(s, '|');
std::string s(buf); v.role = static_cast<Role>(strtol(s + 1, &s, 10));
Reflect(vis, s); v.file_id = static_cast<int>(strtol(s + 1, &s, 10));
} else { }
Reflect(vis, v.range); void Reflect(JsonReader &vis, DeclRef &v) {
Reflect(vis, v.usr); std::string t = vis.GetString();
Reflect(vis, v.kind); char *s = const_cast<char *>(t.c_str());
Reflect(vis, v.role); v.range = Range::FromString(s);
} s = strchr(s, '|') + 1;
v.extent = Range::FromString(s);
s = strchr(s, '|');
v.role = static_cast<Role>(strtol(s + 1, &s, 10));
v.file_id = static_cast<int>(strtol(s + 1, &s, 10));
} }
void Reflect(Reader &vis, Use &v) { void Reflect(JsonWriter &vis, SymbolRef &v) {
if (vis.Format() == SerializeFormat::Json) { char buf[99];
std::string t = vis.GetString(); snprintf(buf, sizeof buf, "%s|%" PRIu64 "|%d|%d", v.range.ToString().c_str(),
char *s = const_cast<char *>(t.c_str()); v.usr, int(v.kind), int(v.role));
v.range = Range::FromString(s); std::string s(buf);
s = strchr(s, '|'); Reflect(vis, s);
v.role = static_cast<Role>(strtol(s + 1, &s, 10));
v.file_id = static_cast<int>(strtol(s + 1, &s, 10));
} else {
Reflect(vis, v.range);
Reflect(vis, v.role);
Reflect(vis, v.file_id);
}
} }
void Reflect(Writer &vis, Use &v) { void Reflect(JsonWriter &vis, Use &v) {
if (vis.Format() == SerializeFormat::Json) { char buf[99];
char buf[99]; snprintf(buf, sizeof buf, "%s|%d|%d", v.range.ToString().c_str(), int(v.role),
snprintf(buf, sizeof buf, "%s|%d|%d", v.range.ToString().c_str(), v.file_id);
int(v.role), v.file_id); std::string s(buf);
std::string s(buf); Reflect(vis, s);
Reflect(vis, s); }
} else { void Reflect(JsonWriter &vis, DeclRef &v) {
Reflect(vis, v.range); char buf[99];
Reflect(vis, v.role); snprintf(buf, sizeof buf, "%s|%s|%d|%d", v.range.ToString().c_str(),
Reflect(vis, v.file_id); v.extent.ToString().c_str(), int(v.role), v.file_id);
} std::string s(buf);
Reflect(vis, s);
} }
void Reflect(Reader &vis, DeclRef &v) { void Reflect(BinaryReader &vis, SymbolRef &v) {
if (vis.Format() == SerializeFormat::Json) { Reflect(vis, v.range);
std::string t = vis.GetString(); Reflect(vis, v.usr);
char *s = const_cast<char *>(t.c_str()); Reflect(vis, v.kind);
v.range = Range::FromString(s); Reflect(vis, v.role);
s = strchr(s, '|') + 1;
v.extent = Range::FromString(s);
s = strchr(s, '|');
v.role = static_cast<Role>(strtol(s + 1, &s, 10));
v.file_id = static_cast<int>(strtol(s + 1, &s, 10));
} else {
Reflect(vis, static_cast<Use &>(v));
Reflect(vis, v.extent);
}
} }
void Reflect(Writer &vis, DeclRef &v) { void Reflect(BinaryReader &vis, Use &v) {
if (vis.Format() == SerializeFormat::Json) { Reflect(vis, v.range);
char buf[99]; Reflect(vis, v.role);
snprintf(buf, sizeof buf, "%s|%s|%d|%d", v.range.ToString().c_str(), Reflect(vis, v.file_id);
v.extent.ToString().c_str(), int(v.role), v.file_id); }
std::string s(buf); void Reflect(BinaryReader &vis, DeclRef &v) {
Reflect(vis, s); Reflect(vis, static_cast<Use &>(v));
} else { Reflect(vis, v.extent);
Reflect(vis, static_cast<Use &>(v)); }
Reflect(vis, v.extent);
} void Reflect(BinaryWriter &vis, SymbolRef &v) {
Reflect(vis, v.range);
Reflect(vis, v.usr);
Reflect(vis, v.kind);
Reflect(vis, v.role);
}
void Reflect(BinaryWriter &vis, Use &v) {
Reflect(vis, v.range);
Reflect(vis, v.role);
Reflect(vis, v.file_id);
}
void Reflect(BinaryWriter &vis, DeclRef &v) {
Reflect(vis, static_cast<Use &>(v));
Reflect(vis, v.extent);
} }
} // namespace ccls } // namespace ccls

View File

@ -34,7 +34,7 @@ using Usr = uint64_t;
// The order matters. In FindSymbolsAtLocation, we want Var/Func ordered in // The order matters. In FindSymbolsAtLocation, we want Var/Func ordered in
// front of others. // front of others.
enum class Kind : uint8_t { Invalid, File, Type, Func, Var }; enum class Kind : uint8_t { Invalid, File, Type, Func, Var };
MAKE_REFLECT_TYPE_PROXY(Kind); REFLECT_UNDERLYING_B(Kind);
enum class Role : uint16_t { enum class Role : uint16_t {
None = 0, None = 0,
@ -49,7 +49,7 @@ enum class Role : uint16_t {
Implicit = 1 << 8, Implicit = 1 << 8,
All = (1 << 9) - 1, All = (1 << 9) - 1,
}; };
MAKE_REFLECT_TYPE_PROXY(Role); REFLECT_UNDERLYING_B(Role);
inline uint16_t operator&(Role lhs, Role rhs) { inline uint16_t operator&(Role lhs, Role rhs) {
return uint16_t(lhs) & uint16_t(rhs); return uint16_t(lhs) & uint16_t(rhs);
} }
@ -118,12 +118,18 @@ struct DeclRef : Use {
Range extent; Range extent;
}; };
void Reflect(Reader &visitor, SymbolRef &value); void Reflect(JsonReader &visitor, SymbolRef &value);
void Reflect(Writer &visitor, SymbolRef &value); void Reflect(JsonReader &visitor, Use &value);
void Reflect(Reader &visitor, Use &value); void Reflect(JsonReader &visitor, DeclRef &value);
void Reflect(Writer &visitor, Use &value); void Reflect(JsonWriter &visitor, SymbolRef &value);
void Reflect(Reader &visitor, DeclRef &value); void Reflect(JsonWriter &visitor, Use &value);
void Reflect(Writer &visitor, DeclRef &value); void Reflect(JsonWriter &visitor, DeclRef &value);
void Reflect(BinaryReader &visitor, SymbolRef &value);
void Reflect(BinaryReader &visitor, Use &value);
void Reflect(BinaryReader &visitor, DeclRef &value);
void Reflect(BinaryWriter &visitor, SymbolRef &value);
void Reflect(BinaryWriter &visitor, Use &value);
void Reflect(BinaryWriter &visitor, DeclRef &value);
template <typename D> struct NameMixin { template <typename D> struct NameMixin {
std::string_view Name(bool qualified) const { std::string_view Name(bool qualified) const {
@ -162,7 +168,7 @@ struct FuncDef : NameMixin<FuncDef> {
std::vector<Usr> GetBases() const { return bases; } std::vector<Usr> GetBases() const { return bases; }
}; };
MAKE_REFLECT_STRUCT(FuncDef, detailed_name, hover, comments, spell, bases, vars, REFLECT_STRUCT(FuncDef, detailed_name, hover, comments, spell, bases, vars,
callees, qual_name_offset, short_name_offset, callees, qual_name_offset, short_name_offset,
short_name_size, kind, parent_kind, storage); short_name_size, kind, parent_kind, storage);
@ -199,7 +205,7 @@ struct TypeDef : NameMixin<TypeDef> {
std::vector<Usr> GetBases() const { return bases; } std::vector<Usr> GetBases() const { return bases; }
}; };
MAKE_REFLECT_STRUCT(TypeDef, detailed_name, hover, comments, spell, bases, REFLECT_STRUCT(TypeDef, detailed_name, hover, comments, spell, bases,
funcs, types, vars, alias_of, qual_name_offset, funcs, types, vars, alias_of, qual_name_offset,
short_name_offset, short_name_size, kind, parent_kind); short_name_offset, short_name_size, kind, parent_kind);
@ -243,7 +249,7 @@ struct VarDef : NameMixin<VarDef> {
std::vector<Usr> GetBases() const { return {}; } std::vector<Usr> GetBases() const { return {}; }
}; };
MAKE_REFLECT_STRUCT(VarDef, detailed_name, hover, comments, spell, type, REFLECT_STRUCT(VarDef, detailed_name, hover, comments, spell, type,
qual_name_offset, short_name_offset, short_name_size, kind, qual_name_offset, short_name_offset, short_name_size, kind,
parent_kind, storage); parent_kind, storage);

View File

@ -4,29 +4,30 @@
#include "lsp.hh" #include "lsp.hh"
#include "log.hh" #include "log.hh"
#include "serializers/json.hh"
#include <rapidjson/document.h>
#include <algorithm> #include <algorithm>
#include <stdio.h> #include <stdio.h>
namespace ccls { namespace ccls {
void Reflect(Reader &visitor, RequestId &value) { void Reflect(JsonReader &vis, RequestId &v) {
if (visitor.IsInt64()) { if (vis.m->IsInt64()) {
value.type = RequestId::kInt; v.type = RequestId::kInt;
value.value = int(visitor.GetInt64()); v.value = int(vis.m->GetInt64());
} else if (visitor.IsInt()) { } else if (vis.m->IsInt()) {
value.type = RequestId::kInt; v.type = RequestId::kInt;
value.value = visitor.GetInt(); v.value = vis.m->GetInt();
} else if (visitor.IsString()) { } else if (vis.m->IsString()) {
value.type = RequestId::kString; v.type = RequestId::kString;
value.value = atoll(visitor.GetString()); v.value = atoll(vis.m->GetString());
} else { } else {
value.type = RequestId::kNone; v.type = RequestId::kNone;
value.value = -1; v.value = -1;
} }
} }
void Reflect(Writer &visitor, RequestId &value) { void Reflect(JsonWriter &visitor, RequestId &value) {
switch (value.type) { switch (value.type) {
case RequestId::kNone: case RequestId::kNone:
visitor.Null(); visitor.Null();
@ -36,7 +37,7 @@ void Reflect(Writer &visitor, RequestId &value) {
break; break;
case RequestId::kString: case RequestId::kString:
auto s = std::to_string(value.value); auto s = std::to_string(value.value);
visitor.String(s.c_str(), s.length()); visitor.String(s.c_str(), s.size());
break; break;
} }
} }

View File

@ -23,8 +23,8 @@ struct RequestId {
bool Valid() const { return type != kNone; } bool Valid() const { return type != kNone; }
}; };
void Reflect(Reader &visitor, RequestId &value); void Reflect(JsonReader &visitor, RequestId &value);
void Reflect(Writer &visitor, RequestId &value); void Reflect(JsonWriter &visitor, RequestId &value);
struct InMessage { struct InMessage {
RequestId id; RequestId id;
@ -68,11 +68,6 @@ struct DocumentUri {
std::string raw_uri; std::string raw_uri;
}; };
template <typename TVisitor>
void Reflect(TVisitor &visitor, DocumentUri &value) {
Reflect(visitor, value.raw_uri);
}
struct Position { struct Position {
int line = 0; int line = 0;
int character = 0; int character = 0;
@ -208,7 +203,7 @@ struct WorkspaceFolder {
}; };
enum class MessageType : int { Error = 1, Warning = 2, Info = 3, Log = 4 }; enum class MessageType : int { Error = 1, Warning = 2, Info = 3, Log = 4 };
MAKE_REFLECT_TYPE_PROXY(MessageType) REFLECT_UNDERLYING(MessageType)
struct Diagnostic { struct Diagnostic {
lsRange range; lsRange range;

View File

@ -5,7 +5,6 @@
#include "pipeline.hh" #include "pipeline.hh"
#include "platform.hh" #include "platform.hh"
#include "serializer.hh" #include "serializer.hh"
#include "serializers/json.hh"
#include "test.hh" #include "test.hh"
#include "working_files.hh" #include "working_files.hh"
@ -17,6 +16,7 @@
#include <llvm/Support/Program.h> #include <llvm/Support/Program.h>
#include <llvm/Support/Signals.h> #include <llvm/Support/Signals.h>
#include <rapidjson/document.h>
#include <rapidjson/error/en.h> #include <rapidjson/error/en.h>
#include <stdio.h> #include <stdio.h>

View File

@ -7,7 +7,9 @@
#include "pipeline.hh" #include "pipeline.hh"
#include "project.hh" #include "project.hh"
#include "query.hh" #include "query.hh"
#include "serializers/json.hh"
#include <rapidjson/document.h>
#include <rapidjson/reader.h>
#include <algorithm> #include <algorithm>
#include <stdexcept> #include <stdexcept>
@ -17,35 +19,35 @@ using namespace clang;
MAKE_HASHABLE(ccls::SymbolIdx, t.usr, t.kind); MAKE_HASHABLE(ccls::SymbolIdx, t.usr, t.kind);
namespace ccls { namespace ccls {
MAKE_REFLECT_STRUCT(CodeActionParam::Context, diagnostics); REFLECT_STRUCT(CodeActionParam::Context, diagnostics);
MAKE_REFLECT_STRUCT(CodeActionParam, textDocument, range, context); REFLECT_STRUCT(CodeActionParam, textDocument, range, context);
void Reflect(Reader &, EmptyParam &) {} void Reflect(JsonReader &, EmptyParam &) {}
MAKE_REFLECT_STRUCT(TextDocumentParam, textDocument); REFLECT_STRUCT(TextDocumentParam, textDocument);
MAKE_REFLECT_STRUCT(DidOpenTextDocumentParam, textDocument); REFLECT_STRUCT(DidOpenTextDocumentParam, textDocument);
MAKE_REFLECT_STRUCT(TextDocumentContentChangeEvent, range, rangeLength, text); REFLECT_STRUCT(TextDocumentContentChangeEvent, range, rangeLength, text);
MAKE_REFLECT_STRUCT(TextDocumentDidChangeParam, textDocument, contentChanges); REFLECT_STRUCT(TextDocumentDidChangeParam, textDocument, contentChanges);
MAKE_REFLECT_STRUCT(TextDocumentPositionParam, textDocument, position); REFLECT_STRUCT(TextDocumentPositionParam, textDocument, position);
MAKE_REFLECT_STRUCT(RenameParam, textDocument, position, newName); REFLECT_STRUCT(RenameParam, textDocument, position, newName);
// completion // completion
MAKE_REFLECT_TYPE_PROXY(CompletionTriggerKind); REFLECT_UNDERLYING(CompletionTriggerKind);
MAKE_REFLECT_STRUCT(CompletionContext, triggerKind, triggerCharacter); REFLECT_STRUCT(CompletionContext, triggerKind, triggerCharacter);
MAKE_REFLECT_STRUCT(CompletionParam, textDocument, position, context); REFLECT_STRUCT(CompletionParam, textDocument, position, context);
// formatting // formatting
MAKE_REFLECT_STRUCT(FormattingOptions, tabSize, insertSpaces); REFLECT_STRUCT(FormattingOptions, tabSize, insertSpaces);
MAKE_REFLECT_STRUCT(DocumentFormattingParam, textDocument, options); REFLECT_STRUCT(DocumentFormattingParam, textDocument, options);
MAKE_REFLECT_STRUCT(DocumentOnTypeFormattingParam, textDocument, position, REFLECT_STRUCT(DocumentOnTypeFormattingParam, textDocument, position, ch,
ch, options); options);
MAKE_REFLECT_STRUCT(DocumentRangeFormattingParam, textDocument, range, options); REFLECT_STRUCT(DocumentRangeFormattingParam, textDocument, range, options);
// workspace // workspace
MAKE_REFLECT_TYPE_PROXY(FileChangeType); REFLECT_UNDERLYING(FileChangeType);
MAKE_REFLECT_STRUCT(DidChangeWatchedFilesParam::Event, uri, type); REFLECT_STRUCT(DidChangeWatchedFilesParam::Event, uri, type);
MAKE_REFLECT_STRUCT(DidChangeWatchedFilesParam, changes); REFLECT_STRUCT(DidChangeWatchedFilesParam, changes);
MAKE_REFLECT_STRUCT(DidChangeWorkspaceFoldersParam::Event, added, removed); REFLECT_STRUCT(DidChangeWorkspaceFoldersParam::Event, added, removed);
MAKE_REFLECT_STRUCT(DidChangeWorkspaceFoldersParam, event); REFLECT_STRUCT(DidChangeWorkspaceFoldersParam, event);
MAKE_REFLECT_STRUCT(WorkspaceSymbolParam, query, folders); REFLECT_STRUCT(WorkspaceSymbolParam, query, folders);
namespace { namespace {
struct CclsSemanticHighlightSymbol { struct CclsSemanticHighlightSymbol {
@ -63,15 +65,15 @@ struct CclsSemanticHighlight {
DocumentUri uri; DocumentUri uri;
std::vector<CclsSemanticHighlightSymbol> symbols; std::vector<CclsSemanticHighlightSymbol> symbols;
}; };
MAKE_REFLECT_STRUCT(CclsSemanticHighlightSymbol, id, parentKind, kind, storage, REFLECT_STRUCT(CclsSemanticHighlightSymbol, id, parentKind, kind, storage,
ranges, lsRanges); ranges, lsRanges);
MAKE_REFLECT_STRUCT(CclsSemanticHighlight, uri, symbols); REFLECT_STRUCT(CclsSemanticHighlight, uri, symbols);
struct CclsSetSkippedRanges { struct CclsSetSkippedRanges {
DocumentUri uri; DocumentUri uri;
std::vector<lsRange> skippedRanges; std::vector<lsRange> skippedRanges;
}; };
MAKE_REFLECT_STRUCT(CclsSetSkippedRanges, uri, skippedRanges); REFLECT_STRUCT(CclsSetSkippedRanges, uri, skippedRanges);
struct ScanLineEvent { struct ScanLineEvent {
Position pos; Position pos;
@ -102,8 +104,9 @@ void ReplyOnce::NotReady(bool file) {
Error(ErrorCode::InternalError, "not indexed"); Error(ErrorCode::InternalError, "not indexed");
} }
void MessageHandler::Bind(const char *method, void (MessageHandler::*handler)(Reader &)) { void MessageHandler::Bind(const char *method,
method2notification[method] = [this, handler](Reader &reader) { void (MessageHandler::*handler)(JsonReader &)) {
method2notification[method] = [this, handler](JsonReader &reader) {
(this->*handler)(reader); (this->*handler)(reader);
}; };
} }
@ -111,7 +114,7 @@ void MessageHandler::Bind(const char *method, void (MessageHandler::*handler)(Re
template <typename Param> template <typename Param>
void MessageHandler::Bind(const char *method, void MessageHandler::Bind(const char *method,
void (MessageHandler::*handler)(Param &)) { void (MessageHandler::*handler)(Param &)) {
method2notification[method] = [this, handler](Reader &reader) { method2notification[method] = [this, handler](JsonReader &reader) {
Param param{}; Param param{};
Reflect(reader, param); Reflect(reader, param);
(this->*handler)(param); (this->*handler)(param);
@ -119,9 +122,10 @@ void MessageHandler::Bind(const char *method,
} }
void MessageHandler::Bind(const char *method, void MessageHandler::Bind(const char *method,
void (MessageHandler::*handler)(Reader &, void (MessageHandler::*handler)(JsonReader &,
ReplyOnce &)) { ReplyOnce &)) {
method2request[method] = [this, handler](Reader &reader, ReplyOnce &reply) { method2request[method] = [this, handler](JsonReader &reader,
ReplyOnce &reply) {
(this->*handler)(reader, reply); (this->*handler)(reader, reply);
}; };
} }
@ -130,7 +134,8 @@ template <typename Param>
void MessageHandler::Bind(const char *method, void MessageHandler::Bind(const char *method,
void (MessageHandler::*handler)(Param &, void (MessageHandler::*handler)(Param &,
ReplyOnce &)) { ReplyOnce &)) {
method2request[method] = [this, handler](Reader &reader, ReplyOnce &reply) { method2request[method] = [this, handler](JsonReader &reader,
ReplyOnce &reply) {
Param param{}; Param param{};
Reflect(reader, param); Reflect(reader, param);
(this->*handler)(param, reply); (this->*handler)(param, reply);
@ -202,7 +207,8 @@ void MessageHandler::Run(InMessage &msg) {
it->second(reader, reply); it->second(reader, reply);
} catch (std::invalid_argument &ex) { } catch (std::invalid_argument &ex) {
reply.Error(ErrorCode::InvalidParams, reply.Error(ErrorCode::InvalidParams,
"invalid params of " + msg.method + ": " + ex.what()); "invalid params of " + msg.method + ": expected " +
ex.what() + " for " + reader.GetPath());
} catch (...) { } catch (...) {
reply.Error(ErrorCode::InternalError, "failed to process " + msg.method); reply.Error(ErrorCode::InternalError, "failed to process " + msg.method);
} }

View File

@ -32,8 +32,8 @@ struct WorkingFile;
struct WorkingFiles; struct WorkingFiles;
namespace pipeline { namespace pipeline {
void Reply(RequestId id, const std::function<void(Writer &)> &fn); void Reply(RequestId id, const std::function<void(JsonWriter &)> &fn);
void ReplyError(RequestId id, const std::function<void(Writer &)> &fn); void ReplyError(RequestId id, const std::function<void(JsonWriter &)> &fn);
} }
struct CodeActionParam { struct CodeActionParam {
@ -63,11 +63,11 @@ struct TextDocumentEdit {
VersionedTextDocumentIdentifier textDocument; VersionedTextDocumentIdentifier textDocument;
std::vector<TextEdit> edits; std::vector<TextEdit> edits;
}; };
MAKE_REFLECT_STRUCT(TextDocumentEdit, textDocument, edits); REFLECT_STRUCT(TextDocumentEdit, textDocument, edits);
struct WorkspaceEdit { struct WorkspaceEdit {
std::vector<TextDocumentEdit> documentChanges; std::vector<TextDocumentEdit> documentChanges;
}; };
MAKE_REFLECT_STRUCT(WorkspaceEdit, documentChanges); REFLECT_STRUCT(WorkspaceEdit, documentChanges);
// completion // completion
enum class CompletionTriggerKind { enum class CompletionTriggerKind {
@ -175,32 +175,39 @@ struct WorkspaceSymbolParam {
// ccls extensions // ccls extensions
std::vector<std::string> folders; std::vector<std::string> folders;
}; };
MAKE_REFLECT_STRUCT(WorkspaceFolder, uri, name); REFLECT_STRUCT(WorkspaceFolder, uri, name);
MAKE_REFLECT_TYPE_PROXY(ErrorCode); inline void Reflect(JsonReader &visitor, DocumentUri &value) {
MAKE_REFLECT_STRUCT(ResponseError, code, message); Reflect(visitor, value.raw_uri);
MAKE_REFLECT_STRUCT(Position, line, character); }
MAKE_REFLECT_STRUCT(lsRange, start, end); inline void Reflect(JsonWriter &visitor, DocumentUri &value) {
MAKE_REFLECT_STRUCT(Location, uri, range); Reflect(visitor, value.raw_uri);
MAKE_REFLECT_TYPE_PROXY(SymbolKind); }
MAKE_REFLECT_STRUCT(TextDocumentIdentifier, uri);
MAKE_REFLECT_STRUCT(TextDocumentItem, uri, languageId, version, text); REFLECT_UNDERLYING(ErrorCode);
MAKE_REFLECT_STRUCT(TextEdit, range, newText); REFLECT_STRUCT(ResponseError, code, message);
MAKE_REFLECT_STRUCT(VersionedTextDocumentIdentifier, uri, version); REFLECT_STRUCT(Position, line, character);
MAKE_REFLECT_STRUCT(Diagnostic, range, severity, code, source, message); REFLECT_STRUCT(lsRange, start, end);
MAKE_REFLECT_STRUCT(ShowMessageParam, type, message); REFLECT_STRUCT(Location, uri, range);
MAKE_REFLECT_TYPE_PROXY(LanguageId); REFLECT_UNDERLYING_B(SymbolKind);
REFLECT_STRUCT(TextDocumentIdentifier, uri);
REFLECT_STRUCT(TextDocumentItem, uri, languageId, version, text);
REFLECT_STRUCT(TextEdit, range, newText);
REFLECT_STRUCT(VersionedTextDocumentIdentifier, uri, version);
REFLECT_STRUCT(Diagnostic, range, severity, code, source, message);
REFLECT_STRUCT(ShowMessageParam, type, message);
REFLECT_UNDERLYING_B(LanguageId);
struct ReplyOnce { struct ReplyOnce {
RequestId id; RequestId id;
template <typename Res> void operator()(Res &&result) const { template <typename Res> void operator()(Res &&result) const {
if (id.Valid()) if (id.Valid())
pipeline::Reply(id, [&](Writer &w) { Reflect(w, result); }); pipeline::Reply(id, [&](JsonWriter &w) { Reflect(w, result); });
} }
void Error(ErrorCode code, std::string message) const { void Error(ErrorCode code, std::string message) const {
ResponseError err{code, std::move(message)}; ResponseError err{code, std::move(message)};
if (id.Valid()) if (id.Valid())
pipeline::ReplyError(id, [&](Writer &w) { Reflect(w, err); }); pipeline::ReplyError(id, [&](JsonWriter &w) { Reflect(w, err); });
} }
void NotReady(bool file); void NotReady(bool file);
}; };
@ -213,33 +220,34 @@ struct MessageHandler {
VFS *vfs = nullptr; VFS *vfs = nullptr;
WorkingFiles *wfiles = nullptr; WorkingFiles *wfiles = nullptr;
llvm::StringMap<std::function<void(Reader &)>> method2notification; llvm::StringMap<std::function<void(JsonReader &)>> method2notification;
llvm::StringMap<std::function<void(Reader &, ReplyOnce &)>> method2request; llvm::StringMap<std::function<void(JsonReader &, ReplyOnce &)>>
method2request;
MessageHandler(); MessageHandler();
void Run(InMessage &msg); void Run(InMessage &msg);
QueryFile *FindFile(const std::string &path, int *out_file_id = nullptr); QueryFile *FindFile(const std::string &path, int *out_file_id = nullptr);
private: private:
void Bind(const char *method, void (MessageHandler::*handler)(Reader &)); void Bind(const char *method, void (MessageHandler::*handler)(JsonReader &));
template <typename Param> template <typename Param>
void Bind(const char *method, void (MessageHandler::*handler)(Param &)); void Bind(const char *method, void (MessageHandler::*handler)(Param &));
void Bind(const char *method, void Bind(const char *method,
void (MessageHandler::*handler)(Reader &, ReplyOnce &)); void (MessageHandler::*handler)(JsonReader &, ReplyOnce &));
template <typename Param> template <typename Param>
void Bind(const char *method, void Bind(const char *method,
void (MessageHandler::*handler)(Param &, ReplyOnce &)); void (MessageHandler::*handler)(Param &, ReplyOnce &));
void ccls_call(Reader &, ReplyOnce &); void ccls_call(JsonReader &, ReplyOnce &);
void ccls_fileInfo(TextDocumentParam &, ReplyOnce &); void ccls_fileInfo(TextDocumentParam &, ReplyOnce &);
void ccls_info(EmptyParam &, ReplyOnce &); void ccls_info(EmptyParam &, ReplyOnce &);
void ccls_inheritance(Reader &, ReplyOnce &); void ccls_inheritance(JsonReader &, ReplyOnce &);
void ccls_member(Reader &, ReplyOnce &); void ccls_member(JsonReader &, ReplyOnce &);
void ccls_navigate(Reader &, ReplyOnce &); void ccls_navigate(JsonReader &, ReplyOnce &);
void ccls_reload(Reader &); void ccls_reload(JsonReader &);
void ccls_vars(Reader &, ReplyOnce &); void ccls_vars(JsonReader &, ReplyOnce &);
void exit(EmptyParam &); void exit(EmptyParam &);
void initialize(Reader &, ReplyOnce &); void initialize(JsonReader &, ReplyOnce &);
void shutdown(EmptyParam &, ReplyOnce &); void shutdown(EmptyParam &, ReplyOnce &);
void textDocument_codeAction(CodeActionParam &, ReplyOnce &); void textDocument_codeAction(CodeActionParam &, ReplyOnce &);
void textDocument_codeLens(TextDocumentParam &, ReplyOnce &); void textDocument_codeLens(TextDocumentParam &, ReplyOnce &);
@ -251,7 +259,7 @@ private:
void textDocument_didSave(TextDocumentParam &); void textDocument_didSave(TextDocumentParam &);
void textDocument_documentHighlight(TextDocumentPositionParam &, ReplyOnce &); void textDocument_documentHighlight(TextDocumentPositionParam &, ReplyOnce &);
void textDocument_documentLink(TextDocumentParam &, ReplyOnce &); void textDocument_documentLink(TextDocumentParam &, ReplyOnce &);
void textDocument_documentSymbol(Reader &, ReplyOnce &); void textDocument_documentSymbol(JsonReader &, ReplyOnce &);
void textDocument_foldingRange(TextDocumentParam &, ReplyOnce &); void textDocument_foldingRange(TextDocumentParam &, ReplyOnce &);
void textDocument_formatting(DocumentFormattingParam &, ReplyOnce &); void textDocument_formatting(DocumentFormattingParam &, ReplyOnce &);
void textDocument_hover(TextDocumentPositionParam &, ReplyOnce &); void textDocument_hover(TextDocumentPositionParam &, ReplyOnce &);
@ -260,14 +268,14 @@ private:
ReplyOnce &); ReplyOnce &);
void textDocument_rangeFormatting(DocumentRangeFormattingParam &, void textDocument_rangeFormatting(DocumentRangeFormattingParam &,
ReplyOnce &); ReplyOnce &);
void textDocument_references(Reader &, ReplyOnce &); void textDocument_references(JsonReader &, ReplyOnce &);
void textDocument_rename(RenameParam &, ReplyOnce &); void textDocument_rename(RenameParam &, ReplyOnce &);
void textDocument_signatureHelp(TextDocumentPositionParam &, ReplyOnce &); void textDocument_signatureHelp(TextDocumentPositionParam &, ReplyOnce &);
void textDocument_typeDefinition(TextDocumentPositionParam &, ReplyOnce &); void textDocument_typeDefinition(TextDocumentPositionParam &, ReplyOnce &);
void workspace_didChangeConfiguration(EmptyParam &); void workspace_didChangeConfiguration(EmptyParam &);
void workspace_didChangeWatchedFiles(DidChangeWatchedFilesParam &); void workspace_didChangeWatchedFiles(DidChangeWatchedFilesParam &);
void workspace_didChangeWorkspaceFolders(DidChangeWorkspaceFoldersParam &); void workspace_didChangeWorkspaceFolders(DidChangeWorkspaceFoldersParam &);
void workspace_executeCommand(Reader &, ReplyOnce &); void workspace_executeCommand(JsonReader &, ReplyOnce &);
void workspace_symbol(WorkspaceSymbolParam &, ReplyOnce &); void workspace_symbol(WorkspaceSymbolParam &, ReplyOnce &);
}; };

View File

@ -18,7 +18,7 @@ enum class CallType : uint8_t {
Derived = 2, Derived = 2,
All = 1 | 2 All = 1 | 2
}; };
MAKE_REFLECT_TYPE_PROXY(CallType); REFLECT_UNDERLYING(CallType);
bool operator&(CallType lhs, CallType rhs) { bool operator&(CallType lhs, CallType rhs) {
return uint8_t(lhs) & uint8_t(rhs); return uint8_t(lhs) & uint8_t(rhs);
@ -40,8 +40,8 @@ struct Param : TextDocumentPositionParam {
int levels = 1; int levels = 1;
bool hierarchy = false; bool hierarchy = false;
}; };
MAKE_REFLECT_STRUCT(Param, textDocument, position, id, callee, callType, REFLECT_STRUCT(Param, textDocument, position, id, callee, callType, qualified,
qualified, levels, hierarchy); levels, hierarchy);
struct Out_cclsCall { struct Out_cclsCall {
Usr usr; Usr usr;
@ -57,8 +57,8 @@ struct Out_cclsCall {
} }
bool operator<(const Out_cclsCall &o) const { return location < o.location; } bool operator<(const Out_cclsCall &o) const { return location < o.location; }
}; };
MAKE_REFLECT_STRUCT(Out_cclsCall, id, name, location, callType, numChildren, REFLECT_STRUCT(Out_cclsCall, id, name, location, callType, numChildren,
children); children);
bool Expand(MessageHandler *m, Out_cclsCall *entry, bool callee, bool Expand(MessageHandler *m, Out_cclsCall *entry, bool callee,
CallType call_type, bool qualified, int levels) { CallType call_type, bool qualified, int levels) {
@ -170,7 +170,7 @@ std::optional<Out_cclsCall> BuildInitial(MessageHandler *m, Usr root_usr,
} }
} // namespace } // namespace
void MessageHandler::ccls_call(Reader &reader, ReplyOnce &reply) { void MessageHandler::ccls_call(JsonReader &reader, ReplyOnce &reply) {
Param param; Param param;
Reflect(reader, param); Reflect(reader, param);
std::optional<Out_cclsCall> result; std::optional<Out_cclsCall> result;

View File

@ -19,8 +19,8 @@ limitations under the License.
#include "query.hh" #include "query.hh"
namespace ccls { namespace ccls {
MAKE_REFLECT_STRUCT(QueryFile::Def, path, args, language, skipped_ranges, REFLECT_STRUCT(QueryFile::Def, path, args, language, skipped_ranges,
dependencies); dependencies);
namespace { namespace {
struct Out_cclsInfo { struct Out_cclsInfo {
@ -34,10 +34,10 @@ struct Out_cclsInfo {
int entries; int entries;
} project; } project;
}; };
MAKE_REFLECT_STRUCT(Out_cclsInfo::DB, files, funcs, types, vars); REFLECT_STRUCT(Out_cclsInfo::DB, files, funcs, types, vars);
MAKE_REFLECT_STRUCT(Out_cclsInfo::Pipeline, pendingIndexRequests); REFLECT_STRUCT(Out_cclsInfo::Pipeline, pendingIndexRequests);
MAKE_REFLECT_STRUCT(Out_cclsInfo::Project, entries); REFLECT_STRUCT(Out_cclsInfo::Project, entries);
MAKE_REFLECT_STRUCT(Out_cclsInfo, db, pipeline, project); REFLECT_STRUCT(Out_cclsInfo, db, pipeline, project);
} // namespace } // namespace
void MessageHandler::ccls_info(EmptyParam &, ReplyOnce &reply) { void MessageHandler::ccls_info(EmptyParam &, ReplyOnce &reply) {

View File

@ -24,8 +24,8 @@ struct Param : TextDocumentPositionParam {
bool hierarchy = false; bool hierarchy = false;
}; };
MAKE_REFLECT_STRUCT(Param, textDocument, position, id, kind, derived, qualified, REFLECT_STRUCT(Param, textDocument, position, id, kind, derived, qualified,
levels, hierarchy); levels, hierarchy);
struct Out_cclsInheritance { struct Out_cclsInheritance {
Usr usr; Usr usr;
@ -39,8 +39,8 @@ struct Out_cclsInheritance {
// Empty if the |levels| limit is reached. // Empty if the |levels| limit is reached.
std::vector<Out_cclsInheritance> children; std::vector<Out_cclsInheritance> children;
}; };
MAKE_REFLECT_STRUCT(Out_cclsInheritance, id, kind, name, location, numChildren, REFLECT_STRUCT(Out_cclsInheritance, id, kind, name, location, numChildren,
children); children);
bool Expand(MessageHandler *m, Out_cclsInheritance *entry, bool derived, bool Expand(MessageHandler *m, Out_cclsInheritance *entry, bool derived,
bool qualified, int levels); bool qualified, int levels);
@ -153,7 +153,7 @@ void Inheritance(MessageHandler *m, Param &param, ReplyOnce &reply) {
} }
} // namespace } // namespace
void MessageHandler::ccls_inheritance(Reader &reader, ReplyOnce &reply) { void MessageHandler::ccls_inheritance(JsonReader &reader, ReplyOnce &reply) {
Param param; Param param;
Reflect(reader, param); Reflect(reader, param);
Inheritance(this, param, reply); Inheritance(this, param, reply);

View File

@ -30,8 +30,8 @@ struct Param : TextDocumentPositionParam {
bool hierarchy = false; bool hierarchy = false;
}; };
MAKE_REFLECT_STRUCT(Param, textDocument, position, id, qualified, levels, kind, REFLECT_STRUCT(Param, textDocument, position, id, qualified, levels, kind,
hierarchy); hierarchy);
struct Out_cclsMember { struct Out_cclsMember {
Usr usr; Usr usr;
@ -45,8 +45,8 @@ struct Out_cclsMember {
// Empty if the |levels| limit is reached. // Empty if the |levels| limit is reached.
std::vector<Out_cclsMember> children; std::vector<Out_cclsMember> children;
}; };
MAKE_REFLECT_STRUCT(Out_cclsMember, id, name, fieldName, location, numChildren, REFLECT_STRUCT(Out_cclsMember, id, name, fieldName, location, numChildren,
children); children);
bool Expand(MessageHandler *m, Out_cclsMember *entry, bool qualified, bool Expand(MessageHandler *m, Out_cclsMember *entry, bool qualified,
int levels, Kind memberKind); int levels, Kind memberKind);
@ -251,7 +251,7 @@ std::optional<Out_cclsMember> BuildInitial(MessageHandler *m, Kind kind,
} }
} // namespace } // namespace
void MessageHandler::ccls_member(Reader &reader, ReplyOnce &reply) { void MessageHandler::ccls_member(JsonReader &reader, ReplyOnce &reply) {
Param param; Param param;
Reflect(reader, param); Reflect(reader, param);
std::optional<Out_cclsMember> result; std::optional<Out_cclsMember> result;

View File

@ -23,7 +23,7 @@ struct Param {
Position position; Position position;
std::string direction; std::string direction;
}; };
MAKE_REFLECT_STRUCT(Param, textDocument, position, direction); REFLECT_STRUCT(Param, textDocument, position, direction);
Maybe<Range> FindParent(QueryFile *file, Pos pos) { Maybe<Range> FindParent(QueryFile *file, Pos pos) {
Maybe<Range> parent; Maybe<Range> parent;
@ -38,8 +38,7 @@ Maybe<Range> FindParent(QueryFile *file, Pos pos) {
} }
} // namespace } // namespace
void MessageHandler::ccls_navigate(Reader &reader, void MessageHandler::ccls_navigate(JsonReader &reader, ReplyOnce &reply) {
ReplyOnce &reply) {
Param param; Param param;
Reflect(reader, param); Reflect(reader, param);
QueryFile *file = FindFile(param.textDocument.uri.GetPath()); QueryFile *file = FindFile(param.textDocument.uri.GetPath());

View File

@ -17,10 +17,10 @@ struct Param {
std::vector<std::string> whitelist; std::vector<std::string> whitelist;
std::vector<std::string> blacklist; std::vector<std::string> blacklist;
}; };
MAKE_REFLECT_STRUCT(Param, dependencies, whitelist, blacklist); REFLECT_STRUCT(Param, dependencies, whitelist, blacklist);
} // namespace } // namespace
void MessageHandler::ccls_reload(Reader &reader) { void MessageHandler::ccls_reload(JsonReader &reader) {
Param param; Param param;
Reflect(reader, param); Reflect(reader, param);
// Send index requests for every file. // Send index requests for every file.

View File

@ -13,10 +13,10 @@ struct Param : TextDocumentPositionParam {
// 4: parameter // 4: parameter
unsigned kind = ~0u; unsigned kind = ~0u;
}; };
MAKE_REFLECT_STRUCT(Param, textDocument, position, kind); REFLECT_STRUCT(Param, textDocument, position, kind);
} // namespace } // namespace
void MessageHandler::ccls_vars(Reader &reader, ReplyOnce &reply) { void MessageHandler::ccls_vars(JsonReader &reader, ReplyOnce &reply) {
Param param; Param param;
Reflect(reader, param); Reflect(reader, param);
QueryFile *file = FindFile(param.textDocument.uri.GetPath()); QueryFile *file = FindFile(param.textDocument.uri.GetPath());

View File

@ -9,12 +9,14 @@
#include "pipeline.hh" #include "pipeline.hh"
#include "platform.hh" #include "platform.hh"
#include "project.hh" #include "project.hh"
#include "serializers/json.hh"
#include "working_files.hh" #include "working_files.hh"
#include <llvm/ADT/Twine.h> #include <llvm/ADT/Twine.h>
#include <llvm/Support/Threading.h> #include <llvm/Support/Threading.h>
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdexcept> #include <stdexcept>
#include <thread> #include <thread>
@ -27,7 +29,7 @@ extern std::string g_init_options;
namespace { namespace {
enum class TextDocumentSyncKind { None = 0, Full = 1, Incremental = 2 }; enum class TextDocumentSyncKind { None = 0, Full = 1, Incremental = 2 };
MAKE_REFLECT_TYPE_PROXY(TextDocumentSyncKind) REFLECT_UNDERLYING(TextDocumentSyncKind)
struct ServerCap { struct ServerCap {
struct SaveOptions { struct SaveOptions {
@ -92,37 +94,36 @@ struct ServerCap {
} workspaceFolders; } workspaceFolders;
} workspace; } workspace;
}; };
MAKE_REFLECT_STRUCT(ServerCap::CodeActionOptions, codeActionKinds); REFLECT_STRUCT(ServerCap::CodeActionOptions, codeActionKinds);
MAKE_REFLECT_STRUCT(ServerCap::CodeLensOptions, resolveProvider); REFLECT_STRUCT(ServerCap::CodeLensOptions, resolveProvider);
MAKE_REFLECT_STRUCT(ServerCap::CompletionOptions, resolveProvider, REFLECT_STRUCT(ServerCap::CompletionOptions, resolveProvider,
triggerCharacters); triggerCharacters);
MAKE_REFLECT_STRUCT(ServerCap::DocumentLinkOptions, resolveProvider); REFLECT_STRUCT(ServerCap::DocumentLinkOptions, resolveProvider);
MAKE_REFLECT_STRUCT(ServerCap::DocumentOnTypeFormattingOptions, REFLECT_STRUCT(ServerCap::DocumentOnTypeFormattingOptions,
firstTriggerCharacter, moreTriggerCharacter); firstTriggerCharacter, moreTriggerCharacter);
MAKE_REFLECT_STRUCT(ServerCap::ExecuteCommandOptions, commands); REFLECT_STRUCT(ServerCap::ExecuteCommandOptions, commands);
MAKE_REFLECT_STRUCT(ServerCap::SaveOptions, includeText); REFLECT_STRUCT(ServerCap::SaveOptions, includeText);
MAKE_REFLECT_STRUCT(ServerCap::SignatureHelpOptions, triggerCharacters); REFLECT_STRUCT(ServerCap::SignatureHelpOptions, triggerCharacters);
MAKE_REFLECT_STRUCT(ServerCap::TextDocumentSyncOptions, openClose, change, REFLECT_STRUCT(ServerCap::TextDocumentSyncOptions, openClose, change, willSave,
willSave, willSaveWaitUntil, save); willSaveWaitUntil, save);
MAKE_REFLECT_STRUCT(ServerCap::Workspace::WorkspaceFolders, supported, REFLECT_STRUCT(ServerCap::Workspace::WorkspaceFolders, supported,
changeNotifications); changeNotifications);
MAKE_REFLECT_STRUCT(ServerCap::Workspace, workspaceFolders); REFLECT_STRUCT(ServerCap::Workspace, workspaceFolders);
MAKE_REFLECT_STRUCT(ServerCap, textDocumentSync, hoverProvider, REFLECT_STRUCT(ServerCap, textDocumentSync, hoverProvider, completionProvider,
completionProvider, signatureHelpProvider, signatureHelpProvider, definitionProvider,
definitionProvider, implementationProvider, implementationProvider, typeDefinitionProvider,
typeDefinitionProvider, referencesProvider, referencesProvider, documentHighlightProvider,
documentHighlightProvider, documentSymbolProvider, documentSymbolProvider, workspaceSymbolProvider,
workspaceSymbolProvider, codeActionProvider, codeActionProvider, codeLensProvider, documentFormattingProvider,
codeLensProvider, documentFormattingProvider, documentRangeFormattingProvider,
documentRangeFormattingProvider, documentOnTypeFormattingProvider, renameProvider,
documentOnTypeFormattingProvider, renameProvider, documentLinkProvider, foldingRangeProvider,
documentLinkProvider, foldingRangeProvider, executeCommandProvider, workspace);
executeCommandProvider, workspace);
struct DynamicReg { struct DynamicReg {
bool dynamicRegistration = false; bool dynamicRegistration = false;
}; };
MAKE_REFLECT_STRUCT(DynamicReg, dynamicRegistration); REFLECT_STRUCT(DynamicReg, dynamicRegistration);
// Workspace specific client capabilities. // Workspace specific client capabilities.
struct WorkspaceClientCap { struct WorkspaceClientCap {
@ -142,10 +143,10 @@ struct WorkspaceClientCap {
DynamicReg executeCommand; DynamicReg executeCommand;
}; };
MAKE_REFLECT_STRUCT(WorkspaceClientCap::WorkspaceEdit, documentChanges); REFLECT_STRUCT(WorkspaceClientCap::WorkspaceEdit, documentChanges);
MAKE_REFLECT_STRUCT(WorkspaceClientCap, applyEdit, workspaceEdit, REFLECT_STRUCT(WorkspaceClientCap, applyEdit, workspaceEdit,
didChangeConfiguration, didChangeWatchedFiles, symbol, didChangeConfiguration, didChangeWatchedFiles, symbol,
executeCommand); executeCommand);
// Text document specific client capabilities. // Text document specific client capabilities.
struct TextDocumentClientCap { struct TextDocumentClientCap {
@ -166,18 +167,18 @@ struct TextDocumentClientCap {
} documentSymbol; } documentSymbol;
}; };
MAKE_REFLECT_STRUCT(TextDocumentClientCap::Completion::CompletionItem, REFLECT_STRUCT(TextDocumentClientCap::Completion::CompletionItem,
snippetSupport); snippetSupport);
MAKE_REFLECT_STRUCT(TextDocumentClientCap::Completion, completionItem); REFLECT_STRUCT(TextDocumentClientCap::Completion, completionItem);
MAKE_REFLECT_STRUCT(TextDocumentClientCap::DocumentSymbol, REFLECT_STRUCT(TextDocumentClientCap::DocumentSymbol,
hierarchicalDocumentSymbolSupport); hierarchicalDocumentSymbolSupport);
MAKE_REFLECT_STRUCT(TextDocumentClientCap, completion, documentSymbol); REFLECT_STRUCT(TextDocumentClientCap, completion, documentSymbol);
struct ClientCap { struct ClientCap {
WorkspaceClientCap workspace; WorkspaceClientCap workspace;
TextDocumentClientCap textDocument; TextDocumentClientCap textDocument;
}; };
MAKE_REFLECT_STRUCT(ClientCap, workspace, textDocument); REFLECT_STRUCT(ClientCap, workspace, textDocument);
struct InitializeParam { struct InitializeParam {
// The rootUri of the workspace. Is null if no // The rootUri of the workspace. Is null if no
@ -199,12 +200,12 @@ struct InitializeParam {
std::vector<WorkspaceFolder> workspaceFolders; std::vector<WorkspaceFolder> workspaceFolders;
}; };
void Reflect(Reader &reader, InitializeParam::Trace &value) { void Reflect(JsonReader &reader, InitializeParam::Trace &value) {
if (!reader.IsString()) { if (!reader.m->IsString()) {
value = InitializeParam::Trace::Off; value = InitializeParam::Trace::Off;
return; return;
} }
std::string v = reader.GetString(); std::string v = reader.m->GetString();
if (v == "off") if (v == "off")
value = InitializeParam::Trace::Off; value = InitializeParam::Trace::Off;
else if (v == "messages") else if (v == "messages")
@ -213,13 +214,13 @@ void Reflect(Reader &reader, InitializeParam::Trace &value) {
value = InitializeParam::Trace::Verbose; value = InitializeParam::Trace::Verbose;
} }
MAKE_REFLECT_STRUCT(InitializeParam, rootUri, initializationOptions, REFLECT_STRUCT(InitializeParam, rootUri, initializationOptions, capabilities,
capabilities, trace, workspaceFolders); trace, workspaceFolders);
struct InitializeResult { struct InitializeResult {
ServerCap capabilities; ServerCap capabilities;
}; };
MAKE_REFLECT_STRUCT(InitializeResult, capabilities); REFLECT_STRUCT(InitializeResult, capabilities);
void *Indexer(void *arg_) { void *Indexer(void *arg_) {
MessageHandler *h; MessageHandler *h;
@ -329,7 +330,7 @@ void Initialize(MessageHandler *m, InitializeParam &param, ReplyOnce &reply) {
m->manager->sessions.SetCapacity(g_config->session.maxNum); m->manager->sessions.SetCapacity(g_config->session.maxNum);
} }
void MessageHandler::initialize(Reader &reader, ReplyOnce &reply) { void MessageHandler::initialize(JsonReader &reader, ReplyOnce &reply) {
InitializeParam param; InitializeParam param;
Reflect(reader, param); Reflect(reader, param);
if (!param.rootUri) { if (!param.rootUri) {

View File

@ -16,10 +16,12 @@ limitations under the License.
#include "message_handler.hh" #include "message_handler.hh"
#include "pipeline.hh" #include "pipeline.hh"
#include "query.hh" #include "query.hh"
#include "serializers/json.hh"
#include <llvm/Support/FormatVariadic.h> #include <llvm/Support/FormatVariadic.h>
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <unordered_set> #include <unordered_set>
namespace ccls { namespace ccls {
@ -29,7 +31,7 @@ struct CodeAction {
const char *kind = "quickfix"; const char *kind = "quickfix";
WorkspaceEdit edit; WorkspaceEdit edit;
}; };
MAKE_REFLECT_STRUCT(CodeAction, title, kind, edit); REFLECT_STRUCT(CodeAction, title, kind, edit);
} }
void MessageHandler::textDocument_codeAction(CodeActionParam &param, void MessageHandler::textDocument_codeAction(CodeActionParam &param,
ReplyOnce &reply) { ReplyOnce &reply) {
@ -72,9 +74,9 @@ struct CodeLens {
lsRange range; lsRange range;
std::optional<Command> command; std::optional<Command> command;
}; };
MAKE_REFLECT_STRUCT(Cmd_xref, usr, kind, field); REFLECT_STRUCT(Cmd_xref, usr, kind, field);
MAKE_REFLECT_STRUCT(Command, title, command, arguments); REFLECT_STRUCT(Command, title, command, arguments);
MAKE_REFLECT_STRUCT(CodeLens, range, command); REFLECT_STRUCT(CodeLens, range, command);
template <typename T> template <typename T>
std::string ToString(T &v) { std::string ToString(T &v) {
@ -174,7 +176,7 @@ void MessageHandler::textDocument_codeLens(TextDocumentParam &param,
reply(result); reply(result);
} }
void MessageHandler::workspace_executeCommand(Reader &reader, void MessageHandler::workspace_executeCommand(JsonReader &reader,
ReplyOnce &reply) { ReplyOnce &reply) {
Command param; Command param;
Reflect(reader, param); Reflect(reader, param);

View File

@ -20,11 +20,11 @@ namespace ccls {
using namespace clang; using namespace clang;
using namespace llvm; using namespace llvm;
MAKE_REFLECT_TYPE_PROXY(InsertTextFormat); REFLECT_UNDERLYING(InsertTextFormat);
MAKE_REFLECT_TYPE_PROXY(CompletionItemKind); REFLECT_UNDERLYING(CompletionItemKind);
void Reflect(Writer &vis, CompletionItem &v) { void Reflect(JsonWriter &vis, CompletionItem &v) {
REFLECT_MEMBER_START(); ReflectMemberStart(vis);
REFLECT_MEMBER(label); REFLECT_MEMBER(label);
REFLECT_MEMBER(kind); REFLECT_MEMBER(kind);
REFLECT_MEMBER(detail); REFLECT_MEMBER(detail);
@ -37,7 +37,7 @@ void Reflect(Writer &vis, CompletionItem &v) {
REFLECT_MEMBER(textEdit); REFLECT_MEMBER(textEdit);
if (v.additionalTextEdits.size()) if (v.additionalTextEdits.size())
REFLECT_MEMBER(additionalTextEdits); REFLECT_MEMBER(additionalTextEdits);
REFLECT_MEMBER_END(); ReflectMemberEnd(vis);
} }
namespace { namespace {
@ -45,7 +45,7 @@ struct CompletionList {
bool isIncomplete = false; bool isIncomplete = false;
std::vector<CompletionItem> items; std::vector<CompletionItem> items;
}; };
MAKE_REFLECT_STRUCT(CompletionList, isIncomplete, items); REFLECT_STRUCT(CompletionList, isIncomplete, items);
#if LLVM_VERSION_MAJOR < 8 #if LLVM_VERSION_MAJOR < 8
void DecorateIncludePaths(const std::smatch &match, void DecorateIncludePaths(const std::smatch &match,

View File

@ -10,7 +10,7 @@
MAKE_HASHABLE(ccls::SymbolIdx, t.usr, t.kind); MAKE_HASHABLE(ccls::SymbolIdx, t.usr, t.kind);
namespace ccls { namespace ccls {
MAKE_REFLECT_STRUCT(SymbolInformation, name, kind, location, containerName); REFLECT_STRUCT(SymbolInformation, name, kind, location, containerName);
namespace { namespace {
struct DocumentHighlight { struct DocumentHighlight {
@ -26,7 +26,7 @@ struct DocumentHighlight {
return !(range == o.range) ? range < o.range : kind < o.kind; return !(range == o.range) ? range < o.range : kind < o.kind;
} }
}; };
MAKE_REFLECT_STRUCT(DocumentHighlight, range, kind, role); REFLECT_STRUCT(DocumentHighlight, range, kind, role);
} // namespace } // namespace
void MessageHandler::textDocument_documentHighlight( void MessageHandler::textDocument_documentHighlight(
@ -73,7 +73,7 @@ struct DocumentLink {
lsRange range; lsRange range;
DocumentUri target; DocumentUri target;
}; };
MAKE_REFLECT_STRUCT(DocumentLink, range, target); REFLECT_STRUCT(DocumentLink, range, target);
} // namespace } // namespace
void MessageHandler::textDocument_documentLink(TextDocumentParam &param, void MessageHandler::textDocument_documentLink(TextDocumentParam &param,
@ -106,7 +106,7 @@ struct DocumentSymbolParam : TextDocumentParam {
int startLine = -1; int startLine = -1;
int endLine = -1; int endLine = -1;
}; };
MAKE_REFLECT_STRUCT(DocumentSymbolParam, textDocument, all, startLine, endLine); REFLECT_STRUCT(DocumentSymbolParam, textDocument, all, startLine, endLine);
struct DocumentSymbol { struct DocumentSymbol {
std::string name; std::string name;
@ -116,10 +116,10 @@ struct DocumentSymbol {
lsRange selectionRange; lsRange selectionRange;
std::vector<std::unique_ptr<DocumentSymbol>> children; std::vector<std::unique_ptr<DocumentSymbol>> children;
}; };
void Reflect(Writer &vis, std::unique_ptr<DocumentSymbol> &v); void Reflect(JsonWriter &vis, std::unique_ptr<DocumentSymbol> &v);
MAKE_REFLECT_STRUCT(DocumentSymbol, name, detail, kind, range, selectionRange, REFLECT_STRUCT(DocumentSymbol, name, detail, kind, range, selectionRange,
children); children);
void Reflect(Writer &vis, std::unique_ptr<DocumentSymbol> &v) { void Reflect(JsonWriter &vis, std::unique_ptr<DocumentSymbol> &v) {
Reflect(vis, *v); Reflect(vis, *v);
} }
@ -147,7 +147,7 @@ void Uniquify(std::vector<std::unique_ptr<DocumentSymbol>> &cs) {
} }
} // namespace } // namespace
void MessageHandler::textDocument_documentSymbol(Reader &reader, void MessageHandler::textDocument_documentSymbol(JsonReader &reader,
ReplyOnce &reply) { ReplyOnce &reply) {
DocumentSymbolParam param; DocumentSymbolParam param;
Reflect(reader, param); Reflect(reader, param);

View File

@ -25,8 +25,8 @@ struct FoldingRange {
int startLine, startCharacter, endLine, endCharacter; int startLine, startCharacter, endLine, endCharacter;
std::string kind = "region"; std::string kind = "region";
}; };
MAKE_REFLECT_STRUCT(FoldingRange, startLine, startCharacter, endLine, REFLECT_STRUCT(FoldingRange, startLine, startCharacter, endLine, endCharacter,
endCharacter, kind); kind);
} // namespace } // namespace
void MessageHandler::textDocument_foldingRange(TextDocumentParam &param, void MessageHandler::textDocument_foldingRange(TextDocumentParam &param,

View File

@ -15,19 +15,19 @@ struct Hover {
std::optional<lsRange> range; std::optional<lsRange> range;
}; };
void Reflect(Writer &vis, MarkedString &v) { void Reflect(JsonWriter &vis, MarkedString &v) {
// If there is a language, emit a `{language:string, value:string}` object. If // If there is a language, emit a `{language:string, value:string}` object. If
// not, emit a string. // not, emit a string.
if (v.language) { if (v.language) {
REFLECT_MEMBER_START(); vis.StartObject();
REFLECT_MEMBER(language); REFLECT_MEMBER(language);
REFLECT_MEMBER(value); REFLECT_MEMBER(value);
REFLECT_MEMBER_END(); vis.EndObject();
} else { } else {
Reflect(vis, v.value); Reflect(vis, v.value);
} }
} }
MAKE_REFLECT_STRUCT(Hover, contents, range); REFLECT_STRUCT(Hover, contents, range);
const char *LanguageIdentifier(LanguageId lang) { const char *LanguageIdentifier(LanguageId lang) {
switch (lang) { switch (lang) {

View File

@ -24,12 +24,13 @@ struct ReferenceParam : public TextDocumentPositionParam {
// Include references with all |Role| bits set. // Include references with all |Role| bits set.
Role role = Role::None; Role role = Role::None;
}; };
MAKE_REFLECT_STRUCT(ReferenceParam::Context, includeDeclaration); REFLECT_STRUCT(ReferenceParam::Context, includeDeclaration);
MAKE_REFLECT_STRUCT(ReferenceParam, textDocument, position, context, folders, REFLECT_STRUCT(ReferenceParam, textDocument, position, context, folders, base,
base, excludeRole, role); excludeRole, role);
} // namespace } // namespace
void MessageHandler::textDocument_references(Reader &reader, ReplyOnce &reply) { void MessageHandler::textDocument_references(JsonReader &reader,
ReplyOnce &reply) {
ReferenceParam param; ReferenceParam param;
Reflect(reader, param); Reflect(reader, param);
QueryFile *file = FindFile(param.textDocument.uri.GetPath()); QueryFile *file = FindFile(param.textDocument.uri.GetPath());

View File

@ -24,10 +24,9 @@ struct SignatureHelp {
int activeSignature = 0; int activeSignature = 0;
int activeParameter = 0; int activeParameter = 0;
}; };
MAKE_REFLECT_STRUCT(ParameterInformation, label); REFLECT_STRUCT(ParameterInformation, label);
MAKE_REFLECT_STRUCT(SignatureInformation, label, documentation, parameters); REFLECT_STRUCT(SignatureInformation, label, documentation, parameters);
MAKE_REFLECT_STRUCT(SignatureHelp, signatures, activeSignature, REFLECT_STRUCT(SignatureHelp, signatures, activeSignature, activeParameter);
activeParameter);
std::string BuildOptional(const CodeCompletionString &CCS, std::string BuildOptional(const CodeCompletionString &CCS,
std::vector<ParameterInformation> &ls_params) { std::vector<ParameterInformation> &ls_params) {

View File

@ -30,7 +30,7 @@ limitations under the License.
#include <limits.h> #include <limits.h>
namespace ccls { namespace ccls {
MAKE_REFLECT_STRUCT(SymbolInformation, name, kind, location, containerName); REFLECT_STRUCT(SymbolInformation, name, kind, location, containerName);
void MessageHandler::workspace_didChangeConfiguration(EmptyParam &) { void MessageHandler::workspace_didChangeConfiguration(EmptyParam &) {
for (const std::string &folder : g_config->workspaceFolders) for (const std::string &folder : g_config->workspaceFolders)

View File

@ -13,7 +13,6 @@
#include "project.hh" #include "project.hh"
#include "query.hh" #include "query.hh"
#include "sema_manager.hh" #include "sema_manager.hh"
#include "serializers/json.hh"
#include <rapidjson/document.h> #include <rapidjson/document.h>
#include <rapidjson/writer.h> #include <rapidjson/writer.h>
@ -37,7 +36,7 @@ struct PublishDiagnosticParam {
DocumentUri uri; DocumentUri uri;
std::vector<Diagnostic> diagnostics; std::vector<Diagnostic> diagnostics;
}; };
MAKE_REFLECT_STRUCT(PublishDiagnosticParam, uri, diagnostics); REFLECT_STRUCT(PublishDiagnosticParam, uri, diagnostics);
} // namespace } // namespace
void VFS::Clear() { void VFS::Clear() {
@ -445,8 +444,8 @@ void LaunchStdin() {
assert(!document->HasParseError()); assert(!document->HasParseError());
JsonReader reader{document.get()}; JsonReader reader{document.get()};
if (!reader.HasMember("jsonrpc") || if (!reader.m->HasMember("jsonrpc") ||
std::string(reader["jsonrpc"]->GetString()) != "2.0") std::string((*reader.m)["jsonrpc"].GetString()) != "2.0")
return; return;
RequestId id; RequestId id;
std::string method; std::string method;
@ -598,7 +597,7 @@ std::optional<std::string> LoadIndexedContent(const std::string &path) {
return ReadContent(GetCachePath(path)); return ReadContent(GetCachePath(path));
} }
void Notify(const char *method, const std::function<void(Writer &)> &fn) { void Notify(const char *method, const std::function<void(JsonWriter &)> &fn) {
rapidjson::StringBuffer output; rapidjson::StringBuffer output;
rapidjson::Writer<rapidjson::StringBuffer> w(output); rapidjson::Writer<rapidjson::StringBuffer> w(output);
w.StartObject(); w.StartObject();
@ -614,7 +613,7 @@ void Notify(const char *method, const std::function<void(Writer &)> &fn) {
} }
static void Reply(RequestId id, const char *key, static void Reply(RequestId id, const char *key,
const std::function<void(Writer &)> &fn) { const std::function<void(JsonWriter &)> &fn) {
rapidjson::StringBuffer output; rapidjson::StringBuffer output;
rapidjson::Writer<rapidjson::StringBuffer> w(output); rapidjson::Writer<rapidjson::StringBuffer> w(output);
w.StartObject(); w.StartObject();
@ -640,11 +639,11 @@ static void Reply(RequestId id, const char *key,
for_stdout->PushBack(output.GetString()); for_stdout->PushBack(output.GetString());
} }
void Reply(RequestId id, const std::function<void(Writer &)> &fn) { void Reply(RequestId id, const std::function<void(JsonWriter &)> &fn) {
Reply(id, "result", fn); Reply(id, "result", fn);
} }
void ReplyError(RequestId id, const std::function<void(Writer &)> &fn) { void ReplyError(RequestId id, const std::function<void(JsonWriter &)> &fn) {
Reply(id, "error", fn); Reply(id, "error", fn);
} }
} // namespace pipeline } // namespace pipeline

View File

@ -54,16 +54,16 @@ void Index(const std::string &path, const std::vector<const char *> &args,
std::optional<std::string> LoadIndexedContent(const std::string& path); std::optional<std::string> LoadIndexedContent(const std::string& path);
void Notify(const char *method, const std::function<void(Writer &)> &fn); void Notify(const char *method, const std::function<void(JsonWriter &)> &fn);
template <typename T> void Notify(const char *method, T &result) { template <typename T> void Notify(const char *method, T &result) {
Notify(method, [&](Writer &w) { Reflect(w, result); }); Notify(method, [&](JsonWriter &w) { Reflect(w, result); });
} }
void Reply(RequestId id, const std::function<void(Writer &)> &fn); void Reply(RequestId id, const std::function<void(JsonWriter &)> &fn);
void ReplyError(RequestId id, const std::function<void(Writer &)> &fn); void ReplyError(RequestId id, const std::function<void(JsonWriter &)> &fn);
template <typename T> void ReplyError(RequestId id, T &result) { template <typename T> void ReplyError(RequestId id, T &result) {
ReplyError(id, [&](Writer &w) { Reflect(w, result); }); ReplyError(id, [&](JsonWriter &w) { Reflect(w, result); });
} }
} // namespace pipeline } // namespace pipeline
} // namespace ccls } // namespace ccls

View File

@ -5,6 +5,9 @@
#include "serializer.hh" #include "serializer.hh"
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <algorithm> #include <algorithm>
#include <limits.h> #include <limits.h>
#include <stdio.h> #include <stdio.h>
@ -57,45 +60,39 @@ std::string Range::ToString() {
return buf; return buf;
} }
// Position void Reflect(JsonReader &vis, Pos &v) { v = Pos::FromString(vis.GetString()); }
void Reflect(Reader &visitor, Pos &value) { void Reflect(JsonReader &vis, Range &v) {
if (visitor.Format() == SerializeFormat::Json) { v = Range::FromString(vis.GetString());
value = Pos::FromString(visitor.GetString());
} else {
Reflect(visitor, value.line);
Reflect(visitor, value.column);
}
}
void Reflect(Writer &visitor, Pos &value) {
if (visitor.Format() == SerializeFormat::Json) {
std::string output = value.ToString();
visitor.String(output.c_str(), output.size());
} else {
Reflect(visitor, value.line);
Reflect(visitor, value.column);
}
} }
// Range void Reflect(JsonWriter &vis, Pos &v) {
void Reflect(Reader &visitor, Range &value) { std::string output = v.ToString();
if (visitor.Format() == SerializeFormat::Json) { vis.String(output.c_str(), output.size());
value = Range::FromString(visitor.GetString());
} else {
Reflect(visitor, value.start.line);
Reflect(visitor, value.start.column);
Reflect(visitor, value.end.line);
Reflect(visitor, value.end.column);
}
} }
void Reflect(Writer &visitor, Range &value) { void Reflect(JsonWriter &vis, Range &v) {
if (visitor.Format() == SerializeFormat::Json) { std::string output = v.ToString();
std::string output = value.ToString(); vis.String(output.c_str(), output.size());
visitor.String(output.c_str(), output.size()); }
} else {
Reflect(visitor, value.start.line); void Reflect(BinaryReader &visitor, Pos &value) {
Reflect(visitor, value.start.column); Reflect(visitor, value.line);
Reflect(visitor, value.end.line); Reflect(visitor, value.column);
Reflect(visitor, value.end.column); }
} void Reflect(BinaryReader &visitor, Range &value) {
Reflect(visitor, value.start.line);
Reflect(visitor, value.start.column);
Reflect(visitor, value.end.line);
Reflect(visitor, value.end.column);
}
void Reflect(BinaryWriter &vis, Pos &v) {
Reflect(vis, v.line);
Reflect(vis, v.column);
}
void Reflect(BinaryWriter &vis, Range &v) {
Reflect(vis, v.start.line);
Reflect(vis, v.start.column);
Reflect(vis, v.end.line);
Reflect(vis, v.end.column);
} }
} // namespace ccls } // namespace ccls

View File

@ -51,12 +51,19 @@ struct Range {
}; };
// Reflection // Reflection
class Reader; struct JsonReader;
class Writer; struct JsonWriter;
void Reflect(Reader &visitor, Pos &value); struct BinaryReader;
void Reflect(Writer &visitor, Pos &value); struct BinaryWriter;
void Reflect(Reader &visitor, Range &value);
void Reflect(Writer &visitor, Range &value); void Reflect(JsonReader &visitor, Pos &value);
void Reflect(JsonReader &visitor, Range &value);
void Reflect(JsonWriter &visitor, Pos &value);
void Reflect(JsonWriter &visitor, Range &value);
void Reflect(BinaryReader &visitor, Pos &value);
void Reflect(BinaryReader &visitor, Range &value);
void Reflect(BinaryWriter &visitor, Pos &value);
void Reflect(BinaryWriter &visitor, Range &value);
} // namespace ccls } // namespace ccls
namespace std { namespace std {

View File

@ -8,7 +8,6 @@
#include "log.hh" #include "log.hh"
#include "pipeline.hh" #include "pipeline.hh"
#include "platform.hh" #include "platform.hh"
#include "serializers/json.hh"
#include "utils.hh" #include "utils.hh"
#include "working_files.hh" #include "working_files.hh"

View File

@ -6,7 +6,8 @@
#include "indexer.hh" #include "indexer.hh"
#include "pipeline.hh" #include "pipeline.hh"
#include "serializer.hh" #include "serializer.hh"
#include "serializers/json.hh"
#include <rapidjson/document.h>
#include <assert.h> #include <assert.h>
#include <stdint.h> #include <stdint.h>

View File

@ -7,8 +7,9 @@
#include "indexer.hh" #include "indexer.hh"
#include "log.hh" #include "log.hh"
#include "message_handler.hh" #include "message_handler.hh"
#include "serializers/binary.hh"
#include "serializers/json.hh" #include <rapidjson/document.h>
#include <rapidjson/prettywriter.h>
#include <llvm/ADT/CachedHashString.h> #include <llvm/ADT/CachedHashString.h>
#include <llvm/ADT/DenseSet.h> #include <llvm/ADT/DenseSet.h>
@ -21,181 +22,198 @@ using namespace llvm;
bool gTestOutputMode = false; bool gTestOutputMode = false;
namespace ccls { namespace ccls {
Reader::~Reader() {}
BinaryReader::~BinaryReader() {}
JsonReader::~JsonReader() {}
Writer::~Writer() {} void JsonReader::IterArray(std::function<void()> fn) {
BinaryWriter::~BinaryWriter() {} if (!m->IsArray())
JsonWriter::~JsonWriter() {} throw std::invalid_argument("array");
// Use "0" to indicate any element for now.
void Reflect(Reader &vis, uint8_t &v) { v = vis.GetUInt8(); } path_.push_back("0");
void Reflect(Writer &vis, uint8_t &v) { vis.UInt8(v); } for (auto &entry : m->GetArray()) {
auto saved = m;
void Reflect(Reader &vis, short &v) { m = &entry;
if (!vis.IsInt()) fn();
throw std::invalid_argument("short"); m = saved;
v = (short)vis.GetInt(); }
path_.pop_back();
} }
void Reflect(Writer &vis, short &v) { vis.Int(v); } void JsonReader::Member(const char *name, std::function<void()> fn) {
path_.push_back(name);
void Reflect(Reader &vis, unsigned short &v) { auto it = m->FindMember(name);
if (!vis.IsInt()) if (it != m->MemberEnd()) {
throw std::invalid_argument("unsigned short"); auto saved = m;
v = (unsigned short)vis.GetInt(); m = &it->value;
fn();
m = saved;
}
path_.pop_back();
} }
void Reflect(Writer &vis, unsigned short &v) { vis.Int(v); } bool JsonReader::IsNull() { return m->IsNull(); }
std::string JsonReader::GetString() { return m->GetString(); }
void Reflect(Reader &vis, int &v) { std::string JsonReader::GetPath() const {
if (!vis.IsInt()) std::string ret;
throw std::invalid_argument("int"); for (auto &t : path_)
v = vis.GetInt(); if (t[0] == '0') {
} ret += '[';
void Reflect(Writer &vis, int &v) { vis.Int(v); } ret += t;
ret += ']';
void Reflect(Reader &vis, unsigned &v) { } else {
if (!vis.IsUInt64()) ret += '/';
throw std::invalid_argument("unsigned"); ret += t;
v = vis.GetUInt32(); }
} return ret;
void Reflect(Writer &vis, unsigned &v) { vis.UInt32(v); }
void Reflect(Reader &vis, long &v) {
if (!vis.IsInt64())
throw std::invalid_argument("long");
v = long(vis.GetInt64());
}
void Reflect(Writer &vis, long &v) { vis.Int64(v); }
void Reflect(Reader &vis, unsigned long &v) {
if (!vis.IsUInt64())
throw std::invalid_argument("unsigned long");
v = (unsigned long)vis.GetUInt64();
}
void Reflect(Writer &vis, unsigned long &v) { vis.UInt64(v); }
void Reflect(Reader &vis, long long &v) {
if (!vis.IsInt64())
throw std::invalid_argument("long long");
v = vis.GetInt64();
}
void Reflect(Writer &vis, long long &v) { vis.Int64(v); }
void Reflect(Reader &vis, unsigned long long &v) {
if (!vis.IsUInt64())
throw std::invalid_argument("unsigned long long");
v = vis.GetUInt64();
}
void Reflect(Writer &vis, unsigned long long &v) { vis.UInt64(v); }
void Reflect(Reader &vis, double &v) {
if (!vis.IsDouble())
throw std::invalid_argument("double");
v = vis.GetDouble();
}
void Reflect(Writer &vis, double &v) { vis.Double(v); }
void Reflect(Reader &vis, bool &v) {
if (!vis.IsBool())
throw std::invalid_argument("bool");
v = vis.GetBool();
}
void Reflect(Writer &vis, bool &v) { vis.Bool(v); }
void Reflect(Reader &vis, std::string &v) {
if (!vis.IsString())
throw std::invalid_argument("std::string");
v = vis.GetString();
}
void Reflect(Writer &vis, std::string &v) {
vis.String(v.c_str(), (rapidjson::SizeType)v.size());
} }
void Reflect(Reader &, std::string_view &) { assert(0); } void JsonWriter::StartArray() { m->StartArray(); }
void Reflect(Writer &vis, std::string_view &data) { void JsonWriter::EndArray() { m->EndArray(); }
void JsonWriter::StartObject() { m->StartObject(); }
void JsonWriter::EndObject() { m->EndObject(); }
void JsonWriter::Key(const char *name) { m->Key(name); }
void JsonWriter::Null() { m->Null(); }
void JsonWriter::Int(int v) { m->Int(v); }
void JsonWriter::String(const char *s) { m->String(s); }
void JsonWriter::String(const char *s, size_t len) { m->String(s, len); }
// clang-format off
void Reflect(JsonReader &vis, bool &v ) { if (!vis.m->IsBool()) throw std::invalid_argument("bool"); v = vis.m->GetBool(); }
void Reflect(JsonReader &vis, unsigned char &v ) { if (!vis.m->IsInt()) throw std::invalid_argument("uint8_t"); v = (uint8_t)vis.m->GetInt(); }
void Reflect(JsonReader &vis, short &v ) { if (!vis.m->IsInt()) throw std::invalid_argument("short"); v = (short)vis.m->GetInt(); }
void Reflect(JsonReader &vis, unsigned short &v ) { if (!vis.m->IsInt()) throw std::invalid_argument("unsigned short"); v = (unsigned short)vis.m->GetInt(); }
void Reflect(JsonReader &vis, int &v ) { if (!vis.m->IsInt()) throw std::invalid_argument("int"); v = vis.m->GetInt(); }
void Reflect(JsonReader &vis, unsigned &v ) { if (!vis.m->IsUint64()) throw std::invalid_argument("unsigned"); v = (unsigned)vis.m->GetUint64(); }
void Reflect(JsonReader &vis, long &v ) { if (!vis.m->IsInt64()) throw std::invalid_argument("long"); v = (long)vis.m->GetInt64(); }
void Reflect(JsonReader &vis, unsigned long &v ) { if (!vis.m->IsUint64()) throw std::invalid_argument("unsigned long"); v = (unsigned long)vis.m->GetUint64(); }
void Reflect(JsonReader &vis, long long &v ) { if (!vis.m->IsInt64()) throw std::invalid_argument("long long"); v = vis.m->GetInt64(); }
void Reflect(JsonReader &vis, unsigned long long &v) { if (!vis.m->IsUint64()) throw std::invalid_argument("unsigned long long"); v = vis.m->GetUint64(); }
void Reflect(JsonReader &vis, double &v ) { if (!vis.m->IsDouble()) throw std::invalid_argument("double"); v = vis.m->GetDouble(); }
void Reflect(JsonReader &vis, const char *&v ) { if (!vis.m->IsString()) throw std::invalid_argument("string"); v = Intern(vis.GetString()); }
void Reflect(JsonReader &vis, std::string &v ) { if (!vis.m->IsString()) throw std::invalid_argument("string"); v = vis.GetString(); }
void Reflect(JsonWriter &vis, bool &v ) { vis.m->Bool(v); }
void Reflect(JsonWriter &vis, unsigned char &v ) { vis.m->Int(v); }
void Reflect(JsonWriter &vis, short &v ) { vis.m->Int(v); }
void Reflect(JsonWriter &vis, unsigned short &v ) { vis.m->Int(v); }
void Reflect(JsonWriter &vis, int &v ) { vis.m->Int(v); }
void Reflect(JsonWriter &vis, unsigned &v ) { vis.m->Uint64(v); }
void Reflect(JsonWriter &vis, long &v ) { vis.m->Int64(v); }
void Reflect(JsonWriter &vis, unsigned long &v ) { vis.m->Uint64(v); }
void Reflect(JsonWriter &vis, long long &v ) { vis.m->Int64(v); }
void Reflect(JsonWriter &vis, unsigned long long &v) { vis.m->Uint64(v); }
void Reflect(JsonWriter &vis, double &v ) { vis.m->Double(v); }
void Reflect(JsonWriter &vis, const char *&v ) { vis.String(v); }
void Reflect(JsonWriter &vis, std::string &v ) { vis.String(v.c_str(), v.size()); }
void Reflect(BinaryReader &vis, bool &v ) { v = vis.Get<bool>(); }
void Reflect(BinaryReader &vis, unsigned char &v ) { v = vis.Get<unsigned char>(); }
void Reflect(BinaryReader &vis, short &v ) { v = (short)vis.VarInt(); }
void Reflect(BinaryReader &vis, unsigned short &v ) { v = (unsigned short)vis.VarUInt(); }
void Reflect(BinaryReader &vis, int &v ) { v = (int)vis.VarInt(); }
void Reflect(BinaryReader &vis, unsigned &v ) { v = (unsigned)vis.VarUInt(); }
void Reflect(BinaryReader &vis, long &v ) { v = (long)vis.VarInt(); }
void Reflect(BinaryReader &vis, unsigned long &v ) { v = (unsigned long)vis.VarUInt(); }
void Reflect(BinaryReader &vis, long long &v ) { v = vis.VarInt(); }
void Reflect(BinaryReader &vis, unsigned long long &v) { v = vis.VarUInt(); }
void Reflect(BinaryReader &vis, double &v ) { v = vis.Get<double>(); }
void Reflect(BinaryReader &vis, const char *&v ) { v = Intern(vis.GetString()); }
void Reflect(BinaryReader &vis, std::string &v ) { v = vis.GetString(); }
void Reflect(BinaryWriter &vis, bool &v ) { vis.Pack(v); }
void Reflect(BinaryWriter &vis, unsigned char &v ) { vis.Pack(v); }
void Reflect(BinaryWriter &vis, short &v ) { vis.VarInt(v); }
void Reflect(BinaryWriter &vis, unsigned short &v ) { vis.VarUInt(v); }
void Reflect(BinaryWriter &vis, int &v ) { vis.VarInt(v); }
void Reflect(BinaryWriter &vis, unsigned &v ) { vis.VarUInt(v); }
void Reflect(BinaryWriter &vis, long &v ) { vis.VarInt(v); }
void Reflect(BinaryWriter &vis, unsigned long &v ) { vis.VarUInt(v); }
void Reflect(BinaryWriter &vis, long long &v ) { vis.VarInt(v); }
void Reflect(BinaryWriter &vis, unsigned long long &v) { vis.VarUInt(v); }
void Reflect(BinaryWriter &vis, double &v ) { vis.Pack(v); }
void Reflect(BinaryWriter &vis, const char *&v ) { vis.String(v); }
void Reflect(BinaryWriter &vis, std::string &v ) { vis.String(v.c_str(), v.size()); }
// clang-format on
void Reflect(JsonWriter &vis, std::string_view &data) {
if (data.empty()) if (data.empty())
vis.String(""); vis.String("");
else else
vis.String(&data[0], (rapidjson::SizeType)data.size()); vis.String(&data[0], (rapidjson::SizeType)data.size());
} }
void Reflect(Reader &vis, const char *&v) { void Reflect(JsonReader &vis, JsonNull &v) {}
const char *str = vis.GetString(); void Reflect(JsonWriter &vis, JsonNull &v) { vis.m->Null(); }
v = Intern(str);
}
void Reflect(Writer &vis, const char *&v) { vis.String(v); }
void Reflect(Reader &vis, JsonNull &v) {
assert(vis.Format() == SerializeFormat::Json);
vis.GetNull();
}
void Reflect(Writer &vis, JsonNull &v) { vis.Null(); }
// std::unordered_map
template <typename V> template <typename V>
void Reflect(Reader &vis, std::unordered_map<Usr, V> &map) { void Reflect(JsonReader &vis, std::unordered_map<Usr, V> &v) {
vis.IterArray([&](Reader &entry) { vis.IterArray([&]() {
V val; V val;
Reflect(entry, val); Reflect(vis, val);
auto usr = val.usr; v[val.usr] = std::move(val);
map[usr] = std::move(val);
}); });
} }
template <typename V> template <typename V>
void Reflect(Writer &vis, std::unordered_map<Usr, V> &map) { void Reflect(JsonWriter &vis, std::unordered_map<Usr, V> &v) {
std::vector<std::pair<uint64_t, V>> xs(map.begin(), map.end()); // Determinism
std::vector<std::pair<uint64_t, V>> xs(v.begin(), v.end());
std::sort(xs.begin(), xs.end(), std::sort(xs.begin(), xs.end(),
[](const auto &a, const auto &b) { return a.first < b.first; }); [](const auto &a, const auto &b) { return a.first < b.first; });
vis.StartArray(xs.size()); vis.StartArray();
for (auto &it : xs) for (auto &it : xs)
Reflect(vis, it.second); Reflect(vis, it.second);
vis.EndArray(); vis.EndArray();
} }
template <typename V>
void Reflect(BinaryReader &vis, std::unordered_map<Usr, V> &v) {
for (auto n = vis.VarUInt(); n; n--) {
V val;
Reflect(vis, val);
v[val.usr] = std::move(val);
}
}
template <typename V>
void Reflect(BinaryWriter &vis, std::unordered_map<Usr, V> &v) {
vis.VarUInt(v.size());
for (auto &it : v)
Reflect(vis, it.second);
}
// Used by IndexFile::dependencies. // Used by IndexFile::dependencies.
void Reflect(Reader &vis, DenseMap<CachedHashStringRef, int64_t> &v) { void Reflect(JsonReader &vis, DenseMap<CachedHashStringRef, int64_t> &v) {
std::string name; std::string name;
if (vis.Format() == SerializeFormat::Json) { for (auto it = vis.m->MemberBegin(); it != vis.m->MemberEnd(); ++it)
auto &vis1 = static_cast<JsonReader&>(vis); v[InternH(it->name.GetString())] = it->value.GetInt64();
for (auto it = vis1.m().MemberBegin(); it != vis1.m().MemberEnd(); ++it) }
v[InternH(it->name.GetString())] = it->value.GetInt64(); void Reflect(JsonWriter &vis, DenseMap<CachedHashStringRef, int64_t> &v) {
} else { vis.StartObject();
vis.IterArray([&](Reader &entry) { for (auto &it : v) {
Reflect(entry, name); vis.m->Key(it.first.val().data()); // llvm 8 -> data()
Reflect(entry, v[InternH(name)]); vis.m->Int64(it.second);
}); }
vis.EndObject();
}
void Reflect(BinaryReader &vis, DenseMap<CachedHashStringRef, int64_t> &v) {
std::string name;
for (auto n = vis.VarUInt(); n; n--) {
Reflect(vis, name);
Reflect(vis, v[InternH(name)]);
} }
} }
void Reflect(Writer &vis, DenseMap<CachedHashStringRef, int64_t> &v) { void Reflect(BinaryWriter &vis, DenseMap<CachedHashStringRef, int64_t> &v) {
if (vis.Format() == SerializeFormat::Json) { std::string key;
auto &vis1 = static_cast<JsonWriter&>(vis); vis.VarUInt(v.size());
vis.StartObject(); for (auto &it : v) {
for (auto &it : v) { key = it.first.val().str();
vis1.m().Key(it.first.val().data()); // llvm 8 -> data() Reflect(vis, key);
vis1.m().Int64(it.second); Reflect(vis, it.second);
}
vis.EndObject();
} else {
vis.StartArray(v.size());
for (auto &it : v) {
std::string key = it.first.val().str();
Reflect(vis, key);
Reflect(vis, it.second);
}
vis.EndArray();
} }
} }
// TODO: Move this to indexer.cc template <typename Vis> void Reflect(Vis &vis, IndexInclude &v) {
void Reflect(Reader &vis, IndexInclude &v) { ReflectMemberStart(vis);
REFLECT_MEMBER_START();
REFLECT_MEMBER(line); REFLECT_MEMBER(line);
REFLECT_MEMBER(resolved_path); REFLECT_MEMBER(resolved_path);
REFLECT_MEMBER_END(); ReflectMemberEnd(vis);
} }
void Reflect(Writer &vis, IndexInclude &v) { void Reflect(JsonWriter &vis, IndexInclude &v) {
REFLECT_MEMBER_START(); ReflectMemberStart(vis);
REFLECT_MEMBER(line); REFLECT_MEMBER(line);
if (gTestOutputMode) { if (gTestOutputMode) {
std::string basename = llvm::sys::path::filename(v.resolved_path); std::string basename = llvm::sys::path::filename(v.resolved_path);
@ -205,23 +223,34 @@ void Reflect(Writer &vis, IndexInclude &v) {
} else { } else {
REFLECT_MEMBER(resolved_path); REFLECT_MEMBER(resolved_path);
} }
REFLECT_MEMBER_END(); ReflectMemberEnd(vis);
} }
template <typename Def> void ReflectHoverAndComments(Reader &vis, Def &def) { template <typename Def>
void ReflectHoverAndComments(JsonReader &vis, Def &def) {
ReflectMember(vis, "hover", def.hover); ReflectMember(vis, "hover", def.hover);
ReflectMember(vis, "comments", def.comments); ReflectMember(vis, "comments", def.comments);
} }
template <typename Def>
template <typename Def> void ReflectHoverAndComments(Writer &vis, Def &def) { void ReflectHoverAndComments(JsonWriter &vis, Def &def) {
// Don't emit empty hover and comments in JSON test mode. // Don't emit empty hover and comments in JSON test mode.
if (!gTestOutputMode || def.hover[0]) if (!gTestOutputMode || def.hover[0])
ReflectMember(vis, "hover", def.hover); ReflectMember(vis, "hover", def.hover);
if (!gTestOutputMode || def.comments[0]) if (!gTestOutputMode || def.comments[0])
ReflectMember(vis, "comments", def.comments); ReflectMember(vis, "comments", def.comments);
} }
template <typename Def>
void ReflectHoverAndComments(BinaryReader &vis, Def &def) {
Reflect(vis, def.hover);
Reflect(vis, def.comments);
}
template <typename Def>
void ReflectHoverAndComments(BinaryWriter &vis, Def &def) {
Reflect(vis, def.hover);
Reflect(vis, def.comments);
}
template <typename Def> void ReflectShortName(Reader &vis, Def &def) { template <typename Def> void ReflectShortName(JsonReader &vis, Def &def) {
if (gTestOutputMode) { if (gTestOutputMode) {
std::string short_name; std::string short_name;
ReflectMember(vis, "short_name", short_name); ReflectMember(vis, "short_name", short_name);
@ -234,8 +263,7 @@ template <typename Def> void ReflectShortName(Reader &vis, Def &def) {
ReflectMember(vis, "short_name_size", def.short_name_size); ReflectMember(vis, "short_name_size", def.short_name_size);
} }
} }
template <typename Def> void ReflectShortName(JsonWriter &vis, Def &def) {
template <typename Def> void ReflectShortName(Writer &vis, Def &def) {
if (gTestOutputMode) { if (gTestOutputMode) {
std::string_view short_name(def.detailed_name + def.short_name_offset, std::string_view short_name(def.detailed_name + def.short_name_offset,
def.short_name_size); def.short_name_size);
@ -245,9 +273,17 @@ template <typename Def> void ReflectShortName(Writer &vis, Def &def) {
ReflectMember(vis, "short_name_size", def.short_name_size); ReflectMember(vis, "short_name_size", def.short_name_size);
} }
} }
template <typename Def> void ReflectShortName(BinaryReader &vis, Def &def) {
Reflect(vis, def.short_name_offset);
Reflect(vis, def.short_name_size);
}
template <typename Def> void ReflectShortName(BinaryWriter &vis, Def &def) {
Reflect(vis, def.short_name_offset);
Reflect(vis, def.short_name_size);
}
template <typename TVisitor> void Reflect(TVisitor &vis, IndexFunc &v) { template <typename TVisitor> void Reflect1(TVisitor &vis, IndexFunc &v) {
REFLECT_MEMBER_START(); ReflectMemberStart(vis);
REFLECT_MEMBER2("usr", v.usr); REFLECT_MEMBER2("usr", v.usr);
REFLECT_MEMBER2("detailed_name", v.def.detailed_name); REFLECT_MEMBER2("detailed_name", v.def.detailed_name);
REFLECT_MEMBER2("qual_name_offset", v.def.qual_name_offset); REFLECT_MEMBER2("qual_name_offset", v.def.qual_name_offset);
@ -264,11 +300,15 @@ template <typename TVisitor> void Reflect(TVisitor &vis, IndexFunc &v) {
REFLECT_MEMBER2("declarations", v.declarations); REFLECT_MEMBER2("declarations", v.declarations);
REFLECT_MEMBER2("derived", v.derived); REFLECT_MEMBER2("derived", v.derived);
REFLECT_MEMBER2("uses", v.uses); REFLECT_MEMBER2("uses", v.uses);
REFLECT_MEMBER_END(); ReflectMemberEnd(vis);
} }
void Reflect(JsonReader &vis, IndexFunc &v) { Reflect1(vis, v); }
void Reflect(JsonWriter &vis, IndexFunc &v) { Reflect1(vis, v); }
void Reflect(BinaryReader &vis, IndexFunc &v) { Reflect1(vis, v); }
void Reflect(BinaryWriter &vis, IndexFunc &v) { Reflect1(vis, v); }
template <typename TVisitor> void Reflect(TVisitor &vis, IndexType &v) { template <typename TVisitor> void Reflect1(TVisitor &vis, IndexType &v) {
REFLECT_MEMBER_START(); ReflectMemberStart(vis);
REFLECT_MEMBER2("usr", v.usr); REFLECT_MEMBER2("usr", v.usr);
REFLECT_MEMBER2("detailed_name", v.def.detailed_name); REFLECT_MEMBER2("detailed_name", v.def.detailed_name);
REFLECT_MEMBER2("qual_name_offset", v.def.qual_name_offset); REFLECT_MEMBER2("qual_name_offset", v.def.qual_name_offset);
@ -287,11 +327,15 @@ template <typename TVisitor> void Reflect(TVisitor &vis, IndexType &v) {
REFLECT_MEMBER2("derived", v.derived); REFLECT_MEMBER2("derived", v.derived);
REFLECT_MEMBER2("instances", v.instances); REFLECT_MEMBER2("instances", v.instances);
REFLECT_MEMBER2("uses", v.uses); REFLECT_MEMBER2("uses", v.uses);
REFLECT_MEMBER_END(); ReflectMemberEnd(vis);
} }
void Reflect(JsonReader &vis, IndexType &v) { Reflect1(vis, v); }
void Reflect(JsonWriter &vis, IndexType &v) { Reflect1(vis, v); }
void Reflect(BinaryReader &vis, IndexType &v) { Reflect1(vis, v); }
void Reflect(BinaryWriter &vis, IndexType &v) { Reflect1(vis, v); }
template <typename TVisitor> void Reflect(TVisitor &vis, IndexVar &v) { template <typename TVisitor> void Reflect1(TVisitor &vis, IndexVar &v) {
REFLECT_MEMBER_START(); ReflectMemberStart(vis);
REFLECT_MEMBER2("usr", v.usr); REFLECT_MEMBER2("usr", v.usr);
REFLECT_MEMBER2("detailed_name", v.def.detailed_name); REFLECT_MEMBER2("detailed_name", v.def.detailed_name);
REFLECT_MEMBER2("qual_name_offset", v.def.qual_name_offset); REFLECT_MEMBER2("qual_name_offset", v.def.qual_name_offset);
@ -305,16 +349,16 @@ template <typename TVisitor> void Reflect(TVisitor &vis, IndexVar &v) {
REFLECT_MEMBER2("declarations", v.declarations); REFLECT_MEMBER2("declarations", v.declarations);
REFLECT_MEMBER2("uses", v.uses); REFLECT_MEMBER2("uses", v.uses);
REFLECT_MEMBER_END(); ReflectMemberEnd(vis);
} }
void Reflect(JsonReader &vis, IndexVar &v) { Reflect1(vis, v); }
void Reflect(JsonWriter &vis, IndexVar &v) { Reflect1(vis, v); }
void Reflect(BinaryReader &vis, IndexVar &v) { Reflect1(vis, v); }
void Reflect(BinaryWriter &vis, IndexVar &v) { Reflect1(vis, v); }
// IndexFile // IndexFile
bool ReflectMemberStart(Writer &vis, IndexFile &v) { template <typename TVisitor> void Reflect1(TVisitor &vis, IndexFile &v) {
vis.StartObject(); ReflectMemberStart(vis);
return true;
}
template <typename TVisitor> void Reflect(TVisitor &vis, IndexFile &v) {
REFLECT_MEMBER_START();
if (!gTestOutputMode) { if (!gTestOutputMode) {
REFLECT_MEMBER(mtime); REFLECT_MEMBER(mtime);
REFLECT_MEMBER(language); REFLECT_MEMBER(language);
@ -328,15 +372,19 @@ template <typename TVisitor> void Reflect(TVisitor &vis, IndexFile &v) {
REFLECT_MEMBER(usr2func); REFLECT_MEMBER(usr2func);
REFLECT_MEMBER(usr2type); REFLECT_MEMBER(usr2type);
REFLECT_MEMBER(usr2var); REFLECT_MEMBER(usr2var);
REFLECT_MEMBER_END(); ReflectMemberEnd(vis);
} }
void ReflectFile(JsonReader &vis, IndexFile &v) { Reflect1(vis, v); }
void ReflectFile(JsonWriter &vis, IndexFile &v) { Reflect1(vis, v); }
void ReflectFile(BinaryReader &vis, IndexFile &v) { Reflect1(vis, v); }
void ReflectFile(BinaryWriter &vis, IndexFile &v) { Reflect1(vis, v); }
void Reflect(Reader &vis, SerializeFormat &v) { void Reflect(JsonReader &vis, SerializeFormat &v) {
v = vis.GetString()[0] == 'j' ? SerializeFormat::Json v = vis.GetString()[0] == 'j' ? SerializeFormat::Json
: SerializeFormat::Binary; : SerializeFormat::Binary;
} }
void Reflect(Writer &vis, SerializeFormat &v) { void Reflect(JsonWriter &vis, SerializeFormat &v) {
switch (v) { switch (v) {
case SerializeFormat::Binary: case SerializeFormat::Binary:
vis.String("binary"); vis.String("binary");
@ -378,7 +426,7 @@ std::string Serialize(SerializeFormat format, IndexFile &file) {
int minor = IndexFile::kMinorVersion; int minor = IndexFile::kMinorVersion;
Reflect(writer, major); Reflect(writer, major);
Reflect(writer, minor); Reflect(writer, minor);
Reflect(writer, file); ReflectFile(writer, file);
return writer.Take(); return writer.Take();
} }
case SerializeFormat::Json: { case SerializeFormat::Json: {
@ -394,7 +442,7 @@ std::string Serialize(SerializeFormat format, IndexFile &file) {
output.Put(c); output.Put(c);
output.Put('\n'); output.Put('\n');
} }
Reflect(json_writer, file); ReflectFile(json_writer, file);
return output.GetString(); return output.GetString();
} }
} }
@ -424,7 +472,7 @@ Deserialize(SerializeFormat format, const std::string &path,
throw std::invalid_argument("Invalid version"); throw std::invalid_argument("Invalid version");
file = std::make_unique<IndexFile>(sys::fs::UniqueID(0, 0), path, file = std::make_unique<IndexFile>(sys::fs::UniqueID(0, 0), path,
file_content); file_content);
Reflect(reader, *file); ReflectFile(reader, *file);
} catch (std::invalid_argument &e) { } catch (std::invalid_argument &e) {
LOG_S(INFO) << "failed to deserialize '" << path << "': " << e.what(); LOG_S(INFO) << "failed to deserialize '" << path << "': " << e.what();
return nullptr; return nullptr;
@ -450,7 +498,7 @@ Deserialize(SerializeFormat format, const std::string &path,
file_content); file_content);
JsonReader json_reader{&reader}; JsonReader json_reader{&reader};
try { try {
Reflect(json_reader, *file); ReflectFile(json_reader, *file);
} catch (std::invalid_argument &e) { } catch (std::invalid_argument &e) {
LOG_S(INFO) << "'" << path << "': failed to deserialize " LOG_S(INFO) << "'" << path << "': failed to deserialize "
<< json_reader.GetPath() << "." << e.what(); << json_reader.GetPath() << "." << e.what();

View File

@ -8,6 +8,7 @@
#include <llvm/Support/Compiler.h> #include <llvm/Support/Compiler.h>
#include <macro_map.h> #include <macro_map.h>
#include <rapidjson/fwd.h>
#include <cassert> #include <cassert>
#include <functional> #include <functional>
@ -28,159 +29,208 @@ enum class SerializeFormat { Binary, Json };
struct JsonNull {}; struct JsonNull {};
class Reader { struct JsonReader {
public: rapidjson::Value *m;
virtual ~Reader(); std::vector<const char *> path_;
virtual SerializeFormat Format() const = 0;
virtual bool IsBool() = 0; JsonReader(rapidjson::Value *m) : m(m) {}
virtual bool IsNull() = 0; void StartObject() {}
virtual bool IsInt() = 0; void EndObject() {}
virtual bool IsInt64() = 0; void IterArray(std::function<void()> fn);
virtual bool IsUInt64() = 0; void Member(const char *name, std::function<void()> fn);
virtual bool IsDouble() = 0; bool IsNull();
virtual bool IsString() = 0; std::string GetString();
std::string GetPath() const;
virtual void GetNull() = 0;
virtual bool GetBool() = 0;
virtual uint8_t GetUInt8() = 0;
virtual int GetInt() = 0;
virtual uint32_t GetUInt32() = 0;
virtual int64_t GetInt64() = 0;
virtual uint64_t GetUInt64() = 0;
virtual double GetDouble() = 0;
virtual const char *GetString() = 0;
virtual bool HasMember(const char *x) = 0;
virtual std::unique_ptr<Reader> operator[](const char *x) = 0;
virtual void IterArray(std::function<void(Reader &)> fn) = 0;
virtual void Member(const char *name, std::function<void()> fn) = 0;
}; };
class Writer { struct JsonWriter {
public: using W =
virtual ~Writer(); rapidjson::Writer<rapidjson::StringBuffer, rapidjson::UTF8<char>,
virtual SerializeFormat Format() const = 0; rapidjson::UTF8<char>, rapidjson::CrtAllocator, 0>;
virtual void Null() = 0; W *m;
virtual void Bool(bool x) = 0;
virtual void Int(int x) = 0; JsonWriter(W *m) : m(m) {}
virtual void Int64(int64_t x) = 0; void StartArray();
virtual void UInt8(uint8_t x) = 0; void EndArray();
virtual void UInt32(uint32_t x) = 0; void StartObject();
virtual void UInt64(uint64_t x) = 0; void EndObject();
virtual void Double(double x) = 0; void Key(const char *name);
virtual void String(const char *x) = 0; void Null();
virtual void String(const char *x, size_t len) = 0; void Int(int v);
virtual void StartArray(size_t) = 0; void String(const char *s);
virtual void EndArray() = 0; void String(const char *s, size_t len);
virtual void StartObject() = 0; };
virtual void EndObject() = 0;
virtual void Key(const char *name) = 0; struct BinaryReader {
const char *p_;
BinaryReader(std::string_view buf) : p_(buf.data()) {}
template <typename T> T Get() {
T ret;
memcpy(&ret, p_, sizeof(T));
p_ += sizeof(T);
return ret;
}
uint64_t VarUInt() {
auto x = *reinterpret_cast<const uint8_t *>(p_++);
if (x < 253)
return x;
if (x == 253)
return Get<uint16_t>();
if (x == 254)
return Get<uint32_t>();
return Get<uint64_t>();
}
int64_t VarInt() {
uint64_t x = VarUInt();
return int64_t(x >> 1 ^ -(x & 1));
}
const char *GetString() {
const char *ret = p_;
while (*p_)
p_++;
p_++;
return ret;
}
};
struct BinaryWriter {
std::string buf_;
template <typename T> void Pack(T x) {
auto i = buf_.size();
buf_.resize(i + sizeof(x));
memcpy(buf_.data() + i, &x, sizeof(x));
}
void VarUInt(uint64_t n) {
if (n < 253)
Pack<uint8_t>(n);
else if (n < 65536) {
Pack<uint8_t>(253);
Pack<uint16_t>(n);
} else if (n < 4294967296) {
Pack<uint8_t>(254);
Pack<uint32_t>(n);
} else {
Pack<uint8_t>(255);
Pack<uint64_t>(n);
}
}
void VarInt(int64_t n) { VarUInt(uint64_t(n) << 1 ^ n >> 63); }
std::string Take() { return std::move(buf_); }
void String(const char *x) { String(x, strlen(x)); }
void String(const char *x, size_t len) {
auto i = buf_.size();
buf_.resize(i + len + 1);
memcpy(buf_.data() + i, x, len);
}
}; };
struct IndexFile; struct IndexFile;
#define REFLECT_MEMBER_START() ReflectMemberStart(vis)
#define REFLECT_MEMBER_END() ReflectMemberEnd(vis);
#define REFLECT_MEMBER(name) ReflectMember(vis, #name, v.name) #define REFLECT_MEMBER(name) ReflectMember(vis, #name, v.name)
#define REFLECT_MEMBER2(name, v) ReflectMember(vis, name, v) #define REFLECT_MEMBER2(name, v) ReflectMember(vis, name, v)
#define MAKE_REFLECT_TYPE_PROXY(type_name) \ #define REFLECT_UNDERLYING(T) \
MAKE_REFLECT_TYPE_PROXY2(type_name, std::underlying_type_t<type_name>) LLVM_ATTRIBUTE_UNUSED inline void Reflect(JsonReader &vis, T &v) { \
#define MAKE_REFLECT_TYPE_PROXY2(type, as_type) \ std::underlying_type_t<T> v0; \
LLVM_ATTRIBUTE_UNUSED inline void Reflect(Reader &vis, type &v) { \ ::ccls::Reflect(vis, v0); \
as_type value0; \ v = static_cast<T>(v0); \
::ccls::Reflect(vis, value0); \
v = static_cast<type>(value0); \
} \ } \
LLVM_ATTRIBUTE_UNUSED inline void Reflect(Writer &vis, type &v) { \ LLVM_ATTRIBUTE_UNUSED inline void Reflect(JsonWriter &vis, T &v) { \
auto value0 = static_cast<as_type>(v); \ auto v0 = static_cast<std::underlying_type_t<T>>(v); \
::ccls::Reflect(vis, value0); \ ::ccls::Reflect(vis, v0); \
}
#define REFLECT_UNDERLYING_B(T) \
REFLECT_UNDERLYING(T) \
LLVM_ATTRIBUTE_UNUSED inline void Reflect(BinaryReader &vis, T &v) { \
std::underlying_type_t<T> v0; \
::ccls::Reflect(vis, v0); \
v = static_cast<T>(v0); \
} \
LLVM_ATTRIBUTE_UNUSED inline void Reflect(BinaryWriter &vis, T &v) { \
auto v0 = static_cast<std::underlying_type_t<T>>(v); \
::ccls::Reflect(vis, v0); \
} }
#define _MAPPABLE_REFLECT_MEMBER(name) REFLECT_MEMBER(name); #define _MAPPABLE_REFLECT_MEMBER(name) REFLECT_MEMBER(name);
#define MAKE_REFLECT_EMPTY_STRUCT(type, ...) \ #define REFLECT_STRUCT(type, ...) \
template <typename TVisitor> void Reflect(TVisitor &vis, type &v) { \ template <typename Vis> void Reflect(Vis &vis, type &v) { \
REFLECT_MEMBER_START(); \ ReflectMemberStart(vis); \
REFLECT_MEMBER_END(); \
}
#define MAKE_REFLECT_STRUCT(type, ...) \
template <typename TVisitor> void Reflect(TVisitor &vis, type &v) { \
REFLECT_MEMBER_START(); \
MACRO_MAP(_MAPPABLE_REFLECT_MEMBER, __VA_ARGS__) \ MACRO_MAP(_MAPPABLE_REFLECT_MEMBER, __VA_ARGS__) \
REFLECT_MEMBER_END(); \ ReflectMemberEnd(vis); \
} }
// clang-format off
// Config has many fields, we need to support at least its number of fields.
#define NUM_VA_ARGS_IMPL(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,N,...) N
#define NUM_VA_ARGS(...) NUM_VA_ARGS_IMPL(__VA_ARGS__,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
// clang-format on
#define _MAPPABLE_REFLECT_ARRAY(name) Reflect(vis, v.name); #define _MAPPABLE_REFLECT_ARRAY(name) Reflect(vis, v.name);
// Reflects the struct so it is serialized as an array instead of an object. void Reflect(JsonReader &vis, bool &v);
// This currently only supports writers. void Reflect(JsonReader &vis, unsigned char &v);
#define MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY(type, ...) \ void Reflect(JsonReader &vis, short &v);
inline void Reflect(Writer &vis, type &v) { \ void Reflect(JsonReader &vis, unsigned short &v);
vis.StartArray(NUM_VA_ARGS(__VA_ARGS__)); \ void Reflect(JsonReader &vis, int &v);
MACRO_MAP(_MAPPABLE_REFLECT_ARRAY, __VA_ARGS__) \ void Reflect(JsonReader &vis, unsigned &v);
vis.EndArray(); \ void Reflect(JsonReader &vis, long &v);
} void Reflect(JsonReader &vis, unsigned long &v);
void Reflect(JsonReader &vis, long long &v);
void Reflect(JsonReader &vis, unsigned long long &v);
void Reflect(JsonReader &vis, double &v);
void Reflect(JsonReader &vis, const char *&v);
void Reflect(JsonReader &vis, std::string &v);
//// Elementary types void Reflect(JsonWriter &vis, bool &v);
void Reflect(JsonWriter &vis, unsigned char &v);
void Reflect(JsonWriter &vis, short &v);
void Reflect(JsonWriter &vis, unsigned short &v);
void Reflect(JsonWriter &vis, int &v);
void Reflect(JsonWriter &vis, unsigned &v);
void Reflect(JsonWriter &vis, long &v);
void Reflect(JsonWriter &vis, unsigned long &v);
void Reflect(JsonWriter &vis, long long &v);
void Reflect(JsonWriter &vis, unsigned long long &v);
void Reflect(JsonWriter &vis, double &v);
void Reflect(JsonWriter &vis, const char *&v);
void Reflect(JsonWriter &vis, std::string &v);
void Reflect(Reader &vis, uint8_t &v); void Reflect(BinaryReader &vis, bool &v);
void Reflect(Writer &vis, uint8_t &v); void Reflect(BinaryReader &vis, unsigned char &v);
void Reflect(BinaryReader &vis, short &v);
void Reflect(BinaryReader &vis, unsigned short &v);
void Reflect(BinaryReader &vis, int &v);
void Reflect(BinaryReader &vis, unsigned &v);
void Reflect(BinaryReader &vis, long &v);
void Reflect(BinaryReader &vis, unsigned long &v);
void Reflect(BinaryReader &vis, long long &v);
void Reflect(BinaryReader &vis, unsigned long long &v);
void Reflect(BinaryReader &vis, double &v);
void Reflect(BinaryReader &vis, const char *&v);
void Reflect(BinaryReader &vis, std::string &v);
void Reflect(Reader &vis, short &v); void Reflect(BinaryWriter &vis, bool &v);
void Reflect(Writer &vis, short &v); void Reflect(BinaryWriter &vis, unsigned char &v);
void Reflect(BinaryWriter &vis, short &v);
void Reflect(BinaryWriter &vis, unsigned short &v);
void Reflect(BinaryWriter &vis, int &v);
void Reflect(BinaryWriter &vis, unsigned &v);
void Reflect(BinaryWriter &vis, long &v);
void Reflect(BinaryWriter &vis, unsigned long &v);
void Reflect(BinaryWriter &vis, long long &v);
void Reflect(BinaryWriter &vis, unsigned long long &v);
void Reflect(BinaryWriter &vis, double &v);
void Reflect(BinaryWriter &vis, const char *&v);
void Reflect(BinaryWriter &vis, std::string &v);
void Reflect(Reader &vis, unsigned short &v); void Reflect(JsonReader &vis, JsonNull &v);
void Reflect(Writer &vis, unsigned short &v); void Reflect(JsonWriter &vis, JsonNull &v);
void Reflect(Reader &vis, int &v); void Reflect(JsonReader &vis, SerializeFormat &v);
void Reflect(Writer &vis, int &v); void Reflect(JsonWriter &vis, SerializeFormat &v);
void Reflect(Reader &vis, unsigned &v); void Reflect(JsonWriter &vis, std::string_view &v);
void Reflect(Writer &vis, unsigned &v);
void Reflect(Reader &vis, long &v);
void Reflect(Writer &vis, long &v);
void Reflect(Reader &vis, unsigned long &v);
void Reflect(Writer &vis, unsigned long &v);
void Reflect(Reader &vis, long long &v);
void Reflect(Writer &vis, long long &v);
void Reflect(Reader &vis, unsigned long long &v);
void Reflect(Writer &vis, unsigned long long &v);
void Reflect(Reader &vis, double &v);
void Reflect(Writer &vis, double &v);
void Reflect(Reader &vis, bool &v);
void Reflect(Writer &vis, bool &v);
void Reflect(Reader &vis, std::string &v);
void Reflect(Writer &vis, std::string &v);
void Reflect(Reader &vis, std::string_view &v);
void Reflect(Writer &vis, std::string_view &v);
void Reflect(Reader &vis, const char *&v);
void Reflect(Writer &vis, const char *&v);
void Reflect(Reader &vis, JsonNull &v);
void Reflect(Writer &vis, JsonNull &v);
void Reflect(Reader &vis, SerializeFormat &v);
void Reflect(Writer &vis, SerializeFormat &v);
//// Type constructors //// Type constructors
@ -188,109 +238,154 @@ void Reflect(Writer &vis, SerializeFormat &v);
// properties (in `key: value` context). Reflect std::optional<T> is used for a // properties (in `key: value` context). Reflect std::optional<T> is used for a
// different purpose, whether an object is nullable (possibly in `value` // different purpose, whether an object is nullable (possibly in `value`
// context). // context).
template <typename T> void Reflect(Reader &vis, std::optional<T> &v) { template <typename T> void Reflect(JsonReader &vis, std::optional<T> &v) {
if (vis.IsNull()) { if (!vis.IsNull()) {
vis.GetNull(); v.emplace();
return;
}
T val;
Reflect(vis, val);
v = std::move(val);
}
template <typename T> void Reflect(Writer &vis, std::optional<T> &v) {
if (v) {
if (vis.Format() != SerializeFormat::Json)
vis.UInt8(1);
Reflect(vis, *v); Reflect(vis, *v);
} else }
}
template <typename T> void Reflect(JsonWriter &vis, std::optional<T> &v) {
if (v)
Reflect(vis, *v);
else
vis.Null(); vis.Null();
} }
template <typename T> void Reflect(BinaryReader &vis, std::optional<T> &v) {
if (*vis.p_++) {
v.emplace();
Reflect(vis, *v);
}
}
template <typename T> void Reflect(BinaryWriter &vis, std::optional<T> &v) {
if (v) {
vis.Pack<unsigned char>(1);
Reflect(vis, *v);
} else {
vis.Pack<unsigned char>(0);
}
}
// The same as std::optional // The same as std::optional
template <typename T> void Reflect(Reader &vis, Maybe<T> &v) { template <typename T> void Reflect(JsonReader &vis, Maybe<T> &v) {
if (vis.IsNull()) { if (!vis.IsNull())
vis.GetNull();
return;
}
T val;
Reflect(vis, val);
v = std::move(val);
}
template <typename T> void Reflect(Writer &vis, Maybe<T> &v) {
if (v) {
if (vis.Format() != SerializeFormat::Json)
vis.UInt8(1);
Reflect(vis, *v); Reflect(vis, *v);
} else }
template <typename T> void Reflect(JsonWriter &vis, Maybe<T> &v) {
if (v)
Reflect(vis, *v);
else
vis.Null(); vis.Null();
} }
template <typename T> void Reflect(BinaryReader &vis, Maybe<T> &v) {
if (*vis.p_++)
Reflect(vis, *v);
}
template <typename T> void Reflect(BinaryWriter &vis, Maybe<T> &v) {
if (v) {
vis.Pack<unsigned char>(1);
Reflect(vis, *v);
} else {
vis.Pack<unsigned char>(0);
}
}
template <typename T> template <typename T>
void ReflectMember(Writer &vis, const char *name, std::optional<T> &v) { void ReflectMember(JsonWriter &vis, const char *name, std::optional<T> &v) {
// For TypeScript std::optional property key?: value in the spec, // For TypeScript std::optional property key?: value in the spec,
// We omit both key and value if value is std::nullopt (null) for JsonWriter // We omit both key and value if value is std::nullopt (null) for JsonWriter
// to reduce output. But keep it for other serialization formats. // to reduce output. But keep it for other serialization formats.
if (v || vis.Format() != SerializeFormat::Json) { if (v) {
vis.Key(name); vis.Key(name);
Reflect(vis, v); Reflect(vis, *v);
} }
} }
template <typename T>
void ReflectMember(BinaryWriter &vis, const char *, std::optional<T> &v) {
Reflect(vis, v);
}
// The same as std::optional // The same as std::optional
template <typename T> template <typename T>
void ReflectMember(Writer &vis, const char *name, Maybe<T> &v) { void ReflectMember(JsonWriter &vis, const char *name, Maybe<T> &v) {
if (v.Valid() || vis.Format() != SerializeFormat::Json) { if (v.Valid()) {
vis.Key(name); vis.Key(name);
Reflect(vis, v); Reflect(vis, v);
} }
} }
template <typename T>
void ReflectMember(BinaryWriter &vis, const char *, Maybe<T> &v) {
Reflect(vis, v);
}
template <typename L, typename R> template <typename L, typename R>
void Reflect(Reader &vis, std::pair<L, R> &v) { void Reflect(JsonReader &vis, std::pair<L, R> &v) {
vis.Member("L", [&]() { Reflect(vis, v.first); }); vis.Member("L", [&]() { Reflect(vis, v.first); });
vis.Member("R", [&]() { Reflect(vis, v.second); }); vis.Member("R", [&]() { Reflect(vis, v.second); });
} }
template <typename L, typename R> template <typename L, typename R>
void Reflect(Writer &vis, std::pair<L, R> &v) { void Reflect(JsonWriter &vis, std::pair<L, R> &v) {
vis.StartObject(); vis.StartObject();
ReflectMember(vis, "L", v.first); ReflectMember(vis, "L", v.first);
ReflectMember(vis, "R", v.second); ReflectMember(vis, "R", v.second);
vis.EndObject(); vis.EndObject();
} }
template <typename L, typename R>
void Reflect(BinaryReader &vis, std::pair<L, R> &v) {
Reflect(vis, v.first);
Reflect(vis, v.second);
}
template <typename L, typename R>
void Reflect(BinaryWriter &vis, std::pair<L, R> &v) {
Reflect(vis, v.first);
Reflect(vis, v.second);
}
// std::vector // std::vector
template <typename T> void Reflect(Reader &vis, std::vector<T> &vs) { template <typename T> void Reflect(JsonReader &vis, std::vector<T> &v) {
vis.IterArray([&](Reader &entry) { vis.IterArray([&]() {
T entry_value; v.emplace_back();
Reflect(entry, entry_value); Reflect(vis, v.back());
vs.push_back(std::move(entry_value));
}); });
} }
template <typename T> void Reflect(Writer &vis, std::vector<T> &vs) { template <typename T> void Reflect(JsonWriter &vis, std::vector<T> &v) {
vis.StartArray(vs.size()); vis.StartArray();
for (auto &v : vs) for (auto &it : v)
Reflect(vis, v); Reflect(vis, it);
vis.EndArray(); vis.EndArray();
} }
template <typename T> void Reflect(BinaryReader &vis, std::vector<T> &v) {
for (auto n = vis.VarUInt(); n; n--) {
v.emplace_back();
Reflect(vis, v.back());
}
}
template <typename T> void Reflect(BinaryWriter &vis, std::vector<T> &v) {
vis.VarUInt(v.size());
for (auto &it : v)
Reflect(vis, it);
}
// ReflectMember // ReflectMember
inline bool ReflectMemberStart(Reader &vis) { return false; } template <typename T> void ReflectMemberStart(T &) {}
inline bool ReflectMemberStart(Writer &vis) { inline void ReflectMemberStart(JsonWriter &vis) { vis.StartObject(); }
vis.StartObject();
return true;
}
inline void ReflectMemberEnd(Reader &vis) {} template <typename T> void ReflectMemberEnd(T &) {}
inline void ReflectMemberEnd(Writer &vis) { vis.EndObject(); } inline void ReflectMemberEnd(JsonWriter &vis) { vis.EndObject(); }
template <typename T> void ReflectMember(Reader &vis, const char *name, T &v) { template <typename T> void ReflectMember(JsonReader &vis, const char *name, T &v) {
vis.Member(name, [&]() { Reflect(vis, v); }); vis.Member(name, [&]() { Reflect(vis, v); });
} }
template <typename T> void ReflectMember(Writer &vis, const char *name, T &v) { template <typename T> void ReflectMember(JsonWriter &vis, const char *name, T &v) {
vis.Key(name); vis.Key(name);
Reflect(vis, v); Reflect(vis, v);
} }
template <typename T> void ReflectMember(BinaryReader &vis, const char *, T &v) {
Reflect(vis, v);
}
template <typename T> void ReflectMember(BinaryWriter &vis, const char *, T &v) {
Reflect(vis, v);
}
// API // API

View File

@ -1,127 +0,0 @@
// Copyright 2017-2018 ccls Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "serializer.hh"
#include <string.h>
namespace ccls {
class BinaryReader : public Reader {
const char *p_;
template <typename T> T Get() {
T ret;
memcpy(&ret, p_, sizeof(T));
p_ += sizeof(T);
return ret;
}
uint64_t VarUInt() {
auto x = *reinterpret_cast<const uint8_t *>(p_++);
if (x < 253)
return x;
if (x == 253)
return Get<uint16_t>();
if (x == 254)
return Get<uint32_t>();
return Get<uint64_t>();
}
int64_t VarInt() {
uint64_t x = VarUInt();
return int64_t(x >> 1 ^ -(x & 1));
}
public:
BinaryReader(std::string_view buf) : p_(buf.data()) {}
virtual ~BinaryReader();
SerializeFormat Format() const override { return SerializeFormat::Binary; }
bool IsBool() override { return true; }
// Abuse how the function is called in serializer.h
bool IsNull() override { return !*p_++; }
bool IsInt() override { return true; }
bool IsInt64() override { return true; }
bool IsUInt64() override { return true; }
bool IsDouble() override { return true; }
bool IsString() override { return true; }
void GetNull() override {}
bool GetBool() override { return Get<bool>(); }
int GetInt() override { return VarInt(); }
int64_t GetInt64() override { return VarInt(); }
uint8_t GetUInt8() override { return Get<uint8_t>(); }
uint32_t GetUInt32() override { return VarUInt(); }
uint64_t GetUInt64() override { return VarUInt(); }
double GetDouble() override { return Get<double>(); }
const char *GetString() override {
const char *ret = p_;
while (*p_)
p_++;
p_++;
return ret;
}
bool HasMember(const char *x) override { return true; }
std::unique_ptr<Reader> operator[](const char *x) override { return {}; }
void IterArray(std::function<void(Reader &)> fn) override {
for (auto n = VarUInt(); n; n--)
fn(*this);
}
void Member(const char *, std::function<void()> fn) override { fn(); }
};
class BinaryWriter : public Writer {
std::string buf_;
template <typename T> void Pack(T x) {
auto i = buf_.size();
buf_.resize(i + sizeof(x));
memcpy(buf_.data() + i, &x, sizeof(x));
}
void VarUInt(uint64_t n) {
if (n < 253)
Pack<uint8_t>(n);
else if (n < 65536) {
Pack<uint8_t>(253);
Pack<uint16_t>(n);
} else if (n < 4294967296) {
Pack<uint8_t>(254);
Pack<uint32_t>(n);
} else {
Pack<uint8_t>(255);
Pack<uint64_t>(n);
}
}
void VarInt(int64_t n) { VarUInt(uint64_t(n) << 1 ^ n >> 63); }
public:
virtual ~BinaryWriter();
SerializeFormat Format() const override { return SerializeFormat::Binary; }
std::string Take() { return std::move(buf_); }
void Null() override { Pack(uint8_t(0)); }
void Bool(bool x) override { Pack(x); }
void Int(int x) override { VarInt(x); }
void Int64(int64_t x) override { VarInt(x); }
void UInt8(uint8_t x) override { Pack(x); }
void UInt32(uint32_t x) override { VarUInt(x); }
void UInt64(uint64_t x) override { VarUInt(x); }
void Double(double x) override { Pack(x); }
void String(const char *x) override { String(x, strlen(x)); }
void String(const char *x, size_t len) override {
auto i = buf_.size();
buf_.resize(i + len + 1);
memcpy(buf_.data() + i, x, len);
}
void StartArray(size_t n) override { VarUInt(n); }
void EndArray() override {}
void StartObject() override {}
void EndObject() override {}
void Key(const char *name) override {}
};
} // namespace ccls

View File

@ -1,108 +0,0 @@
// Copyright 2017-2018 ccls Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "serializer.hh"
#include <rapidjson/document.h>
#include <rapidjson/prettywriter.h>
namespace ccls {
class JsonReader : public Reader {
rapidjson::GenericValue<rapidjson::UTF8<>> *m_;
std::vector<const char *> path_;
public:
JsonReader(rapidjson::GenericValue<rapidjson::UTF8<>> *m) : m_(m) {}
virtual ~JsonReader();
SerializeFormat Format() const override { return SerializeFormat::Json; }
rapidjson::GenericValue<rapidjson::UTF8<>> &m() { return *m_; }
bool IsBool() override { return m_->IsBool(); }
bool IsNull() override { return m_->IsNull(); }
bool IsInt() override { return m_->IsInt(); }
bool IsInt64() override { return m_->IsInt64(); }
bool IsUInt64() override { return m_->IsUint64(); }
bool IsDouble() override { return m_->IsDouble(); }
bool IsString() override { return m_->IsString(); }
void GetNull() override {}
bool GetBool() override { return m_->GetBool(); }
int GetInt() override { return m_->GetInt(); }
int64_t GetInt64() override { return m_->GetInt64(); }
uint8_t GetUInt8() override { return uint8_t(m_->GetInt()); }
uint32_t GetUInt32() override { return uint32_t(m_->GetUint64()); }
uint64_t GetUInt64() override { return m_->GetUint64(); }
double GetDouble() override { return m_->GetDouble(); }
const char *GetString() override { return m_->GetString(); }
bool HasMember(const char *x) override { return m_->HasMember(x); }
std::unique_ptr<Reader> operator[](const char *x) override {
auto &sub = (*m_)[x];
return std::unique_ptr<JsonReader>(new JsonReader(&sub));
}
void IterArray(std::function<void(Reader &)> fn) override {
if (!m_->IsArray())
throw std::invalid_argument("array");
// Use "0" to indicate any element for now.
path_.push_back("0");
for (auto &entry : m_->GetArray()) {
auto saved = m_;
m_ = &entry;
fn(*this);
m_ = saved;
}
path_.pop_back();
}
void Member(const char *name, std::function<void()> fn) override {
path_.push_back(name);
auto it = m_->FindMember(name);
if (it != m_->MemberEnd()) {
auto saved = m_;
m_ = &it->value;
fn();
m_ = saved;
}
path_.pop_back();
}
std::string GetPath() const {
std::string ret;
for (auto &t : path_) {
ret += '/';
ret += t;
}
ret.pop_back();
return ret;
}
};
class JsonWriter : public Writer {
rapidjson::Writer<rapidjson::StringBuffer> *m_;
public:
JsonWriter(rapidjson::Writer<rapidjson::StringBuffer> *m) : m_(m) {}
virtual ~JsonWriter();
SerializeFormat Format() const override { return SerializeFormat::Json; }
rapidjson::Writer<rapidjson::StringBuffer> &m() { return *m_; }
void Null() override { m_->Null(); }
void Bool(bool x) override { m_->Bool(x); }
void Int(int x) override { m_->Int(x); }
void Int64(int64_t x) override { m_->Int64(x); }
void UInt8(uint8_t x) override { m_->Int(x); }
void UInt32(uint32_t x) override { m_->Uint64(x); }
void UInt64(uint64_t x) override { m_->Uint64(x); }
void Double(double x) override { m_->Double(x); }
void String(const char *x) override { m_->String(x); }
void String(const char *x, size_t len) override { m_->String(x, len); }
void StartArray(size_t) override { m_->StartArray(); }
void EndArray() override { m_->EndArray(); }
void StartObject() override { m_->StartObject(); }
void EndObject() override { m_->EndObject(); }
void Key(const char *name) override { m_->Key(name); }
};
} // namespace ccls