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 a599aef482
commit a47fb42e30
34 changed files with 875 additions and 952 deletions

View File

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

View File

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

View File

@ -34,7 +34,7 @@ using Usr = uint64_t;
// The order matters. In FindSymbolsAtLocation, we want Var/Func ordered in
// front of others.
enum class Kind : uint8_t { Invalid, File, Type, Func, Var };
MAKE_REFLECT_TYPE_PROXY(Kind);
REFLECT_UNDERLYING_B(Kind);
enum class Role : uint16_t {
None = 0,
@ -49,7 +49,7 @@ enum class Role : uint16_t {
Implicit = 1 << 8,
All = (1 << 9) - 1,
};
MAKE_REFLECT_TYPE_PROXY(Role);
REFLECT_UNDERLYING_B(Role);
inline uint16_t operator&(Role lhs, Role rhs) {
return uint16_t(lhs) & uint16_t(rhs);
}
@ -118,12 +118,18 @@ struct DeclRef : Use {
Range extent;
};
void Reflect(Reader &visitor, SymbolRef &value);
void Reflect(Writer &visitor, SymbolRef &value);
void Reflect(Reader &visitor, Use &value);
void Reflect(Writer &visitor, Use &value);
void Reflect(Reader &visitor, DeclRef &value);
void Reflect(Writer &visitor, DeclRef &value);
void Reflect(JsonReader &visitor, SymbolRef &value);
void Reflect(JsonReader &visitor, Use &value);
void Reflect(JsonReader &visitor, DeclRef &value);
void Reflect(JsonWriter &visitor, SymbolRef &value);
void Reflect(JsonWriter &visitor, Use &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 {
std::string_view Name(bool qualified) const {
@ -162,7 +168,7 @@ struct FuncDef : NameMixin<FuncDef> {
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,
short_name_size, kind, parent_kind, storage);
@ -199,7 +205,7 @@ struct TypeDef : NameMixin<TypeDef> {
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,
short_name_offset, short_name_size, kind, parent_kind);
@ -243,7 +249,7 @@ struct VarDef : NameMixin<VarDef> {
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,
parent_kind, storage);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -11,7 +11,7 @@ struct Param {
Position position;
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> parent;
@ -26,8 +26,7 @@ Maybe<Range> FindParent(QueryFile *file, Pos pos) {
}
} // namespace
void MessageHandler::ccls_navigate(Reader &reader,
ReplyOnce &reply) {
void MessageHandler::ccls_navigate(JsonReader &reader, ReplyOnce &reply) {
Param param;
Reflect(reader, param);
QueryFile *file = FindFile(param.textDocument.uri.GetPath());

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -15,19 +15,19 @@ struct Hover {
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
// not, emit a string.
if (v.language) {
REFLECT_MEMBER_START();
vis.StartObject();
REFLECT_MEMBER(language);
REFLECT_MEMBER(value);
REFLECT_MEMBER_END();
vis.EndObject();
} else {
Reflect(vis, v.value);
}
}
MAKE_REFLECT_STRUCT(Hover, contents, range);
REFLECT_STRUCT(Hover, contents, range);
const char *LanguageIdentifier(LanguageId lang) {
switch (lang) {

View File

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

View File

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

View File

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

View File

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

View File

@ -54,16 +54,16 @@ void Index(const std::string &path, const std::vector<const char *> &args,
std::optional<std::string> LoadIndexedContent(const std::string& path);
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) {
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) {
ReplyError(id, [&](Writer &w) { Reflect(w, result); });
ReplyError(id, [&](JsonWriter &w) { Reflect(w, result); });
}
} // namespace pipeline
} // namespace ccls

View File

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

View File

@ -51,12 +51,19 @@ struct Range {
};
// Reflection
class Reader;
class Writer;
void Reflect(Reader &visitor, Pos &value);
void Reflect(Writer &visitor, Pos &value);
void Reflect(Reader &visitor, Range &value);
void Reflect(Writer &visitor, Range &value);
struct JsonReader;
struct JsonWriter;
struct BinaryReader;
struct BinaryWriter;
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 std {

View File

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

View File

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

View File

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

View File

@ -8,6 +8,7 @@
#include <llvm/Support/Compiler.h>
#include <macro_map.h>
#include <rapidjson/fwd.h>
#include <cassert>
#include <functional>
@ -28,159 +29,208 @@ enum class SerializeFormat { Binary, Json };
struct JsonNull {};
class Reader {
public:
virtual ~Reader();
virtual SerializeFormat Format() const = 0;
struct JsonReader {
rapidjson::Value *m;
std::vector<const char *> path_;
virtual bool IsBool() = 0;
virtual bool IsNull() = 0;
virtual bool IsInt() = 0;
virtual bool IsInt64() = 0;
virtual bool IsUInt64() = 0;
virtual bool IsDouble() = 0;
virtual bool IsString() = 0;
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;
JsonReader(rapidjson::Value *m) : m(m) {}
void StartObject() {}
void EndObject() {}
void IterArray(std::function<void()> fn);
void Member(const char *name, std::function<void()> fn);
bool IsNull();
std::string GetString();
std::string GetPath() const;
};
class Writer {
public:
virtual ~Writer();
virtual SerializeFormat Format() const = 0;
struct JsonWriter {
using W =
rapidjson::Writer<rapidjson::StringBuffer, rapidjson::UTF8<char>,
rapidjson::UTF8<char>, rapidjson::CrtAllocator, 0>;
virtual void Null() = 0;
virtual void Bool(bool x) = 0;
virtual void Int(int x) = 0;
virtual void Int64(int64_t x) = 0;
virtual void UInt8(uint8_t x) = 0;
virtual void UInt32(uint32_t x) = 0;
virtual void UInt64(uint64_t x) = 0;
virtual void Double(double x) = 0;
virtual void String(const char *x) = 0;
virtual void String(const char *x, size_t len) = 0;
virtual void StartArray(size_t) = 0;
virtual void EndArray() = 0;
virtual void StartObject() = 0;
virtual void EndObject() = 0;
virtual void Key(const char *name) = 0;
W *m;
JsonWriter(W *m) : m(m) {}
void StartArray();
void EndArray();
void StartObject();
void EndObject();
void Key(const char *name);
void Null();
void Int(int v);
void String(const char *s);
void String(const char *s, size_t len);
};
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;
#define REFLECT_MEMBER_START() ReflectMemberStart(vis)
#define REFLECT_MEMBER_END() ReflectMemberEnd(vis);
#define REFLECT_MEMBER(name) ReflectMember(vis, #name, v.name)
#define REFLECT_MEMBER2(name, v) ReflectMember(vis, name, v)
#define MAKE_REFLECT_TYPE_PROXY(type_name) \
MAKE_REFLECT_TYPE_PROXY2(type_name, std::underlying_type_t<type_name>)
#define MAKE_REFLECT_TYPE_PROXY2(type, as_type) \
LLVM_ATTRIBUTE_UNUSED inline void Reflect(Reader &vis, type &v) { \
as_type value0; \
::ccls::Reflect(vis, value0); \
v = static_cast<type>(value0); \
#define REFLECT_UNDERLYING(T) \
LLVM_ATTRIBUTE_UNUSED inline void Reflect(JsonReader &vis, T &v) { \
std::underlying_type_t<T> v0; \
::ccls::Reflect(vis, v0); \
v = static_cast<T>(v0); \
} \
LLVM_ATTRIBUTE_UNUSED inline void Reflect(Writer &vis, type &v) { \
auto value0 = static_cast<as_type>(v); \
::ccls::Reflect(vis, value0); \
LLVM_ATTRIBUTE_UNUSED inline void Reflect(JsonWriter &vis, T &v) { \
auto v0 = static_cast<std::underlying_type_t<T>>(v); \
::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 MAKE_REFLECT_EMPTY_STRUCT(type, ...) \
template <typename TVisitor> void Reflect(TVisitor &vis, type &v) { \
REFLECT_MEMBER_START(); \
REFLECT_MEMBER_END(); \
}
#define MAKE_REFLECT_STRUCT(type, ...) \
template <typename TVisitor> void Reflect(TVisitor &vis, type &v) { \
REFLECT_MEMBER_START(); \
#define REFLECT_STRUCT(type, ...) \
template <typename Vis> void Reflect(Vis &vis, type &v) { \
ReflectMemberStart(vis); \
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);
// Reflects the struct so it is serialized as an array instead of an object.
// This currently only supports writers.
#define MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY(type, ...) \
inline void Reflect(Writer &vis, type &v) { \
vis.StartArray(NUM_VA_ARGS(__VA_ARGS__)); \
MACRO_MAP(_MAPPABLE_REFLECT_ARRAY, __VA_ARGS__) \
vis.EndArray(); \
}
void Reflect(JsonReader &vis, bool &v);
void Reflect(JsonReader &vis, unsigned char &v);
void Reflect(JsonReader &vis, short &v);
void Reflect(JsonReader &vis, unsigned short &v);
void Reflect(JsonReader &vis, int &v);
void Reflect(JsonReader &vis, unsigned &v);
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(Writer &vis, uint8_t &v);
void Reflect(BinaryReader &vis, bool &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(Writer &vis, short &v);
void Reflect(BinaryWriter &vis, bool &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(Writer &vis, unsigned short &v);
void Reflect(JsonReader &vis, JsonNull &v);
void Reflect(JsonWriter &vis, JsonNull &v);
void Reflect(Reader &vis, int &v);
void Reflect(Writer &vis, int &v);
void Reflect(JsonReader &vis, SerializeFormat &v);
void Reflect(JsonWriter &vis, SerializeFormat &v);
void Reflect(Reader &vis, unsigned &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);
void Reflect(JsonWriter &vis, std::string_view &v);
//// Type constructors
@ -188,109 +238,154 @@ void Reflect(Writer &vis, SerializeFormat &v);
// properties (in `key: value` context). Reflect std::optional<T> is used for a
// different purpose, whether an object is nullable (possibly in `value`
// context).
template <typename T> void Reflect(Reader &vis, std::optional<T> &v) {
if (vis.IsNull()) {
vis.GetNull();
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);
template <typename T> void Reflect(JsonReader &vis, std::optional<T> &v) {
if (!vis.IsNull()) {
v.emplace();
Reflect(vis, *v);
} else
}
}
template <typename T> void Reflect(JsonWriter &vis, std::optional<T> &v) {
if (v)
Reflect(vis, *v);
else
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
template <typename T> void Reflect(Reader &vis, Maybe<T> &v) {
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);
template <typename T> void Reflect(JsonReader &vis, Maybe<T> &v) {
if (!vis.IsNull())
Reflect(vis, *v);
} else
}
template <typename T> void Reflect(JsonWriter &vis, Maybe<T> &v) {
if (v)
Reflect(vis, *v);
else
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>
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,
// We omit both key and value if value is std::nullopt (null) for JsonWriter
// to reduce output. But keep it for other serialization formats.
if (v || vis.Format() != SerializeFormat::Json) {
if (v) {
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
template <typename T>
void ReflectMember(Writer &vis, const char *name, Maybe<T> &v) {
if (v.Valid() || vis.Format() != SerializeFormat::Json) {
void ReflectMember(JsonWriter &vis, const char *name, Maybe<T> &v) {
if (v.Valid()) {
vis.Key(name);
Reflect(vis, v);
}
}
template <typename T>
void ReflectMember(BinaryWriter &vis, const char *, Maybe<T> &v) {
Reflect(vis, v);
}
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("R", [&]() { Reflect(vis, v.second); });
}
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();
ReflectMember(vis, "L", v.first);
ReflectMember(vis, "R", v.second);
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
template <typename T> void Reflect(Reader &vis, std::vector<T> &vs) {
vis.IterArray([&](Reader &entry) {
T entry_value;
Reflect(entry, entry_value);
vs.push_back(std::move(entry_value));
template <typename T> void Reflect(JsonReader &vis, std::vector<T> &v) {
vis.IterArray([&]() {
v.emplace_back();
Reflect(vis, v.back());
});
}
template <typename T> void Reflect(Writer &vis, std::vector<T> &vs) {
vis.StartArray(vs.size());
for (auto &v : vs)
Reflect(vis, v);
template <typename T> void Reflect(JsonWriter &vis, std::vector<T> &v) {
vis.StartArray();
for (auto &it : v)
Reflect(vis, it);
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
inline bool ReflectMemberStart(Reader &vis) { return false; }
inline bool ReflectMemberStart(Writer &vis) {
vis.StartObject();
return true;
}
template <typename T> void ReflectMemberStart(T &) {}
inline void ReflectMemberStart(JsonWriter &vis) { vis.StartObject(); }
inline void ReflectMemberEnd(Reader &vis) {}
inline void ReflectMemberEnd(Writer &vis) { vis.EndObject(); }
template <typename T> void ReflectMemberEnd(T &) {}
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); });
}
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);
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

View File

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

View File

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