diff --git a/src/config.h b/src/config.h index b3bcde8c..fc0d0166 100644 --- a/src/config.h +++ b/src/config.h @@ -134,7 +134,7 @@ struct Config { // auto-completion. An example value is { ".h", ".hpp" } // // This is significantly faster than using a regex. - std::vector includeSuffixWhitelist = {".h", ".hpp", ".hh"}; + std::vector includeSuffixWhitelist = {".h", ".hpp", ".hh", ".inc"}; std::vector includeWhitelist; } completion; diff --git a/src/message_handler.cc b/src/message_handler.cc index 7a2b2bb2..f5ebd8d3 100644 --- a/src/message_handler.cc +++ b/src/message_handler.cc @@ -4,6 +4,7 @@ #include "message_handler.h" #include "log.hh" +#include "match.h" #include "pipeline.hh" #include "project.h" #include "query_utils.h" @@ -47,74 +48,34 @@ struct ScanLineEvent { }; } // namespace -SemanticHighlightSymbolCache::Entry::Entry( - SemanticHighlightSymbolCache *all_caches, const std::string &path) - : all_caches_(all_caches), path(path) {} - -std::optional SemanticHighlightSymbolCache::Entry::TryGetStableId( - SymbolKind kind, const std::string &detailed_name) { - TNameToId *map = GetMapForSymbol_(kind); - auto it = map->find(detailed_name); - if (it != map->end()) - return it->second; - - return std::nullopt; -} - -int SemanticHighlightSymbolCache::Entry::GetStableId( - SymbolKind kind, const std::string &detailed_name) { - std::optional id = TryGetStableId(kind, detailed_name); - if (id) - return *id; - - // Create a new id. First try to find a key in another map. - all_caches_->cache_.IterateValues([&](const std::shared_ptr &entry) { - std::optional other_id = entry->TryGetStableId(kind, detailed_name); - if (other_id) { - id = other_id; - return false; - } - return true; - }); - - // Create a new id. - TNameToId *map = GetMapForSymbol_(kind); - if (!id) - id = all_caches_->next_stable_id_++; - return (*map)[detailed_name] = *id; -} - -SemanticHighlightSymbolCache::Entry::TNameToId * -SemanticHighlightSymbolCache::Entry::GetMapForSymbol_(SymbolKind kind) { +int SemanticHighlight::GetStableId(SymbolKind kind, Usr usr) { + decltype(func2id) *map; switch (kind) { - case SymbolKind::Type: - return &detailed_type_name_to_stable_id; case SymbolKind::Func: - return &detailed_func_name_to_stable_id; + map = &func2id; + break; + case SymbolKind::Type: + map = &type2id; + break; case SymbolKind::Var: - return &detailed_var_name_to_stable_id; + map = &var2id; + break; case SymbolKind::File: case SymbolKind::Invalid: - break; + llvm_unreachable(""); } - assert(false); - return nullptr; + + auto it = map->try_emplace(usr, next_id); + if (it.second) + next_id++; + return it.first->second; } -SemanticHighlightSymbolCache::SemanticHighlightSymbolCache() - : cache_(kCacheSize) {} - -void SemanticHighlightSymbolCache::Init() { +void SemanticHighlight::Init() { match_ = std::make_unique(g_config->highlight.whitelist, g_config->highlight.blacklist); } -std::shared_ptr -SemanticHighlightSymbolCache::GetCacheForFile(const std::string &path) { - return cache_.Get( - path, [&, this]() { return std::make_shared(this, path); }); -} - MessageHandler::MessageHandler() { // Dynamically allocate |message_handlers|, otherwise there will be static // initialization order races. @@ -184,15 +145,12 @@ void EmitSkippedRanges(WorkingFile *working_file, pipeline::WriteStdout(kMethodType_CclsPublishSkippedRanges, out); } -void EmitSemanticHighlighting(DB *db, - SemanticHighlightSymbolCache *semantic_cache, +void EmitSemanticHighlighting(DB *db, SemanticHighlight *highlight, WorkingFile *wfile, QueryFile *file) { assert(file->def); if (wfile->buffer_content.size() > g_config->largeFileSize || - !semantic_cache->match_->IsMatch(file->def->path)) + !highlight->match_->IsMatch(file->def->path)) return; - auto semantic_cache_for_file = - semantic_cache->GetCacheForFile(file->def->path); // Group symbols together. std::unordered_map @@ -288,8 +246,7 @@ void EmitSemanticHighlighting(DB *db, it->second.lsRanges.push_back(*loc); } else { Out_CclsPublishSemanticHighlighting::Symbol symbol; - symbol.stableId = semantic_cache_for_file->GetStableId( - sym.kind, std::string(detailed_name)); + symbol.stableId = highlight->GetStableId(sym.kind, sym.usr); symbol.parentKind = parent_kind; symbol.kind = kind; symbol.storage = storage; diff --git a/src/message_handler.h b/src/message_handler.h index b015635f..801761c2 100644 --- a/src/message_handler.h +++ b/src/message_handler.h @@ -5,7 +5,6 @@ #include "lru_cache.h" #include "lsp.h" -#include "match.h" #include "method.h" #include "query.h" @@ -17,6 +16,7 @@ struct CompletionManager; struct Config; class DiagnosticsPublisher; +struct GroupMatch; struct VFS; struct IncludeComplete; struct MultiQueueWaiter; @@ -27,35 +27,13 @@ struct WorkingFiles; // Caches symbols for a single file for semantic highlighting to provide // relatively stable ids. Only supports xxx files at a time. -struct SemanticHighlightSymbolCache { - struct Entry { - SemanticHighlightSymbolCache *all_caches_ = nullptr; - - // The path this cache belongs to. - std::string path; - // Detailed symbol name to stable id. - using TNameToId = std::unordered_map; - TNameToId detailed_type_name_to_stable_id; - TNameToId detailed_func_name_to_stable_id; - TNameToId detailed_var_name_to_stable_id; - - Entry(SemanticHighlightSymbolCache *all_caches, const std::string &path); - - std::optional TryGetStableId(SymbolKind kind, - const std::string &detailed_name); - int GetStableId(SymbolKind kind, const std::string &detailed_name); - - TNameToId *GetMapForSymbol_(SymbolKind kind); - }; - - constexpr static int kCacheSize = 10; - LruCache cache_; - uint32_t next_stable_id_ = 0; +struct SemanticHighlight { + llvm::DenseMap func2id, type2id, var2id; + uint32_t next_id = 0; std::unique_ptr match_; - SemanticHighlightSymbolCache(); void Init(); - std::shared_ptr GetCacheForFile(const std::string &path); + int GetStableId(SymbolKind kind, Usr usr); }; struct Out_CclsPublishSemanticHighlighting @@ -102,7 +80,7 @@ struct MessageHandler { Project *project = nullptr; DiagnosticsPublisher *diag_pub = nullptr; VFS *vfs = nullptr; - SemanticHighlightSymbolCache *semantic_cache = nullptr; + SemanticHighlight *highlight = nullptr; WorkingFiles *working_files = nullptr; CompletionManager *clang_complete = nullptr; IncludeComplete *include_complete = nullptr; @@ -132,6 +110,5 @@ bool FindFileOrFail(DB *db, Project *project, std::optional id, void EmitSkippedRanges(WorkingFile *working_file, const std::vector &skipped_ranges); -void EmitSemanticHighlighting(DB *db, - SemanticHighlightSymbolCache *semantic_cache, +void EmitSemanticHighlighting(DB *db, SemanticHighlight *highlight, WorkingFile *working_file, QueryFile *file); diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index 284d47f3..23c4bf24 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -476,7 +476,7 @@ struct Handler_Initialize : BaseMessageHandler { diag_pub->Init(); idx::Init(); - semantic_cache->Init(); + highlight->Init(); // Open up / load the project. project->Load(project_path); diff --git a/src/messages/textDocument_didOpen.cc b/src/messages/textDocument_didOpen.cc index 6bbb9114..7721b21e 100644 --- a/src/messages/textDocument_didOpen.cc +++ b/src/messages/textDocument_didOpen.cc @@ -48,7 +48,7 @@ struct Handler_TextDocumentDidOpen FindFileOrFail(db, project, std::nullopt, path, &file); if (file && file->def) { EmitSkippedRanges(working_file, file->def->skipped_ranges); - EmitSemanticHighlighting(db, semantic_cache, working_file, file); + EmitSemanticHighlighting(db, highlight, working_file, file); } include_complete->AddFile(working_file->filename); diff --git a/src/pipeline.cc b/src/pipeline.cc index 5bc8bc32..bfc6368e 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -8,6 +8,7 @@ #include "include_complete.h" #include "log.hh" #include "lsp.h" +#include "match.h" #include "message_handler.h" #include "pipeline.hh" #include "platform.h" @@ -358,7 +359,7 @@ void Indexer_Main(CompletionManager *completion, VFS *vfs, Project *project, indexer_waiter->Wait(index_request); } -void Main_OnIndexed(DB *db, SemanticHighlightSymbolCache *semantic_cache, +void Main_OnIndexed(DB *db, SemanticHighlight *highlight, WorkingFiles *working_files, IndexUpdate *update) { if (update->refresh) { LOG_S(INFO) @@ -369,7 +370,7 @@ void Main_OnIndexed(DB *db, SemanticHighlightSymbolCache *semantic_cache, if (db->name2file_id.find(filename) == db->name2file_id.end()) continue; QueryFile *file = &db->files[db->name2file_id[filename]]; - EmitSemanticHighlighting(db, semantic_cache, f.get(), file); + EmitSemanticHighlighting(db, highlight, f.get(), file); } return; } @@ -389,7 +390,7 @@ void Main_OnIndexed(DB *db, SemanticHighlightSymbolCache *semantic_cache, wfile->SetIndexContent(g_config->index.onChange ? wfile->buffer_content : def_u.second); EmitSkippedRanges(wfile, def_u.first.skipped_ranges); - EmitSemanticHighlighting(db, semantic_cache, wfile, + EmitSemanticHighlighting(db, highlight, wfile, &db->files[update->file_id]); } } @@ -460,7 +461,7 @@ void LaunchStdout() { void MainLoop() { Project project; - SemanticHighlightSymbolCache semantic_cache; + SemanticHighlight highlight; WorkingFiles working_files; VFS vfs; DiagnosticsPublisher diag_pub; @@ -491,7 +492,7 @@ void MainLoop() { handler->project = &project; handler->diag_pub = &diag_pub; handler->vfs = &vfs; - handler->semantic_cache = &semantic_cache; + handler->highlight = &highlight; handler->working_files = &working_files; handler->clang_complete = &clang_complete; handler->include_complete = &include_complete; @@ -518,7 +519,7 @@ void MainLoop() { if (!update) break; did_work = true; - Main_OnIndexed(&db, &semantic_cache, &working_files, &*update); + Main_OnIndexed(&db, &highlight, &working_files, &*update); } if (!did_work) { diff --git a/src/test.cc b/src/test.cc index f54b00aa..d1d82715 100644 --- a/src/test.cc +++ b/src/test.cc @@ -11,6 +11,8 @@ #include "utils.h" #include +#include +using namespace llvm; #include #include @@ -68,6 +70,12 @@ struct TextReplacer { } }; +void TrimInPlace(std::string &s) { + auto f = [](char c) { return !isspace(c); }; + s.erase(s.begin(), std::find_if(s.begin(), s.end(), f)); + s.erase(std::find_if(s.rbegin(), s.rend(), f).base(), s.end()); +} + void ParseTestExpectation( const std::string &filename, const std::vector &lines_with_endings, TextReplacer *replacer, @@ -77,7 +85,7 @@ void ParseTestExpectation( { bool in_output = false; for (std::string line : lines_with_endings) { - TrimInPlace(line); + line = StringRef(line).trim().str(); if (StartsWith(line, "EXTRA_FLAGS:")) { assert(!in_output && "multiple EXTRA_FLAGS sections"); @@ -113,8 +121,7 @@ void ParseTestExpectation( // one token assume it is a filename. std::vector tokens = SplitString(line_with_ending, " "); if (tokens.size() > 1) { - active_output_filename = tokens[1]; - TrimInPlace(active_output_filename); + active_output_filename = StringRef(tokens[1]).trim().str(); } else { active_output_filename = filename; } diff --git a/src/utils.cc b/src/utils.cc index 981e783f..9dfd7bec 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -21,16 +21,6 @@ using namespace llvm; #include #include -void TrimInPlace(std::string &s) { - auto f = [](char c) { return !isspace(c); }; - s.erase(s.begin(), std::find_if(s.begin(), s.end(), f)); - s.erase(std::find_if(s.rbegin(), s.rend(), f).base(), s.end()); -} -std::string Trim(std::string s) { - TrimInPlace(s); - return s; -} - uint64_t HashUsr(std::string_view s) { union { uint64_t ret; diff --git a/src/utils.h b/src/utils.h index 93f5cafe..61c50dfd 100644 --- a/src/utils.h +++ b/src/utils.h @@ -16,9 +16,6 @@ namespace llvm { class StringRef; } -void TrimInPlace(std::string &s); -std::string Trim(std::string s); - uint64_t HashUsr(std::string_view s); uint64_t HashUsr(llvm::StringRef s);