mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-22 07:35:08 +00:00
Goto definition for includes
This commit is contained in:
parent
c03f99ce1f
commit
41e1dff4c9
@ -28,6 +28,7 @@ be productive with cquery. Here's a list of implemented features:
|
|||||||
* diagnostics
|
* diagnostics
|
||||||
* code actions (clang FixIts)
|
* code actions (clang FixIts)
|
||||||
* darken/fade code disabled by preprocessor
|
* darken/fade code disabled by preprocessor
|
||||||
|
* goto definition on include to jump to file
|
||||||
|
|
||||||
# Setup - build cquery, install extension, setup project
|
# Setup - build cquery, install extension, setup project
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "clang_utils.h"
|
#include "clang_utils.h"
|
||||||
|
|
||||||
#include "libclangmm/Utility.h"
|
#include "libclangmm/Utility.h"
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -79,3 +80,9 @@ optional<lsDiagnostic> BuildDiagnostic(CXDiagnostic diagnostic) {
|
|||||||
|
|
||||||
return ls_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);
|
||||||
|
}
|
||||||
|
@ -10,3 +10,6 @@
|
|||||||
using namespace std::experimental;
|
using namespace std::experimental;
|
||||||
|
|
||||||
optional<lsDiagnostic> BuildDiagnostic(CXDiagnostic diagnostic);
|
optional<lsDiagnostic> BuildDiagnostic(CXDiagnostic diagnostic);
|
||||||
|
|
||||||
|
// Returns the absolute path to |file|.
|
||||||
|
std::string FileName(CXFile file);
|
||||||
|
@ -1948,6 +1948,19 @@ bool QueryDbMainLoop(
|
|||||||
break;
|
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);
|
ipc->SendOutMessageToClient(IpcId::TextDocumentDefinition, response);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,10 @@
|
|||||||
#include "file_consumer.h"
|
#include "file_consumer.h"
|
||||||
|
|
||||||
|
#include "clang_utils.h"
|
||||||
#include "indexer.h"
|
#include "indexer.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "utils.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) {
|
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];
|
return a.data[0] == b.data[0] && a.data[1] == b.data[1] && a.data[2] == b.data[2];
|
||||||
}
|
}
|
||||||
|
@ -328,8 +328,24 @@ CXIdxClientFile enteredMainFile(CXClientData client_data,
|
|||||||
|
|
||||||
CXIdxClientFile ppIncludedFile(CXClientData client_data,
|
CXIdxClientFile ppIncludedFile(CXClientData client_data,
|
||||||
const CXIdxIncludedFileInfo* file) {
|
const CXIdxIncludedFileInfo* file) {
|
||||||
// Clang include logic is broken. This function is never
|
IndexParam* param = static_cast<IndexParam*>(client_data);
|
||||||
// called and clang_findIncludesInFile doesn't work.
|
|
||||||
|
// 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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,6 +494,15 @@ struct IdCache {
|
|||||||
IdCache(const std::string& primary_file);
|
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 {
|
struct IndexFile {
|
||||||
IdCache id_cache;
|
IdCache id_cache;
|
||||||
|
|
||||||
@ -516,6 +525,7 @@ struct IndexFile {
|
|||||||
// Source ranges that were not processed.
|
// Source ranges that were not processed.
|
||||||
std::vector<Range> skipped_by_preprocessor;
|
std::vector<Range> skipped_by_preprocessor;
|
||||||
|
|
||||||
|
std::vector<IndexInclude> includes;
|
||||||
std::vector<std::string> dependencies;
|
std::vector<std::string> dependencies;
|
||||||
std::vector<IndexType> types;
|
std::vector<IndexType> types;
|
||||||
std::vector<IndexFunc> funcs;
|
std::vector<IndexFunc> funcs;
|
||||||
|
@ -164,6 +164,7 @@ void CompareGroups(
|
|||||||
QueryFile::Def BuildFileDef(const IdMap& id_map, const IndexFile& indexed) {
|
QueryFile::Def BuildFileDef(const IdMap& id_map, const IndexFile& indexed) {
|
||||||
QueryFile::Def def;
|
QueryFile::Def def;
|
||||||
def.path = indexed.path;
|
def.path = indexed.path;
|
||||||
|
def.includes = indexed.includes;
|
||||||
|
|
||||||
auto add_outline = [&def, &id_map](SymbolIdx idx, Range range) {
|
auto add_outline = [&def, &id_map](SymbolIdx idx, Range range) {
|
||||||
def.outline.push_back(SymbolRef(idx, id_map.ToQuery(range)));
|
def.outline.push_back(SymbolRef(idx, id_map.ToQuery(range)));
|
||||||
|
@ -161,6 +161,8 @@ void Reflect(TVisitor& visitor, MergeableUpdate<TId, TValue>& value) {
|
|||||||
struct QueryFile {
|
struct QueryFile {
|
||||||
struct Def {
|
struct Def {
|
||||||
std::string path;
|
std::string path;
|
||||||
|
// Includes in the file.
|
||||||
|
std::vector<IndexInclude> includes;
|
||||||
// Outline of the file (ie, for code lens).
|
// Outline of the file (ie, for code lens).
|
||||||
std::vector<SymbolRef> outline;
|
std::vector<SymbolRef> outline;
|
||||||
// Every symbol found in the file (ie, for goto definition)
|
// Every symbol found in the file (ie, for goto definition)
|
||||||
|
@ -199,6 +199,7 @@ void Reflect(TVisitor& visitor, IndexFile& value) {
|
|||||||
REFLECT_MEMBER(import_file);
|
REFLECT_MEMBER(import_file);
|
||||||
REFLECT_MEMBER(args);
|
REFLECT_MEMBER(args);
|
||||||
}
|
}
|
||||||
|
REFLECT_MEMBER(includes);
|
||||||
REFLECT_MEMBER(dependencies);
|
REFLECT_MEMBER(dependencies);
|
||||||
REFLECT_MEMBER(skipped_by_preprocessor);
|
REFLECT_MEMBER(skipped_by_preprocessor);
|
||||||
REFLECT_MEMBER(types);
|
REFLECT_MEMBER(types);
|
||||||
|
@ -50,6 +50,10 @@ OUTPUT: funky_enum.h
|
|||||||
}
|
}
|
||||||
OUTPUT: funky_enum.cc
|
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"],
|
"dependencies": ["C:/Users/jacob/Desktop/superindex/indexer/tests/multi_file/funky_enum.h"],
|
||||||
"types": [{
|
"types": [{
|
||||||
"id": 0,
|
"id": 0,
|
||||||
|
@ -115,6 +115,10 @@ OUTPUT: header.h
|
|||||||
}
|
}
|
||||||
OUTPUT: impl.cc
|
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"],
|
"dependencies": ["C:/Users/jacob/Desktop/superindex/indexer/tests/multi_file/header.h"],
|
||||||
"funcs": [{
|
"funcs": [{
|
||||||
"id": 0,
|
"id": 0,
|
||||||
|
@ -17,6 +17,10 @@ OUTPUT: simple_header.h
|
|||||||
}
|
}
|
||||||
OUTPUT: simple_impl.cc
|
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"],
|
"dependencies": ["C:/Users/jacob/Desktop/superindex/indexer/tests/multi_file/simple_header.h"],
|
||||||
"funcs": [{
|
"funcs": [{
|
||||||
"id": 0,
|
"id": 0,
|
||||||
|
@ -26,6 +26,10 @@ OUTPUT: static.h
|
|||||||
}
|
}
|
||||||
OUTPUT: static.cc
|
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"],
|
"dependencies": ["C:/Users/jacob/Desktop/superindex/indexer/tests/multi_file/static.h"],
|
||||||
"types": [{
|
"types": [{
|
||||||
"id": 0,
|
"id": 0,
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
385
tests/stl.cc
385
tests/stl.cc
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user