mirror of
https://github.com/MaskRay/ccls.git
synced 2025-02-16 21:58:08 +00:00
For completion, only tell clang about relevant dirty working files.
The heuristic may not be perfect, but it is probably good enough. clang_codeCompleteAt seems to get slower as more and more CXUnsavedFile instances are uploaded.
This commit is contained in:
parent
27dad9a277
commit
93ba0c532b
@ -298,7 +298,8 @@ void TryEnsureDocumentParsed(ClangCompleteManager* manager,
|
||||
args.push_back("-fspell-checking");
|
||||
}
|
||||
|
||||
WorkingFilesSnapshot snapshot = session->working_files->AsSnapshot();
|
||||
WorkingFiles::Snapshot snapshot =
|
||||
session->working_files->AsSnapshot({StripFileType(session->file.filename)});
|
||||
std::vector<CXUnsavedFile> unsaved = snapshot.AsUnsavedFiles();
|
||||
|
||||
LOG_S(INFO) << "Creating completion session with arguments "
|
||||
@ -389,9 +390,12 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) {
|
||||
if (!session->tu)
|
||||
continue;
|
||||
|
||||
WorkingFilesSnapshot snapshot =
|
||||
completion_manager->working_files_->AsSnapshot();
|
||||
timer.Reset();
|
||||
WorkingFiles::Snapshot snapshot =
|
||||
completion_manager->working_files_->AsSnapshot({StripFileType(path)});
|
||||
std::vector<CXUnsavedFile> unsaved = snapshot.AsUnsavedFiles();
|
||||
timer.ResetAndPrint("[complete] Creating WorkingFile snapshot");
|
||||
|
||||
|
||||
// Emit code completion data.
|
||||
if (request->position) {
|
||||
|
23
src/utils.cc
23
src/utils.cc
@ -86,6 +86,13 @@ bool EndsWithAny(const std::string& value,
|
||||
[&value](const std::string& ending) { return EndsWith(value, ending); });
|
||||
}
|
||||
|
||||
bool FindAnyPartial(const std::string& value,
|
||||
const std::vector<std::string>& values) {
|
||||
return std::any_of(
|
||||
std::begin(values), std::end(values),
|
||||
[&value](const std::string& v) { return value.find(v) != std::string::npos; });
|
||||
}
|
||||
|
||||
std::string GetBaseName(const std::string& path) {
|
||||
size_t last_slash = path.find_last_of('/');
|
||||
if (last_slash != std::string::npos && (last_slash + 1) < path.size())
|
||||
@ -93,6 +100,13 @@ std::string GetBaseName(const std::string& path) {
|
||||
return path;
|
||||
}
|
||||
|
||||
std::string StripFileType(const std::string& path) {
|
||||
size_t last_period = path.find_last_of('.');
|
||||
if (last_period != std::string::npos)
|
||||
return path.substr(0, last_period);
|
||||
return path;
|
||||
}
|
||||
|
||||
// See http://stackoverflow.com/a/29752943
|
||||
std::string ReplaceAll(const std::string& source,
|
||||
const std::string& from,
|
||||
@ -609,3 +623,12 @@ TEST_SUITE("Update \\n to \\r\\n") {
|
||||
REQUIRE(UpdateToRnNewlines("f1\r\nfo2\r\nfoo3") == "f1\r\nfo2\r\nfoo3");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_SUITE("StripFileType") {
|
||||
TEST_CASE("all") {
|
||||
REQUIRE(StripFileType("") == "");
|
||||
REQUIRE(StripFileType("bar") == "bar");
|
||||
REQUIRE(StripFileType("bar.cc") == "bar");
|
||||
REQUIRE(StripFileType("foo/bar.cc") == "foo/bar");
|
||||
}
|
||||
}
|
||||
|
@ -27,9 +27,13 @@ bool StartsWithAny(const std::string& value,
|
||||
const std::vector<std::string>& startings);
|
||||
bool EndsWithAny(const std::string& value,
|
||||
const std::vector<std::string>& endings);
|
||||
bool FindAnyPartial(const std::string& value,
|
||||
const std::vector<std::string>& values);
|
||||
|
||||
// Returns the basename of |path|, ie, "foo/bar.cc" => "bar.cc".
|
||||
std::string GetBaseName(const std::string& path);
|
||||
// Returns |path| without the filetype, ie, "foo/bar.cc" => "foo/bar".
|
||||
std::string StripFileType(const std::string& path);
|
||||
|
||||
std::string ReplaceAll(const std::string& source,
|
||||
const std::string& from,
|
||||
|
@ -31,6 +31,20 @@ lsPosition GetPositionForOffset(const std::string& content, int offset) {
|
||||
|
||||
} // namespace
|
||||
|
||||
std::vector<CXUnsavedFile> WorkingFiles::Snapshot::AsUnsavedFiles() const {
|
||||
std::vector<CXUnsavedFile> result;
|
||||
result.reserve(files.size());
|
||||
for (auto& file : files) {
|
||||
CXUnsavedFile unsaved;
|
||||
unsaved.Filename = file.filename.c_str();
|
||||
unsaved.Contents = file.content.c_str();
|
||||
unsaved.Length = (unsigned long)file.content.size();
|
||||
|
||||
result.push_back(unsaved);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
WorkingFile::WorkingFile(const std::string& filename,
|
||||
const std::string& buffer_content)
|
||||
: filename(filename), buffer_content(buffer_content) {
|
||||
@ -358,27 +372,16 @@ void WorkingFiles::OnClose(const lsTextDocumentItem& close) {
|
||||
<< " because it was not open";
|
||||
}
|
||||
|
||||
std::vector<CXUnsavedFile> WorkingFilesSnapshot::AsUnsavedFiles() const {
|
||||
std::vector<CXUnsavedFile> result;
|
||||
result.reserve(files.size());
|
||||
for (auto& file : files) {
|
||||
CXUnsavedFile unsaved;
|
||||
unsaved.Filename = file.filename.c_str();
|
||||
unsaved.Contents = file.content.c_str();
|
||||
unsaved.Length = (unsigned long)file.content.size();
|
||||
|
||||
result.push_back(unsaved);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
WorkingFilesSnapshot WorkingFiles::AsSnapshot() {
|
||||
WorkingFiles::Snapshot WorkingFiles::AsSnapshot(
|
||||
const std::vector<std::string>& filter_paths) {
|
||||
std::lock_guard<std::mutex> lock(files_mutex);
|
||||
|
||||
WorkingFilesSnapshot result;
|
||||
Snapshot result;
|
||||
result.files.reserve(files.size());
|
||||
for (auto& file : files)
|
||||
result.files.push_back({file->filename, file->buffer_content});
|
||||
for (const auto& file : files) {
|
||||
if (filter_paths.empty() || FindAnyPartial(file->filename, filter_paths))
|
||||
result.files.push_back({file->filename, file->buffer_content});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -75,16 +75,18 @@ struct WorkingFile {
|
||||
std::string* existing_completion) const;
|
||||
};
|
||||
|
||||
struct WorkingFilesSnapshot {
|
||||
std::vector<CXUnsavedFile> AsUnsavedFiles() const;
|
||||
struct File {
|
||||
std::string filename;
|
||||
std::string content;
|
||||
};
|
||||
std::vector<File> files;
|
||||
};
|
||||
|
||||
struct WorkingFiles {
|
||||
struct Snapshot {
|
||||
struct File {
|
||||
std::string filename;
|
||||
std::string content;
|
||||
};
|
||||
|
||||
std::vector<CXUnsavedFile> AsUnsavedFiles() const;
|
||||
std::vector<File> files;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// :: IMPORTANT :: All methods in this class are guarded by a single lock.
|
||||
//
|
||||
@ -104,7 +106,10 @@ struct WorkingFiles {
|
||||
void OnChange(const lsTextDocumentDidChangeParams& change);
|
||||
void OnClose(const lsTextDocumentItem& close);
|
||||
|
||||
WorkingFilesSnapshot AsSnapshot();
|
||||
// If |filter_paths| is non-empty, only files which contain any of the given
|
||||
// strings. For example, {"foo", "bar"} means that every result has either the
|
||||
// string "foo" or "bar" contained within it.
|
||||
Snapshot AsSnapshot(const std::vector<std::string>& filter_paths);
|
||||
|
||||
// Use unique_ptrs so we can handout WorkingFile ptrs and not have them
|
||||
// invalidated if we resize files.
|
||||
|
Loading…
Reference in New Issue
Block a user