Refactor serializer

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

View File

@ -259,28 +259,28 @@ struct Config {
int maxNum = 2000;
} 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

@ -20,7 +20,6 @@ limitations under the License.
#include "pipeline.hh"
#include "platform.hh"
#include "sema_manager.hh"
#include "serializer.hh"
#include <clang/AST/AST.h>
#include <clang/Frontend/FrontendAction.h>
@ -1185,7 +1184,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)
@ -1377,8 +1376,7 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs,
}
} // namespace idx
void Reflect(Reader &vis, SymbolRef &v) {
if (vis.Format() == SerializeFormat::Json) {
void Reflect(JsonReader &vis, SymbolRef &v) {
std::string t = vis.GetString();
char *s = const_cast<char *>(t.c_str());
v.range = Range::FromString(s);
@ -1386,58 +1384,16 @@ void Reflect(Reader &vis, SymbolRef &v) {
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(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(Reader &vis, Use &v) {
if (vis.Format() == SerializeFormat::Json) {
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));
} else {
Reflect(vis, v.range);
Reflect(vis, v.role);
Reflect(vis, v.file_id);
}
}
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(Reader &vis, DeclRef &v) {
if (vis.Format() == SerializeFormat::Json) {
void Reflect(JsonReader &vis, DeclRef &v) {
std::string t = vis.GetString();
char *s = const_cast<char *>(t.c_str());
v.range = Range::FromString(s);
@ -1446,21 +1402,59 @@ void Reflect(Reader &vis, DeclRef &v) {
s = strchr(s, '|');
v.role = static_cast<Role>(strtol(s + 1, &s, 10));
v.file_id = static_cast<int>(strtol(s + 1, &s, 10));
} else {
Reflect(vis, static_cast<Use &>(v));
Reflect(vis, v.extent);
}
}
void Reflect(Writer &vis, DeclRef &v) {
if (vis.Format() == SerializeFormat::Json) {
void Reflect(JsonWriter &vis, SymbolRef &v) {
char buf[99];
snprintf(buf, sizeof buf, "%s|%" PRIu64 "|%d|%d", v.range.ToString().c_str(),
v.usr, int(v.kind), int(v.role));
std::string s(buf);
Reflect(vis, s);
}
void Reflect(JsonWriter &vis, Use &v) {
char buf[99];
snprintf(buf, sizeof buf, "%s|%d|%d", v.range.ToString().c_str(), int(v.role),
v.file_id);
std::string s(buf);
Reflect(vis, s);
}
void Reflect(JsonWriter &vis, DeclRef &v) {
char buf[99];
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 {
}
void Reflect(BinaryReader &vis, SymbolRef &v) {
Reflect(vis, v.range);
Reflect(vis, v.usr);
Reflect(vis, v.kind);
Reflect(vis, v.role);
}
void Reflect(BinaryReader &vis, Use &v) {
Reflect(vis, v.range);
Reflect(vis, v.role);
Reflect(vis, v.file_id);
}
void Reflect(BinaryReader &vis, DeclRef &v) {
Reflect(vis, static_cast<Use &>(v));
Reflect(vis, v.extent);
}
void Reflect(BinaryWriter &vis, SymbolRef &v) {
Reflect(vis, v.range);
Reflect(vis, v.usr);
Reflect(vis, v.kind);
Reflect(vis, v.role);
}
void Reflect(BinaryWriter &vis, Use &v) {
Reflect(vis, v.range);
Reflect(vis, v.role);
Reflect(vis, v.file_id);
}
void Reflect(BinaryWriter &vis, DeclRef &v) {
Reflect(vis, static_cast<Use &>(v));
Reflect(vis, v.extent);
}
}
} // namespace ccls

View File

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

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

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

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

View File

@ -19,7 +19,9 @@ limitations under the License.
#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>
@ -29,35 +31,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 {
@ -75,15 +77,15 @@ struct CclsSemanticHighlight {
DocumentUri uri;
std::vector<CclsSemanticHighlightSymbol> symbols;
};
MAKE_REFLECT_STRUCT(CclsSemanticHighlightSymbol, id, parentKind, kind, storage,
REFLECT_STRUCT(CclsSemanticHighlightSymbol, id, parentKind, kind, storage,
ranges, lsRanges);
MAKE_REFLECT_STRUCT(CclsSemanticHighlight, uri, symbols);
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;
@ -114,8 +116,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);
};
}
@ -123,7 +126,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);
@ -131,9 +134,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);
};
}
@ -142,7 +146,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);
@ -214,7 +219,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

