This commit is contained in:
Jacob Dufault 2017-03-16 00:36:49 -07:00
parent efe3a55719
commit 12acaa1b49
6 changed files with 142 additions and 45 deletions

View File

@ -469,12 +469,81 @@ QueryableFile* FindFile(QueryableDatabase* db, const std::string& filename) {
lsLocation GetLsLocation(QueryableLocation& location) { lsLocation GetLsLocation(const QueryableLocation& location) {
return lsLocation( return lsLocation(
lsDocumentUri::FromPath(location.path), lsDocumentUri::FromPath(location.path),
lsRange(lsPosition(location.line - 1, location.column - 1))); lsRange(lsPosition(location.line - 1, location.column - 1)));
} }
void AddCodeLens(std::vector<TCodeLens>* result, QueryableLocation loc, const std::vector<QueryableLocation>& uses, bool only_interesting, const char* singular, const char* plural) {
TCodeLens code_lens;
code_lens.range.start.line = loc.line - 1; // TODO: cleanup indexer to negate by 1.
code_lens.range.start.character = loc.column - 1; // TODO: cleanup indexer to negate by 1.
// TODO: store range information.
code_lens.range.end.line = code_lens.range.start.line;
code_lens.range.end.character = code_lens.range.start.character;
code_lens.command = lsCommand<lsCodeLensCommandArguments>();
code_lens.command->command = "superindex.showReferences";
code_lens.command->arguments.uri = lsDocumentUri::FromPath(loc.path);
code_lens.command->arguments.position = code_lens.range.start;
// Add unique uses.
std::unordered_set<lsLocation> unique_uses;
for (const QueryableLocation& use : uses) {
if (only_interesting && !use.interesting) continue;
unique_uses.insert(GetLsLocation(use));
}
code_lens.command->arguments.locations.assign(unique_uses.begin(), unique_uses.end());
// User visible label
int num_usages = unique_uses.size();
code_lens.command->title = std::to_string(num_usages) + " ";
if (num_usages == 1)
code_lens.command->title += singular;
else
code_lens.command->title += plural;
if (unique_uses.size() > 0)
result->push_back(code_lens);
}
void AddCodeLens(std::vector<TCodeLens>* result, QueryableLocation loc, const std::vector<UsrRef>& uses, bool only_interesting, const char* singular, const char* plural) {
std::vector<QueryableLocation> uses0;
uses0.reserve(uses.size());
for (const UsrRef& use : uses)
uses0.push_back(use.loc);
AddCodeLens(result, loc, uses0, only_interesting, singular, plural);
}
void AddCodeLens(std::vector<TCodeLens>* result, QueryableDatabase* db, QueryableLocation loc, const std::vector<Usr>& usrs, bool only_interesting, const char* singular, const char* plural) {
std::vector<QueryableLocation> uses0;
uses0.reserve(usrs.size());
for (const Usr& usr : usrs) {
SymbolIdx symbol = db->usr_to_symbol[usr];
switch (symbol.kind) {
case SymbolKind::Type: {
QueryableTypeDef* def = &db->types[symbol.idx];
if (def->def.definition)
uses0.push_back(def->def.definition.value());
break;
}
case SymbolKind::Func: {
QueryableFuncDef* def = &db->funcs[symbol.idx];
if (def->def.definition)
uses0.push_back(def->def.definition.value());
break;
}
case SymbolKind::Var: {
assert(false && "unexpected");
break;
}
}
}
AddCodeLens(result, loc, uses0, only_interesting, singular, plural);
}
void QueryDbMainLoop(IpcServer* language_client, IpcServer* indexers, QueryableDatabase* db) { void QueryDbMainLoop(IpcServer* language_client, IpcServer* indexers, QueryableDatabase* db) {
std::vector<std::unique_ptr<IpcMessage>> messages = language_client->TakeMessages(); std::vector<std::unique_ptr<IpcMessage>> messages = language_client->TakeMessages();
for (auto& message : messages) { for (auto& message : messages) {
@ -581,57 +650,30 @@ void QueryDbMainLoop(IpcServer* language_client, IpcServer* indexers, QueryableD
QueryableFile* file = FindFile(db, msg->document); QueryableFile* file = FindFile(db, msg->document);
if (file) { if (file) {
for (UsrRef ref : file->outline) { for (UsrRef ref : file->outline) {
SymbolIdx symbol = db->usr_to_symbol[ref.usr]; SymbolIdx symbol = db->usr_to_symbol[ref.usr];
TCodeLens code_lens;
code_lens.range.start.line = ref.loc.line - 1; // TODO: cleanup indexer to negate by 1.
code_lens.range.start.character = ref.loc.column - 1; // TODO: cleanup indexer to negate by 1.
// TODO: store range information.
code_lens.range.end.line = code_lens.range.start.line;
code_lens.range.end.character = code_lens.range.start.character;
code_lens.command = lsCommand<lsCodeLensCommandArguments>();
code_lens.command->command = "superindex.showReferences";
code_lens.command->arguments.uri = file_as_uri;
code_lens.command->arguments.position = code_lens.range.start;
switch (symbol.kind) { switch (symbol.kind) {
case SymbolKind::Type: { case SymbolKind::Type: {
QueryableTypeDef& def = db->types[symbol.idx]; QueryableTypeDef& def = db->types[symbol.idx];
for (QueryableLocation& usage : def.uses) { AddCodeLens(&response.code_lens, ref.loc, def.uses, true/*only_interesting*/, "reference", "references");
if (!usage.interesting) AddCodeLens(&response.code_lens, db, ref.loc, def.derived, false /*only_interesting*/, "derived", "derived");
continue;
code_lens.command->arguments.locations.push_back(GetLsLocation(usage));
}
break; break;
} }
case SymbolKind::Func: { case SymbolKind::Func: {
QueryableFuncDef& def = db->funcs[symbol.idx]; QueryableFuncDef& def = db->funcs[symbol.idx];
for (QueryableLocation& usage : def.uses) AddCodeLens(&response.code_lens, ref.loc, def.uses, false /*only_interesting*/, "reference", "references");
code_lens.command->arguments.locations.push_back(GetLsLocation(usage)); AddCodeLens(&response.code_lens, ref.loc, def.callers, false /*only_interesting*/, "caller", "callers");
AddCodeLens(&response.code_lens, ref.loc, def.def.callees, false /*only_interesting*/, "callee", "callees");
AddCodeLens(&response.code_lens, db, ref.loc, def.derived, false /*only_interesting*/, "derived", "derived");
break; break;
} }
case SymbolKind::Var: { case SymbolKind::Var: {
QueryableVarDef& def = db->vars[symbol.idx]; QueryableVarDef& def = db->vars[symbol.idx];
for (QueryableLocation& usage : def.uses) AddCodeLens(&response.code_lens, ref.loc, def.uses, false /*only_interesting*/, "reference", "references");
code_lens.command->arguments.locations.push_back(GetLsLocation(usage));
break; break;
} }
}; };
// TODO: we are getting too many references
int num_usages = code_lens.command->arguments.locations.size();
code_lens.command->title = std::to_string(num_usages) + " reference";
if (num_usages != 1)
code_lens.command->title += "s";
response.code_lens.push_back(code_lens);
} }
} }
@ -968,7 +1010,7 @@ void LanguageServerMain(std::string process_name) {
client_ipc.SendToServer(&check_alive); client_ipc.SendToServer(&check_alive);
// TODO: Tune this value or make it configurable. // TODO: Tune this value or make it configurable.
std::this_thread::sleep_for(std::chrono::milliseconds(10)); std::this_thread::sleep_for(std::chrono::milliseconds(100));
// Check if we got an IsAlive message back. // Check if we got an IsAlive message back.
std::vector<std::unique_ptr<IpcMessage>> messages = client_ipc.TakeMessages(); std::vector<std::unique_ptr<IpcMessage>> messages = client_ipc.TakeMessages();
@ -1023,7 +1065,7 @@ void LanguageServerMain(std::string process_name) {
LanguageServerMainLoop(&client_ipc); LanguageServerMainLoop(&client_ipc);
std::this_thread::sleep_for(std::chrono::milliseconds(10)); std::this_thread::sleep_for(std::chrono::milliseconds(10));
} }
} }
@ -1111,10 +1153,10 @@ int main(int argc, char** argv) {
PreMain(); PreMain();
if (argc == 1) { //if (argc == 1) {
QueryDbMain(); // QueryDbMain();
return 0; // return 0;
} //}
if (argc == 1) { if (argc == 1) {
RunTests(); RunTests();
return 0; return 0;

View File

@ -650,7 +650,6 @@ void AddDeclInitializerUsages(IndexedFile* db, clang::Cursor decl_cursor) {
void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
// TODO: we can minimize processing for cursors which return false for clang_Location_isFromMainFile (ie, only add usages) // TODO: we can minimize processing for cursors which return false for clang_Location_isFromMainFile (ie, only add usages)
bool is_system_def = clang_Location_isInSystemHeader(clang_getCursorLocation(decl->cursor)); bool is_system_def = clang_Location_isInSystemHeader(clang_getCursorLocation(decl->cursor));
if (is_system_def) if (is_system_def)
return; return;
@ -1118,6 +1117,8 @@ void emptyIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl)
void emptyIndexEntityReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {} void emptyIndexEntityReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {}
IndexedFile Parse(std::string filename, std::vector<std::string> args, bool dump_ast) { IndexedFile Parse(std::string filename, std::vector<std::string> args, bool dump_ast) {
clang_toggleCrashRecovery(1);
args.push_back("-std=c++11"); args.push_back("-std=c++11");
args.push_back("-fms-compatibility"); args.push_back("-fms-compatibility");
args.push_back("-fdelayed-template-parsing"); args.push_back("-fdelayed-template-parsing");
@ -1151,8 +1152,10 @@ IndexedFile Parse(std::string filename, std::vector<std::string> args, bool dump
NamespaceHelper ns; NamespaceHelper ns;
IndexParam param(&db, &ns); IndexParam param(&db, &ns);
std::cerr << "!! [START] Indexing " << filename << std::endl;
clang_indexTranslationUnit(index_action, &param, callbacks, sizeof(callbacks), clang_indexTranslationUnit(index_action, &param, callbacks, sizeof(callbacks),
CXIndexOpt_IndexFunctionLocalSymbols | CXIndexOpt_SkipParsedBodiesInSession, tu.cx_tu); CXIndexOpt_IndexFunctionLocalSymbols | CXIndexOpt_SkipParsedBodiesInSession, tu.cx_tu);
std::cerr << "!! [END] Indexing " << filename << std::endl;
clang_IndexAction_dispose(index_action); clang_IndexAction_dispose(index_action);

2
ipc.cc
View File

@ -286,7 +286,7 @@ void IpcDirectionalChannel::PushMessage(IpcMessage* message) {
size_t sent_payload_size = shared_buffer->bytes_available() - sizeof(JsonMessage); size_t sent_payload_size = shared_buffer->bytes_available() - sizeof(JsonMessage);
shared_buffer->free_message()->Setup(message->ipc_id, partial_message_id, true /*has_more_chunks*/, sent_payload_size, payload); shared_buffer->free_message()->Setup(message->ipc_id, partial_message_id, true /*has_more_chunks*/, sent_payload_size, payload);
shared_buffer->metadata()->bytes_used += sizeof(JsonMessage) + sent_payload_size; shared_buffer->metadata()->bytes_used += sizeof(JsonMessage) + sent_payload_size;
shared_buffer->free_message()->ipc_id = IpcId::Invalid; //shared_buffer->free_message()->ipc_id = IpcId::Invalid; // Note: free_message() may be past writable memory.
if (count++ > 50) { if (count++ > 50) {
std::cerr << "x50 Sending partial message with payload_size=" << sent_payload_size << std::endl; std::cerr << "x50 Sending partial message with payload_size=" << sent_payload_size << std::endl;

View File

@ -7,6 +7,7 @@
#include <rapidjson/writer.h> #include <rapidjson/writer.h>
#include "optional.h" #include "optional.h"
#include "serializer.h" #include "serializer.h"
#include "utils.h"
using std::experimental::optional; using std::experimental::optional;
using std::experimental::nullopt; using std::experimental::nullopt;
@ -406,6 +407,10 @@ struct lsDocumentUri {
return result; return result;
} }
bool operator==(const lsDocumentUri& other) const {
return raw_uri == other.raw_uri;
}
void SetPath(const std::string& path) { void SetPath(const std::string& path) {
// file:///c%3A/Users/jacob/Desktop/superindex/indexer/full_tests // file:///c%3A/Users/jacob/Desktop/superindex/indexer/full_tests
raw_uri = path; raw_uri = path;
@ -437,6 +442,7 @@ struct lsDocumentUri {
return result; return result;
} }
}; };
MAKE_HASHABLE(lsDocumentUri, t.raw_uri);
template<typename TVisitor> template<typename TVisitor>
void Reflect(TVisitor& visitor, lsDocumentUri& value) { void Reflect(TVisitor& visitor, lsDocumentUri& value) {
@ -451,7 +457,12 @@ struct lsPosition {
lsPosition() {} lsPosition() {}
lsPosition(int line, int character) : line(line), character(character) {} lsPosition(int line, int character) : line(line), character(character) {}
bool operator==(const lsPosition& other) const {
return line == other.line && character == other.character;
}
}; };
MAKE_HASHABLE(lsPosition, t.line, t.character);
template<typename TVisitor> template<typename TVisitor>
void Reflect(TVisitor& visitor, lsPosition& value) { void Reflect(TVisitor& visitor, lsPosition& value) {
@ -468,7 +479,12 @@ struct lsRange {
lsRange() {} lsRange() {}
lsRange(lsPosition position) : start(position), end(position) {} lsRange(lsPosition position) : start(position), end(position) {}
bool operator==(const lsRange& other) const {
return start == other.start && end == other.end;
}
}; };
MAKE_HASHABLE(lsRange, t.start, t.end);
template<typename TVisitor> template<typename TVisitor>
void Reflect(TVisitor& visitor, lsRange& value) { void Reflect(TVisitor& visitor, lsRange& value) {
@ -485,7 +501,12 @@ struct lsLocation {
lsLocation() {} lsLocation() {}
lsLocation(lsDocumentUri uri, lsRange range) : uri(uri), range(range) {} lsLocation(lsDocumentUri uri, lsRange range) : uri(uri), range(range) {}
bool operator==(const lsLocation& other) const {
return uri == other.uri && range == other.range;
}
}; };
MAKE_HASHABLE(lsLocation, t.uri, t.range);
template<typename TVisitor> template<typename TVisitor>
void Reflect(TVisitor& visitor, lsLocation& value) { void Reflect(TVisitor& visitor, lsLocation& value) {

View File

@ -76,6 +76,7 @@ void DiffDocuments(rapidjson::Document& expected, rapidjson::Document& actual) {
} }
void VerifySerializeToFrom(IndexedFile& file) { void VerifySerializeToFrom(IndexedFile& file) {
return; // TODO: reenable
std::string expected = file.ToString(); std::string expected = file.ToString();
std::string actual = Deserialize("foo.cc", Serialize(file)).ToString(); std::string actual = Deserialize("foo.cc", Serialize(file)).ToString();
if (expected != actual) { if (expected != actual) {
@ -98,7 +99,7 @@ void RunTests() {
for (std::string path : GetFilesInFolder("tests", true /*recursive*/, true /*add_folder_to_path*/)) { for (std::string path : GetFilesInFolder("tests", true /*recursive*/, true /*add_folder_to_path*/)) {
//if (path != "tests/templates/specialized_func_definition.cc") continue; //if (path != "tests/templates/specialized_func_definition.cc") continue;
//if (path != "tests/templates/namespace_template_class_template_func_usage_folded_into_one.cc") continue; //if (path != "tests/templates/namespace_template_class_template_func_usage_folded_into_one.cc") continue;
//if (path == "tests/inheritance/class_inherit_templated_parent.cc") continue; if (path != "tests/foo2.cc") continue;
//if (path != "tests/namespaces/namespace_reference.cc") continue; //if (path != "tests/namespaces/namespace_reference.cc") continue;
//if (path != "tests/templates/implicit_variable_instantiation.cc") continue; //if (path != "tests/templates/implicit_variable_instantiation.cc") continue;
@ -113,7 +114,7 @@ void RunTests() {
// Run test. // Run test.
std::cout << "[START] " << path << std::endl; std::cout << "[START] " << path << std::endl;
IndexedFile db = Parse(path, {}, false /*dump_ast*/); IndexedFile db = Parse(path, {"-IC:/Users/jacob/Desktop/superindex/src"}, false /*dump_ast*/);
VerifySerializeToFrom(db); VerifySerializeToFrom(db);
std::string actual_output = db.ToString(); std::string actual_output = db.ToString();

30
utils.h
View File

@ -20,3 +20,33 @@ template<typename T, typename... Args>
std::unique_ptr<T> MakeUnique(Args&&... args) { std::unique_ptr<T> MakeUnique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
} }
// http://stackoverflow.com/a/38140932
//
// struct SomeHashKey {
// std::string key1;
// std::string key2;
// bool key3;
// };
// MAKE_HASHABLE(SomeHashKey, t.key1, t.key2, t.key3)
inline void hash_combine(std::size_t& seed) { }
template <typename T, typename... Rest>
inline void hash_combine(std::size_t& seed, const T& v, Rest... rest) {
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
hash_combine(seed, rest...);
}
#define MAKE_HASHABLE(type, ...) \
namespace std {\
template<> struct hash<type> {\
std::size_t operator()(const type &t) const {\
std::size_t ret = 0;\
hash_combine(ret, __VA_ARGS__);\
return ret;\
}\
};\
}