mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-24 08:35:08 +00:00
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:
parent
872d7c5de9
commit
04e80544b9
@ -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);
|
||||
|
154
src/indexer.cc
154
src/indexer.cc
@ -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,90 +1376,85 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs,
|
||||
}
|
||||
} // namespace idx
|
||||
|
||||
void Reflect(Reader &vis, SymbolRef &v) {
|
||||
if (vis.Format() == SerializeFormat::Json) {
|
||||
std::string t = vis.GetString();
|
||||
char *s = const_cast<char *>(t.c_str());
|
||||
v.range = Range::FromString(s);
|
||||
s = strchr(s, '|');
|
||||
v.usr = strtoull(s + 1, &s, 10);
|
||||
v.kind = static_cast<Kind>(strtol(s + 1, &s, 10));
|
||||
v.role = static_cast<Role>(strtol(s + 1, &s, 10));
|
||||
} else {
|
||||
Reflect(vis, v.range);
|
||||
Reflect(vis, v.usr);
|
||||
Reflect(vis, v.kind);
|
||||
Reflect(vis, v.role);
|
||||
}
|
||||
void Reflect(JsonReader &vis, SymbolRef &v) {
|
||||
std::string t = vis.GetString();
|
||||
char *s = const_cast<char *>(t.c_str());
|
||||
v.range = Range::FromString(s);
|
||||
s = strchr(s, '|');
|
||||
v.usr = strtoull(s + 1, &s, 10);
|
||||
v.kind = static_cast<Kind>(strtol(s + 1, &s, 10));
|
||||
v.role = static_cast<Role>(strtol(s + 1, &s, 10));
|
||||
}
|
||||
void Reflect(Writer &vis, SymbolRef &v) {
|
||||
if (vis.Format() == SerializeFormat::Json) {
|
||||
char buf[99];
|
||||
snprintf(buf, sizeof buf, "%s|%" PRIu64 "|%d|%d",
|
||||
v.range.ToString().c_str(), v.usr, int(v.kind), int(v.role));
|
||||
std::string s(buf);
|
||||
Reflect(vis, s);
|
||||
} else {
|
||||
Reflect(vis, v.range);
|
||||
Reflect(vis, v.usr);
|
||||
Reflect(vis, v.kind);
|
||||
Reflect(vis, v.role);
|
||||
}
|
||||
void Reflect(JsonReader &vis, Use &v) {
|
||||
std::string t = vis.GetString();
|
||||
char *s = const_cast<char *>(t.c_str());
|
||||
v.range = Range::FromString(s);
|
||||
s = strchr(s, '|');
|
||||
v.role = static_cast<Role>(strtol(s + 1, &s, 10));
|
||||
v.file_id = static_cast<int>(strtol(s + 1, &s, 10));
|
||||
}
|
||||
void Reflect(JsonReader &vis, DeclRef &v) {
|
||||
std::string t = vis.GetString();
|
||||
char *s = const_cast<char *>(t.c_str());
|
||||
v.range = Range::FromString(s);
|
||||
s = strchr(s, '|') + 1;
|
||||
v.extent = Range::FromString(s);
|
||||
s = strchr(s, '|');
|
||||
v.role = static_cast<Role>(strtol(s + 1, &s, 10));
|
||||
v.file_id = static_cast<int>(strtol(s + 1, &s, 10));
|
||||
}
|
||||
|
||||
void Reflect(Reader &vis, Use &v) {
|
||||
if (vis.Format() == SerializeFormat::Json) {
|
||||
std::string t = vis.GetString();
|
||||
char *s = const_cast<char *>(t.c_str());
|
||||
v.range = Range::FromString(s);
|
||||
s = strchr(s, '|');
|
||||
v.role = static_cast<Role>(strtol(s + 1, &s, 10));
|
||||
v.file_id = static_cast<int>(strtol(s + 1, &s, 10));
|
||||
} else {
|
||||
Reflect(vis, v.range);
|
||||
Reflect(vis, v.role);
|
||||
Reflect(vis, v.file_id);
|
||||
}
|
||||
void Reflect(JsonWriter &vis, SymbolRef &v) {
|
||||
char buf[99];
|
||||
snprintf(buf, sizeof buf, "%s|%" PRIu64 "|%d|%d", v.range.ToString().c_str(),
|
||||
v.usr, int(v.kind), int(v.role));
|
||||
std::string s(buf);
|
||||
Reflect(vis, s);
|
||||
}
|
||||
void Reflect(Writer &vis, Use &v) {
|
||||
if (vis.Format() == SerializeFormat::Json) {
|
||||
char buf[99];
|
||||
snprintf(buf, sizeof buf, "%s|%d|%d", v.range.ToString().c_str(),
|
||||
int(v.role), v.file_id);
|
||||
std::string s(buf);
|
||||
Reflect(vis, s);
|
||||
} else {
|
||||
Reflect(vis, v.range);
|
||||
Reflect(vis, v.role);
|
||||
Reflect(vis, v.file_id);
|
||||
}
|
||||
void Reflect(JsonWriter &vis, Use &v) {
|
||||
char buf[99];
|
||||
snprintf(buf, sizeof buf, "%s|%d|%d", v.range.ToString().c_str(), int(v.role),
|
||||
v.file_id);
|
||||
std::string s(buf);
|
||||
Reflect(vis, s);
|
||||
}
|
||||
void Reflect(JsonWriter &vis, DeclRef &v) {
|
||||
char buf[99];
|
||||
snprintf(buf, sizeof buf, "%s|%s|%d|%d", v.range.ToString().c_str(),
|
||||
v.extent.ToString().c_str(), int(v.role), v.file_id);
|
||||
std::string s(buf);
|
||||
Reflect(vis, s);
|
||||
}
|
||||
|
||||
void Reflect(Reader &vis, DeclRef &v) {
|
||||
if (vis.Format() == SerializeFormat::Json) {
|
||||
std::string t = vis.GetString();
|
||||
char *s = const_cast<char *>(t.c_str());
|
||||
v.range = Range::FromString(s);
|
||||
s = strchr(s, '|') + 1;
|
||||
v.extent = Range::FromString(s);
|
||||
s = strchr(s, '|');
|
||||
v.role = static_cast<Role>(strtol(s + 1, &s, 10));
|
||||
v.file_id = static_cast<int>(strtol(s + 1, &s, 10));
|
||||
} else {
|
||||
Reflect(vis, static_cast<Use &>(v));
|
||||
Reflect(vis, v.extent);
|
||||
}
|
||||
void Reflect(BinaryReader &vis, SymbolRef &v) {
|
||||
Reflect(vis, v.range);
|
||||
Reflect(vis, v.usr);
|
||||
Reflect(vis, v.kind);
|
||||
Reflect(vis, v.role);
|
||||
}
|
||||
void Reflect(Writer &vis, DeclRef &v) {
|
||||
if (vis.Format() == SerializeFormat::Json) {
|
||||
char buf[99];
|
||||
snprintf(buf, sizeof buf, "%s|%s|%d|%d", v.range.ToString().c_str(),
|
||||
v.extent.ToString().c_str(), int(v.role), v.file_id);
|
||||
std::string s(buf);
|
||||
Reflect(vis, s);
|
||||
} else {
|
||||
Reflect(vis, static_cast<Use &>(v));
|
||||
Reflect(vis, v.extent);
|
||||
}
|
||||
void Reflect(BinaryReader &vis, Use &v) {
|
||||
Reflect(vis, v.range);
|
||||
Reflect(vis, v.role);
|
||||
Reflect(vis, v.file_id);
|
||||
}
|
||||
void Reflect(BinaryReader &vis, DeclRef &v) {
|
||||
Reflect(vis, static_cast<Use &>(v));
|
||||
Reflect(vis, v.extent);
|
||||
}
|
||||
|
||||
void Reflect(BinaryWriter &vis, SymbolRef &v) {
|
||||
Reflect(vis, v.range);
|
||||
Reflect(vis, v.usr);
|
||||
Reflect(vis, v.kind);
|
||||
Reflect(vis, v.role);
|
||||
}
|
||||
void Reflect(BinaryWriter &vis, Use &v) {
|
||||
Reflect(vis, v.range);
|
||||
Reflect(vis, v.role);
|
||||
Reflect(vis, v.file_id);
|
||||
}
|
||||
void Reflect(BinaryWriter &vis, DeclRef &v) {
|
||||
Reflect(vis, static_cast<Use &>(v));
|
||||
Reflect(vis, v.extent);
|
||||
}
|
||||
} // namespace ccls
|
||||
|
@ -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);
|
||||
|
||||
|
31
src/lsp.cc
31
src/lsp.cc
@ -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;
|
||||
}
|
||||
}
|
||||
|
11
src/lsp.hh
11
src/lsp.hh
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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,
|
||||
ranges, lsRanges);
|
||||
MAKE_REFLECT_STRUCT(CclsSemanticHighlight, uri, symbols);
|
||||
REFLECT_STRUCT(CclsSemanticHighlightSymbol, id, parentKind, kind, storage,
|
||||
ranges, lsRanges);
|
||||
REFLECT_STRUCT(CclsSemanticHighlight, uri, symbols);
|
||||
|
||||
struct CclsSetSkippedRanges {
|
||||
DocumentUri uri;
|
||||
std::vector<lsRange> skippedRanges;
|
||||
};
|
||||
MAKE_REFLECT_STRUCT(CclsSetSkippedRanges, uri, skippedRanges);
|
||||
REFLECT_STRUCT(CclsSetSkippedRanges, uri, skippedRanges);
|
||||
|
||||
struct ScanLineEvent {
|
||||
Position pos;
|
||||
@ -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);
|
||||
}
|
||||
|
@ -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 &);
|
||||
};
|
||||
|
||||
|
@ -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,8 +69,8 @@ struct Out_cclsCall {
|
||||
}
|
||||
bool operator<(const Out_cclsCall &o) const { return location < o.location; }
|
||||
};
|
||||
MAKE_REFLECT_STRUCT(Out_cclsCall, id, name, location, callType, numChildren,
|
||||
children);
|
||||
REFLECT_STRUCT(Out_cclsCall, id, name, location, callType, numChildren,
|
||||
children);
|
||||
|
||||
bool Expand(MessageHandler *m, Out_cclsCall *entry, bool callee,
|
||||
CallType call_type, bool qualified, int levels) {
|
||||
@ -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;
|
||||
|
@ -19,8 +19,8 @@ limitations under the License.
|
||||
#include "query.hh"
|
||||
|
||||
namespace ccls {
|
||||
MAKE_REFLECT_STRUCT(QueryFile::Def, path, args, language, skipped_ranges,
|
||||
dependencies);
|
||||
REFLECT_STRUCT(QueryFile::Def, path, args, language, skipped_ranges,
|
||||
dependencies);
|
||||
|
||||
namespace {
|
||||
struct Out_cclsInfo {
|
||||
@ -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) {
|
||||
|
@ -36,8 +36,8 @@ struct Param : TextDocumentPositionParam {
|
||||
bool hierarchy = false;
|
||||
};
|
||||
|
||||
MAKE_REFLECT_STRUCT(Param, textDocument, position, id, kind, derived, qualified,
|
||||
levels, hierarchy);
|
||||
REFLECT_STRUCT(Param, textDocument, position, id, kind, derived, qualified,
|
||||
levels, hierarchy);
|
||||
|
||||
struct Out_cclsInheritance {
|
||||
Usr usr;
|
||||
@ -51,8 +51,8 @@ struct Out_cclsInheritance {
|
||||
// Empty if the |levels| limit is reached.
|
||||
std::vector<Out_cclsInheritance> children;
|
||||
};
|
||||
MAKE_REFLECT_STRUCT(Out_cclsInheritance, id, kind, name, location, numChildren,
|
||||
children);
|
||||
REFLECT_STRUCT(Out_cclsInheritance, id, kind, name, location, numChildren,
|
||||
children);
|
||||
|
||||
bool Expand(MessageHandler *m, Out_cclsInheritance *entry, bool derived,
|
||||
bool qualified, int levels);
|
||||
@ -165,7 +165,7 @@ void Inheritance(MessageHandler *m, Param ¶m, 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);
|
||||
|
@ -42,8 +42,8 @@ struct Param : TextDocumentPositionParam {
|
||||
bool hierarchy = false;
|
||||
};
|
||||
|
||||
MAKE_REFLECT_STRUCT(Param, textDocument, position, id, qualified, levels, kind,
|
||||
hierarchy);
|
||||
REFLECT_STRUCT(Param, textDocument, position, id, qualified, levels, kind,
|
||||
hierarchy);
|
||||
|
||||
struct Out_cclsMember {
|
||||
Usr usr;
|
||||
@ -57,8 +57,8 @@ struct Out_cclsMember {
|
||||
// Empty if the |levels| limit is reached.
|
||||
std::vector<Out_cclsMember> children;
|
||||
};
|
||||
MAKE_REFLECT_STRUCT(Out_cclsMember, id, name, fieldName, location, numChildren,
|
||||
children);
|
||||
REFLECT_STRUCT(Out_cclsMember, id, name, fieldName, location, numChildren,
|
||||
children);
|
||||
|
||||
bool Expand(MessageHandler *m, Out_cclsMember *entry, bool qualified,
|
||||
int levels, Kind memberKind);
|
||||
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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.
|
||||
|
@ -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());
|
||||
|
@ -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,37 +106,36 @@ struct ServerCap {
|
||||
} workspaceFolders;
|
||||
} workspace;
|
||||
};
|
||||
MAKE_REFLECT_STRUCT(ServerCap::CodeActionOptions, codeActionKinds);
|
||||
MAKE_REFLECT_STRUCT(ServerCap::CodeLensOptions, resolveProvider);
|
||||
MAKE_REFLECT_STRUCT(ServerCap::CompletionOptions, resolveProvider,
|
||||
triggerCharacters);
|
||||
MAKE_REFLECT_STRUCT(ServerCap::DocumentLinkOptions, resolveProvider);
|
||||
MAKE_REFLECT_STRUCT(ServerCap::DocumentOnTypeFormattingOptions,
|
||||
firstTriggerCharacter, moreTriggerCharacter);
|
||||
MAKE_REFLECT_STRUCT(ServerCap::ExecuteCommandOptions, commands);
|
||||
MAKE_REFLECT_STRUCT(ServerCap::SaveOptions, includeText);
|
||||
MAKE_REFLECT_STRUCT(ServerCap::SignatureHelpOptions, triggerCharacters);
|
||||
MAKE_REFLECT_STRUCT(ServerCap::TextDocumentSyncOptions, openClose, change,
|
||||
willSave, willSaveWaitUntil, save);
|
||||
MAKE_REFLECT_STRUCT(ServerCap::Workspace::WorkspaceFolders, supported,
|
||||
changeNotifications);
|
||||
MAKE_REFLECT_STRUCT(ServerCap::Workspace, workspaceFolders);
|
||||
MAKE_REFLECT_STRUCT(ServerCap, textDocumentSync, hoverProvider,
|
||||
completionProvider, signatureHelpProvider,
|
||||
definitionProvider, implementationProvider,
|
||||
typeDefinitionProvider, referencesProvider,
|
||||
documentHighlightProvider, documentSymbolProvider,
|
||||
workspaceSymbolProvider, codeActionProvider,
|
||||
codeLensProvider, documentFormattingProvider,
|
||||
documentRangeFormattingProvider,
|
||||
documentOnTypeFormattingProvider, renameProvider,
|
||||
documentLinkProvider, foldingRangeProvider,
|
||||
executeCommandProvider, workspace);
|
||||
REFLECT_STRUCT(ServerCap::CodeActionOptions, codeActionKinds);
|
||||
REFLECT_STRUCT(ServerCap::CodeLensOptions, resolveProvider);
|
||||
REFLECT_STRUCT(ServerCap::CompletionOptions, resolveProvider,
|
||||
triggerCharacters);
|
||||
REFLECT_STRUCT(ServerCap::DocumentLinkOptions, resolveProvider);
|
||||
REFLECT_STRUCT(ServerCap::DocumentOnTypeFormattingOptions,
|
||||
firstTriggerCharacter, moreTriggerCharacter);
|
||||
REFLECT_STRUCT(ServerCap::ExecuteCommandOptions, commands);
|
||||
REFLECT_STRUCT(ServerCap::SaveOptions, includeText);
|
||||
REFLECT_STRUCT(ServerCap::SignatureHelpOptions, triggerCharacters);
|
||||
REFLECT_STRUCT(ServerCap::TextDocumentSyncOptions, openClose, change, willSave,
|
||||
willSaveWaitUntil, save);
|
||||
REFLECT_STRUCT(ServerCap::Workspace::WorkspaceFolders, supported,
|
||||
changeNotifications);
|
||||
REFLECT_STRUCT(ServerCap::Workspace, workspaceFolders);
|
||||
REFLECT_STRUCT(ServerCap, textDocumentSync, hoverProvider, completionProvider,
|
||||
signatureHelpProvider, definitionProvider,
|
||||
implementationProvider, typeDefinitionProvider,
|
||||
referencesProvider, documentHighlightProvider,
|
||||
documentSymbolProvider, workspaceSymbolProvider,
|
||||
codeActionProvider, codeLensProvider, documentFormattingProvider,
|
||||
documentRangeFormattingProvider,
|
||||
documentOnTypeFormattingProvider, renameProvider,
|
||||
documentLinkProvider, foldingRangeProvider,
|
||||
executeCommandProvider, workspace);
|
||||
|
||||
struct DynamicReg {
|
||||
bool dynamicRegistration = false;
|
||||
};
|
||||
MAKE_REFLECT_STRUCT(DynamicReg, dynamicRegistration);
|
||||
REFLECT_STRUCT(DynamicReg, dynamicRegistration);
|
||||
|
||||
// Workspace specific client capabilities.
|
||||
struct WorkspaceClientCap {
|
||||
@ -154,10 +155,10 @@ struct WorkspaceClientCap {
|
||||
DynamicReg executeCommand;
|
||||
};
|
||||
|
||||
MAKE_REFLECT_STRUCT(WorkspaceClientCap::WorkspaceEdit, documentChanges);
|
||||
MAKE_REFLECT_STRUCT(WorkspaceClientCap, applyEdit, workspaceEdit,
|
||||
didChangeConfiguration, didChangeWatchedFiles, symbol,
|
||||
executeCommand);
|
||||
REFLECT_STRUCT(WorkspaceClientCap::WorkspaceEdit, documentChanges);
|
||||
REFLECT_STRUCT(WorkspaceClientCap, applyEdit, workspaceEdit,
|
||||
didChangeConfiguration, didChangeWatchedFiles, symbol,
|
||||
executeCommand);
|
||||
|
||||
// Text document specific client capabilities.
|
||||
struct TextDocumentClientCap {
|
||||
@ -178,18 +179,18 @@ struct TextDocumentClientCap {
|
||||
} documentSymbol;
|
||||
};
|
||||
|
||||
MAKE_REFLECT_STRUCT(TextDocumentClientCap::Completion::CompletionItem,
|
||||
snippetSupport);
|
||||
MAKE_REFLECT_STRUCT(TextDocumentClientCap::Completion, completionItem);
|
||||
MAKE_REFLECT_STRUCT(TextDocumentClientCap::DocumentSymbol,
|
||||
hierarchicalDocumentSymbolSupport);
|
||||
MAKE_REFLECT_STRUCT(TextDocumentClientCap, completion, documentSymbol);
|
||||
REFLECT_STRUCT(TextDocumentClientCap::Completion::CompletionItem,
|
||||
snippetSupport);
|
||||
REFLECT_STRUCT(TextDocumentClientCap::Completion, completionItem);
|
||||
REFLECT_STRUCT(TextDocumentClientCap::DocumentSymbol,
|
||||
hierarchicalDocumentSymbolSupport);
|
||||
REFLECT_STRUCT(TextDocumentClientCap, completion, documentSymbol);
|
||||
|
||||
struct ClientCap {
|
||||
WorkspaceClientCap workspace;
|
||||
TextDocumentClientCap textDocument;
|
||||
};
|
||||
MAKE_REFLECT_STRUCT(ClientCap, workspace, textDocument);
|
||||
REFLECT_STRUCT(ClientCap, workspace, textDocument);
|
||||
|
||||
struct InitializeParam {
|
||||
// The rootUri of the workspace. Is null if no
|
||||
@ -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 ¶m, 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) {
|
||||
|
@ -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 ¶m,
|
||||
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 ¶m,
|
||||
reply(result);
|
||||
}
|
||||
|
||||
void MessageHandler::workspace_executeCommand(Reader &reader,
|
||||
void MessageHandler::workspace_executeCommand(JsonReader &reader,
|
||||
ReplyOnce &reply) {
|
||||
Command param;
|
||||
Reflect(reader, param);
|
||||
|
@ -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,
|
||||
|
@ -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 ¶m,
|
||||
@ -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,
|
||||
children);
|
||||
void Reflect(Writer &vis, std::unique_ptr<DocumentSymbol> &v) {
|
||||
void Reflect(JsonWriter &vis, std::unique_ptr<DocumentSymbol> &v);
|
||||
REFLECT_STRUCT(DocumentSymbol, name, detail, kind, range, selectionRange,
|
||||
children);
|
||||
void Reflect(JsonWriter &vis, std::unique_ptr<DocumentSymbol> &v) {
|
||||
Reflect(vis, *v);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
@ -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 ¶m,
|
||||
|
@ -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) {
|
||||
|
@ -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());
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
Reflect(visitor, value.start.line);
|
||||
Reflect(visitor, value.start.column);
|
||||
Reflect(visitor, value.end.line);
|
||||
Reflect(visitor, value.end.column);
|
||||
}
|
||||
void Reflect(JsonWriter &vis, Range &v) {
|
||||
std::string output = v.ToString();
|
||||
vis.String(output.c_str(), output.size());
|
||||
}
|
||||
|
||||
void Reflect(BinaryReader &visitor, Pos &value) {
|
||||
Reflect(visitor, value.line);
|
||||
Reflect(visitor, value.column);
|
||||
}
|
||||
void Reflect(BinaryReader &visitor, Range &value) {
|
||||
Reflect(visitor, value.start.line);
|
||||
Reflect(visitor, value.start.column);
|
||||
Reflect(visitor, value.end.line);
|
||||
Reflect(visitor, value.end.column);
|
||||
}
|
||||
|
||||
void Reflect(BinaryWriter &vis, Pos &v) {
|
||||
Reflect(vis, v.line);
|
||||
Reflect(vis, v.column);
|
||||
}
|
||||
void Reflect(BinaryWriter &vis, Range &v) {
|
||||
Reflect(vis, v.start.line);
|
||||
Reflect(vis, v.start.column);
|
||||
Reflect(vis, v.end.line);
|
||||
Reflect(vis, v.end.column);
|
||||
}
|
||||
} // namespace ccls
|
||||
|
@ -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 {
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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();
|
||||
}
|
||||
template <typename V>
|
||||
void Reflect(BinaryReader &vis, std::unordered_map<Usr, V> &v) {
|
||||
for (auto n = vis.VarUInt(); n; n--) {
|
||||
V val;
|
||||
Reflect(vis, val);
|
||||
v[val.usr] = std::move(val);
|
||||
}
|
||||
}
|
||||
template <typename V>
|
||||
void Reflect(BinaryWriter &vis, std::unordered_map<Usr, V> &v) {
|
||||
vis.VarUInt(v.size());
|
||||
for (auto &it : v)
|
||||
Reflect(vis, it.second);
|
||||
}
|
||||
|
||||
// Used by IndexFile::dependencies.
|
||||
void Reflect(Reader &vis, DenseMap<CachedHashStringRef, int64_t> &v) {
|
||||
void Reflect(JsonReader &vis, DenseMap<CachedHashStringRef, int64_t> &v) {
|
||||
std::string name;
|
||||
if (vis.Format() == SerializeFormat::Json) {
|
||||
auto &vis1 = static_cast<JsonReader&>(vis);
|
||||
for (auto it = vis1.m().MemberBegin(); it != vis1.m().MemberEnd(); ++it)
|
||||
v[InternH(it->name.GetString())] = it->value.GetInt64();
|
||||
} else {
|
||||
vis.IterArray([&](Reader &entry) {
|
||||
Reflect(entry, name);
|
||||
Reflect(entry, v[InternH(name)]);
|
||||
});
|
||||
for (auto it = vis.m->MemberBegin(); it != vis.m->MemberEnd(); ++it)
|
||||
v[InternH(it->name.GetString())] = it->value.GetInt64();
|
||||
}
|
||||
void Reflect(JsonWriter &vis, DenseMap<CachedHashStringRef, int64_t> &v) {
|
||||
vis.StartObject();
|
||||
for (auto &it : v) {
|
||||
vis.m->Key(it.first.val().data()); // llvm 8 -> data()
|
||||
vis.m->Int64(it.second);
|
||||
}
|
||||
vis.EndObject();
|
||||
}
|
||||
void Reflect(BinaryReader &vis, DenseMap<CachedHashStringRef, int64_t> &v) {
|
||||
std::string name;
|
||||
for (auto n = vis.VarUInt(); n; n--) {
|
||||
Reflect(vis, name);
|
||||
Reflect(vis, v[InternH(name)]);
|
||||
}
|
||||
}
|
||||
void Reflect(Writer &vis, DenseMap<CachedHashStringRef, int64_t> &v) {
|
||||
if (vis.Format() == SerializeFormat::Json) {
|
||||
auto &vis1 = static_cast<JsonWriter&>(vis);
|
||||
vis.StartObject();
|
||||
for (auto &it : v) {
|
||||
vis1.m().Key(it.first.val().data()); // llvm 8 -> data()
|
||||
vis1.m().Int64(it.second);
|
||||
}
|
||||
vis.EndObject();
|
||||
} else {
|
||||
vis.StartArray(v.size());
|
||||
for (auto &it : v) {
|
||||
std::string key = it.first.val().str();
|
||||
Reflect(vis, key);
|
||||
Reflect(vis, it.second);
|
||||
}
|
||||
vis.EndArray();
|
||||
void Reflect(BinaryWriter &vis, DenseMap<CachedHashStringRef, int64_t> &v) {
|
||||
std::string key;
|
||||
vis.VarUInt(v.size());
|
||||
for (auto &it : v) {
|
||||
key = it.first.val().str();
|
||||
Reflect(vis, key);
|
||||
Reflect(vis, it.second);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Move this to indexer.cc
|
||||
void Reflect(Reader &vis, IndexInclude &v) {
|
||||
REFLECT_MEMBER_START();
|
||||
template <typename Vis> void Reflect(Vis &vis, IndexInclude &v) {
|
||||
ReflectMemberStart(vis);
|
||||
REFLECT_MEMBER(line);
|
||||
REFLECT_MEMBER(resolved_path);
|
||||
REFLECT_MEMBER_END();
|
||||
ReflectMemberEnd(vis);
|
||||
}
|
||||
void Reflect(Writer &vis, IndexInclude &v) {
|
||||
REFLECT_MEMBER_START();
|
||||
void Reflect(JsonWriter &vis, IndexInclude &v) {
|
||||
ReflectMemberStart(vis);
|
||||
REFLECT_MEMBER(line);
|
||||
if (gTestOutputMode) {
|
||||
std::string basename = llvm::sys::path::filename(v.resolved_path);
|
||||
@ -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();
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
@ -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
|
Loading…
Reference in New Issue
Block a user