@ -32,8 +32,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 {
@ -63,11 +63,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 {
@ -175,32 +175,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);
};
@ -213,33 +220,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 &);
@ -251,7 +259,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 &);
@ -260,14 +268,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

@ -30,7 +30,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);
@ -52,8 +52,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;
@ -69,7 +69,7 @@ struct Out_cclsCall {
}
bool operator<(const Out_cclsCall &o) const { return location < o.location; }
};
MAKE_REFLECT_STRUCT(Out_cclsCall, id, name, location, callType, numChildren,
REFLECT_STRUCT(Out_cclsCall, id, name, location, callType, numChildren,
children);
bool Expand(MessageHandler *m, Out_cclsCall *entry, bool callee,
@ -182,7 +182,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

@ -19,7 +19,7 @@ limitations under the License.
#include "query.hh"
namespace ccls {
MAKE_REFLECT_STRUCT(QueryFile::Def, path, args, language, skipped_ranges,
REFLECT_STRUCT(QueryFile::Def, path, args, language, skipped_ranges,
dependencies);
namespace {
@ -34,10 +34,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

@ -36,7 +36,7 @@ struct Param : TextDocumentPositionParam {
bool hierarchy = false;
};
MAKE_REFLECT_STRUCT(Param, textDocument, position, id, kind, derived, qualified,
REFLECT_STRUCT(Param, textDocument, position, id, kind, derived, qualified,
levels, hierarchy);
struct Out_cclsInheritance {
@ -51,7 +51,7 @@ 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,
REFLECT_STRUCT(Out_cclsInheritance, id, kind, name, location, numChildren,
children);
bool Expand(MessageHandler *m, Out_cclsInheritance *entry, bool derived,
@ -165,7 +165,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

@ -42,7 +42,7 @@ struct Param : TextDocumentPositionParam {
bool hierarchy = false;
};
MAKE_REFLECT_STRUCT(Param, textDocument, position, id, qualified, levels, kind,
REFLECT_STRUCT(Param, textDocument, position, id, qualified, levels, kind,
hierarchy);
struct Out_cclsMember {
@ -57,7 +57,7 @@ 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,
REFLECT_STRUCT(Out_cclsMember, id, name, fieldName, location, numChildren,
children);
bool Expand(MessageHandler *m, Out_cclsMember *entry, bool qualified,
@ -263,7 +263,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

@ -23,7 +23,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;
@ -38,8 +38,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

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

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

@ -21,12 +21,14 @@ limitations under the License.
#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>
@ -39,7 +41,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 {
@ -104,28 +106,27 @@ struct ServerCap {
} workspaceFolders;
} workspace;
};
MAKE_REFLECT_STRUCT(ServerCap::CodeActionOptions, codeActionKinds);
MAKE_REFLECT_STRUCT(ServerCap::CodeLensOptions, resolveProvider);
MAKE_REFLECT_STRUCT(ServerCap::CompletionOptions, resolveProvider,
REFLECT_STRUCT(ServerCap::CodeActionOptions, codeActionKinds);
REFLECT_STRUCT(ServerCap::CodeLensOptions, resolveProvider);
REFLECT_STRUCT(ServerCap::CompletionOptions, resolveProvider,
triggerCharacters);
MAKE_REFLECT_STRUCT(ServerCap::DocumentLinkOptions, resolveProvider);
MAKE_REFLECT_STRUCT(ServerCap::DocumentOnTypeFormattingOptions,
REFLECT_STRUCT(ServerCap::DocumentLinkOptions, resolveProvider);
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,
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);
MAKE_REFLECT_STRUCT(ServerCap::Workspace, workspaceFolders);
MAKE_REFLECT_STRUCT(ServerCap, textDocumentSync, hoverProvider,
completionProvider, signatureHelpProvider,
definitionProvider, implementationProvider,
typeDefinitionProvider, referencesProvider,
documentHighlightProvider, documentSymbolProvider,
workspaceSymbolProvider, codeActionProvider,
codeLensProvider, documentFormattingProvider,
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,
@ -134,7 +135,7 @@ MAKE_REFLECT_STRUCT(ServerCap, textDocumentSync, hoverProvider,
struct DynamicReg {
bool dynamicRegistration = false;
};
MAKE_REFLECT_STRUCT(DynamicReg, dynamicRegistration);
REFLECT_STRUCT(DynamicReg, dynamicRegistration);
// Workspace specific client capabilities.
struct WorkspaceClientCap {
@ -154,8 +155,8 @@ struct WorkspaceClientCap {
DynamicReg executeCommand;
};
MAKE_REFLECT_STRUCT(WorkspaceClientCap::WorkspaceEdit, documentChanges);
MAKE_REFLECT_STRUCT(WorkspaceClientCap, applyEdit, workspaceEdit,
REFLECT_STRUCT(WorkspaceClientCap::WorkspaceEdit, documentChanges);
REFLECT_STRUCT(WorkspaceClientCap, applyEdit, workspaceEdit,
didChangeConfiguration, didChangeWatchedFiles, symbol,
executeCommand);
@ -178,18 +179,18 @@ struct TextDocumentClientCap {
} documentSymbol;
};
MAKE_REFLECT_STRUCT(TextDocumentClientCap::Completion::CompletionItem,
REFLECT_STRUCT(TextDocumentClientCap::Completion::CompletionItem,
snippetSupport);
MAKE_REFLECT_STRUCT(TextDocumentClientCap::Completion, completionItem);
MAKE_REFLECT_STRUCT(TextDocumentClientCap::DocumentSymbol,
REFLECT_STRUCT(TextDocumentClientCap::Completion, completionItem);
REFLECT_STRUCT(TextDocumentClientCap::DocumentSymbol,
hierarchicalDocumentSymbolSupport);
MAKE_REFLECT_STRUCT(TextDocumentClientCap, completion, documentSymbol);
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
@ -211,12 +212,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")
@ -225,13 +226,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;
@ -341,7 +342,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

@ -16,10 +16,12 @@ limitations under the License.
#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 {
@ -29,7 +31,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) {
@ -72,9 +74,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) {
@ -174,7 +176,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

@ -32,11 +32,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);
@ -49,7 +49,7 @@ void Reflect(Writer &vis, CompletionItem &v) {
REFLECT_MEMBER(textEdit);
if (v.additionalTextEdits.size())
REFLECT_MEMBER(additionalTextEdits);
REFLECT_MEMBER_END();
ReflectMemberEnd(vis);
}
namespace {
@ -57,7 +57,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

@ -22,7 +22,7 @@ limitations under the License.
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 {
@ -38,7 +38,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(
@ -85,7 +85,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,
@ -118,7 +118,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;
@ -128,10 +128,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,
void Reflect(JsonWriter &vis, std::unique_ptr<DocumentSymbol> &v);
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(vis, *v);
}
@ -159,7 +159,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

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

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

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

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

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

@ -25,7 +25,6 @@ limitations under the License.
#include "project.hh"
#include "query.hh"
#include "sema_manager.hh"
#include "serializers/json.hh"
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
@ -49,7 +48,7 @@ struct PublishDiagnosticParam {
DocumentUri uri;
std::vector<Diagnostic> diagnostics;
};
MAKE_REFLECT_STRUCT(PublishDiagnosticParam, uri, diagnostics);
REFLECT_STRUCT(PublishDiagnosticParam, uri, diagnostics);
} // namespace
void VFS::Clear() {
@ -457,8 +456,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;
@ -610,7 +609,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();
@ -626,7 +625,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();
@ -652,11 +651,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

@ -51,16 +51,16 @@ void Index(const std::string &path, const std::vector<const char *> &args,
std::optional<std::string> LoadIndexedContent(const std::string& path);
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

@ -17,6 +17,9 @@ limitations under the License.
#include "serializer.hh"
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <algorithm>
#include <limits.h>
#include <stdio.h>
@ -69,45 +72,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 {
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

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

@ -20,7 +20,6 @@ limitations under the License.
#include "log.hh"
#include "pipeline.hh"
#include "platform.hh"
#include "serializers/json.hh"
#include "utils.hh"
#include "working_files.hh"

View File

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

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

@ -20,6 +20,7 @@ limitations under the License.
#include <llvm/Support/Compiler.h>
#include <macro_map.h>
#include <rapidjson/fwd.h>
#include <cassert>
#include <functional>
@ -40,159 +41,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
@ -200,109 +250,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,139 +0,0 @@
/* Copyright 2017-2018 ccls Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#pragma once
#include "serializer.hh"
#include <string.h>
namespace ccls {
class BinaryReader : public Reader {
const char *p_;
template <typename T> T Get() {
T ret;
memcpy(&ret, p_, sizeof(T));
p_ += sizeof(T);
return ret;
}
uint64_t VarUInt() {
auto x = *reinterpret_cast<const uint8_t *>(p_++);
if (x < 253)
return x;
if (x == 253)
return Get<uint16_t>();
if (x == 254)
return Get<uint32_t>();
return Get<uint64_t>();
}
int64_t VarInt() {
uint64_t x = VarUInt();
return int64_t(x >> 1 ^ -(x & 1));
}
public:
BinaryReader(std::string_view buf) : p_(buf.data()) {}
virtual ~BinaryReader();
SerializeFormat Format() const override { return SerializeFormat::Binary; }
bool IsBool() override { return true; }
// Abuse how the function is called in serializer.h
bool IsNull() override { return !*p_++; }
bool IsInt() override { return true; }
bool IsInt64() override { return true; }
bool IsUInt64() override { return true; }
bool IsDouble() override { return true; }
bool IsString() override { return true; }
void GetNull() override {}
bool GetBool() override { return Get<bool>(); }
int GetInt() override { return VarInt(); }
int64_t GetInt64() override { return VarInt(); }
uint8_t GetUInt8() override { return Get<uint8_t>(); }
uint32_t GetUInt32() override { return VarUInt(); }
uint64_t GetUInt64() override { return VarUInt(); }
double GetDouble() override { return Get<double>(); }
const char *GetString() override {
const char *ret = p_;
while (*p_)
p_++;
p_++;
return ret;
}
bool HasMember(const char *x) override { return true; }
std::unique_ptr<Reader> operator[](const char *x) override { return {}; }
void IterArray(std::function<void(Reader &)> fn) override {
for (auto n = VarUInt(); n; n--)
fn(*this);
}
void Member(const char *, std::function<void()> fn) override { fn(); }
};
class BinaryWriter : public Writer {
std::string buf_;
template <typename T> void Pack(T x) {
auto i = buf_.size();
buf_.resize(i + sizeof(x));
memcpy(buf_.data() + i, &x, sizeof(x));
}
void VarUInt(uint64_t n) {
if (n < 253)
Pack<uint8_t>(n);
else if (n < 65536) {
Pack<uint8_t>(253);
Pack<uint16_t>(n);
} else if (n < 4294967296) {
Pack<uint8_t>(254);
Pack<uint32_t>(n);
} else {
Pack<uint8_t>(255);
Pack<uint64_t>(n);
}
}
void VarInt(int64_t n) { VarUInt(uint64_t(n) << 1 ^ n >> 63); }
public:
virtual ~BinaryWriter();
SerializeFormat Format() const override { return SerializeFormat::Binary; }
std::string Take() { return std::move(buf_); }
void Null() override { Pack(uint8_t(0)); }
void Bool(bool x) override { Pack(x); }
void Int(int x) override { VarInt(x); }
void Int64(int64_t x) override { VarInt(x); }
void UInt8(uint8_t x) override { Pack(x); }
void UInt32(uint32_t x) override { VarUInt(x); }
void UInt64(uint64_t x) override { VarUInt(x); }
void Double(double x) override { Pack(x); }
void String(const char *x) override { String(x, strlen(x)); }
void String(const char *x, size_t len) override {
auto i = buf_.size();
buf_.resize(i + len + 1);
memcpy(buf_.data() + i, x, len);
}
void StartArray(size_t n) override { VarUInt(n); }
void EndArray() override {}
void StartObject() override {}
void EndObject() override {}
void Key(const char *name) override {}
};
} // namespace ccls

View File

@ -1,120 +0,0 @@
/* Copyright 2017-2018 ccls Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#pragma once
#include "serializer.hh"
#include <rapidjson/document.h>
#include <rapidjson/prettywriter.h>
namespace ccls {
class JsonReader : public Reader {
rapidjson::GenericValue<rapidjson::UTF8<>> *m_;
std::vector<const char *> path_;
public:
JsonReader(rapidjson::GenericValue<rapidjson::UTF8<>> *m) : m_(m) {}
virtual ~JsonReader();
SerializeFormat Format() const override { return SerializeFormat::Json; }
rapidjson::GenericValue<rapidjson::UTF8<>> &m() { return *m_; }
bool IsBool() override { return m_->IsBool(); }
bool IsNull() override { return m_->IsNull(); }
bool IsInt() override { return m_->IsInt(); }
bool IsInt64() override { return m_->IsInt64(); }
bool IsUInt64() override { return m_->IsUint64(); }
bool IsDouble() override { return m_->IsDouble(); }
bool IsString() override { return m_->IsString(); }
void GetNull() override {}
bool GetBool() override { return m_->GetBool(); }
int GetInt() override { return m_->GetInt(); }
int64_t GetInt64() override { return m_->GetInt64(); }
uint8_t GetUInt8() override { return uint8_t(m_->GetInt()); }
uint32_t GetUInt32() override { return uint32_t(m_->GetUint64()); }
uint64_t GetUInt64() override { return m_->GetUint64(); }
double GetDouble() override { return m_->GetDouble(); }
const char *GetString() override { return m_->GetString(); }
bool HasMember(const char *x) override { return m_->HasMember(x); }
std::unique_ptr<Reader> operator[](const char *x) override {
auto &sub = (*m_)[x];
return std::unique_ptr<JsonReader>(new JsonReader(&sub));
}
void IterArray(std::function<void(Reader &)> fn) override {
if (!m_->IsArray())
throw std::invalid_argument("array");
// Use "0" to indicate any element for now.
path_.push_back("0");
for (auto &entry : m_->GetArray()) {
auto saved = m_;
m_ = &entry;
fn(*this);
m_ = saved;
}
path_.pop_back();
}
void Member(const char *name, std::function<void()> fn) override {
path_.push_back(name);
auto it = m_->FindMember(name);
if (it != m_->MemberEnd()) {
auto saved = m_;
m_ = &it->value;
fn();
m_ = saved;
}
path_.pop_back();
}
std::string GetPath() const {
std::string ret;
for (auto &t : path_) {
ret += '/';
ret += t;
}
ret.pop_back();
return ret;
}
};
class JsonWriter : public Writer {
rapidjson::Writer<rapidjson::StringBuffer> *m_;
public:
JsonWriter(rapidjson::Writer<rapidjson::StringBuffer> *m) : m_(m) {}
virtual ~JsonWriter();
SerializeFormat Format() const override { return SerializeFormat::Json; }
rapidjson::Writer<rapidjson::StringBuffer> &m() { return *m_; }
void Null() override { m_->Null(); }
void Bool(bool x) override { m_->Bool(x); }
void Int(int x) override { m_->Int(x); }
void Int64(int64_t x) override { m_->Int64(x); }
void UInt8(uint8_t x) override { m_->Int(x); }
void UInt32(uint32_t x) override { m_->Uint64(x); }
void UInt64(uint64_t x) override { m_->Uint64(x); }
void Double(double x) override { m_->Double(x); }
void String(const char *x) override { m_->String(x); }
void String(const char *x, size_t len) override { m_->String(x, len); }
void StartArray(size_t) override { m_->StartArray(); }
void EndArray() override { m_->EndArray(); }
void StartObject() override { m_->StartObject(); }
void EndObject() override { m_->EndObject(); }
void Key(const char *name) override { m_->Key(name); }
};
} // namespace ccls