2017-02-23 08:47:07 +00:00
|
|
|
#include "serializer.h"
|
|
|
|
|
2017-03-14 08:33:39 +00:00
|
|
|
#include "indexer.h"
|
|
|
|
|
2017-04-20 06:02:24 +00:00
|
|
|
namespace {
|
|
|
|
bool gTestOutputMode = false;
|
|
|
|
} // namespace
|
2017-02-24 08:39:25 +00:00
|
|
|
|
2017-03-07 09:32:29 +00:00
|
|
|
// int
|
|
|
|
void Reflect(Reader& visitor, int& value) {
|
|
|
|
value = visitor.GetInt();
|
|
|
|
}
|
|
|
|
void Reflect(Writer& visitor, int& value) {
|
|
|
|
visitor.Int(value);
|
2017-02-23 08:47:07 +00:00
|
|
|
}
|
2017-04-20 04:57:44 +00:00
|
|
|
// int64_t
|
|
|
|
void Reflect(Reader& visitor, int64_t& value) {
|
|
|
|
value = visitor.GetInt64();
|
|
|
|
}
|
|
|
|
void Reflect(Writer& visitor, int64_t& value) {
|
|
|
|
visitor.Int64(value);
|
|
|
|
}
|
2017-03-07 09:32:29 +00:00
|
|
|
// bool
|
|
|
|
void Reflect(Reader& visitor, bool& value) {
|
|
|
|
value = visitor.GetBool();
|
|
|
|
}
|
|
|
|
void Reflect(Writer& visitor, bool& value) {
|
|
|
|
visitor.Bool(value);
|
2017-02-23 08:47:07 +00:00
|
|
|
}
|
2017-03-07 09:32:29 +00:00
|
|
|
// std::string
|
|
|
|
void Reflect(Reader& visitor, std::string& value) {
|
|
|
|
value = visitor.GetString();
|
|
|
|
}
|
|
|
|
void Reflect(Writer& visitor, std::string& value) {
|
2017-04-19 05:38:39 +00:00
|
|
|
visitor.String(value.c_str(), (rapidjson::SizeType)value.size());
|
2017-02-23 08:47:07 +00:00
|
|
|
}
|
|
|
|
|
2017-03-01 08:36:11 +00:00
|
|
|
|
2017-03-08 08:09:15 +00:00
|
|
|
// ReflectMember
|
|
|
|
void ReflectMember(Writer& visitor, const char* name, std::string& value) {
|
|
|
|
if (value.empty())
|
|
|
|
return;
|
|
|
|
visitor.Key(name);
|
|
|
|
Reflect(visitor, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-04-05 08:06:18 +00:00
|
|
|
// Position
|
|
|
|
void Reflect(Reader& visitor, Position& value) {
|
|
|
|
value = Position(visitor.GetString());
|
2017-02-23 08:47:07 +00:00
|
|
|
}
|
2017-04-05 08:06:18 +00:00
|
|
|
void Reflect(Writer& visitor, Position& value) {
|
2017-03-07 09:32:29 +00:00
|
|
|
std::string output = value.ToString();
|
2017-04-19 05:38:39 +00:00
|
|
|
visitor.String(output.c_str(), (rapidjson::SizeType)output.size());
|
2017-03-07 09:32:29 +00:00
|
|
|
}
|
|
|
|
|
2017-02-23 08:47:07 +00:00
|
|
|
|
2017-04-05 08:06:18 +00:00
|
|
|
// Range
|
|
|
|
void Reflect(Reader& visitor, Range& value) {
|
|
|
|
value = Range(visitor.GetString());
|
|
|
|
}
|
|
|
|
void Reflect(Writer& visitor, Range& value) {
|
|
|
|
std::string output = value.ToString();
|
2017-04-19 05:38:39 +00:00
|
|
|
visitor.String(output.c_str(), (rapidjson::SizeType)output.size());
|
2017-04-05 08:06:18 +00:00
|
|
|
}
|
|
|
|
|
2017-03-07 09:32:29 +00:00
|
|
|
// Id<T>
|
|
|
|
template<typename T>
|
|
|
|
void Reflect(Reader& visitor, Id<T>& id) {
|
|
|
|
id.id = visitor.GetUint64();
|
|
|
|
}
|
|
|
|
template<typename T>
|
|
|
|
void Reflect(Writer& visitor, Id<T>& value) {
|
|
|
|
visitor.Uint64(value.id);
|
2017-02-23 08:47:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-07 09:32:29 +00:00
|
|
|
// Ref<IndexedFuncDef>
|
|
|
|
void Reflect(Reader& visitor, Ref<IndexedFuncDef>& value) {
|
|
|
|
const char* str_value = visitor.GetString();
|
2017-04-13 07:47:47 +00:00
|
|
|
uint64_t id = atol(str_value);
|
2017-03-07 09:32:29 +00:00
|
|
|
const char* loc_string = strchr(str_value, '@') + 1;
|
2017-02-23 08:47:07 +00:00
|
|
|
|
2017-04-13 07:47:47 +00:00
|
|
|
value.id_ = Id<IndexedFuncDef>(id);
|
2017-04-05 08:06:18 +00:00
|
|
|
value.loc = Range(loc_string);
|
2017-02-23 08:47:07 +00:00
|
|
|
}
|
2017-03-07 09:32:29 +00:00
|
|
|
void Reflect(Writer& visitor, Ref<IndexedFuncDef>& value) {
|
2017-04-13 07:47:47 +00:00
|
|
|
if (value.id_.id == -1) {
|
|
|
|
std::string s = "-1@" + value.loc.ToString();
|
|
|
|
visitor.String(s.c_str());
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
std::string s = std::to_string(value.id_.id) + "@" + value.loc.ToString();
|
|
|
|
visitor.String(s.c_str());
|
|
|
|
}
|
2017-02-28 08:37:20 +00:00
|
|
|
}
|
|
|
|
|
2017-03-07 09:32:29 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-04-03 01:34:15 +00:00
|
|
|
// TODO: Move this to indexer.cpp
|
|
|
|
// TODO: Rename indexer.cpp to indexer.cc
|
|
|
|
// TODO: Do not serialize a USR if it has no usages/etc outside of USR info.
|
2017-03-07 09:32:29 +00:00
|
|
|
|
|
|
|
// IndexedTypeDef
|
|
|
|
bool ReflectMemberStart(Reader& reader, IndexedTypeDef& value) {
|
2017-04-03 01:34:15 +00:00
|
|
|
//value.is_bad_def = false;
|
2017-03-07 09:32:29 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool ReflectMemberStart(Writer& writer, IndexedTypeDef& value) {
|
2017-04-19 00:05:14 +00:00
|
|
|
// TODO: this is crashing
|
|
|
|
// if (!value.HasInterestingState())
|
|
|
|
// std::cerr << "bad";
|
|
|
|
// assert(value.HasInterestingState());
|
2017-04-03 01:34:15 +00:00
|
|
|
|
2017-04-19 00:05:14 +00:00
|
|
|
if (!value.HasInterestingState())
|
|
|
|
return false;
|
2017-03-07 09:32:29 +00:00
|
|
|
DefaultReflectMemberStart(writer);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
template<typename TVisitor>
|
|
|
|
void Reflect(TVisitor& visitor, IndexedTypeDef& value) {
|
|
|
|
REFLECT_MEMBER_START();
|
|
|
|
REFLECT_MEMBER2("id", value.id);
|
|
|
|
REFLECT_MEMBER2("usr", value.def.usr);
|
|
|
|
REFLECT_MEMBER2("short_name", value.def.short_name);
|
2017-04-15 04:58:07 +00:00
|
|
|
REFLECT_MEMBER2("detailed_name", value.def.detailed_name);
|
2017-04-05 08:29:15 +00:00
|
|
|
REFLECT_MEMBER2("definition_spelling", value.def.definition_spelling);
|
|
|
|
REFLECT_MEMBER2("definition_extent", value.def.definition_extent);
|
2017-03-07 09:32:29 +00:00
|
|
|
REFLECT_MEMBER2("alias_of", value.def.alias_of);
|
|
|
|
REFLECT_MEMBER2("parents", value.def.parents);
|
|
|
|
REFLECT_MEMBER2("derived", value.derived);
|
|
|
|
REFLECT_MEMBER2("types", value.def.types);
|
|
|
|
REFLECT_MEMBER2("funcs", value.def.funcs);
|
|
|
|
REFLECT_MEMBER2("vars", value.def.vars);
|
2017-04-03 01:34:15 +00:00
|
|
|
REFLECT_MEMBER2("instantiations", value.instantiations);
|
2017-03-07 09:32:29 +00:00
|
|
|
REFLECT_MEMBER2("uses", value.uses);
|
|
|
|
REFLECT_MEMBER_END();
|
2017-03-01 04:12:57 +00:00
|
|
|
}
|
|
|
|
|
2017-03-07 09:32:29 +00:00
|
|
|
|
|
|
|
// IndexedFuncDef
|
|
|
|
bool ReflectMemberStart(Reader& reader, IndexedFuncDef& value) {
|
2017-04-03 01:34:15 +00:00
|
|
|
//value.is_bad_def = false;
|
2017-03-07 09:32:29 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool ReflectMemberStart(Writer& writer, IndexedFuncDef& value) {
|
2017-04-19 00:05:14 +00:00
|
|
|
// TODO: this is crashing
|
|
|
|
// if (!value.HasInterestingState())
|
|
|
|
// std::cerr << "bad";
|
|
|
|
// assert(value.HasInterestingState());
|
|
|
|
|
2017-04-03 01:34:15 +00:00
|
|
|
if (!value.HasInterestingState())
|
2017-04-19 00:05:14 +00:00
|
|
|
return false;
|
2017-03-07 09:32:29 +00:00
|
|
|
DefaultReflectMemberStart(writer);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
template<typename TVisitor>
|
|
|
|
void Reflect(TVisitor& visitor, IndexedFuncDef& value) {
|
|
|
|
REFLECT_MEMBER_START();
|
|
|
|
REFLECT_MEMBER2("id", value.id);
|
|
|
|
REFLECT_MEMBER2("usr", value.def.usr);
|
|
|
|
REFLECT_MEMBER2("short_name", value.def.short_name);
|
2017-04-15 04:58:07 +00:00
|
|
|
REFLECT_MEMBER2("detailed_name", value.def.detailed_name);
|
2017-03-07 09:32:29 +00:00
|
|
|
REFLECT_MEMBER2("declarations", value.declarations);
|
2017-04-05 08:29:15 +00:00
|
|
|
REFLECT_MEMBER2("definition_spelling", value.def.definition_spelling);
|
|
|
|
REFLECT_MEMBER2("definition_extent", value.def.definition_extent);
|
2017-03-07 09:32:29 +00:00
|
|
|
REFLECT_MEMBER2("declaring_type", value.def.declaring_type);
|
|
|
|
REFLECT_MEMBER2("base", value.def.base);
|
|
|
|
REFLECT_MEMBER2("derived", value.derived);
|
|
|
|
REFLECT_MEMBER2("locals", value.def.locals);
|
|
|
|
REFLECT_MEMBER2("callers", value.callers);
|
|
|
|
REFLECT_MEMBER2("callees", value.def.callees);
|
|
|
|
REFLECT_MEMBER_END();
|
2017-03-01 04:12:57 +00:00
|
|
|
}
|
|
|
|
|
2017-03-07 09:32:29 +00:00
|
|
|
|
|
|
|
// IndexedVarDef
|
|
|
|
bool ReflectMemberStart(Reader& reader, IndexedVarDef& value) {
|
2017-04-03 01:34:15 +00:00
|
|
|
//value.is_bad_def = false;
|
2017-03-07 09:32:29 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool ReflectMemberStart(Writer& writer, IndexedVarDef& value) {
|
2017-04-19 00:05:14 +00:00
|
|
|
// TODO: this is crashing
|
|
|
|
// if (!value.HasInterestingState())
|
|
|
|
// std::cerr << "bad";
|
|
|
|
// assert(value.HasInterestingState());
|
2017-04-03 01:34:15 +00:00
|
|
|
|
2017-04-19 00:05:14 +00:00
|
|
|
if (!value.HasInterestingState())
|
|
|
|
return false;
|
2017-03-07 09:32:29 +00:00
|
|
|
DefaultReflectMemberStart(writer);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
template<typename TVisitor>
|
|
|
|
void Reflect(TVisitor& visitor, IndexedVarDef& value) {
|
|
|
|
REFLECT_MEMBER_START();
|
|
|
|
REFLECT_MEMBER2("id", value.id);
|
|
|
|
REFLECT_MEMBER2("usr", value.def.usr);
|
|
|
|
REFLECT_MEMBER2("short_name", value.def.short_name);
|
2017-04-15 04:58:07 +00:00
|
|
|
REFLECT_MEMBER2("detailed_name", value.def.detailed_name);
|
2017-03-07 09:32:29 +00:00
|
|
|
REFLECT_MEMBER2("declaration", value.def.declaration);
|
2017-04-05 08:29:15 +00:00
|
|
|
REFLECT_MEMBER2("definition_spelling", value.def.definition_spelling);
|
|
|
|
REFLECT_MEMBER2("definition_extent", value.def.definition_extent);
|
2017-03-07 09:32:29 +00:00
|
|
|
REFLECT_MEMBER2("variable_type", value.def.variable_type);
|
|
|
|
REFLECT_MEMBER2("declaring_type", value.def.declaring_type);
|
|
|
|
REFLECT_MEMBER2("uses", value.uses);
|
|
|
|
REFLECT_MEMBER_END();
|
2017-02-28 08:37:20 +00:00
|
|
|
}
|
|
|
|
|
2017-03-01 04:12:57 +00:00
|
|
|
|
2017-03-07 09:32:29 +00:00
|
|
|
// IndexedFile
|
|
|
|
bool ReflectMemberStart(Writer& visitor, IndexedFile& value) {
|
|
|
|
auto it = value.id_cache.usr_to_type_id.find("");
|
|
|
|
if (it != value.id_cache.usr_to_type_id.end()) {
|
|
|
|
value.Resolve(it->second)->def.short_name = "<fundamental>";
|
|
|
|
assert(value.Resolve(it->second)->uses.size() == 0);
|
2017-03-01 04:12:57 +00:00
|
|
|
}
|
|
|
|
|
2017-04-20 06:02:24 +00:00
|
|
|
value.version = IndexedFile::kCurrentVersion;
|
2017-03-07 09:32:29 +00:00
|
|
|
DefaultReflectMemberStart(visitor);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
template<typename TVisitor>
|
|
|
|
void Reflect(TVisitor& visitor, IndexedFile& value) {
|
|
|
|
REFLECT_MEMBER_START();
|
2017-04-20 06:02:24 +00:00
|
|
|
if (!gTestOutputMode) {
|
|
|
|
REFLECT_MEMBER(version);
|
|
|
|
REFLECT_MEMBER(last_modification_time);
|
|
|
|
}
|
2017-04-11 05:26:27 +00:00
|
|
|
REFLECT_MEMBER(dependencies);
|
2017-03-07 18:17:49 +00:00
|
|
|
REFLECT_MEMBER(types);
|
|
|
|
REFLECT_MEMBER(funcs);
|
|
|
|
REFLECT_MEMBER(vars);
|
2017-03-07 09:32:29 +00:00
|
|
|
REFLECT_MEMBER_END();
|
2017-03-01 04:12:57 +00:00
|
|
|
}
|
|
|
|
|
2017-03-07 09:32:29 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string Serialize(IndexedFile& file) {
|
2017-03-01 04:12:57 +00:00
|
|
|
rapidjson::StringBuffer output;
|
2017-03-27 04:04:48 +00:00
|
|
|
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(output);
|
|
|
|
//Writer writer(output);
|
2017-03-01 04:12:57 +00:00
|
|
|
writer.SetFormatOptions(
|
|
|
|
rapidjson::PrettyFormatOptions::kFormatSingleLineArray);
|
|
|
|
writer.SetIndent(' ', 2);
|
|
|
|
|
2017-03-07 09:32:29 +00:00
|
|
|
Reflect(writer, file);
|
2017-03-01 04:12:57 +00:00
|
|
|
|
|
|
|
return output.GetString();
|
|
|
|
}
|
|
|
|
|
2017-04-03 01:34:15 +00:00
|
|
|
optional<IndexedFile> Deserialize(std::string path, std::string serialized) {
|
2017-03-07 09:32:29 +00:00
|
|
|
rapidjson::Document reader;
|
|
|
|
reader.Parse(serialized.c_str());
|
2017-04-03 01:34:15 +00:00
|
|
|
if (reader.HasParseError())
|
|
|
|
return nullopt;
|
2017-03-01 04:12:57 +00:00
|
|
|
|
|
|
|
IndexedFile file(path);
|
2017-03-07 09:32:29 +00:00
|
|
|
Reflect(reader, file);
|
2017-04-19 00:05:14 +00:00
|
|
|
|
2017-04-10 00:08:54 +00:00
|
|
|
// Restore non-serialized state.
|
|
|
|
file.path = path;
|
|
|
|
file.id_cache.primary_file = file.path;
|
|
|
|
for (const auto& type : file.types) {
|
|
|
|
file.id_cache.type_id_to_usr[type.id] = type.def.usr;
|
|
|
|
file.id_cache.usr_to_type_id[type.def.usr] = type.id;
|
|
|
|
}
|
|
|
|
for (const auto& func : file.funcs) {
|
|
|
|
file.id_cache.func_id_to_usr[func.id] = func.def.usr;
|
|
|
|
file.id_cache.usr_to_func_id[func.def.usr] = func.id;
|
|
|
|
}
|
|
|
|
for (const auto& var : file.vars) {
|
|
|
|
file.id_cache.var_id_to_usr[var.id] = var.def.usr;
|
|
|
|
file.id_cache.usr_to_var_id[var.def.usr] = var.id;
|
|
|
|
}
|
2017-03-07 09:32:29 +00:00
|
|
|
|
2017-03-01 04:12:57 +00:00
|
|
|
return file;
|
|
|
|
}
|
2017-04-20 06:02:24 +00:00
|
|
|
|
|
|
|
void SetTestOutputMode() {
|
|
|
|
gTestOutputMode = true;
|
|
|
|
}
|