mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-26 01:21:57 +00:00
Add FileContentsWithOffsets
This commit is contained in:
parent
8098e4f01d
commit
cf4603c6fa
@ -17,7 +17,11 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const bool kIndexStdDeclarations = true;
|
constexpr bool kIndexStdDeclarations = true;
|
||||||
|
|
||||||
|
// For typedef/using spanning less than or equal to (this number) of lines,
|
||||||
|
// display their declarations on hover.
|
||||||
|
constexpr int kMaxLinesDisplayTypeAliasDeclarations = 3;
|
||||||
|
|
||||||
void AddFuncRef(std::vector<IndexFuncRef>* result, IndexFuncRef ref) {
|
void AddFuncRef(std::vector<IndexFuncRef>* result, IndexFuncRef ref) {
|
||||||
if (!result->empty() && (*result)[result->size() - 1] == ref)
|
if (!result->empty() && (*result)[result->size() - 1] == ref)
|
||||||
@ -195,7 +199,7 @@ struct ConstructorCache {
|
|||||||
struct IndexParam {
|
struct IndexParam {
|
||||||
std::unordered_set<CXFile> seen_cx_files;
|
std::unordered_set<CXFile> seen_cx_files;
|
||||||
std::vector<std::string> seen_files;
|
std::vector<std::string> seen_files;
|
||||||
std::unordered_map<std::string, std::string> file_contents;
|
std::unordered_map<std::string, FileContentsWithOffsets> file_contents;
|
||||||
std::unordered_map<std::string, int64_t> file_modification_times;
|
std::unordered_map<std::string, int64_t> file_modification_times;
|
||||||
|
|
||||||
// Only use this when strictly needed (ie, primary translation unit is
|
// Only use this when strictly needed (ie, primary translation unit is
|
||||||
@ -242,10 +246,10 @@ IndexFile* ConsumeFile(IndexParam* param, CXFile file) {
|
|||||||
// Capture file contents in |param->file_contents| if it was not specified
|
// Capture file contents in |param->file_contents| if it was not specified
|
||||||
// at the start of indexing.
|
// at the start of indexing.
|
||||||
if (db &&
|
if (db &&
|
||||||
param->file_contents.find(file_name) == param->file_contents.end()) {
|
!param->file_contents.count(file_name)) {
|
||||||
optional<std::string> content = ReadContent(file_name);
|
optional<std::string> content = ReadContent(file_name);
|
||||||
if (content)
|
if (content)
|
||||||
param->file_contents[file_name] = *content;
|
param->file_contents.emplace(file_name, *content);
|
||||||
else
|
else
|
||||||
LOG_S(ERROR) << "[indexer] Failed to read file content for "
|
LOG_S(ERROR) << "[indexer] Failed to read file content for "
|
||||||
<< file_name;
|
<< file_name;
|
||||||
@ -1248,17 +1252,21 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
|||||||
|
|
||||||
type->def.hover = type->def.detailed_name;
|
type->def.hover = type->def.detailed_name;
|
||||||
|
|
||||||
// For single line Typedef/CXXTypeAlias, display the declaration line,
|
// For Typedef/CXXTypeAlias spanning a few lines, display the declaration line,
|
||||||
// with spelling name replaced with qualified name.
|
// with spelling name replaced with qualified name.
|
||||||
// TODO Think how to display multi-line declaration like `typedef struct { ... } foo;`
|
// TODO Think how to display multi-line declaration like `typedef struct { ... } foo;`
|
||||||
if (extent.start.line == extent.end.line) {
|
if (extent.end.line - extent.start.line <
|
||||||
std::string decl_text = GetDocumentContentInRange(
|
kMaxLinesDisplayTypeAliasDeclarations) {
|
||||||
param->tu->cx_tu, clang_getCursorExtent(decl->cursor));
|
FileContentsWithOffsets& fc = param->file_contents[db->path];
|
||||||
if (decl_text.size() == extent.end.column - extent.start.column) {
|
optional<int> extent_start = fc.ToOffset(extent.start),
|
||||||
|
spell_start = fc.ToOffset(spell.start),
|
||||||
|
spell_end = fc.ToOffset(spell.end),
|
||||||
|
extent_end = fc.ToOffset(extent.end);
|
||||||
|
if (extent_start && spell_start && spell_end && extent_end) {
|
||||||
type->def.hover =
|
type->def.hover =
|
||||||
decl_text.substr(0, spell.start.column - extent.start.column) +
|
fc.contents.substr(*extent_start, *spell_start - *extent_start) +
|
||||||
type->def.detailed_name +
|
type->def.detailed_name +
|
||||||
decl_text.substr(spell.end.column - extent.start.column);
|
fc.contents.substr(*spell_end, *extent_end - *spell_end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1604,6 +1612,33 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
|
|||||||
FileContents::FileContents(const std::string& path, const std::string& content)
|
FileContents::FileContents(const std::string& path, const std::string& content)
|
||||||
: path(path), content(content) {}
|
: path(path), content(content) {}
|
||||||
|
|
||||||
|
FileContentsWithOffsets::FileContentsWithOffsets() : line_offsets_{0} {}
|
||||||
|
|
||||||
|
FileContentsWithOffsets::FileContentsWithOffsets(std::string s) {
|
||||||
|
contents = s;
|
||||||
|
line_offsets_.push_back(0);
|
||||||
|
for (size_t i = 0; i < s.size(); i++)
|
||||||
|
if (s[i] == '\n')
|
||||||
|
line_offsets_.push_back(i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<int> FileContentsWithOffsets::ToOffset(Position p) const {
|
||||||
|
if (0 < p.line && size_t(p.line) <= line_offsets_.size()) {
|
||||||
|
int ret = line_offsets_[p.line - 1] + p.column - 1;
|
||||||
|
if (size_t(ret) <= contents.size())
|
||||||
|
return {ret};
|
||||||
|
}
|
||||||
|
return nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<std::string> FileContentsWithOffsets::ContentsInRange(Range range) const {
|
||||||
|
optional<int> start_offset = ToOffset(range.start),
|
||||||
|
end_offset = ToOffset(range.end);
|
||||||
|
if (start_offset && end_offset && *start_offset < *end_offset)
|
||||||
|
return {contents.substr(*start_offset, *end_offset - *start_offset)};
|
||||||
|
return nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::unique_ptr<IndexFile>> Parse(
|
std::vector<std::unique_ptr<IndexFile>> Parse(
|
||||||
Config* config,
|
Config* config,
|
||||||
FileConsumer::SharedState* file_consumer_shared,
|
FileConsumer::SharedState* file_consumer_shared,
|
||||||
@ -1670,8 +1705,8 @@ std::vector<std::unique_ptr<IndexFile>> ParseWithTu(
|
|||||||
FileConsumer file_consumer(file_consumer_shared, file);
|
FileConsumer file_consumer(file_consumer_shared, file);
|
||||||
IndexParam param(tu, &file_consumer);
|
IndexParam param(tu, &file_consumer);
|
||||||
for (const CXUnsavedFile& contents : file_contents) {
|
for (const CXUnsavedFile& contents : file_contents) {
|
||||||
param.file_contents[contents.Filename] =
|
param.file_contents.emplace(
|
||||||
std::string(contents.Contents, contents.Length);
|
contents.Filename, std::string(contents.Contents, contents.Length));
|
||||||
}
|
}
|
||||||
|
|
||||||
CXFile cx_file = clang_getFile(tu->cx_tu, file.c_str());
|
CXFile cx_file = clang_getFile(tu->cx_tu, file.c_str());
|
||||||
@ -1710,7 +1745,7 @@ std::vector<std::unique_ptr<IndexFile>> ParseWithTu(
|
|||||||
entry->args = args;
|
entry->args = args;
|
||||||
|
|
||||||
// Update file contents and modification time.
|
// Update file contents and modification time.
|
||||||
entry->file_contents_ = param.file_contents[entry->path];
|
entry->file_contents_ = param.file_contents[entry->path].contents;
|
||||||
entry->last_modification_time = param.file_modification_times[entry->path];
|
entry->last_modification_time = param.file_modification_times[entry->path];
|
||||||
|
|
||||||
// Update dependencies for the file. Do not include the file in its own
|
// Update dependencies for the file. Do not include the file in its own
|
||||||
|
@ -516,6 +516,18 @@ struct FileContents {
|
|||||||
FileContents(const std::string& path, const std::string& content);
|
FileContents(const std::string& path, const std::string& content);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FileContentsWithOffsets {
|
||||||
|
std::string contents;
|
||||||
|
// {0, 1 + position of first newline, 1 + position of second newline, ...}
|
||||||
|
std::vector<int> line_offsets_;
|
||||||
|
|
||||||
|
FileContentsWithOffsets();
|
||||||
|
FileContentsWithOffsets(std::string s);
|
||||||
|
|
||||||
|
optional<int> ToOffset(Position p) const;
|
||||||
|
optional<std::string> ContentsInRange(Range range) const;
|
||||||
|
};
|
||||||
|
|
||||||
// |import_file| is the cc file which is what gets passed to clang.
|
// |import_file| is the cc file which is what gets passed to clang.
|
||||||
// |desired_index_file| is the (h or cc) file which has actually changed.
|
// |desired_index_file| is the (h or cc) file which has actually changed.
|
||||||
// |dependencies| are the existing dependencies of |import_file| if this is a
|
// |dependencies| are the existing dependencies of |import_file| if this is a
|
||||||
|
Loading…
Reference in New Issue
Block a user