Goto definition for includes

This commit is contained in:
Jacob Dufault 2017-05-20 20:46:15 -07:00
parent c03f99ce1f
commit 41e1dff4c9
17 changed files with 471 additions and 16 deletions

View File

@ -28,6 +28,7 @@ be productive with cquery. Here's a list of implemented features:
* diagnostics
* code actions (clang FixIts)
* darken/fade code disabled by preprocessor
* goto definition on include to jump to file
# Setup - build cquery, install extension, setup project

View File

@ -1,6 +1,7 @@
#include "clang_utils.h"
#include "libclangmm/Utility.h"
#include "platform.h"
namespace {
@ -79,3 +80,9 @@ optional<lsDiagnostic> BuildDiagnostic(CXDiagnostic diagnostic) {
return ls_diagnostic;
}
std::string FileName(CXFile file) {
CXString cx_name = clang_getFileName(file);
std::string name = clang::ToString(cx_name);
return NormalizePath(name);
}

View File

@ -10,3 +10,6 @@
using namespace std::experimental;
optional<lsDiagnostic> BuildDiagnostic(CXDiagnostic diagnostic);
// Returns the absolute path to |file|.
std::string FileName(CXFile file);

View File

@ -1948,6 +1948,19 @@ bool QueryDbMainLoop(
break;
}
// No symbols - check for includes.
if (response.result.empty()) {
for (const IndexInclude& include : file->def.includes) {
if (include.line == target_line) {
lsLocation result;
std::cerr << "!! resolved to " << include.resolved_path << std::endl;
result.uri = lsDocumentUri::FromPath(include.resolved_path);
response.result.push_back(result);
break;
}
}
}
ipc->SendOutMessageToClient(IpcId::TextDocumentDefinition, response);
break;
}

View File

@ -1,19 +1,10 @@
#include "file_consumer.h"
#include "clang_utils.h"
#include "indexer.h"
#include "platform.h"
#include "utils.h"
namespace {
std::string FileName(CXFile file) {
CXString cx_name = clang_getFileName(file);
std::string name = clang::ToString(cx_name);
return NormalizePath(name);
}
} // namespace
bool operator==(const CXFileUniqueID& a, const CXFileUniqueID& b) {
return a.data[0] == b.data[0] && a.data[1] == b.data[1] && a.data[2] == b.data[2];
}

View File

@ -328,8 +328,24 @@ CXIdxClientFile enteredMainFile(CXClientData client_data,
CXIdxClientFile ppIncludedFile(CXClientData client_data,
const CXIdxIncludedFileInfo* file) {
// Clang include logic is broken. This function is never
// called and clang_findIncludesInFile doesn't work.
IndexParam* param = static_cast<IndexParam*>(client_data);
// file->hashLoc only has the position of the hash. We don't have the full
// range for the include.
CXSourceLocation hash_loc = clang_indexLoc_getCXSourceLocation(file->hashLoc);
CXFile cx_file;
unsigned int line;
clang_getSpellingLocation(hash_loc, &cx_file, &line, nullptr, nullptr);
IndexFile* db = ConsumeFile(param, cx_file);
if (!db)
return nullptr;
IndexInclude include;
include.line = line;
include.resolved_path = FileName(file->file);
db->includes.push_back(include);
return nullptr;
}

View File

@ -494,6 +494,15 @@ struct IdCache {
IdCache(const std::string& primary_file);
};
struct IndexInclude {
// Line that has the include directive. We don't have complete range
// information - a line is good enough for clicking.
int line = 0;
// Absolute path to the index.
std::string resolved_path;
};
MAKE_REFLECT_STRUCT(IndexInclude, line, resolved_path);
struct IndexFile {
IdCache id_cache;
@ -516,6 +525,7 @@ struct IndexFile {
// Source ranges that were not processed.
std::vector<Range> skipped_by_preprocessor;
std::vector<IndexInclude> includes;
std::vector<std::string> dependencies;
std::vector<IndexType> types;
std::vector<IndexFunc> funcs;

View File

@ -164,6 +164,7 @@ void CompareGroups(
QueryFile::Def BuildFileDef(const IdMap& id_map, const IndexFile& indexed) {
QueryFile::Def def;
def.path = indexed.path;
def.includes = indexed.includes;
auto add_outline = [&def, &id_map](SymbolIdx idx, Range range) {
def.outline.push_back(SymbolRef(idx, id_map.ToQuery(range)));

View File

@ -161,6 +161,8 @@ void Reflect(TVisitor& visitor, MergeableUpdate<TId, TValue>& value) {
struct QueryFile {
struct Def {
std::string path;
// Includes in the file.
std::vector<IndexInclude> includes;
// Outline of the file (ie, for code lens).
std::vector<SymbolRef> outline;
// Every symbol found in the file (ie, for goto definition)

View File

@ -199,6 +199,7 @@ void Reflect(TVisitor& visitor, IndexFile& value) {
REFLECT_MEMBER(import_file);
REFLECT_MEMBER(args);
}
REFLECT_MEMBER(includes);
REFLECT_MEMBER(dependencies);
REFLECT_MEMBER(skipped_by_preprocessor);
REFLECT_MEMBER(types);

View File

@ -50,6 +50,10 @@ OUTPUT: funky_enum.h
}
OUTPUT: funky_enum.cc
{
"includes": [{
"line": 2,
"resolved_path": "C:/Users/jacob/Desktop/superindex/indexer/tests/multi_file/funky_enum.h"
}],
"dependencies": ["C:/Users/jacob/Desktop/superindex/indexer/tests/multi_file/funky_enum.h"],
"types": [{
"id": 0,

View File

@ -115,6 +115,10 @@ OUTPUT: header.h
}
OUTPUT: impl.cc
{
"includes": [{
"line": 1,
"resolved_path": "C:/Users/jacob/Desktop/superindex/indexer/tests/multi_file/header.h"
}],
"dependencies": ["C:/Users/jacob/Desktop/superindex/indexer/tests/multi_file/header.h"],
"funcs": [{
"id": 0,

View File

@ -17,6 +17,10 @@ OUTPUT: simple_header.h
}
OUTPUT: simple_impl.cc
{
"includes": [{
"line": 1,
"resolved_path": "C:/Users/jacob/Desktop/superindex/indexer/tests/multi_file/simple_header.h"
}],
"dependencies": ["C:/Users/jacob/Desktop/superindex/indexer/tests/multi_file/simple_header.h"],
"funcs": [{
"id": 0,

View File

@ -26,6 +26,10 @@ OUTPUT: static.h
}
OUTPUT: static.cc
{
"includes": [{
"line": 1,
"resolved_path": "C:/Users/jacob/Desktop/superindex/indexer/tests/multi_file/static.h"
}],
"dependencies": ["C:/Users/jacob/Desktop/superindex/indexer/tests/multi_file/static.h"],
"types": [{
"id": 0,

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long