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 872d7c5de9
commit 04e80544b9
34 changed files with 875 additions and 976 deletions

View File

@ -259,28 +259,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

@ -20,7 +20,6 @@ limitations under the License.
#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>
@ -1185,7 +1184,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)
@ -1377,8 +1376,7 @@ 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);
@ -1386,58 +1384,16 @@ void Reflect(Reader &vis, SymbolRef &v) {
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) {
char buf[99];
snprintf(buf, sizeof buf, "%s|%" PRIu64 "|%d|%d",
v.range.ToString().c_str(), v.usr, int(v.kind), int(v.role));
std::string s(buf);
Reflect(vis, s);
} else {
Reflect(vis, v.range);
Reflect(vis, v.usr);
Reflect(vis, v.kind);
Reflect(vis, v.role);
}
}
void Reflect(Reader &vis, Use &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.role = static_cast<Role>(strtol(s + 1, &s, 10)); v.role = static_cast<Role>(strtol(s + 1, &s, 10));
v.file_id = static_cast<int>(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(JsonReader &vis, DeclRef &v) {
if (vis.Format() == SerializeFormat::Json) {
char buf[99];
snprintf(buf, sizeof buf, "%s|%d|%d", v.range.ToString().c_str(),
int(v.role), v.file_id);
std::string s(buf);
Reflect(vis, s);
} else {
Reflect(vis, v.range);
Reflect(vis, v.role);
Reflect(vis, v.file_id);
}
}
void Reflect(Reader &vis, DeclRef &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);
@ -1446,21 +1402,59 @@ void Reflect(Reader &vis, DeclRef &v) {
s = strchr(s, '|'); s = strchr(s, '|');
v.role = static_cast<Role>(strtol(s + 1, &s, 10)); v.role = static_cast<Role>(strtol(s + 1, &s, 10));
v.file_id = static_cast<int>(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) {
if (vis.Format() == SerializeFormat::Json) { void Reflect(JsonWriter &vis, SymbolRef &v) {
char buf[99];
snprintf(buf, sizeof buf, "%s|%" PRIu64 "|%d|%d", v.range.ToString().c_str(),
v.usr, int(v.kind), int(v.role));
std::string s(buf);
Reflect(vis, s);
}
void Reflect(JsonWriter &vis, Use &v) {
char buf[99];
snprintf(buf, sizeof buf, "%s|%d|%d", v.range.ToString().c_str(), int(v.role),
v.file_id);
std::string s(buf);
Reflect(vis, s);
}
void Reflect(JsonWriter &vis, DeclRef &v) {
char buf[99]; char buf[99];
snprintf(buf, sizeof buf, "%s|%s|%d|%d", v.range.ToString().c_str(), snprintf(buf, sizeof buf, "%s|%s|%d|%d", v.range.ToString().c_str(),
v.extent.ToString().c_str(), int(v.role), v.file_id); v.extent.ToString().c_str(), int(v.role), v.file_id);
std::string s(buf); std::string s(buf);
Reflect(vis, s); Reflect(vis, s);
} else { }
void Reflect(BinaryReader &vis, SymbolRef &v) {
Reflect(vis, v.range);
Reflect(vis, v.usr);
Reflect(vis, v.kind);
Reflect(vis, v.role);
}
void Reflect(BinaryReader &vis, Use &v) {
Reflect(vis, v.range);
Reflect(vis, v.role);
Reflect(vis, v.file_id);
}
void Reflect(BinaryReader &vis, DeclRef &v) {
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, static_cast<Use &>(v));
Reflect(vis, v.extent); Reflect(vis, v.extent);
}
} }
} // namespace ccls } // namespace ccls

View File

@ -46,7 +46,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,
@ -61,7 +61,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);
} }
@ -130,12 +130,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 {
@ -174,7 +180,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);
@ -211,7 +217,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);
@ -255,7 +261,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

@ -16,29 +16,30 @@ limitations under the License.
#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();
@ -48,7 +49,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

@ -35,8 +35,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;
@ -80,11 +80,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;
@ -220,7 +215,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

@ -17,7 +17,6 @@ limitations under the License.
#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"
@ -29,6 +28,7 @@ limitations under the License.
#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

@ -19,7 +19,9 @@ limitations under the License.
#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>
@ -29,35 +31,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 {
@ -75,15 +77,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;
@ -114,8 +116,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);
}; };
} }
@ -123,7 +126,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);
@ -131,9 +134,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);
}; };
} }
@ -142,7 +146,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);
@ -214,7 +219,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

