mirror of
https://github.com/MaskRay/ccls.git
synced 2025-04-16 13:52:17 +00:00
Format code
This commit is contained in:
parent
566b508b8e
commit
01fe19f280
@ -38,8 +38,8 @@ struct RealCacheManager : ICacheManager {
|
|||||||
if (!file_content || !serialized_indexed_content)
|
if (!file_content || !serialized_indexed_content)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return Deserialize(config_->cacheFormat, path, *serialized_indexed_content,*file_content,
|
return Deserialize(config_->cacheFormat, path, *serialized_indexed_content,
|
||||||
IndexFile::kMajorVersion);
|
*file_content, IndexFile::kMajorVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetCachePath(const std::string& source_file) {
|
std::string GetCachePath(const std::string& source_file) {
|
||||||
@ -91,7 +91,8 @@ struct FakeCacheManager : ICacheManager {
|
|||||||
std::unique_ptr<IndexFile> RawCacheLoad(const std::string& path) override {
|
std::unique_ptr<IndexFile> RawCacheLoad(const std::string& path) override {
|
||||||
for (const FakeCacheEntry& entry : entries_) {
|
for (const FakeCacheEntry& entry : entries_) {
|
||||||
if (entry.path == path) {
|
if (entry.path == path) {
|
||||||
return Deserialize(SerializeFormat::Json, path, entry.json, "<empty>", nullopt);
|
return Deserialize(SerializeFormat::Json, path, entry.json, "<empty>",
|
||||||
|
nullopt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,59 +161,87 @@ void BuildCompletionItemTexts(std::vector<lsCompletionItem>& out,
|
|||||||
int num_chunks = clang_getNumCompletionChunks(completion_string);
|
int num_chunks = clang_getNumCompletionChunks(completion_string);
|
||||||
for (int i = 0; i < num_chunks; ++i) {
|
for (int i = 0; i < num_chunks; ++i) {
|
||||||
CXCompletionChunkKind kind =
|
CXCompletionChunkKind kind =
|
||||||
clang_getCompletionChunkKind(completion_string, i);
|
clang_getCompletionChunkKind(completion_string, i);
|
||||||
|
|
||||||
std::string text;
|
std::string text;
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case CXCompletionChunk_LeftParen: text = '('; break;
|
case CXCompletionChunk_LeftParen:
|
||||||
case CXCompletionChunk_RightParen: text = ')'; break;
|
text = '(';
|
||||||
case CXCompletionChunk_LeftBracket: text = '['; break;
|
break;
|
||||||
case CXCompletionChunk_RightBracket: text = ']'; break;
|
case CXCompletionChunk_RightParen:
|
||||||
case CXCompletionChunk_LeftBrace: text = '{'; break;
|
text = ')';
|
||||||
case CXCompletionChunk_RightBrace: text = '}'; break;
|
break;
|
||||||
case CXCompletionChunk_LeftAngle: text = '<'; break;
|
case CXCompletionChunk_LeftBracket:
|
||||||
case CXCompletionChunk_RightAngle: text = '>'; break;
|
text = '[';
|
||||||
case CXCompletionChunk_Comma: text = ", "; break;
|
break;
|
||||||
case CXCompletionChunk_Colon: text = ':'; break;
|
case CXCompletionChunk_RightBracket:
|
||||||
case CXCompletionChunk_SemiColon: text = ';'; break;
|
text = ']';
|
||||||
case CXCompletionChunk_Equal: text = '='; break;
|
break;
|
||||||
case CXCompletionChunk_HorizontalSpace: text = ' '; break;
|
case CXCompletionChunk_LeftBrace:
|
||||||
case CXCompletionChunk_VerticalSpace: text = ' '; break;
|
text = '{';
|
||||||
|
break;
|
||||||
|
case CXCompletionChunk_RightBrace:
|
||||||
|
text = '}';
|
||||||
|
break;
|
||||||
|
case CXCompletionChunk_LeftAngle:
|
||||||
|
text = '<';
|
||||||
|
break;
|
||||||
|
case CXCompletionChunk_RightAngle:
|
||||||
|
text = '>';
|
||||||
|
break;
|
||||||
|
case CXCompletionChunk_Comma:
|
||||||
|
text = ", ";
|
||||||
|
break;
|
||||||
|
case CXCompletionChunk_Colon:
|
||||||
|
text = ':';
|
||||||
|
break;
|
||||||
|
case CXCompletionChunk_SemiColon:
|
||||||
|
text = ';';
|
||||||
|
break;
|
||||||
|
case CXCompletionChunk_Equal:
|
||||||
|
text = '=';
|
||||||
|
break;
|
||||||
|
case CXCompletionChunk_HorizontalSpace:
|
||||||
|
text = ' ';
|
||||||
|
break;
|
||||||
|
case CXCompletionChunk_VerticalSpace:
|
||||||
|
text = ' ';
|
||||||
|
break;
|
||||||
|
|
||||||
case CXCompletionChunk_ResultType:
|
case CXCompletionChunk_ResultType:
|
||||||
result_type =
|
result_type =
|
||||||
ToString(clang_getCompletionChunkText(completion_string, i));
|
ToString(clang_getCompletionChunkText(completion_string, i));
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case CXCompletionChunk_TypedText:
|
case CXCompletionChunk_TypedText:
|
||||||
case CXCompletionChunk_Placeholder:
|
case CXCompletionChunk_Placeholder:
|
||||||
case CXCompletionChunk_Text:
|
case CXCompletionChunk_Text:
|
||||||
case CXCompletionChunk_Informative:
|
case CXCompletionChunk_Informative:
|
||||||
text = ToString(clang_getCompletionChunkText(completion_string, i));
|
text = ToString(clang_getCompletionChunkText(completion_string, i));
|
||||||
|
|
||||||
for (auto i = out_first; i < out.size(); ++i) {
|
for (auto i = out_first; i < out.size(); ++i) {
|
||||||
// first typed text is used for filtering
|
// first typed text is used for filtering
|
||||||
if (kind == CXCompletionChunk_TypedText && !out[i].filterText)
|
if (kind == CXCompletionChunk_TypedText && !out[i].filterText)
|
||||||
out[i].filterText = text;
|
out[i].filterText = text;
|
||||||
|
|
||||||
if (kind == CXCompletionChunk_Placeholder)
|
if (kind == CXCompletionChunk_Placeholder)
|
||||||
out[i].parameters_.push_back(text);
|
out[i].parameters_.push_back(text);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CXCompletionChunk_CurrentParameter:
|
||||||
|
// We have our own parsing logic for active parameter. This doesn't seem
|
||||||
|
// to be very reliable.
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case CXCompletionChunk_Optional: {
|
||||||
|
CXCompletionString nested =
|
||||||
|
clang_getCompletionChunkCompletionString(completion_string, i);
|
||||||
|
// duplicate last element, the recursive call will complete it
|
||||||
|
out.push_back(out.back());
|
||||||
|
BuildCompletionItemTexts(out, nested, include_snippets);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case CXCompletionChunk_CurrentParameter:
|
|
||||||
// We have our own parsing logic for active parameter. This doesn't seem
|
|
||||||
// to be very reliable.
|
|
||||||
continue;
|
|
||||||
|
|
||||||
case CXCompletionChunk_Optional: {
|
|
||||||
CXCompletionString nested =
|
|
||||||
clang_getCompletionChunkCompletionString(completion_string, i);
|
|
||||||
// duplicate last element, the recursive call will complete it
|
|
||||||
out.push_back(out.back());
|
|
||||||
BuildCompletionItemTexts(out, nested, include_snippets);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto i = out_first; i < out.size(); ++i)
|
for (auto i = out_first; i < out.size(); ++i)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "position.h"
|
|
||||||
#include "nt_string.h"
|
#include "nt_string.h"
|
||||||
|
#include "position.h"
|
||||||
|
|
||||||
#include <clang-c/Index.h>
|
#include <clang-c/Index.h>
|
||||||
#include <optional.h>
|
#include <optional.h>
|
||||||
|
@ -98,23 +98,27 @@ std::unique_ptr<ClangTranslationUnit> ClangTranslationUnit::Create(
|
|||||||
auto make_msg = [&]() {
|
auto make_msg = [&]() {
|
||||||
return "Please try running the following, identify which flag causes the "
|
return "Please try running the following, identify which flag causes the "
|
||||||
"issue, and report a bug. cquery will then filter the flag for you "
|
"issue, and report a bug. cquery will then filter the flag for you "
|
||||||
" automatically:\n$ " + StringJoin(args, " ") + " -fsyntax-only";
|
" automatically:\n$ " +
|
||||||
|
StringJoin(args, " ") + " -fsyntax-only";
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (error_code) {
|
switch (error_code) {
|
||||||
case CXError_Success:
|
case CXError_Success:
|
||||||
return MakeUnique<ClangTranslationUnit>(cx_tu);
|
return MakeUnique<ClangTranslationUnit>(cx_tu);
|
||||||
case CXError_Failure:
|
case CXError_Failure:
|
||||||
LOG_S(ERROR) << "libclang generic failure for " << filepath << ". " << make_msg();
|
LOG_S(ERROR) << "libclang generic failure for " << filepath << ". "
|
||||||
|
<< make_msg();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
case CXError_Crashed:
|
case CXError_Crashed:
|
||||||
LOG_S(ERROR) << "libclang crashed for " << filepath << ". " << make_msg();
|
LOG_S(ERROR) << "libclang crashed for " << filepath << ". " << make_msg();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
case CXError_InvalidArguments:
|
case CXError_InvalidArguments:
|
||||||
LOG_S(ERROR) << "libclang had invalid arguments for " << filepath << ". " << make_msg();
|
LOG_S(ERROR) << "libclang had invalid arguments for " << filepath << ". "
|
||||||
|
<< make_msg();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
case CXError_ASTReadError:
|
case CXError_ASTReadError:
|
||||||
LOG_S(ERROR) << "libclang had ast read error for " << filepath << ". " << make_msg();
|
LOG_S(ERROR) << "libclang had ast read error for " << filepath << ". "
|
||||||
|
<< make_msg();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,8 +135,8 @@ struct Config {
|
|||||||
int includeMaxPathSize = 30;
|
int includeMaxPathSize = 30;
|
||||||
|
|
||||||
// Whitelist that file paths will be tested against. If a file path does not
|
// Whitelist that file paths will be tested against. If a file path does not
|
||||||
// end in one of these values, it will not be considered for auto-completion.
|
// end in one of these values, it will not be considered for
|
||||||
// An example value is { ".h", ".hpp" }
|
// auto-completion. An example value is { ".h", ".hpp" }
|
||||||
//
|
//
|
||||||
// This is significantly faster than using a regex.
|
// This is significantly faster than using a regex.
|
||||||
std::vector<std::string> includeSuffixWhitelist = {".h", ".hpp", ".hh"};
|
std::vector<std::string> includeSuffixWhitelist = {".h", ".hpp", ".hh"};
|
||||||
@ -154,8 +154,8 @@ struct Config {
|
|||||||
bool attributeMakeCallsToCtor = true;
|
bool attributeMakeCallsToCtor = true;
|
||||||
|
|
||||||
// If a translation unit's absolute path matches any EMCAScript regex in the
|
// If a translation unit's absolute path matches any EMCAScript regex in the
|
||||||
// whitelist, or does not match any regex in the blacklist, it will be indexed.
|
// whitelist, or does not match any regex in the blacklist, it will be
|
||||||
// To only index files in the whitelist, add ".*" to the blacklist.
|
// indexed. To only index files in the whitelist, add ".*" to the blacklist.
|
||||||
// `std::regex_search(path, regex, std::regex_constants::match_any)`
|
// `std::regex_search(path, regex, std::regex_constants::match_any)`
|
||||||
//
|
//
|
||||||
// Example: `ash/.*\.cc`
|
// Example: `ash/.*\.cc`
|
||||||
|
@ -75,7 +75,8 @@ IndexFile* FileConsumer::TryConsumeFile(CXFile file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read the file contents, if we fail then we cannot index the file.
|
// Read the file contents, if we fail then we cannot index the file.
|
||||||
optional<std::string> contents = GetFileContents(file_name, file_contents_map);
|
optional<std::string> contents =
|
||||||
|
GetFileContents(file_name, file_contents_map);
|
||||||
if (!contents) {
|
if (!contents) {
|
||||||
*is_first_ownership = false;
|
*is_first_ownership = false;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -143,7 +143,8 @@ ShouldParse FileNeedsParse(
|
|||||||
return ShouldParse::NoSuchFile;
|
return ShouldParse::NoSuchFile;
|
||||||
|
|
||||||
optional<int64_t> last_cached_modification =
|
optional<int64_t> last_cached_modification =
|
||||||
timestamp_manager->GetLastCachedModificationTime(cache_manager.get(), path);
|
timestamp_manager->GetLastCachedModificationTime(cache_manager.get(),
|
||||||
|
path);
|
||||||
|
|
||||||
// File has been changed.
|
// File has been changed.
|
||||||
if (!last_cached_modification ||
|
if (!last_cached_modification ||
|
||||||
@ -236,8 +237,9 @@ CacheLoadResult TryLoadFromCache(
|
|||||||
PerformanceImportFile perf;
|
PerformanceImportFile perf;
|
||||||
|
|
||||||
std::vector<Index_DoIdMap> result;
|
std::vector<Index_DoIdMap> result;
|
||||||
result.push_back(Index_DoIdMap(cache_manager->TakeOrLoad(path_to_index), cache_manager, perf,
|
result.push_back(Index_DoIdMap(cache_manager->TakeOrLoad(path_to_index),
|
||||||
is_interactive, false /*write_to_disk*/));
|
cache_manager, perf, is_interactive,
|
||||||
|
false /*write_to_disk*/));
|
||||||
for (const std::string& dependency : previous_index->dependencies) {
|
for (const std::string& dependency : previous_index->dependencies) {
|
||||||
// Only load a dependency if it is not already loaded.
|
// Only load a dependency if it is not already loaded.
|
||||||
//
|
//
|
||||||
@ -257,8 +259,9 @@ CacheLoadResult TryLoadFromCache(
|
|||||||
if (!dependency_index)
|
if (!dependency_index)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
result.push_back(Index_DoIdMap(std::move(dependency_index), cache_manager, perf,
|
result.push_back(Index_DoIdMap(std::move(dependency_index), cache_manager,
|
||||||
is_interactive, false /*write_to_disk*/));
|
perf, is_interactive,
|
||||||
|
false /*write_to_disk*/));
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueManager::instance()->do_id_map.EnqueueAll(std::move(result));
|
QueueManager::instance()->do_id_map.EnqueueAll(std::move(result));
|
||||||
@ -344,7 +347,7 @@ void ParseFile(Config* config,
|
|||||||
|
|
||||||
LOG_S(INFO) << "Parsing " << path_to_index;
|
LOG_S(INFO) << "Parsing " << path_to_index;
|
||||||
std::vector<FileContents> file_contents = PreloadFileContents(
|
std::vector<FileContents> file_contents = PreloadFileContents(
|
||||||
request.cache_manager, entry, request.contents, path_to_index);
|
request.cache_manager, entry, request.contents, path_to_index);
|
||||||
|
|
||||||
std::vector<Index_DoIdMap> result;
|
std::vector<Index_DoIdMap> result;
|
||||||
PerformanceImportFile perf;
|
PerformanceImportFile perf;
|
||||||
@ -375,8 +378,8 @@ void ParseFile(Config* config,
|
|||||||
// When main thread does IdMap request it will request the previous index if
|
// When main thread does IdMap request it will request the previous index if
|
||||||
// needed.
|
// needed.
|
||||||
LOG_S(INFO) << "Emitting index result for " << new_index->path;
|
LOG_S(INFO) << "Emitting index result for " << new_index->path;
|
||||||
result.push_back(Index_DoIdMap(std::move(new_index), request.cache_manager, perf,
|
result.push_back(Index_DoIdMap(std::move(new_index), request.cache_manager,
|
||||||
request.is_interactive,
|
perf, request.is_interactive,
|
||||||
true /*write_to_disk*/));
|
true /*write_to_disk*/));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -401,8 +404,8 @@ bool IndexMain_DoParse(
|
|||||||
entry.filename = request->path;
|
entry.filename = request->path;
|
||||||
entry.args = request->args;
|
entry.args = request->args;
|
||||||
ParseFile(config, working_files, file_consumer_shared, timestamp_manager,
|
ParseFile(config, working_files, file_consumer_shared, timestamp_manager,
|
||||||
modification_timestamp_fetcher, import_manager,
|
modification_timestamp_fetcher, import_manager, indexer,
|
||||||
indexer, request.value(), entry);
|
request.value(), entry);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,7 +480,8 @@ bool IndexMain_LoadPreviousIndex() {
|
|||||||
if (!response)
|
if (!response)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
response->previous = response->cache_manager->TryTakeOrLoad(response->current->path);
|
response->previous =
|
||||||
|
response->cache_manager->TryTakeOrLoad(response->current->path);
|
||||||
LOG_IF_S(ERROR, !response->previous)
|
LOG_IF_S(ERROR, !response->previous)
|
||||||
<< "Unable to load previous index for already imported index "
|
<< "Unable to load previous index for already imported index "
|
||||||
<< response->current->path;
|
<< response->current->path;
|
||||||
@ -584,14 +588,13 @@ void Indexer_Main(Config* config,
|
|||||||
// IndexMain_DoCreateIndexUpdate so we don't starve querydb from doing any
|
// IndexMain_DoCreateIndexUpdate so we don't starve querydb from doing any
|
||||||
// work. Running both also lets the user query the partially constructed
|
// work. Running both also lets the user query the partially constructed
|
||||||
// index.
|
// index.
|
||||||
did_work = IndexMain_DoParse(
|
did_work =
|
||||||
config, working_files, file_consumer_shared,
|
IndexMain_DoParse(config, working_files, file_consumer_shared,
|
||||||
timestamp_manager, &modification_timestamp_fetcher,
|
timestamp_manager, &modification_timestamp_fetcher,
|
||||||
import_manager, indexer.get()) ||
|
import_manager, indexer.get()) ||
|
||||||
did_work;
|
did_work;
|
||||||
|
|
||||||
did_work = IndexMain_DoCreateIndexUpdate(timestamp_manager) ||
|
did_work = IndexMain_DoCreateIndexUpdate(timestamp_manager) || did_work;
|
||||||
did_work;
|
|
||||||
|
|
||||||
did_work = IndexMain_LoadPreviousIndex() || did_work;
|
did_work = IndexMain_LoadPreviousIndex() || did_work;
|
||||||
|
|
||||||
@ -743,10 +746,9 @@ TEST_SUITE("ImportPipeline") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool PumpOnce() {
|
bool PumpOnce() {
|
||||||
return IndexMain_DoParse(&config, &working_files, &file_consumer_shared,
|
return IndexMain_DoParse(
|
||||||
×tamp_manager,
|
&config, &working_files, &file_consumer_shared, ×tamp_manager,
|
||||||
&modification_timestamp_fetcher, &import_manager,
|
&modification_timestamp_fetcher, &import_manager, indexer.get());
|
||||||
indexer.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MakeRequest(const std::string& path,
|
void MakeRequest(const std::string& path,
|
||||||
|
@ -82,7 +82,7 @@ lsCompletionItem BuildCompletionItem(Config* config,
|
|||||||
bool is_stl) {
|
bool is_stl) {
|
||||||
lsCompletionItem item;
|
lsCompletionItem item;
|
||||||
item.label = ElideLongPath(config, path);
|
item.label = ElideLongPath(config, path);
|
||||||
item.detail = path; // the include path, used in de-duplicating
|
item.detail = path; // the include path, used in de-duplicating
|
||||||
item.textEdit = lsTextEdit();
|
item.textEdit = lsTextEdit();
|
||||||
item.textEdit->newText = path;
|
item.textEdit->newText = path;
|
||||||
item.insertTextFormat = lsInsertTextFormat::PlainText;
|
item.insertTextFormat = lsInsertTextFormat::PlainText;
|
||||||
@ -142,7 +142,8 @@ void IncludeComplete::InsertCompletionItem(const std::string& absolute_path,
|
|||||||
completion_items[it->second].detail.length() > item.detail.length())
|
completion_items[it->second].detail.length() > item.detail.length())
|
||||||
absolute_path_to_completion_item[absolute_path] = completion_items.size();
|
absolute_path_to_completion_item[absolute_path] = completion_items.size();
|
||||||
} else {
|
} else {
|
||||||
lsCompletionItem& inserted_item = completion_items[inserted_paths[item.detail]];
|
lsCompletionItem& inserted_item =
|
||||||
|
completion_items[inserted_paths[item.detail]];
|
||||||
// Update |use_angle_brackets_|, prefer quotes.
|
// Update |use_angle_brackets_|, prefer quotes.
|
||||||
if (!item.use_angle_brackets_)
|
if (!item.use_angle_brackets_)
|
||||||
inserted_item.use_angle_brackets_ = false;
|
inserted_item.use_angle_brackets_ = false;
|
||||||
@ -150,8 +151,7 @@ void IncludeComplete::InsertCompletionItem(const std::string& absolute_path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IncludeComplete::AddFile(const std::string& absolute_path) {
|
void IncludeComplete::AddFile(const std::string& absolute_path) {
|
||||||
if (!EndsWithAny(absolute_path,
|
if (!EndsWithAny(absolute_path, config_->completion.includeSuffixWhitelist))
|
||||||
config_->completion.includeSuffixWhitelist))
|
|
||||||
return;
|
return;
|
||||||
if (match_ && !match_->IsMatch(absolute_path))
|
if (match_ && !match_->IsMatch(absolute_path))
|
||||||
return;
|
return;
|
||||||
@ -183,8 +183,7 @@ void IncludeComplete::InsertIncludesFromDirectory(std::string directory,
|
|||||||
GetFilesInFolder(
|
GetFilesInFolder(
|
||||||
directory, true /*recursive*/, false /*add_folder_to_path*/,
|
directory, true /*recursive*/, false /*add_folder_to_path*/,
|
||||||
[&](const std::string& path) {
|
[&](const std::string& path) {
|
||||||
if (!EndsWithAny(path,
|
if (!EndsWithAny(path, config_->completion.includeSuffixWhitelist))
|
||||||
config_->completion.includeSuffixWhitelist))
|
|
||||||
return;
|
return;
|
||||||
if (match_ && !match_->IsMatch(directory + path))
|
if (match_ && !match_->IsMatch(directory + path))
|
||||||
return;
|
return;
|
||||||
|
169
src/indexer.cc
169
src/indexer.cc
@ -83,25 +83,25 @@ Role GetRole(const CXIdxEntityRefInfo* ref_info, Role role) {
|
|||||||
|
|
||||||
SymbolKind GetSymbolKind(CXCursorKind kind) {
|
SymbolKind GetSymbolKind(CXCursorKind kind) {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
default:
|
default:
|
||||||
return SymbolKind::Invalid;
|
return SymbolKind::Invalid;
|
||||||
|
|
||||||
case CXCursor_FunctionDecl:
|
case CXCursor_FunctionDecl:
|
||||||
case CXCursor_CXXMethod:
|
case CXCursor_CXXMethod:
|
||||||
case CXCursor_Constructor:
|
case CXCursor_Constructor:
|
||||||
case CXCursor_Destructor:
|
case CXCursor_Destructor:
|
||||||
case CXCursor_ConversionFunction:
|
case CXCursor_ConversionFunction:
|
||||||
case CXCursor_FunctionTemplate:
|
case CXCursor_FunctionTemplate:
|
||||||
case CXCursor_OverloadedDeclRef:
|
case CXCursor_OverloadedDeclRef:
|
||||||
case CXCursor_LambdaExpr:
|
case CXCursor_LambdaExpr:
|
||||||
return SymbolKind::Func;
|
return SymbolKind::Func;
|
||||||
|
|
||||||
case CXCursor_Namespace:
|
case CXCursor_Namespace:
|
||||||
case CXCursor_EnumDecl:
|
case CXCursor_EnumDecl:
|
||||||
case CXCursor_UnionDecl:
|
case CXCursor_UnionDecl:
|
||||||
case CXCursor_StructDecl:
|
case CXCursor_StructDecl:
|
||||||
case CXCursor_ClassDecl:
|
case CXCursor_ClassDecl:
|
||||||
return SymbolKind::Type;
|
return SymbolKind::Type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,7 +306,9 @@ struct IndexParam {
|
|||||||
NamespaceHelper ns;
|
NamespaceHelper ns;
|
||||||
ConstructorCache ctors;
|
ConstructorCache ctors;
|
||||||
|
|
||||||
IndexParam(Config* config, ClangTranslationUnit* tu, FileConsumer* file_consumer)
|
IndexParam(Config* config,
|
||||||
|
ClangTranslationUnit* tu,
|
||||||
|
FileConsumer* file_consumer)
|
||||||
: config(config), tu(tu), file_consumer(file_consumer) {}
|
: config(config), tu(tu), file_consumer(file_consumer) {}
|
||||||
|
|
||||||
#if CINDEX_HAVE_PRETTY
|
#if CINDEX_HAVE_PRETTY
|
||||||
@ -324,8 +326,8 @@ struct IndexParam {
|
|||||||
CXPrintingPolicy_TerseOutput, 1);
|
CXPrintingPolicy_TerseOutput, 1);
|
||||||
clang_PrintingPolicy_setProperty(print_policy,
|
clang_PrintingPolicy_setProperty(print_policy,
|
||||||
CXPrintingPolicy_FullyQualifiedName, 1);
|
CXPrintingPolicy_FullyQualifiedName, 1);
|
||||||
clang_PrintingPolicy_setProperty(print_policy,
|
clang_PrintingPolicy_setProperty(
|
||||||
CXPrintingPolicy_SuppressInitializers, 1);
|
print_policy, CXPrintingPolicy_SuppressInitializers, 1);
|
||||||
print_policy_more = clang_getCursorPrintingPolicy(cursor);
|
print_policy_more = clang_getCursorPrintingPolicy(cursor);
|
||||||
clang_PrintingPolicy_setProperty(print_policy_more,
|
clang_PrintingPolicy_setProperty(print_policy_more,
|
||||||
CXPrintingPolicy_FullyQualifiedName, 1);
|
CXPrintingPolicy_FullyQualifiedName, 1);
|
||||||
@ -348,7 +350,8 @@ IndexFile* ConsumeFile(IndexParam* param, CXFile file) {
|
|||||||
if (param->seen_cx_files.insert(file).second) {
|
if (param->seen_cx_files.insert(file).second) {
|
||||||
std::string file_name = FileName(file);
|
std::string file_name = FileName(file);
|
||||||
// file_name may be empty when it contains .. and is outside of WorkingDir.
|
// file_name may be empty when it contains .. and is outside of WorkingDir.
|
||||||
// https://reviews.llvm.org/D42893 https://github.com/cquery-project/cquery/issues/413
|
// https://reviews.llvm.org/D42893
|
||||||
|
// https://github.com/cquery-project/cquery/issues/413
|
||||||
if (!file_name.empty()) {
|
if (!file_name.empty()) {
|
||||||
// Add to all files we have seen so we can generate proper dependency
|
// Add to all files we have seen so we can generate proper dependency
|
||||||
// graph.
|
// graph.
|
||||||
@ -464,17 +467,17 @@ std::string GetDocumentContentInRange(CXTranslationUnit cx_tu,
|
|||||||
|
|
||||||
void SetUsePreflight(IndexFile* db, ClangCursor parent) {
|
void SetUsePreflight(IndexFile* db, ClangCursor parent) {
|
||||||
switch (GetSymbolKind(parent.get_kind())) {
|
switch (GetSymbolKind(parent.get_kind())) {
|
||||||
case SymbolKind::Func:
|
case SymbolKind::Func:
|
||||||
(void)db->ToFuncId(parent.cx_cursor);
|
(void)db->ToFuncId(parent.cx_cursor);
|
||||||
break;
|
break;
|
||||||
case SymbolKind::Type:
|
case SymbolKind::Type:
|
||||||
(void)db->ToTypeId(parent.cx_cursor);
|
(void)db->ToTypeId(parent.cx_cursor);
|
||||||
break;
|
break;
|
||||||
case SymbolKind::Var:
|
case SymbolKind::Var:
|
||||||
(void)db->ToVarId(parent.cx_cursor);
|
(void)db->ToVarId(parent.cx_cursor);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,11 +511,11 @@ void SetTypeName(IndexType* type,
|
|||||||
name = "(anon)";
|
name = "(anon)";
|
||||||
if (!container)
|
if (!container)
|
||||||
parent.cursor = cursor.get_semantic_parent().cx_cursor;
|
parent.cursor = cursor.get_semantic_parent().cx_cursor;
|
||||||
// Investigate why clang_getCursorPrettyPrinted gives `struct A {}` `namespace ns {}`
|
// Investigate why clang_getCursorPrettyPrinted gives `struct A {}` `namespace
|
||||||
// which are not qualified.
|
// ns {}` which are not qualified.
|
||||||
//type->def.detailed_name = param->PrettyPrintCursor(cursor.cx_cursor);
|
// type->def.detailed_name = param->PrettyPrintCursor(cursor.cx_cursor);
|
||||||
type->def.detailed_name =
|
type->def.detailed_name =
|
||||||
param->ns.QualifiedName(container ? container : &parent, name);
|
param->ns.QualifiedName(container ? container : &parent, name);
|
||||||
auto idx = type->def.detailed_name.find(name);
|
auto idx = type->def.detailed_name.find(name);
|
||||||
assert(idx != std::string::npos);
|
assert(idx != std::string::npos);
|
||||||
type->def.short_name_offset = idx;
|
type->def.short_name_offset = idx;
|
||||||
@ -584,7 +587,7 @@ void SetVarDetail(IndexVar* var,
|
|||||||
? param->PrettyPrintCursor(cursor.cx_cursor)
|
? param->PrettyPrintCursor(cursor.cx_cursor)
|
||||||
:
|
:
|
||||||
#endif
|
#endif
|
||||||
param->ns.QualifiedName(semanticContainer, short_name);
|
param->ns.QualifiedName(semanticContainer, short_name);
|
||||||
|
|
||||||
if (cursor.get_kind() == CXCursor_EnumConstantDecl && semanticContainer) {
|
if (cursor.get_kind() == CXCursor_EnumConstantDecl && semanticContainer) {
|
||||||
CXType enum_type = clang_getCanonicalType(
|
CXType enum_type = clang_getCanonicalType(
|
||||||
@ -658,19 +661,22 @@ void OnIndexReference_Function(IndexFile* db,
|
|||||||
IndexFunc* called = db->Resolve(called_id);
|
IndexFunc* called = db->Resolve(called_id);
|
||||||
parent->def.callees.push_back(
|
parent->def.callees.push_back(
|
||||||
SymbolRef(loc, called->id, SymbolKind::Func, role));
|
SymbolRef(loc, called->id, SymbolKind::Func, role));
|
||||||
AddFuncUse(&called->uses, Use(loc, parent->id, SymbolKind::Func, role, {}));
|
AddFuncUse(&called->uses,
|
||||||
|
Use(loc, parent->id, SymbolKind::Func, role, {}));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SymbolKind::Type: {
|
case SymbolKind::Type: {
|
||||||
IndexType* parent = db->Resolve(db->ToTypeId(parent_cursor.cx_cursor));
|
IndexType* parent = db->Resolve(db->ToTypeId(parent_cursor.cx_cursor));
|
||||||
IndexFunc* called = db->Resolve(called_id);
|
IndexFunc* called = db->Resolve(called_id);
|
||||||
called = db->Resolve(called_id);
|
called = db->Resolve(called_id);
|
||||||
AddFuncUse(&called->uses, Use(loc, parent->id, SymbolKind::Type, role, {}));
|
AddFuncUse(&called->uses,
|
||||||
|
Use(loc, parent->id, SymbolKind::Type, role, {}));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
IndexFunc* called = db->Resolve(called_id);
|
IndexFunc* called = db->Resolve(called_id);
|
||||||
AddFuncUse(&called->uses, Use(loc, Id<void>(), SymbolKind::File, role, {}));
|
AddFuncUse(&called->uses,
|
||||||
|
Use(loc, Id<void>(), SymbolKind::File, role, {}));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -789,26 +795,31 @@ CXCursor fromContainer(const CXIdxContainerInfo* parent) {
|
|||||||
return parent ? parent->cursor : clang_getNullCursor();
|
return parent ? parent->cursor : clang_getNullCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddUseSpell(IndexFile* db,
|
void AddUseSpell(IndexFile* db, std::vector<Use>& uses, ClangCursor cursor) {
|
||||||
std::vector<Use>& uses,
|
AddUse(db, uses, cursor.get_spell(), cursor.get_lexical_parent().cx_cursor,
|
||||||
ClangCursor cursor) {
|
Role::Reference);
|
||||||
AddUse(db, uses, cursor.get_spell(),
|
|
||||||
cursor.get_lexical_parent().cx_cursor, Role::Reference);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void UniqueAddUse(IndexFile* db, std::vector<Use>& uses, Range range, Args&&... args) {
|
void UniqueAddUse(IndexFile* db,
|
||||||
|
std::vector<Use>& uses,
|
||||||
|
Range range,
|
||||||
|
Args&&... args) {
|
||||||
if (std::find_if(uses.begin(), uses.end(),
|
if (std::find_if(uses.begin(), uses.end(),
|
||||||
[&](Use use) { return use.range == range; }) == uses.end())
|
[&](Use use) { return use.range == range; }) == uses.end())
|
||||||
AddUse(db, uses, range, std::forward<Args>(args)...);
|
AddUse(db, uses, range, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void UniqueAddUseSpell(IndexFile* db, std::vector<Use>& uses, ClangCursor cursor, Args&&... args) {
|
void UniqueAddUseSpell(IndexFile* db,
|
||||||
|
std::vector<Use>& uses,
|
||||||
|
ClangCursor cursor,
|
||||||
|
Args&&... args) {
|
||||||
Range range = cursor.get_spell();
|
Range range = cursor.get_spell();
|
||||||
if (std::find_if(uses.begin(), uses.end(),
|
if (std::find_if(uses.begin(), uses.end(),
|
||||||
[&](Use use) { return use.range == range; }) == uses.end())
|
[&](Use use) { return use.range == range; }) == uses.end())
|
||||||
AddUse(db, uses, range, cursor.get_lexical_parent().cx_cursor, std::forward<Args>(args)...);
|
AddUse(db, uses, range, cursor.get_lexical_parent().cx_cursor,
|
||||||
|
std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
IdCache::IdCache(const std::string& primary_file)
|
IdCache::IdCache(const std::string& primary_file)
|
||||||
@ -1292,8 +1303,8 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
|
|||||||
SetUsePreflight(db, sem_parent);
|
SetUsePreflight(db, sem_parent);
|
||||||
SetUsePreflight(db, lex_parent);
|
SetUsePreflight(db, lex_parent);
|
||||||
ref_var = db->Resolve(ref_var_id);
|
ref_var = db->Resolve(ref_var_id);
|
||||||
ref_var->def.spell = SetUse(db, ref_cursor.get_spell(),
|
ref_var->def.spell =
|
||||||
sem_parent, Role::Definition);
|
SetUse(db, ref_cursor.get_spell(), sem_parent, Role::Definition);
|
||||||
ref_var->def.extent =
|
ref_var->def.extent =
|
||||||
SetUse(db, ref_cursor.get_extent(), lex_parent, Role::None);
|
SetUse(db, ref_cursor.get_extent(), lex_parent, Role::None);
|
||||||
ref_var = db->Resolve(ref_var_id);
|
ref_var = db->Resolve(ref_var_id);
|
||||||
@ -1328,9 +1339,8 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
|
|||||||
case CXCursor_FunctionDecl:
|
case CXCursor_FunctionDecl:
|
||||||
case CXCursor_FunctionTemplate: {
|
case CXCursor_FunctionTemplate: {
|
||||||
IndexFuncId called_id = db->ToFuncId(overloaded.get_usr_hash());
|
IndexFuncId called_id = db->ToFuncId(overloaded.get_usr_hash());
|
||||||
OnIndexReference_Function(db, cursor.get_spell(),
|
OnIndexReference_Function(db, cursor.get_spell(), data->container,
|
||||||
data->container, called_id,
|
called_id, Role::Call);
|
||||||
Role::Call);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1353,11 +1363,11 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
|
|||||||
SetUsePreflight(db, sem_parent);
|
SetUsePreflight(db, sem_parent);
|
||||||
SetUsePreflight(db, lex_parent);
|
SetUsePreflight(db, lex_parent);
|
||||||
ref_type = db->Resolve(ref_type_id);
|
ref_type = db->Resolve(ref_type_id);
|
||||||
ref_type->def.spell = SetUse(db, ref_cursor.get_spell(),
|
ref_type->def.spell =
|
||||||
sem_parent, Role::Definition);
|
SetUse(db, ref_cursor.get_spell(), sem_parent, Role::Definition);
|
||||||
ref_type->def.extent =
|
ref_type->def.extent =
|
||||||
SetUse(db, ref_cursor.get_extent(), lex_parent, Role::None);
|
SetUse(db, ref_cursor.get_extent(), lex_parent, Role::None);
|
||||||
#if 0&&CINDEX_HAVE_PRETTY
|
#if 0 && CINDEX_HAVE_PRETTY
|
||||||
ref_type->def.detailed_name = param->PrettyPrintCursor(ref_cursor.cx_cursor);
|
ref_type->def.detailed_name = param->PrettyPrintCursor(ref_cursor.cx_cursor);
|
||||||
#else
|
#else
|
||||||
ref_type->def.detailed_name = ref_cursor.get_spell_name();
|
ref_type->def.detailed_name = ref_cursor.get_spell_name();
|
||||||
@ -1387,11 +1397,11 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
|
|||||||
SetUsePreflight(db, sem_parent);
|
SetUsePreflight(db, sem_parent);
|
||||||
SetUsePreflight(db, lex_parent);
|
SetUsePreflight(db, lex_parent);
|
||||||
ref_type = db->Resolve(ref_type_id);
|
ref_type = db->Resolve(ref_type_id);
|
||||||
ref_type->def.spell = SetUse(db, ref_cursor.get_spell(),
|
ref_type->def.spell =
|
||||||
sem_parent, Role::Definition);
|
SetUse(db, ref_cursor.get_spell(), sem_parent, Role::Definition);
|
||||||
ref_type->def.extent =
|
ref_type->def.extent =
|
||||||
SetUse(db, ref_cursor.get_extent(), lex_parent, Role::None);
|
SetUse(db, ref_cursor.get_extent(), lex_parent, Role::None);
|
||||||
#if 0&&CINDEX_HAVE_PRETTY
|
#if 0 && CINDEX_HAVE_PRETTY
|
||||||
// template<class T> void f(T t){} // weird, the name is empty
|
// template<class T> void f(T t){} // weird, the name is empty
|
||||||
ref_type->def.detailed_name = param->PrettyPrintCursor(ref_cursor.cx_cursor);
|
ref_type->def.detailed_name = param->PrettyPrintCursor(ref_cursor.cx_cursor);
|
||||||
#else
|
#else
|
||||||
@ -1523,8 +1533,8 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
|||||||
IndexType* ns = db->Resolve(ns_id);
|
IndexType* ns = db->Resolve(ns_id);
|
||||||
ns->def.kind = GetSymbolKind(decl->entityInfo->kind);
|
ns->def.kind = GetSymbolKind(decl->entityInfo->kind);
|
||||||
if (ns->def.detailed_name.empty()) {
|
if (ns->def.detailed_name.empty()) {
|
||||||
SetTypeName(ns, cursor, decl->semanticContainer,
|
SetTypeName(ns, cursor, decl->semanticContainer, decl->entityInfo->name,
|
||||||
decl->entityInfo->name, param);
|
param);
|
||||||
ns->def.spell = SetUse(db, spell, sem_parent, Role::Definition);
|
ns->def.spell = SetUse(db, spell, sem_parent, Role::Definition);
|
||||||
ns->def.extent =
|
ns->def.extent =
|
||||||
SetUse(db, cursor.get_extent(), lex_parent, Role::None);
|
SetUse(db, cursor.get_extent(), lex_parent, Role::None);
|
||||||
@ -1592,8 +1602,8 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
|||||||
// the function declaration is encountered since we won't receive ParmDecl
|
// the function declaration is encountered since we won't receive ParmDecl
|
||||||
// declarations for unnamed parameters.
|
// declarations for unnamed parameters.
|
||||||
// TODO: See if we can remove this function call.
|
// TODO: See if we can remove this function call.
|
||||||
AddDeclTypeUsages(db, cursor, var->def.type,
|
AddDeclTypeUsages(db, cursor, var->def.type, decl->semanticContainer,
|
||||||
decl->semanticContainer, decl->lexicalContainer);
|
decl->lexicalContainer);
|
||||||
|
|
||||||
// We don't need to assign declaring type multiple times if this variable
|
// We don't need to assign declaring type multiple times if this variable
|
||||||
// has already been seen.
|
// has already been seen.
|
||||||
@ -1687,10 +1697,9 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
|||||||
// indexing the definition, then there will not be any (ie) outline
|
// indexing the definition, then there will not be any (ie) outline
|
||||||
// information.
|
// information.
|
||||||
if (!is_template_specialization) {
|
if (!is_template_specialization) {
|
||||||
|
// Build detailed name. The type desc looks like void (void *). We
|
||||||
// Build detailed name. The type desc looks like void (void *). We
|
// insert the qualified name before the first '('.
|
||||||
// insert the qualified name before the first '('.
|
// FIXME GetFunctionSignature should set index
|
||||||
// FIXME GetFunctionSignature should set index
|
|
||||||
#if CINDEX_HAVE_PRETTY
|
#if CINDEX_HAVE_PRETTY
|
||||||
func->def.detailed_name = param->PrettyPrintCursor(decl->cursor);
|
func->def.detailed_name = param->PrettyPrintCursor(decl->cursor);
|
||||||
#else
|
#else
|
||||||
@ -1802,7 +1811,8 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UniqueAddUse(db, type->uses, spell, fromContainer(decl->lexicalContainer));
|
UniqueAddUse(db, type->uses, spell,
|
||||||
|
fromContainer(decl->lexicalContainer));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1833,14 +1843,16 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
|||||||
|
|
||||||
if (decl->isDefinition) {
|
if (decl->isDefinition) {
|
||||||
type->def.spell = SetUse(db, spell, sem_parent, Role::Definition);
|
type->def.spell = SetUse(db, spell, sem_parent, Role::Definition);
|
||||||
type->def.extent = SetUse(db, decl_cursor.get_extent(), lex_parent, Role::None);
|
type->def.extent =
|
||||||
|
SetUse(db, decl_cursor.get_extent(), lex_parent, Role::None);
|
||||||
|
|
||||||
if (decl_cursor.get_kind() == CXCursor_EnumDecl) {
|
if (decl_cursor.get_kind() == CXCursor_EnumDecl) {
|
||||||
ClangType enum_type = clang_getEnumDeclIntegerType(decl->cursor);
|
ClangType enum_type = clang_getEnumDeclIntegerType(decl->cursor);
|
||||||
if (!enum_type.is_fundamental()) {
|
if (!enum_type.is_fundamental()) {
|
||||||
IndexType* int_type =
|
IndexType* int_type =
|
||||||
db->Resolve(db->ToTypeId(enum_type.get_usr_hash()));
|
db->Resolve(db->ToTypeId(enum_type.get_usr_hash()));
|
||||||
AddUse(db, int_type->uses, spell, fromContainer(decl->lexicalContainer));
|
AddUse(db, int_type->uses, spell,
|
||||||
|
fromContainer(decl->lexicalContainer));
|
||||||
// type is invalidated.
|
// type is invalidated.
|
||||||
type = db->Resolve(type_id);
|
type = db->Resolve(type_id);
|
||||||
}
|
}
|
||||||
@ -1999,8 +2011,10 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
|
|||||||
ClangCursor lex_parent = referenced.get_lexical_parent();
|
ClangCursor lex_parent = referenced.get_lexical_parent();
|
||||||
SetUsePreflight(db, sem_parent);
|
SetUsePreflight(db, sem_parent);
|
||||||
SetUsePreflight(db, lex_parent);
|
SetUsePreflight(db, lex_parent);
|
||||||
ns->def.spell = SetUse(db, referenced.get_spell(), sem_parent, Role::Definition);
|
ns->def.spell =
|
||||||
ns->def.extent = SetUse(db, referenced.get_extent(), lex_parent, Role::None);
|
SetUse(db, referenced.get_spell(), sem_parent, Role::Definition);
|
||||||
|
ns->def.extent =
|
||||||
|
SetUse(db, referenced.get_extent(), lex_parent, Role::None);
|
||||||
std::string name = referenced.get_spell_name();
|
std::string name = referenced.get_spell_name();
|
||||||
SetTypeName(ns, referenced, nullptr, name.c_str(), param);
|
SetTypeName(ns, referenced, nullptr, name.c_str(), param);
|
||||||
}
|
}
|
||||||
@ -2031,7 +2045,8 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
|
|||||||
Range spell = referenced.get_spell(&referenced_file);
|
Range spell = referenced.get_spell(&referenced_file);
|
||||||
if (file == referenced_file) {
|
if (file == referenced_file) {
|
||||||
var->def.spell = SetUse(db, spell, lex_parent, Role::Definition);
|
var->def.spell = SetUse(db, spell, lex_parent, Role::Definition);
|
||||||
var->def.extent = SetUse(db, referenced.get_extent(), lex_parent, Role::None);
|
var->def.extent =
|
||||||
|
SetUse(db, referenced.get_extent(), lex_parent, Role::None);
|
||||||
|
|
||||||
// TODO Some of the logic here duplicates CXIdxEntity_Variable branch
|
// TODO Some of the logic here duplicates CXIdxEntity_Variable branch
|
||||||
// of OnIndexDeclaration. But there `decl` is of type CXIdxDeclInfo
|
// of OnIndexDeclaration. But there `decl` is of type CXIdxDeclInfo
|
||||||
@ -2041,7 +2056,8 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
|
|||||||
var->def.kind = lsSymbolKind::Parameter;
|
var->def.kind = lsSymbolKind::Parameter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UniqueAddUse(db, var->uses, loc, fromContainer(ref->container), GetRole(ref, Role::Reference));
|
UniqueAddUse(db, var->uses, loc, fromContainer(ref->container),
|
||||||
|
GetRole(ref, Role::Reference));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2152,7 +2168,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
|
|||||||
case CXIdxEntity_ObjCProtocol:
|
case CXIdxEntity_ObjCProtocol:
|
||||||
case CXIdxEntity_ObjCClass:
|
case CXIdxEntity_ObjCClass:
|
||||||
case CXIdxEntity_Typedef:
|
case CXIdxEntity_Typedef:
|
||||||
case CXIdxEntity_CXXInterface: // MSVC __interface
|
case CXIdxEntity_CXXInterface: // MSVC __interface
|
||||||
case CXIdxEntity_CXXTypeAlias:
|
case CXIdxEntity_CXXTypeAlias:
|
||||||
case CXIdxEntity_Enum:
|
case CXIdxEntity_Enum:
|
||||||
case CXIdxEntity_Union:
|
case CXIdxEntity_Union:
|
||||||
@ -2414,7 +2430,8 @@ void Reflect(Writer& visitor, Reference& value) {
|
|||||||
if (visitor.Format() == SerializeFormat::Json) {
|
if (visitor.Format() == SerializeFormat::Json) {
|
||||||
std::string s = value.range.ToString();
|
std::string s = value.range.ToString();
|
||||||
// RawId(-1) -> "-1"
|
// RawId(-1) -> "-1"
|
||||||
s += '|' + std::to_string(static_cast<std::make_signed<RawId>::type>(value.id.id));
|
s += '|' + std::to_string(
|
||||||
|
static_cast<std::make_signed<RawId>::type>(value.id.id));
|
||||||
s += '|' + std::to_string(int(value.kind));
|
s += '|' + std::to_string(int(value.kind));
|
||||||
s += '|' + std::to_string(int(value.role));
|
s += '|' + std::to_string(int(value.role));
|
||||||
Reflect(visitor, s);
|
Reflect(visitor, s);
|
||||||
|
@ -111,19 +111,15 @@ struct Reference {
|
|||||||
std::tuple<Range, Id<void>, SymbolKind, Role> ToTuple() const {
|
std::tuple<Range, Id<void>, SymbolKind, Role> ToTuple() const {
|
||||||
return std::make_tuple(range, id, kind, role);
|
return std::make_tuple(range, id, kind, role);
|
||||||
}
|
}
|
||||||
bool operator==(const Reference& o) const {
|
bool operator==(const Reference& o) const { return ToTuple() == o.ToTuple(); }
|
||||||
return ToTuple() == o.ToTuple();
|
bool operator<(const Reference& o) const { return ToTuple() < o.ToTuple(); }
|
||||||
}
|
|
||||||
bool operator<(const Reference& o) const {
|
|
||||||
return ToTuple() < o.ToTuple();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// |id,kind| refer to the referenced entity.
|
// |id,kind| refer to the referenced entity.
|
||||||
struct SymbolRef : Reference {
|
struct SymbolRef : Reference {
|
||||||
SymbolRef() = default;
|
SymbolRef() = default;
|
||||||
SymbolRef(Range range, Id<void> id, SymbolKind kind, Role role)
|
SymbolRef(Range range, Id<void> id, SymbolKind kind, Role role)
|
||||||
: Reference{range, id, kind, role} {}
|
: Reference{range, id, kind, role} {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Represents an occurrence of a variable/type, |id,kind| refer to the lexical
|
// Represents an occurrence of a variable/type, |id,kind| refer to the lexical
|
||||||
@ -133,7 +129,7 @@ struct Use : Reference {
|
|||||||
Id<QueryFile> file;
|
Id<QueryFile> file;
|
||||||
Use() = default;
|
Use() = default;
|
||||||
Use(Range range, Id<void> id, SymbolKind kind, Role role, Id<QueryFile> file)
|
Use(Range range, Id<void> id, SymbolKind kind, Role role, Id<QueryFile> file)
|
||||||
: Reference{range, id, kind, role}, file(file) {}
|
: Reference{range, id, kind, role}, file(file) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
void Reflect(Reader& visitor, Reference& value);
|
void Reflect(Reader& visitor, Reference& value);
|
||||||
@ -184,8 +180,7 @@ struct TypeDefDefinitionData {
|
|||||||
lsSymbolKind kind = lsSymbolKind::Unknown;
|
lsSymbolKind kind = lsSymbolKind::Unknown;
|
||||||
|
|
||||||
bool operator==(const TypeDefDefinitionData& o) const {
|
bool operator==(const TypeDefDefinitionData& o) const {
|
||||||
return detailed_name == o.detailed_name &&
|
return detailed_name == o.detailed_name && spell == o.spell &&
|
||||||
spell == o.spell &&
|
|
||||||
extent == o.extent && alias_of == o.alias_of &&
|
extent == o.extent && alias_of == o.alias_of &&
|
||||||
parents == o.parents && types == o.types && funcs == o.funcs &&
|
parents == o.parents && types == o.types && funcs == o.funcs &&
|
||||||
vars == o.vars && kind == o.kind && hover == o.hover &&
|
vars == o.vars && kind == o.kind && hover == o.hover &&
|
||||||
@ -273,12 +268,11 @@ struct FuncDefDefinitionData {
|
|||||||
StorageClass storage = StorageClass::Invalid;
|
StorageClass storage = StorageClass::Invalid;
|
||||||
|
|
||||||
bool operator==(const FuncDefDefinitionData& o) const {
|
bool operator==(const FuncDefDefinitionData& o) const {
|
||||||
return detailed_name == o.detailed_name &&
|
return detailed_name == o.detailed_name && spell == o.spell &&
|
||||||
spell == o.spell &&
|
extent == o.extent && declaring_type == o.declaring_type &&
|
||||||
extent == o.extent &&
|
base == o.base && locals == o.locals && callees == o.callees &&
|
||||||
declaring_type == o.declaring_type && base == o.base &&
|
kind == o.kind && storage == o.storage && hover == o.hover &&
|
||||||
locals == o.locals && callees == o.callees && kind == o.kind &&
|
comments == o.comments;
|
||||||
storage == o.storage && hover == o.hover && comments == o.comments;
|
|
||||||
}
|
}
|
||||||
bool operator!=(const FuncDefDefinitionData& o) const {
|
bool operator!=(const FuncDefDefinitionData& o) const {
|
||||||
return !(*this == o);
|
return !(*this == o);
|
||||||
@ -344,9 +338,7 @@ struct IndexFunc {
|
|||||||
bool operator<(const IndexFunc& other) const { return id < other.id; }
|
bool operator<(const IndexFunc& other) const { return id < other.id; }
|
||||||
};
|
};
|
||||||
MAKE_HASHABLE(IndexFunc, t.id);
|
MAKE_HASHABLE(IndexFunc, t.id);
|
||||||
MAKE_REFLECT_STRUCT(IndexFunc::Declaration,
|
MAKE_REFLECT_STRUCT(IndexFunc::Declaration, spell, param_spellings);
|
||||||
spell,
|
|
||||||
param_spellings);
|
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
struct VarDefDefinitionData {
|
struct VarDefDefinitionData {
|
||||||
@ -372,15 +364,12 @@ struct VarDefDefinitionData {
|
|||||||
// (declaration).
|
// (declaration).
|
||||||
StorageClass storage = StorageClass::Invalid;
|
StorageClass storage = StorageClass::Invalid;
|
||||||
|
|
||||||
bool is_local() const {
|
bool is_local() const { return kind == lsSymbolKind::Variable; }
|
||||||
return kind == lsSymbolKind::Variable;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const VarDefDefinitionData& o) const {
|
bool operator==(const VarDefDefinitionData& o) const {
|
||||||
return detailed_name == o.detailed_name && spell == o.spell &&
|
return detailed_name == o.detailed_name && spell == o.spell &&
|
||||||
extent == o.extent && type == o.type &&
|
extent == o.extent && type == o.type && kind == o.kind &&
|
||||||
kind == o.kind && storage == o.storage && hover == o.hover &&
|
storage == o.storage && hover == o.hover && comments == o.comments;
|
||||||
comments == o.comments;
|
|
||||||
}
|
}
|
||||||
bool operator!=(const VarDefDefinitionData& o) const { return !(*this == o); }
|
bool operator!=(const VarDefDefinitionData& o) const { return !(*this == o); }
|
||||||
|
|
||||||
|
@ -318,7 +318,8 @@ TEST_SUITE("Substring") {
|
|||||||
REQUIRE(SubsequenceCountSkip("aa", "baa") == std::make_tuple(true, 1));
|
REQUIRE(SubsequenceCountSkip("aa", "baa") == std::make_tuple(true, 1));
|
||||||
REQUIRE(SubsequenceCountSkip("aA", "aA") == std::make_tuple(true, 0));
|
REQUIRE(SubsequenceCountSkip("aA", "aA") == std::make_tuple(true, 0));
|
||||||
REQUIRE(SubsequenceCountSkip("aA", "aa") == std::make_tuple(false, 1));
|
REQUIRE(SubsequenceCountSkip("aA", "aa") == std::make_tuple(false, 1));
|
||||||
REQUIRE(SubsequenceCountSkip("incstdioh", "include <stdio.h>") == std::make_tuple(true, 7));
|
REQUIRE(SubsequenceCountSkip("incstdioh", "include <stdio.h>") ==
|
||||||
|
std::make_tuple(true, 7));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,10 +15,9 @@ lsPosition CharPos(std::string_view search,
|
|||||||
char character,
|
char character,
|
||||||
int character_offset = 0);
|
int character_offset = 0);
|
||||||
|
|
||||||
struct ParseIncludeLineResult
|
struct ParseIncludeLineResult {
|
||||||
{
|
|
||||||
bool ok;
|
bool ok;
|
||||||
std::string text; // include the "include" part
|
std::string text; // include the "include" part
|
||||||
std::smatch match;
|
std::smatch match;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
23
src/maybe.h
23
src/maybe.h
@ -10,7 +10,7 @@ template <typename T>
|
|||||||
class Maybe {
|
class Maybe {
|
||||||
T storage;
|
T storage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr Maybe() = default;
|
constexpr Maybe() = default;
|
||||||
Maybe(const Maybe&) = default;
|
Maybe(const Maybe&) = default;
|
||||||
Maybe(std::nullopt_t) {}
|
Maybe(std::nullopt_t) {}
|
||||||
@ -23,14 +23,12 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
const T *operator->() const { return &storage; }
|
const T* operator->() const { return &storage; }
|
||||||
T *operator->() { return &storage; }
|
T* operator->() { return &storage; }
|
||||||
const T& operator*() const { return storage; }
|
const T& operator*() const { return storage; }
|
||||||
T& operator*() { return storage; }
|
T& operator*() { return storage; }
|
||||||
|
|
||||||
bool HasValue() const {
|
bool HasValue() const { return storage.HasValueForMaybe_(); }
|
||||||
return storage.HasValueForMaybe_();
|
|
||||||
}
|
|
||||||
explicit operator bool() const { return HasValue(); }
|
explicit operator bool() const { return HasValue(); }
|
||||||
operator optional<T>() const {
|
operator optional<T>() const {
|
||||||
if (HasValue())
|
if (HasValue())
|
||||||
@ -38,16 +36,9 @@ public:
|
|||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator=(optional<T>&& o) {
|
void operator=(optional<T>&& o) { storage = o ? *o : T(); }
|
||||||
storage = o ? *o : T();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Does not test if has_value()
|
// Does not test if has_value()
|
||||||
bool operator==(const Maybe& o) const {
|
bool operator==(const Maybe& o) const { return storage == o.storage; }
|
||||||
return storage == o.storage;
|
bool operator!=(const Maybe& o) const { return !(*this == o); }
|
||||||
}
|
|
||||||
bool operator!=(const Maybe& o) const {
|
|
||||||
return !(*this == o);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -56,8 +56,7 @@ std::vector<Out_CqueryCallTree::CallEntry> BuildInitialCallTree(
|
|||||||
const QueryFunc::Def* def = root_func.AnyDef();
|
const QueryFunc::Def* def = root_func.AnyDef();
|
||||||
if (!def || !def->spell)
|
if (!def || !def->spell)
|
||||||
return {};
|
return {};
|
||||||
optional<lsLocation> def_loc =
|
optional<lsLocation> def_loc = GetLsLocation(db, working_files, *def->spell);
|
||||||
GetLsLocation(db, working_files, *def->spell);
|
|
||||||
if (!def_loc)
|
if (!def_loc)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
@ -82,8 +81,7 @@ std::vector<Out_CqueryCallTree::CallEntry> BuildExpandCallTree(
|
|||||||
|
|
||||||
std::vector<Out_CqueryCallTree::CallEntry> result;
|
std::vector<Out_CqueryCallTree::CallEntry> result;
|
||||||
|
|
||||||
auto handle_caller = [&](Use caller,
|
auto handle_caller = [&](Use caller, Out_CqueryCallTree::CallType call_type) {
|
||||||
Out_CqueryCallTree::CallType call_type) {
|
|
||||||
optional<lsLocation> call_location =
|
optional<lsLocation> call_location =
|
||||||
GetLsLocation(db, working_files, caller);
|
GetLsLocation(db, working_files, caller);
|
||||||
if (!call_location)
|
if (!call_location)
|
||||||
@ -133,8 +131,7 @@ std::vector<Out_CqueryCallTree::CallEntry> BuildExpandCallTree(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Use> base_callers =
|
std::vector<Use> base_callers = GetCallersForAllBaseFunctions(db, root_func);
|
||||||
GetCallersForAllBaseFunctions(db, root_func);
|
|
||||||
std::vector<Use> derived_callers =
|
std::vector<Use> derived_callers =
|
||||||
GetCallersForAllDerivedFunctions(db, root_func);
|
GetCallersForAllDerivedFunctions(db, root_func);
|
||||||
result.reserve(root_func.uses.size() + base_callers.size() +
|
result.reserve(root_func.uses.size() + base_callers.size() +
|
||||||
|
@ -33,8 +33,9 @@ struct CqueryDerivedHandler : BaseMessageHandler<Ipc_CqueryDerived> {
|
|||||||
break;
|
break;
|
||||||
} else if (sym.kind == SymbolKind::Func) {
|
} else if (sym.kind == SymbolKind::Func) {
|
||||||
QueryFunc& func = db->GetFunc(sym);
|
QueryFunc& func = db->GetFunc(sym);
|
||||||
out.result = GetLsLocationExs(db, working_files, ToUses(db, func.derived),
|
out.result =
|
||||||
config->xref.container, config->xref.maxNum);
|
GetLsLocationExs(db, working_files, ToUses(db, func.derived),
|
||||||
|
config->xref.container, config->xref.maxNum);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,10 @@ REGISTER_IPC_MESSAGE(Ipc_CqueryIndexFile);
|
|||||||
struct CqueryIndexFileHandler : BaseMessageHandler<Ipc_CqueryIndexFile> {
|
struct CqueryIndexFileHandler : BaseMessageHandler<Ipc_CqueryIndexFile> {
|
||||||
void Run(Ipc_CqueryIndexFile* request) override {
|
void Run(Ipc_CqueryIndexFile* request) override {
|
||||||
LOG_S(INFO) << "Indexing file " << request->params.path;
|
LOG_S(INFO) << "Indexing file " << request->params.path;
|
||||||
QueueManager::instance()->index_request.PushBack(Index_Request(
|
QueueManager::instance()->index_request.PushBack(
|
||||||
NormalizePath(request->params.path), request->params.args,
|
Index_Request(NormalizePath(request->params.path), request->params.args,
|
||||||
request->params.is_interactive, request->params.contents, ICacheManager::Make(config)));
|
request->params.is_interactive, request->params.contents,
|
||||||
|
ICacheManager::Make(config)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(CqueryIndexFileHandler);
|
REGISTER_MESSAGE_HANDLER(CqueryIndexFileHandler);
|
||||||
|
@ -69,7 +69,7 @@ BuildInheritanceHierarchyForType(QueryDatabase* db,
|
|||||||
base.name = "[[Base]]";
|
base.name = "[[Base]]";
|
||||||
base.location = entry.location;
|
base.location = entry.location;
|
||||||
base.children =
|
base.children =
|
||||||
BuildParentInheritanceHierarchyForType(db, working_files, root_type);
|
BuildParentInheritanceHierarchyForType(db, working_files, root_type);
|
||||||
if (!base.children.empty())
|
if (!base.children.empty())
|
||||||
entry.children.push_back(base);
|
entry.children.push_back(base);
|
||||||
|
|
||||||
@ -128,8 +128,7 @@ BuildInheritanceHierarchyForFunc(QueryDatabase* db,
|
|||||||
// Name and location.
|
// Name and location.
|
||||||
entry.name = def->detailed_name;
|
entry.name = def->detailed_name;
|
||||||
if (def->spell)
|
if (def->spell)
|
||||||
entry.location =
|
entry.location = GetLsLocation(db, working_files, *def->spell);
|
||||||
GetLsLocation(db, working_files, *def->spell);
|
|
||||||
|
|
||||||
entry.children.reserve(root_func.derived.size());
|
entry.children.reserve(root_func.derived.size());
|
||||||
|
|
||||||
|
@ -67,8 +67,7 @@ ExpandNode(QueryDatabase* db, WorkingFiles* working_files, QueryTypeId root) {
|
|||||||
entry.name = def1->ShortName();
|
entry.name = def1->ShortName();
|
||||||
entry.type_id = def1->type ? *def1->type : QueryTypeId();
|
entry.type_id = def1->type ? *def1->type : QueryTypeId();
|
||||||
if (def->spell) {
|
if (def->spell) {
|
||||||
optional<lsLocation> loc =
|
optional<lsLocation> loc = GetLsLocation(db, working_files, *def1->spell);
|
||||||
GetLsLocation(db, working_files, *def1->spell);
|
|
||||||
// TODO invalid location
|
// TODO invalid location
|
||||||
if (loc)
|
if (loc)
|
||||||
entry.location = *loc;
|
entry.location = *loc;
|
||||||
|
@ -19,11 +19,17 @@ const double kDamping = 0.1;
|
|||||||
template <typename Q>
|
template <typename Q>
|
||||||
struct Kind;
|
struct Kind;
|
||||||
template <>
|
template <>
|
||||||
struct Kind<QueryFunc> { static constexpr SymbolKind value = SymbolKind::Func; };
|
struct Kind<QueryFunc> {
|
||||||
|
static constexpr SymbolKind value = SymbolKind::Func;
|
||||||
|
};
|
||||||
template <>
|
template <>
|
||||||
struct Kind<QueryType> { static constexpr SymbolKind value = SymbolKind::Type; };
|
struct Kind<QueryType> {
|
||||||
|
static constexpr SymbolKind value = SymbolKind::Type;
|
||||||
|
};
|
||||||
template <>
|
template <>
|
||||||
struct Kind<QueryVar> { static constexpr SymbolKind value = SymbolKind::Var; };
|
struct Kind<QueryVar> {
|
||||||
|
static constexpr SymbolKind value = SymbolKind::Var;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename Q>
|
template <typename Q>
|
||||||
void Add(const std::unordered_map<SymbolIdx, int>& sym2id,
|
void Add(const std::unordered_map<SymbolIdx, int>& sym2id,
|
||||||
@ -109,7 +115,8 @@ struct CqueryRandomHandler : BaseMessageHandler<Ipc_CqueryRandom> {
|
|||||||
double d = 0;
|
double d = 0;
|
||||||
for (int i = 0; i < n; i++)
|
for (int i = 0; i < n; i++)
|
||||||
d = std::max(d, fabs(x[i] - y[i]));
|
d = std::max(d, fabs(x[i] - y[i]));
|
||||||
if (d < 1e-5) break;
|
if (d < 1e-5)
|
||||||
|
break;
|
||||||
x.swap(y);
|
x.swap(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,8 @@ struct lsCompletionOptions {
|
|||||||
// for
|
// for
|
||||||
// '::' and '>' for '->'. See
|
// '::' and '>' for '->'. See
|
||||||
// https://github.com/Microsoft/language-server-protocol/issues/138.
|
// https://github.com/Microsoft/language-server-protocol/issues/138.
|
||||||
std::vector<std::string> triggerCharacters = {".", ":", ">", "#", "<", "\"", "/"};
|
std::vector<std::string> triggerCharacters = {".", ":", ">", "#",
|
||||||
|
"<", "\"", "/"};
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(lsCompletionOptions, resolveProvider, triggerCharacters);
|
MAKE_REFLECT_STRUCT(lsCompletionOptions, resolveProvider, triggerCharacters);
|
||||||
|
|
||||||
@ -572,11 +573,12 @@ struct InitializeHandler : BaseMessageHandler<Ipc_InitializeRequest> {
|
|||||||
// Set project root.
|
// Set project root.
|
||||||
config->projectRoot = NormalizePath(request->params.rootUri->GetPath());
|
config->projectRoot = NormalizePath(request->params.rootUri->GetPath());
|
||||||
EnsureEndsInSlash(config->projectRoot);
|
EnsureEndsInSlash(config->projectRoot);
|
||||||
// Create two cache directories for files inside and outside of the project.
|
// Create two cache directories for files inside and outside of the
|
||||||
|
// project.
|
||||||
MakeDirectoryRecursive(config->cacheDirectory +
|
MakeDirectoryRecursive(config->cacheDirectory +
|
||||||
EscapeFileName(config->projectRoot));
|
EscapeFileName(config->projectRoot));
|
||||||
MakeDirectoryRecursive(config->cacheDirectory +
|
MakeDirectoryRecursive(config->cacheDirectory + '@' +
|
||||||
'@' + EscapeFileName(config->projectRoot));
|
EscapeFileName(config->projectRoot));
|
||||||
|
|
||||||
Timer time;
|
Timer time;
|
||||||
|
|
||||||
@ -595,7 +597,7 @@ struct InitializeHandler : BaseMessageHandler<Ipc_InitializeRequest> {
|
|||||||
// guess an appropriate value. Default to 80% utilization.
|
// guess an appropriate value. Default to 80% utilization.
|
||||||
const float kDefaultTargetUtilization = 0.8f;
|
const float kDefaultTargetUtilization = 0.8f;
|
||||||
config->index.threads = (int)(std::thread::hardware_concurrency() *
|
config->index.threads = (int)(std::thread::hardware_concurrency() *
|
||||||
kDefaultTargetUtilization);
|
kDefaultTargetUtilization);
|
||||||
if (config->index.threads <= 0)
|
if (config->index.threads <= 0)
|
||||||
config->index.threads = 1;
|
config->index.threads = 1;
|
||||||
}
|
}
|
||||||
@ -614,19 +616,20 @@ struct InitializeHandler : BaseMessageHandler<Ipc_InitializeRequest> {
|
|||||||
|
|
||||||
auto* queue = QueueManager::instance();
|
auto* queue = QueueManager::instance();
|
||||||
time.Reset();
|
time.Reset();
|
||||||
project->ForAllFilteredFiles(config, [&](int i,
|
project->ForAllFilteredFiles(
|
||||||
const Project::Entry& entry) {
|
config, [&](int i, const Project::Entry& entry) {
|
||||||
optional<std::string> content = ReadContent(entry.filename);
|
optional<std::string> content = ReadContent(entry.filename);
|
||||||
if (!content) {
|
if (!content) {
|
||||||
LOG_S(ERROR) << "When loading project, canont read file "
|
LOG_S(ERROR) << "When loading project, canont read file "
|
||||||
<< entry.filename;
|
<< entry.filename;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bool is_interactive =
|
bool is_interactive =
|
||||||
working_files->GetFileByFilename(entry.filename) != nullptr;
|
working_files->GetFileByFilename(entry.filename) != nullptr;
|
||||||
queue->index_request.PushBack(Index_Request(
|
queue->index_request.PushBack(Index_Request(
|
||||||
entry.filename, entry.args, is_interactive, *content, ICacheManager::Make(config), request->id));
|
entry.filename, entry.args, is_interactive, *content,
|
||||||
});
|
ICacheManager::Make(config), request->id));
|
||||||
|
});
|
||||||
|
|
||||||
// We need to support multiple concurrent index processes.
|
// We need to support multiple concurrent index processes.
|
||||||
time.ResetAndPrint("[perf] Dispatched initial index requests");
|
time.ResetAndPrint("[perf] Dispatched initial index requests");
|
||||||
|
@ -211,8 +211,8 @@ optional<lsTextEdit> BuildAutoImplementForFunction(QueryDatabase* db,
|
|||||||
if (func_decl.file == decl_file_id) {
|
if (func_decl.file == decl_file_id) {
|
||||||
int dist = func_decl.range.start.line - decl.range.start.line;
|
int dist = func_decl.range.start.line - decl.range.start.line;
|
||||||
if (abs(dist) < abs(best_dist)) {
|
if (abs(dist) < abs(best_dist)) {
|
||||||
optional<lsLocation> def_loc = GetLsLocation(
|
optional<lsLocation> def_loc =
|
||||||
db, working_files, *def1->extent);
|
GetLsLocation(db, working_files, *def1->extent);
|
||||||
if (!def_loc)
|
if (!def_loc)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -237,8 +237,7 @@ struct TextDocumentCodeLensHandler
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
AddCodeLens("base", "base", &common, OffsetStartColumn(use, 1),
|
AddCodeLens("base", "base", &common, OffsetStartColumn(use, 1),
|
||||||
ToUses(db, def->base),
|
ToUses(db, def->base), false /*force_display*/);
|
||||||
false /*force_display*/);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -122,8 +122,6 @@ void FilterAndSortCompletionResponse(
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
auto& items = complete_response->result.items;
|
auto& items = complete_response->result.items;
|
||||||
|
|
||||||
auto finalize = [&]() {
|
auto finalize = [&]() {
|
||||||
|
@ -24,12 +24,10 @@ struct Out_TextDocumentDefinition
|
|||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(Out_TextDocumentDefinition, jsonrpc, id, result);
|
MAKE_REFLECT_STRUCT(Out_TextDocumentDefinition, jsonrpc, id, result);
|
||||||
|
|
||||||
std::vector<Use> GetGotoDefinitionTargets(QueryDatabase* db,
|
std::vector<Use> GetGotoDefinitionTargets(QueryDatabase* db, SymbolRef sym) {
|
||||||
SymbolRef sym) {
|
|
||||||
switch (sym.kind) {
|
switch (sym.kind) {
|
||||||
case SymbolKind::Var: {
|
case SymbolKind::Var: {
|
||||||
std::vector<Use> ret =
|
std::vector<Use> ret = GetDeclarationsOfSymbolForGotoDefinition(db, sym);
|
||||||
GetDeclarationsOfSymbolForGotoDefinition(db, sym);
|
|
||||||
// If there is no declaration, jump the its type.
|
// If there is no declaration, jump the its type.
|
||||||
if (ret.empty()) {
|
if (ret.empty()) {
|
||||||
for (auto& def : db->GetVar(sym).def)
|
for (auto& def : db->GetVar(sym).def)
|
||||||
@ -158,7 +156,8 @@ struct TextDocumentDefinitionHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (best_i != -1) {
|
if (best_i != -1) {
|
||||||
Maybe<Use> use = GetDefinitionSpellingOfSymbol(db, db->symbols[best_i]);
|
Maybe<Use> use =
|
||||||
|
GetDefinitionSpellingOfSymbol(db, db->symbols[best_i]);
|
||||||
assert(use);
|
assert(use);
|
||||||
if (auto ls_loc = GetLsLocationEx(db, working_files, *use,
|
if (auto ls_loc = GetLsLocationEx(db, working_files, *use,
|
||||||
config->xref.container))
|
config->xref.container))
|
||||||
|
@ -53,7 +53,8 @@ struct WorkspaceDidChangeWatchedFilesHandler
|
|||||||
LOG_S(ERROR) << "Unable to read file content after saving " << path;
|
LOG_S(ERROR) << "Unable to read file content after saving " << path;
|
||||||
else {
|
else {
|
||||||
QueueManager::instance()->index_request.PushBack(
|
QueueManager::instance()->index_request.PushBack(
|
||||||
Index_Request(path, entry.args, is_interactive, *content, ICacheManager::Make(config)));
|
Index_Request(path, entry.args, is_interactive, *content,
|
||||||
|
ICacheManager::Make(config)));
|
||||||
if (is_interactive)
|
if (is_interactive)
|
||||||
clang_complete->NotifySave(path);
|
clang_complete->NotifySave(path);
|
||||||
}
|
}
|
||||||
@ -61,7 +62,8 @@ struct WorkspaceDidChangeWatchedFilesHandler
|
|||||||
}
|
}
|
||||||
case lsFileChangeType::Deleted:
|
case lsFileChangeType::Deleted:
|
||||||
QueueManager::instance()->index_request.PushBack(
|
QueueManager::instance()->index_request.PushBack(
|
||||||
Index_Request(path, entry.args, is_interactive, std::string(), ICacheManager::Make(config)));
|
Index_Request(path, entry.args, is_interactive, std::string(),
|
||||||
|
ICacheManager::Make(config)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,6 @@ MAKE_REFLECT_STRUCT(Out_WorkspaceSymbol, jsonrpc, id, result);
|
|||||||
|
|
||||||
///// Fuzzy matching
|
///// Fuzzy matching
|
||||||
|
|
||||||
|
|
||||||
struct WorkspaceSymbolHandler : BaseMessageHandler<Ipc_WorkspaceSymbol> {
|
struct WorkspaceSymbolHandler : BaseMessageHandler<Ipc_WorkspaceSymbol> {
|
||||||
void Run(Ipc_WorkspaceSymbol* request) override {
|
void Run(Ipc_WorkspaceSymbol* request) override {
|
||||||
Out_WorkspaceSymbol out;
|
Out_WorkspaceSymbol out;
|
||||||
@ -135,7 +134,8 @@ struct WorkspaceSymbolHandler : BaseMessageHandler<Ipc_WorkspaceSymbol> {
|
|||||||
std::vector<std::pair<int, int>> permutation(result_indices.size());
|
std::vector<std::pair<int, int>> permutation(result_indices.size());
|
||||||
for (int i = 0; i < int(result_indices.size()); i++) {
|
for (int i = 0; i < int(result_indices.size()); i++) {
|
||||||
permutation[i] = {
|
permutation[i] = {
|
||||||
FuzzyEvaluate(query, db->GetSymbolDetailedName(result_indices[i]), score, dp),
|
FuzzyEvaluate(query, db->GetSymbolDetailedName(result_indices[i]),
|
||||||
|
score, dp),
|
||||||
i};
|
i};
|
||||||
}
|
}
|
||||||
std::sort(permutation.begin(), permutation.end(),
|
std::sort(permutation.begin(), permutation.end(),
|
||||||
|
@ -37,6 +37,6 @@ class NtString {
|
|||||||
}
|
}
|
||||||
bool operator==(const NtString& o) const {
|
bool operator==(const NtString& o) const {
|
||||||
return str && o.str ? strcmp(c_str(), o.c_str()) == 0
|
return str && o.str ? strcmp(c_str(), o.c_str()) == 0
|
||||||
: c_str() == o.c_str();
|
: c_str() == o.c_str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef __has_builtin
|
#ifndef __has_builtin
|
||||||
# define __has_builtin(x) 0
|
#define __has_builtin(x) 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
void cquery_unreachable_internal(const char* msg, const char* file, int line);
|
void cquery_unreachable_internal(const char* msg, const char* file, int line);
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
#define CQUERY_UNREACHABLE(msg) cquery_unreachable_internal(msg, __FILE__, __LINE__)
|
#define CQUERY_UNREACHABLE(msg) \
|
||||||
|
cquery_unreachable_internal(msg, __FILE__, __LINE__)
|
||||||
#else
|
#else
|
||||||
#define CQUERY_UNREACHABLE(msg)
|
#define CQUERY_UNREACHABLE(msg)
|
||||||
#endif
|
#endif
|
||||||
|
123
src/project.cc
123
src/project.cc
@ -150,18 +150,19 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
|
|||||||
// ie, compiler schedular such as goma. This allows correct parsing for
|
// ie, compiler schedular such as goma. This allows correct parsing for
|
||||||
// command lines like "goma clang -c foo".
|
// command lines like "goma clang -c foo".
|
||||||
std::string::size_type dot;
|
std::string::size_type dot;
|
||||||
while (i < entry.args.size() && entry.args[i][0] != '-' &&
|
while (
|
||||||
// Do not skip over main source filename
|
i < entry.args.size() && entry.args[i][0] != '-' &&
|
||||||
NormalizePathWithTestOptOut(entry.args[i]) != result.filename &&
|
// Do not skip over main source filename
|
||||||
// There may be other filenames (e.g. more than one source filenames)
|
NormalizePathWithTestOptOut(entry.args[i]) != result.filename &&
|
||||||
// preceding main source filename. We use a heuristic here. `.` may
|
// There may be other filenames (e.g. more than one source filenames)
|
||||||
// occur in both command names and source filenames. If `.` occurs in
|
// preceding main source filename. We use a heuristic here. `.` may
|
||||||
// the last 4 bytes of entry.args[i] and not followed by a digit, e.g.
|
// occur in both command names and source filenames. If `.` occurs in
|
||||||
// .c .cpp, We take it as a source filename. Others (like ./a/b/goma
|
// the last 4 bytes of entry.args[i] and not followed by a digit, e.g.
|
||||||
// clang-4.0) are seen as commands.
|
// .c .cpp, We take it as a source filename. Others (like ./a/b/goma
|
||||||
((dot = entry.args[i].rfind('.')) == std::string::npos ||
|
// clang-4.0) are seen as commands.
|
||||||
dot + 4 < entry.args[i].size() || isdigit(entry.args[i][dot + 1]) ||
|
((dot = entry.args[i].rfind('.')) == std::string::npos ||
|
||||||
!entry.args[i].compare(dot + 1, 3, "exe")))
|
dot + 4 < entry.args[i].size() || isdigit(entry.args[i][dot + 1]) ||
|
||||||
|
!entry.args[i].compare(dot + 1, 3, "exe")))
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
// Compiler driver.
|
// Compiler driver.
|
||||||
@ -174,14 +175,14 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
|
|||||||
if (config->mode == ProjectMode::DotCquery &&
|
if (config->mode == ProjectMode::DotCquery &&
|
||||||
!AnyStartsWith(entry.args, "-std=")) {
|
!AnyStartsWith(entry.args, "-std=")) {
|
||||||
switch (SourceFileLanguage(entry.file)) {
|
switch (SourceFileLanguage(entry.file)) {
|
||||||
case LanguageId::C:
|
case LanguageId::C:
|
||||||
result.args.push_back("-std=gnu11");
|
result.args.push_back("-std=gnu11");
|
||||||
break;
|
break;
|
||||||
case LanguageId::Cpp:
|
case LanguageId::Cpp:
|
||||||
result.args.push_back("-std=gnu++14");
|
result.args.push_back("-std=gnu++14");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,17 +307,17 @@ std::vector<Project::Entry> LoadFromDirectoryListing(Config* init_opts,
|
|||||||
std::unordered_map<std::string, std::vector<std::string>> folder_args;
|
std::unordered_map<std::string, std::vector<std::string>> folder_args;
|
||||||
std::vector<std::string> files;
|
std::vector<std::string> files;
|
||||||
|
|
||||||
GetFilesInFolder(
|
GetFilesInFolder(config->project_dir, true /*recursive*/,
|
||||||
config->project_dir, true /*recursive*/, true /*add_folder_to_path*/,
|
true /*add_folder_to_path*/,
|
||||||
[&folder_args, &files](const std::string& path) {
|
[&folder_args, &files](const std::string& path) {
|
||||||
if (SourceFileLanguage(path) != LanguageId::Unknown) {
|
if (SourceFileLanguage(path) != LanguageId::Unknown) {
|
||||||
files.push_back(path);
|
files.push_back(path);
|
||||||
} else if (GetBaseName(path) == ".cquery") {
|
} else if (GetBaseName(path) == ".cquery") {
|
||||||
LOG_S(INFO) << "Using .cquery arguments from " << path;
|
LOG_S(INFO) << "Using .cquery arguments from " << path;
|
||||||
folder_args.emplace(GetDirName(path),
|
folder_args.emplace(GetDirName(path),
|
||||||
ReadCompilerArgumentsFromFile(path));
|
ReadCompilerArgumentsFromFile(path));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const auto& project_dir_args = folder_args[config->project_dir];
|
const auto& project_dir_args = folder_args[config->project_dir];
|
||||||
LOG_IF_S(INFO, !project_dir_args.empty())
|
LOG_IF_S(INFO, !project_dir_args.empty())
|
||||||
@ -407,7 +408,7 @@ std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
|
|||||||
comp_db_dir.c_str(), &cx_db_load_error);
|
comp_db_dir.c_str(), &cx_db_load_error);
|
||||||
if (!init_opts->compilationDatabaseCommand.empty()) {
|
if (!init_opts->compilationDatabaseCommand.empty()) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// TODO
|
// TODO
|
||||||
#else
|
#else
|
||||||
unlink((comp_db_dir + "/compile_commands.json").c_str());
|
unlink((comp_db_dir + "/compile_commands.json").c_str());
|
||||||
rmdir(comp_db_dir.c_str());
|
rmdir(comp_db_dir.c_str());
|
||||||
@ -656,16 +657,16 @@ TEST_SUITE("Project") {
|
|||||||
CheckFlags(
|
CheckFlags(
|
||||||
/* raw */ {"clang", "-lstdc++", "myfile.cc"},
|
/* raw */ {"clang", "-lstdc++", "myfile.cc"},
|
||||||
/* expected */
|
/* expected */
|
||||||
{"clang", "-working-directory", "/dir/",
|
{"clang", "-working-directory", "/dir/", "-lstdc++", "&/dir/myfile.cc",
|
||||||
"-lstdc++", "&/dir/myfile.cc", "-resource-dir=/w/resource_dir/",
|
"-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option",
|
||||||
"-Wno-unknown-warning-option", "-fparse-all-comments"});
|
"-fparse-all-comments"});
|
||||||
|
|
||||||
CheckFlags(
|
CheckFlags(
|
||||||
/* raw */ {"clang.exe"},
|
/* raw */ {"clang.exe"},
|
||||||
/* expected */
|
/* expected */
|
||||||
{"clang.exe", "-working-directory", "/dir/",
|
{"clang.exe", "-working-directory", "/dir/",
|
||||||
"-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option",
|
"-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option",
|
||||||
"-fparse-all-comments"});
|
"-fparse-all-comments"});
|
||||||
|
|
||||||
CheckFlags(
|
CheckFlags(
|
||||||
/* raw */ {"goma", "clang"},
|
/* raw */ {"goma", "clang"},
|
||||||
@ -683,40 +684,36 @@ TEST_SUITE("Project") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Windows path normalization") {
|
TEST_CASE("Windows path normalization") {
|
||||||
CheckFlags(
|
CheckFlags("E:/workdir", "E:/workdir/bar.cc", /* raw */ {"clang", "bar.cc"},
|
||||||
"E:/workdir", "E:/workdir/bar.cc", /* raw */ {"clang", "bar.cc"},
|
/* expected */
|
||||||
/* expected */
|
{"clang", "-working-directory", "E:/workdir",
|
||||||
{"clang", "-working-directory", "E:/workdir",
|
"&E:/workdir/bar.cc", "-resource-dir=/w/resource_dir/",
|
||||||
"&E:/workdir/bar.cc", "-resource-dir=/w/resource_dir/",
|
"-Wno-unknown-warning-option", "-fparse-all-comments"});
|
||||||
"-Wno-unknown-warning-option", "-fparse-all-comments"});
|
|
||||||
|
|
||||||
CheckFlags(
|
CheckFlags("E:/workdir", "E:/workdir/bar.cc",
|
||||||
"E:/workdir", "E:/workdir/bar.cc",
|
/* raw */ {"clang", "E:/workdir/bar.cc"},
|
||||||
/* raw */ {"clang", "E:/workdir/bar.cc"},
|
/* expected */
|
||||||
/* expected */
|
{"clang", "-working-directory", "E:/workdir",
|
||||||
{"clang", "-working-directory", "E:/workdir",
|
"&E:/workdir/bar.cc", "-resource-dir=/w/resource_dir/",
|
||||||
"&E:/workdir/bar.cc", "-resource-dir=/w/resource_dir/",
|
"-Wno-unknown-warning-option", "-fparse-all-comments"});
|
||||||
"-Wno-unknown-warning-option", "-fparse-all-comments"});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Path in args") {
|
TEST_CASE("Path in args") {
|
||||||
CheckFlags(
|
CheckFlags("/home/user", "/home/user/foo/bar.c",
|
||||||
"/home/user", "/home/user/foo/bar.c",
|
/* raw */ {"cc", "-O0", "foo/bar.c"},
|
||||||
/* raw */ {"cc", "-O0", "foo/bar.c"},
|
/* expected */
|
||||||
/* expected */
|
{"cc", "-working-directory", "/home/user", "-O0",
|
||||||
{"cc", "-working-directory", "/home/user", "-O0",
|
"&/home/user/foo/bar.c", "-resource-dir=/w/resource_dir/",
|
||||||
"&/home/user/foo/bar.c", "-resource-dir=/w/resource_dir/",
|
"-Wno-unknown-warning-option", "-fparse-all-comments"});
|
||||||
"-Wno-unknown-warning-option", "-fparse-all-comments"});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Implied binary") {
|
TEST_CASE("Implied binary") {
|
||||||
CheckFlags(
|
CheckFlags("/home/user", "/home/user/foo/bar.cc",
|
||||||
"/home/user", "/home/user/foo/bar.cc",
|
/* raw */ {"clang", "-DDONT_IGNORE_ME"},
|
||||||
/* raw */ {"clang", "-DDONT_IGNORE_ME"},
|
/* expected */
|
||||||
/* expected */
|
{"clang", "-working-directory", "/home/user", "-DDONT_IGNORE_ME",
|
||||||
{"clang", "-working-directory", "/home/user",
|
"-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option",
|
||||||
"-DDONT_IGNORE_ME", "-resource-dir=/w/resource_dir/",
|
"-fparse-all-comments"});
|
||||||
"-Wno-unknown-warning-option", "-fparse-all-comments"});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks flag parsing for a random chromium file in comparison to what
|
// Checks flag parsing for a random chromium file in comparison to what
|
||||||
|
79
src/query.cc
79
src/query.cc
@ -106,9 +106,8 @@ optional<QueryVar::Def> ToQuery(const IdMap& id_map, const IndexVar::Def& var) {
|
|||||||
// the destination type already exists, it will be combined. This makes merging
|
// the destination type already exists, it will be combined. This makes merging
|
||||||
// updates take longer but reduces import time on the querydb thread.
|
// updates take longer but reduces import time on the querydb thread.
|
||||||
template <typename TId, typename TValue>
|
template <typename TId, typename TValue>
|
||||||
void AddMergeableRange(
|
void AddMergeableRange(std::vector<MergeableUpdate<TId, TValue>>* dest,
|
||||||
std::vector<MergeableUpdate<TId, TValue>>* dest,
|
std::vector<MergeableUpdate<TId, TValue>>&& source) {
|
||||||
std::vector<MergeableUpdate<TId, TValue>>&& source) {
|
|
||||||
// TODO: Consider caching the lookup table. It can probably save even more
|
// TODO: Consider caching the lookup table. It can probably save even more
|
||||||
// time at the cost of some additional memory.
|
// time at the cost of some additional memory.
|
||||||
|
|
||||||
@ -208,7 +207,8 @@ void CompareGroups(std::vector<T>& previous_data,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryFile::DefUpdate BuildFileDefUpdate(const IdMap& id_map, const IndexFile& indexed) {
|
QueryFile::DefUpdate BuildFileDefUpdate(const IdMap& id_map,
|
||||||
|
const IndexFile& indexed) {
|
||||||
QueryFile::Def def;
|
QueryFile::Def def;
|
||||||
def.file = id_map.primary_file;
|
def.file = id_map.primary_file;
|
||||||
def.path = indexed.path;
|
def.path = indexed.path;
|
||||||
@ -234,8 +234,7 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IdMap& id_map, const IndexFile& in
|
|||||||
}();
|
}();
|
||||||
|
|
||||||
auto add_all_symbols = [&](Use use, Id<void> id, SymbolKind kind) {
|
auto add_all_symbols = [&](Use use, Id<void> id, SymbolKind kind) {
|
||||||
def.all_symbols.push_back(
|
def.all_symbols.push_back(SymbolRef(use.range, id, kind, use.role));
|
||||||
SymbolRef(use.range, id, kind, use.role));
|
|
||||||
};
|
};
|
||||||
auto add_outline = [&](Use use, Id<void> id, SymbolKind kind) {
|
auto add_outline = [&](Use use, Id<void> id, SymbolKind kind) {
|
||||||
def.outline.push_back(SymbolRef(use.range, id, kind, use.role));
|
def.outline.push_back(SymbolRef(use.range, id, kind, use.role));
|
||||||
@ -440,20 +439,20 @@ QueryVarId IdMap::ToQuery(IndexVarId id) const {
|
|||||||
Use IdMap::ToQuery(Reference ref) const {
|
Use IdMap::ToQuery(Reference ref) const {
|
||||||
Use ret(ref.range, ref.id, ref.kind, ref.role, primary_file);
|
Use ret(ref.range, ref.id, ref.kind, ref.role, primary_file);
|
||||||
switch (ref.kind) {
|
switch (ref.kind) {
|
||||||
case SymbolKind::Invalid:
|
case SymbolKind::Invalid:
|
||||||
break;
|
break;
|
||||||
case SymbolKind::File:
|
case SymbolKind::File:
|
||||||
ret.id = primary_file;
|
ret.id = primary_file;
|
||||||
break;
|
break;
|
||||||
case SymbolKind::Func:
|
case SymbolKind::Func:
|
||||||
ret.id = ToQuery(IndexFuncId(ref.id));
|
ret.id = ToQuery(IndexFuncId(ref.id));
|
||||||
break;
|
break;
|
||||||
case SymbolKind::Type:
|
case SymbolKind::Type:
|
||||||
ret.id = ToQuery(IndexTypeId(ref.id));
|
ret.id = ToQuery(IndexTypeId(ref.id));
|
||||||
break;
|
break;
|
||||||
case SymbolKind::Var:
|
case SymbolKind::Var:
|
||||||
ret.id = ToQuery(IndexVarId(ref.id));
|
ret.id = ToQuery(IndexVarId(ref.id));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -532,9 +531,9 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
|
|||||||
previous_id_map.ToQuery(type->id), {},
|
previous_id_map.ToQuery(type->id), {},
|
||||||
previous_id_map.ToQuery(type->declarations)));
|
previous_id_map.ToQuery(type->declarations)));
|
||||||
if (!type->derived.empty())
|
if (!type->derived.empty())
|
||||||
types_derived.push_back(QueryType::DerivedUpdate(
|
types_derived.push_back(
|
||||||
previous_id_map.ToQuery(type->id), {},
|
QueryType::DerivedUpdate(previous_id_map.ToQuery(type->id), {},
|
||||||
previous_id_map.ToQuery(type->derived)));
|
previous_id_map.ToQuery(type->derived)));
|
||||||
if (!type->instances.empty())
|
if (!type->instances.empty())
|
||||||
types_instances.push_back(QueryType::InstancesUpdate(
|
types_instances.push_back(QueryType::InstancesUpdate(
|
||||||
previous_id_map.ToQuery(type->id), {},
|
previous_id_map.ToQuery(type->id), {},
|
||||||
@ -601,13 +600,13 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
|
|||||||
previous_id_map.ToQuery(func->id), {},
|
previous_id_map.ToQuery(func->id), {},
|
||||||
previous_id_map.ToQuery(func->declarations)));
|
previous_id_map.ToQuery(func->declarations)));
|
||||||
if (!func->derived.empty())
|
if (!func->derived.empty())
|
||||||
funcs_derived.push_back(QueryFunc::DerivedUpdate(
|
funcs_derived.push_back(
|
||||||
previous_id_map.ToQuery(func->id), {},
|
QueryFunc::DerivedUpdate(previous_id_map.ToQuery(func->id), {},
|
||||||
previous_id_map.ToQuery(func->derived)));
|
previous_id_map.ToQuery(func->derived)));
|
||||||
if (!func->uses.empty())
|
if (!func->uses.empty())
|
||||||
funcs_uses.push_back(QueryFunc::UsesUpdate(
|
funcs_uses.push_back(
|
||||||
previous_id_map.ToQuery(func->id), {},
|
QueryFunc::UsesUpdate(previous_id_map.ToQuery(func->id), {},
|
||||||
previous_id_map.ToQuery(func->uses)));
|
previous_id_map.ToQuery(func->uses)));
|
||||||
},
|
},
|
||||||
/*onAdded:*/
|
/*onAdded:*/
|
||||||
[this, ¤t_id_map](IndexFunc* func) {
|
[this, ¤t_id_map](IndexFunc* func) {
|
||||||
@ -643,8 +642,7 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
|
|||||||
current->usr, std::move(*current_remapped_def)));
|
current->usr, std::move(*current_remapped_def)));
|
||||||
}
|
}
|
||||||
|
|
||||||
PROCESS_UPDATE_DIFF(QueryFuncId, funcs_declarations, declarations,
|
PROCESS_UPDATE_DIFF(QueryFuncId, funcs_declarations, declarations, Use);
|
||||||
Use);
|
|
||||||
PROCESS_UPDATE_DIFF(QueryFuncId, funcs_derived, derived, QueryFuncId);
|
PROCESS_UPDATE_DIFF(QueryFuncId, funcs_derived, derived, QueryFuncId);
|
||||||
PROCESS_UPDATE_DIFF(QueryFuncId, funcs_uses, uses, Use);
|
PROCESS_UPDATE_DIFF(QueryFuncId, funcs_uses, uses, Use);
|
||||||
});
|
});
|
||||||
@ -663,7 +661,7 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
|
|||||||
if (!var->uses.empty())
|
if (!var->uses.empty())
|
||||||
vars_uses.push_back(
|
vars_uses.push_back(
|
||||||
QueryVar::UsesUpdate(previous_id_map.ToQuery(var->id), {},
|
QueryVar::UsesUpdate(previous_id_map.ToQuery(var->id), {},
|
||||||
previous_id_map.ToQuery(var->uses)));
|
previous_id_map.ToQuery(var->uses)));
|
||||||
},
|
},
|
||||||
/*onAdded:*/
|
/*onAdded:*/
|
||||||
[this, ¤t_id_map](IndexVar* var) {
|
[this, ¤t_id_map](IndexVar* var) {
|
||||||
@ -703,7 +701,8 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
|
|||||||
// This function runs on an indexer thread.
|
// This function runs on an indexer thread.
|
||||||
void IndexUpdate::Merge(IndexUpdate&& update) {
|
void IndexUpdate::Merge(IndexUpdate&& update) {
|
||||||
#define INDEX_UPDATE_APPEND(name) AddRange(&name, std::move(update.name));
|
#define INDEX_UPDATE_APPEND(name) AddRange(&name, std::move(update.name));
|
||||||
#define INDEX_UPDATE_MERGE(name) AddMergeableRange(&name, std::move(update.name));
|
#define INDEX_UPDATE_MERGE(name) \
|
||||||
|
AddMergeableRange(&name, std::move(update.name));
|
||||||
|
|
||||||
INDEX_UPDATE_APPEND(files_removed);
|
INDEX_UPDATE_APPEND(files_removed);
|
||||||
INDEX_UPDATE_APPEND(files_def_update);
|
INDEX_UPDATE_APPEND(files_def_update);
|
||||||
@ -987,7 +986,6 @@ std::string_view QueryDatabase::GetSymbolShortName(RawId symbol_idx) const {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_SUITE("query") {
|
TEST_SUITE("query") {
|
||||||
IndexUpdate GetDelta(IndexFile previous, IndexFile current) {
|
IndexUpdate GetDelta(IndexFile previous, IndexFile current) {
|
||||||
QueryDatabase db;
|
QueryDatabase db;
|
||||||
@ -1051,11 +1049,9 @@ TEST_SUITE("query") {
|
|||||||
REQUIRE(update.funcs_uses.size() == 1);
|
REQUIRE(update.funcs_uses.size() == 1);
|
||||||
REQUIRE(update.funcs_uses[0].id == QueryFuncId(0));
|
REQUIRE(update.funcs_uses[0].id == QueryFuncId(0));
|
||||||
REQUIRE(update.funcs_uses[0].to_remove.size() == 1);
|
REQUIRE(update.funcs_uses[0].to_remove.size() == 1);
|
||||||
REQUIRE(update.funcs_uses[0].to_remove[0].range ==
|
REQUIRE(update.funcs_uses[0].to_remove[0].range == Range(Position(1, 0)));
|
||||||
Range(Position(1, 0)));
|
|
||||||
REQUIRE(update.funcs_uses[0].to_add.size() == 1);
|
REQUIRE(update.funcs_uses[0].to_add.size() == 1);
|
||||||
REQUIRE(update.funcs_uses[0].to_add[0].range ==
|
REQUIRE(update.funcs_uses[0].to_add[0].range == Range(Position(2, 0)));
|
||||||
Range(Position(2, 0)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("type usages") {
|
TEST_CASE("type usages") {
|
||||||
@ -1113,7 +1109,8 @@ TEST_SUITE("query") {
|
|||||||
|
|
||||||
TEST_CASE("Remove variable with usage") {
|
TEST_CASE("Remove variable with usage") {
|
||||||
auto load_index_from_json = [](const char* json) {
|
auto load_index_from_json = [](const char* json) {
|
||||||
return Deserialize(SerializeFormat::Json, "foo.cc", json, "<empty>", nullopt);
|
return Deserialize(SerializeFormat::Json, "foo.cc", json, "<empty>",
|
||||||
|
nullopt);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto previous = load_index_from_json(R"RAW(
|
auto previous = load_index_from_json(R"RAW(
|
||||||
@ -1220,8 +1217,8 @@ TEST_SUITE("query") {
|
|||||||
// Apply initial file.
|
// Apply initial file.
|
||||||
{
|
{
|
||||||
IdMap previous_map(&db, previous->id_cache);
|
IdMap previous_map(&db, previous->id_cache);
|
||||||
IndexUpdate import_update =
|
IndexUpdate import_update = IndexUpdate::CreateDelta(
|
||||||
IndexUpdate::CreateDelta(nullptr, &previous_map, nullptr, previous.get());
|
nullptr, &previous_map, nullptr, previous.get());
|
||||||
db.ApplyIndexUpdate(&import_update);
|
db.ApplyIndexUpdate(&import_update);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
31
src/query.h
31
src/query.h
@ -76,7 +76,8 @@ struct WithFileContent {
|
|||||||
T value;
|
T value;
|
||||||
std::string file_content;
|
std::string file_content;
|
||||||
|
|
||||||
WithFileContent(const T& value, const std::string& file_content) : value(value), file_content(file_content) {}
|
WithFileContent(const T& value, const std::string& file_content)
|
||||||
|
: value(value), file_content(file_content) {}
|
||||||
};
|
};
|
||||||
template <typename TVisitor, typename T>
|
template <typename TVisitor, typename T>
|
||||||
void Reflect(TVisitor& visitor, WithFileContent<T>& value) {
|
void Reflect(TVisitor& visitor, WithFileContent<T>& value) {
|
||||||
@ -144,9 +145,7 @@ struct QueryEntity {
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
const Def* AnyDef() const {
|
const Def* AnyDef() const { return const_cast<QueryEntity*>(this)->AnyDef(); }
|
||||||
return const_cast<QueryEntity*>(this)->AnyDef();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QueryType : QueryEntity<QueryType, TypeDefDefinitionData<QueryFamily>> {
|
struct QueryType : QueryEntity<QueryType, TypeDefDefinitionData<QueryFamily>> {
|
||||||
@ -296,14 +295,17 @@ struct QueryDatabase {
|
|||||||
|
|
||||||
// Marks the given Usrs as invalid.
|
// Marks the given Usrs as invalid.
|
||||||
void RemoveUsrs(SymbolKind usr_kind, const std::vector<Usr>& to_remove);
|
void RemoveUsrs(SymbolKind usr_kind, const std::vector<Usr>& to_remove);
|
||||||
void RemoveUsrs(SymbolKind usr_kind, const std::vector<WithUsr<QueryFileId>>& to_remove);
|
void RemoveUsrs(SymbolKind usr_kind,
|
||||||
|
const std::vector<WithUsr<QueryFileId>>& to_remove);
|
||||||
// Insert the contents of |update| into |db|.
|
// Insert the contents of |update| into |db|.
|
||||||
void ApplyIndexUpdate(IndexUpdate* update);
|
void ApplyIndexUpdate(IndexUpdate* update);
|
||||||
void ImportOrUpdate(const std::vector<QueryFile::DefUpdate>& updates);
|
void ImportOrUpdate(const std::vector<QueryFile::DefUpdate>& updates);
|
||||||
void ImportOrUpdate(std::vector<QueryType::DefUpdate>&& updates);
|
void ImportOrUpdate(std::vector<QueryType::DefUpdate>&& updates);
|
||||||
void ImportOrUpdate(std::vector<QueryFunc::DefUpdate>&& updates);
|
void ImportOrUpdate(std::vector<QueryFunc::DefUpdate>&& updates);
|
||||||
void ImportOrUpdate(std::vector<QueryVar::DefUpdate>&& updates);
|
void ImportOrUpdate(std::vector<QueryVar::DefUpdate>&& updates);
|
||||||
void UpdateSymbols(Maybe<Id<void>>* symbol_idx, SymbolKind kind, Id<void> idx);
|
void UpdateSymbols(Maybe<Id<void>>* symbol_idx,
|
||||||
|
SymbolKind kind,
|
||||||
|
Id<void> idx);
|
||||||
std::string_view GetSymbolDetailedName(RawId symbol_idx) const;
|
std::string_view GetSymbolDetailedName(RawId symbol_idx) const;
|
||||||
std::string_view GetSymbolShortName(RawId symbol_idx) const;
|
std::string_view GetSymbolShortName(RawId symbol_idx) const;
|
||||||
|
|
||||||
@ -313,18 +315,10 @@ struct QueryDatabase {
|
|||||||
Maybe<QueryFuncId> GetQueryFuncIdFromUsr(Usr usr);
|
Maybe<QueryFuncId> GetQueryFuncIdFromUsr(Usr usr);
|
||||||
Maybe<QueryVarId> GetQueryVarIdFromUsr(Usr usr);
|
Maybe<QueryVarId> GetQueryVarIdFromUsr(Usr usr);
|
||||||
|
|
||||||
QueryFile& GetFile(SymbolIdx ref) {
|
QueryFile& GetFile(SymbolIdx ref) { return files[ref.id.id]; }
|
||||||
return files[ref.id.id];
|
QueryFunc& GetFunc(SymbolIdx ref) { return funcs[ref.id.id]; }
|
||||||
}
|
QueryType& GetType(SymbolIdx ref) { return types[ref.id.id]; }
|
||||||
QueryFunc& GetFunc(SymbolIdx ref) {
|
QueryVar& GetVar(SymbolIdx ref) { return vars[ref.id.id]; }
|
||||||
return funcs[ref.id.id];
|
|
||||||
}
|
|
||||||
QueryType& GetType(SymbolIdx ref) {
|
|
||||||
return types[ref.id.id];
|
|
||||||
}
|
|
||||||
QueryVar& GetVar(SymbolIdx ref) {
|
|
||||||
return vars[ref.id.id];
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename I>
|
template <typename I>
|
||||||
@ -377,7 +371,6 @@ struct IdMap {
|
|||||||
}
|
}
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
spp::sparse_hash_map<IndexTypeId, QueryTypeId> cached_type_ids_;
|
spp::sparse_hash_map<IndexTypeId, QueryTypeId> cached_type_ids_;
|
||||||
spp::sparse_hash_map<IndexFuncId, QueryFuncId> cached_func_ids_;
|
spp::sparse_hash_map<IndexFuncId, QueryFuncId> cached_func_ids_;
|
||||||
|
@ -40,8 +40,7 @@ std::vector<Use> ToUsesHelper(std::vector<Q>& entities,
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Maybe<Use> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
|
Maybe<Use> GetDefinitionSpellingOfSymbol(QueryDatabase* db, SymbolIdx sym) {
|
||||||
SymbolIdx sym) {
|
|
||||||
Maybe<Use> ret;
|
Maybe<Use> ret;
|
||||||
EachEntityDef(db, sym, [&](const auto& def) { return !(ret = def.spell); });
|
EachEntityDef(db, sym, [&](const auto& def) { return !(ret = def.spell); });
|
||||||
return ret;
|
return ret;
|
||||||
@ -102,9 +101,8 @@ std::vector<Use> ToUses(QueryDatabase* db, const std::vector<QueryVarId>& ids) {
|
|||||||
return ToUsesHelper(db->vars, ids);
|
return ToUsesHelper(db->vars, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Use> GetDeclarationsOfSymbolForGotoDefinition(
|
std::vector<Use> GetDeclarationsOfSymbolForGotoDefinition(QueryDatabase* db,
|
||||||
QueryDatabase* db,
|
SymbolIdx sym) {
|
||||||
SymbolIdx sym) {
|
|
||||||
switch (sym.kind) {
|
switch (sym.kind) {
|
||||||
case SymbolKind::Func:
|
case SymbolKind::Func:
|
||||||
return db->GetFunc(sym).declarations;
|
return db->GetFunc(sym).declarations;
|
||||||
|
@ -5,22 +5,17 @@
|
|||||||
|
|
||||||
#include <optional.h>
|
#include <optional.h>
|
||||||
|
|
||||||
Maybe<Use> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
|
Maybe<Use> GetDefinitionSpellingOfSymbol(QueryDatabase* db, SymbolIdx sym);
|
||||||
SymbolIdx sym);
|
|
||||||
Maybe<Use> GetDefinitionExtentOfSymbol(QueryDatabase* db, SymbolIdx sym);
|
Maybe<Use> GetDefinitionExtentOfSymbol(QueryDatabase* db, SymbolIdx sym);
|
||||||
Maybe<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
|
Maybe<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
|
||||||
SymbolIdx sym);
|
SymbolIdx sym);
|
||||||
|
|
||||||
std::vector<Use> ToUses(QueryDatabase* db,
|
std::vector<Use> ToUses(QueryDatabase* db, const std::vector<QueryFuncId>& ids);
|
||||||
const std::vector<QueryFuncId>& ids);
|
std::vector<Use> ToUses(QueryDatabase* db, const std::vector<QueryTypeId>& ids);
|
||||||
std::vector<Use> ToUses(QueryDatabase* db,
|
std::vector<Use> ToUses(QueryDatabase* db, const std::vector<QueryVarId>& ids);
|
||||||
const std::vector<QueryTypeId>& ids);
|
|
||||||
std::vector<Use> ToUses(QueryDatabase* db,
|
|
||||||
const std::vector<QueryVarId>& ids);
|
|
||||||
|
|
||||||
std::vector<Use> GetDeclarationsOfSymbolForGotoDefinition(
|
std::vector<Use> GetDeclarationsOfSymbolForGotoDefinition(QueryDatabase* db,
|
||||||
QueryDatabase* db,
|
SymbolIdx sym);
|
||||||
SymbolIdx sym);
|
|
||||||
|
|
||||||
bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root);
|
bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root);
|
||||||
std::vector<Use> GetCallersForAllBaseFunctions(QueryDatabase* db,
|
std::vector<Use> GetCallersForAllBaseFunctions(QueryDatabase* db,
|
||||||
@ -104,7 +99,9 @@ void EachUse(QueryDatabase* db, SymbolIdx sym, bool include_decl, Fn&& fn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Q, typename Fn>
|
template <typename Q, typename Fn>
|
||||||
void EachDefinedEntity(std::vector<Q>& collection, const std::vector<Id<Q>>& ids, Fn&& fn) {
|
void EachDefinedEntity(std::vector<Q>& collection,
|
||||||
|
const std::vector<Id<Q>>& ids,
|
||||||
|
Fn&& fn) {
|
||||||
for (Id<Q> x : ids) {
|
for (Id<Q> x : ids) {
|
||||||
Q& obj = collection[x.id];
|
Q& obj = collection[x.id];
|
||||||
if (!obj.def.empty())
|
if (!obj.def.empty())
|
||||||
|
@ -6,12 +6,13 @@
|
|||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
Index_Request::Index_Request(const std::string& path,
|
Index_Request::Index_Request(
|
||||||
const std::vector<std::string>& args,
|
const std::string& path,
|
||||||
bool is_interactive,
|
const std::vector<std::string>& args,
|
||||||
const std::string& contents,
|
bool is_interactive,
|
||||||
const std::shared_ptr<ICacheManager>& cache_manager,
|
const std::string& contents,
|
||||||
lsRequestId id)
|
const std::shared_ptr<ICacheManager>& cache_manager,
|
||||||
|
lsRequestId id)
|
||||||
: path(path),
|
: path(path),
|
||||||
args(args),
|
args(args),
|
||||||
is_interactive(is_interactive),
|
is_interactive(is_interactive),
|
||||||
@ -19,11 +20,12 @@ Index_Request::Index_Request(const std::string& path,
|
|||||||
cache_manager(cache_manager),
|
cache_manager(cache_manager),
|
||||||
id(id) {}
|
id(id) {}
|
||||||
|
|
||||||
Index_DoIdMap::Index_DoIdMap(std::unique_ptr<IndexFile> current,
|
Index_DoIdMap::Index_DoIdMap(
|
||||||
const std::shared_ptr<ICacheManager>& cache_manager,
|
std::unique_ptr<IndexFile> current,
|
||||||
PerformanceImportFile perf,
|
const std::shared_ptr<ICacheManager>& cache_manager,
|
||||||
bool is_interactive,
|
PerformanceImportFile perf,
|
||||||
bool write_to_disk)
|
bool is_interactive,
|
||||||
|
bool write_to_disk)
|
||||||
: current(std::move(current)),
|
: current(std::move(current)),
|
||||||
cache_manager(cache_manager),
|
cache_manager(cache_manager),
|
||||||
perf(perf),
|
perf(perf),
|
||||||
@ -36,10 +38,11 @@ Index_OnIdMapped::File::File(std::unique_ptr<IndexFile> file,
|
|||||||
std::unique_ptr<IdMap> ids)
|
std::unique_ptr<IdMap> ids)
|
||||||
: file(std::move(file)), ids(std::move(ids)) {}
|
: file(std::move(file)), ids(std::move(ids)) {}
|
||||||
|
|
||||||
Index_OnIdMapped::Index_OnIdMapped(const std::shared_ptr<ICacheManager>& cache_manager,
|
Index_OnIdMapped::Index_OnIdMapped(
|
||||||
PerformanceImportFile perf,
|
const std::shared_ptr<ICacheManager>& cache_manager,
|
||||||
bool is_interactive,
|
PerformanceImportFile perf,
|
||||||
bool write_to_disk)
|
bool is_interactive,
|
||||||
|
bool write_to_disk)
|
||||||
: cache_manager(cache_manager),
|
: cache_manager(cache_manager),
|
||||||
perf(perf),
|
perf(perf),
|
||||||
is_interactive(is_interactive),
|
is_interactive(is_interactive),
|
||||||
@ -47,7 +50,7 @@ Index_OnIdMapped::Index_OnIdMapped(const std::shared_ptr<ICacheManager>& cache_m
|
|||||||
|
|
||||||
Index_OnIndexed::Index_OnIndexed(IndexUpdate&& update,
|
Index_OnIndexed::Index_OnIndexed(IndexUpdate&& update,
|
||||||
PerformanceImportFile perf)
|
PerformanceImportFile perf)
|
||||||
: update(std::move(update)), perf(perf) {}
|
: update(std::move(update)), perf(perf) {}
|
||||||
|
|
||||||
QueueManager* QueueManager::instance_ = nullptr;
|
QueueManager* QueueManager::instance_ = nullptr;
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@ struct Index_Request {
|
|||||||
std::shared_ptr<ICacheManager> cache_manager;
|
std::shared_ptr<ICacheManager> cache_manager;
|
||||||
lsRequestId id;
|
lsRequestId id;
|
||||||
|
|
||||||
|
|
||||||
Index_Request(const std::string& path,
|
Index_Request(const std::string& path,
|
||||||
const std::vector<std::string>& args,
|
const std::vector<std::string>& args,
|
||||||
bool is_interactive,
|
bool is_interactive,
|
||||||
|
@ -18,10 +18,10 @@ void EnableRecording(std::string path) {
|
|||||||
assert(!g_file_in && !g_file_out);
|
assert(!g_file_in && !g_file_out);
|
||||||
|
|
||||||
// Open the files.
|
// Open the files.
|
||||||
g_file_in = new std::ofstream(path + ".in",
|
g_file_in = new std::ofstream(
|
||||||
std::ios::out | std::ios::trunc | std::ios::binary);
|
path + ".in", std::ios::out | std::ios::trunc | std::ios::binary);
|
||||||
g_file_out = new std::ofstream(path + ".out",
|
g_file_out = new std::ofstream(
|
||||||
std::ios::out | std::ios::trunc | std::ios::binary);
|
path + ".out", std::ios::out | std::ios::trunc | std::ios::binary);
|
||||||
|
|
||||||
// Make sure we can write to the files.
|
// Make sure we can write to the files.
|
||||||
bool bad = false;
|
bool bad = false;
|
||||||
|
@ -357,11 +357,12 @@ std::string Serialize(SerializeFormat format, IndexFile& file) {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<IndexFile> Deserialize(SerializeFormat format,
|
std::unique_ptr<IndexFile> Deserialize(
|
||||||
const std::string& path,
|
SerializeFormat format,
|
||||||
const std::string& serialized_index_content,
|
const std::string& path,
|
||||||
const std::string& file_content,
|
const std::string& serialized_index_content,
|
||||||
optional<int> expected_version) {
|
const std::string& file_content,
|
||||||
|
optional<int> expected_version) {
|
||||||
if (serialized_index_content.empty())
|
if (serialized_index_content.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@ -401,7 +402,8 @@ std::unique_ptr<IndexFile> Deserialize(SerializeFormat format,
|
|||||||
throw std::invalid_argument("Invalid");
|
throw std::invalid_argument("Invalid");
|
||||||
msgpack::unpacker upk;
|
msgpack::unpacker upk;
|
||||||
upk.reserve_buffer(serialized_index_content.size());
|
upk.reserve_buffer(serialized_index_content.size());
|
||||||
memcpy(upk.buffer(), serialized_index_content.data(), serialized_index_content.size());
|
memcpy(upk.buffer(), serialized_index_content.data(),
|
||||||
|
serialized_index_content.size());
|
||||||
upk.buffer_consumed(serialized_index_content.size());
|
upk.buffer_consumed(serialized_index_content.size());
|
||||||
file = MakeUnique<IndexFile>(path, file_content);
|
file = MakeUnique<IndexFile>(path, file_content);
|
||||||
MessagePackReader reader(&upk);
|
MessagePackReader reader(&upk);
|
||||||
|
@ -358,10 +358,11 @@ void ReflectMember(Writer& visitor, const char* name, T& value) {
|
|||||||
// API
|
// API
|
||||||
|
|
||||||
std::string Serialize(SerializeFormat format, IndexFile& file);
|
std::string Serialize(SerializeFormat format, IndexFile& file);
|
||||||
std::unique_ptr<IndexFile> Deserialize(SerializeFormat format,
|
std::unique_ptr<IndexFile> Deserialize(
|
||||||
const std::string& path,
|
SerializeFormat format,
|
||||||
const std::string& serialized_index_content,
|
const std::string& path,
|
||||||
const std::string& file_content,
|
const std::string& serialized_index_content,
|
||||||
optional<int> expected_version);
|
const std::string& file_content,
|
||||||
|
optional<int> expected_version);
|
||||||
|
|
||||||
void SetTestOutputMode();
|
void SetTestOutputMode();
|
||||||
|
@ -109,8 +109,8 @@ enum class lsSymbolKind : uint8_t {
|
|||||||
TypeParameter = 26,
|
TypeParameter = 26,
|
||||||
|
|
||||||
// cquery extensions
|
// cquery extensions
|
||||||
// See also https://github.com/Microsoft/language-server-protocol/issues/344 for new SymbolKind
|
// See also https://github.com/Microsoft/language-server-protocol/issues/344
|
||||||
// clang/Index/IndexSymbol.h clang::index::SymbolKind
|
// for new SymbolKind clang/Index/IndexSymbol.h clang::index::SymbolKind
|
||||||
Parameter = 13,
|
Parameter = 13,
|
||||||
StaticMethod = 254,
|
StaticMethod = 254,
|
||||||
Macro = 255,
|
Macro = 255,
|
||||||
|
@ -167,10 +167,10 @@ bool RunIndexTests(const std::string& filter_path, bool enable_update) {
|
|||||||
true /*add_folder_to_path*/)) {
|
true /*add_folder_to_path*/)) {
|
||||||
bool is_fail_allowed = false;
|
bool is_fail_allowed = false;
|
||||||
|
|
||||||
if (EndsWithAny(path, { ".m", ".mm" })) {
|
if (EndsWithAny(path, {".m", ".mm"})) {
|
||||||
if (!RunObjectiveCIndexTests()) {
|
if (!RunObjectiveCIndexTests()) {
|
||||||
std::cout << "Skipping \"" << path << "\" since this platform does not "
|
std::cout << "Skipping \"" << path << "\" since this platform does not "
|
||||||
<< "support running Objective-C tests." << std::endl;
|
<< "support running Objective-C tests." << std::endl;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,9 +209,7 @@ struct ThreadedQueue : public BaseThreadQueue {
|
|||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<T> TryPopFront() {
|
optional<T> TryPopFront() { return TryPopFrontHelper(3); }
|
||||||
return TryPopFrontHelper(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
optional<T> TryPopBack() {
|
optional<T> TryPopBack() {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
@ -229,13 +227,9 @@ struct ThreadedQueue : public BaseThreadQueue {
|
|||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<T> TryPopFrontLow() {
|
optional<T> TryPopFrontLow() { return TryPopFrontHelper(1); }
|
||||||
return TryPopFrontHelper(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
optional<T> TryPopFrontHigh() {
|
optional<T> TryPopFrontHigh() { return TryPopFrontHelper(2); }
|
||||||
return TryPopFrontHelper(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
mutable std::mutex mutex_;
|
mutable std::mutex mutex_;
|
||||||
|
|
||||||
|
@ -123,8 +123,10 @@ std::string GetDirName(std::string path) {
|
|||||||
if (path.size() && path.back() == '/')
|
if (path.size() && path.back() == '/')
|
||||||
path.pop_back();
|
path.pop_back();
|
||||||
size_t last_slash = path.find_last_of('/');
|
size_t last_slash = path.find_last_of('/');
|
||||||
if (last_slash == std::string::npos) return ".";
|
if (last_slash == std::string::npos)
|
||||||
if (last_slash == 0) return "/";
|
return ".";
|
||||||
|
if (last_slash == 0)
|
||||||
|
return "/";
|
||||||
return path.substr(0, last_slash);
|
return path.substr(0, last_slash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -33,7 +33,8 @@ bool EndsWithAny(const std::string& value,
|
|||||||
const std::vector<std::string>& endings);
|
const std::vector<std::string>& endings);
|
||||||
bool FindAnyPartial(const std::string& value,
|
bool FindAnyPartial(const std::string& value,
|
||||||
const std::vector<std::string>& values);
|
const std::vector<std::string>& values);
|
||||||
// Returns the dirname of |path|, i.e. "foo/bar.cc" => "foo", "foo" => ".", "/foo" => "/".
|
// Returns the dirname of |path|, i.e. "foo/bar.cc" => "foo", "foo" => ".",
|
||||||
|
// "/foo" => "/".
|
||||||
std::string GetDirName(std::string path);
|
std::string GetDirName(std::string path);
|
||||||
// Returns the basename of |path|, ie, "foo/bar.cc" => "bar.cc".
|
// Returns the basename of |path|, ie, "foo/bar.cc" => "bar.cc".
|
||||||
std::string GetBaseName(const std::string& path);
|
std::string GetBaseName(const std::string& path);
|
||||||
|
Loading…
Reference in New Issue
Block a user