@ -30,7 +30,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);
@ -52,8 +52,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;
@ -69,7 +69,7 @@ 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,
@ -182,7 +182,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,7 +19,7 @@ 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 {
@ -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

@ -36,7 +36,7 @@ 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 {
@ -51,7 +51,7 @@ 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,
@ -165,7 +165,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

@ -42,7 +42,7 @@ 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 {
@ -57,7 +57,7 @@ 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,
@ -263,7 +263,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

@ -29,10 +29,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

@ -25,10 +25,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

@ -21,12 +21,14 @@ limitations under the License.
#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>
@ -39,7 +41,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 {
@ -104,28 +106,27 @@ 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,
@ -134,7 +135,7 @@ MAKE_REFLECT_STRUCT(ServerCap, textDocumentSync, hoverProvider,
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 {
@ -154,8 +155,8 @@ 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);
@ -178,18 +179,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
@ -211,12 +212,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")
@ -225,13 +226,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;
@ -341,7 +342,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

@ -32,11 +32,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);
@ -49,7 +49,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 {
@ -57,7 +57,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

@ -22,7 +22,7 @@ limitations under the License.
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 {
@ -38,7 +38,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(
@ -85,7 +85,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,
@ -118,7 +118,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;
@ -128,10 +128,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);
} }
@ -159,7 +159,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

@ -27,19 +27,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

@ -36,12 +36,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

@ -36,10 +36,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

@ -25,7 +25,6 @@ limitations under the License.
#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>
@ -49,7 +48,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() {
@ -457,8 +456,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;
@ -610,7 +609,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();
@ -626,7 +625,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();
@ -652,11 +651,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

@ -51,16 +51,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

@ -17,6 +17,9 @@ limitations under the License.
#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>
@ -69,45 +72,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 {
void Reflect(BinaryReader &visitor, Pos &value) {
Reflect(visitor, value.line);
Reflect(visitor, value.column);
}
void Reflect(BinaryReader &visitor, Range &value) {
Reflect(visitor, value.start.line); Reflect(visitor, value.start.line);
Reflect(visitor, value.start.column); Reflect(visitor, value.start.column);
Reflect(visitor, value.end.line); Reflect(visitor, value.end.line);
Reflect(visitor, value.end.column); 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

@ -63,12 +63,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

@ -20,7 +20,6 @@ limitations under the License.
#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

@ -18,7 +18,8 @@ limitations under the License.
#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

@ -19,8 +19,9 @@ limitations under the License.
#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>
@ -33,181 +34,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>
// Used by IndexFile::dependencies. void Reflect(BinaryReader &vis, std::unordered_map<Usr, V> &v) {
void Reflect(Reader &vis, DenseMap<CachedHashStringRef, int64_t> &v) { for (auto n = vis.VarUInt(); n; n--) {
std::string name; V val;
if (vis.Format() == SerializeFormat::Json) { Reflect(vis, val);
auto &vis1 = static_cast<JsonReader&>(vis); v[val.usr] = std::move(val);
for (auto it = vis1.m().MemberBegin(); it != vis1.m().MemberEnd(); ++it)
v[InternH(it->name.GetString())] = it->value.GetInt64();
} else {
vis.IterArray([&](Reader &entry) {
Reflect(entry, name);
Reflect(entry, v[InternH(name)]);
});
} }
} }
void Reflect(Writer &vis, DenseMap<CachedHashStringRef, int64_t> &v) { template <typename V>
if (vis.Format() == SerializeFormat::Json) { void Reflect(BinaryWriter &vis, std::unordered_map<Usr, V> &v) {
auto &vis1 = static_cast<JsonWriter&>(vis); vis.VarUInt(v.size());
for (auto &it : v)
Reflect(vis, it.second);
}
// Used by IndexFile::dependencies.
void Reflect(JsonReader &vis, DenseMap<CachedHashStringRef, int64_t> &v) {
std::string name;
for (auto it = vis.m->MemberBegin(); it != vis.m->MemberEnd(); ++it)
v[InternH(it->name.GetString())] = it->value.GetInt64();
}
void Reflect(JsonWriter &vis, DenseMap<CachedHashStringRef, int64_t> &v) {
vis.StartObject(); vis.StartObject();
for (auto &it : v) { for (auto &it : v) {
vis1.m().Key(it.first.val().data()); // llvm 8 -> data() vis.m->Key(it.first.val().data()); // llvm 8 -> data()
vis1.m().Int64(it.second); vis.m->Int64(it.second);
} }
vis.EndObject(); vis.EndObject();
} else { }
vis.StartArray(v.size()); 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(BinaryWriter &vis, DenseMap<CachedHashStringRef, int64_t> &v) {
std::string key;
vis.VarUInt(v.size());
for (auto &it : v) { for (auto &it : v) {
std::string key = it.first.val().str(); key = it.first.val().str();
Reflect(vis, key); Reflect(vis, key);
Reflect(vis, it.second); 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);
@ -217,23 +235,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);
@ -246,8 +275,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);
@ -257,9 +285,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);
@ -276,11 +312,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);
@ -299,11 +339,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);
@ -317,16 +361,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);
@ -340,15 +384,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");
@ -390,7 +438,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: {
@ -406,7 +454,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();
} }
} }
@ -436,7 +484,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;
@ -462,7 +510,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

@ -20,6 +20,7 @@ limitations under the License.
#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>
@ -40,159 +41,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
@ -200,109 +250,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,139 +0,0 @@
/* Copyright 2017-2018 ccls Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#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,120 +0,0 @@
/* Copyright 2017-2018 ccls Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#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