From d7a183c796aded02af2ef43e3a8f850a92094d17 Mon Sep 17 00:00:00 2001 From: Jacob Dufault Date: Fri, 22 Dec 2017 07:29:13 -0800 Subject: [PATCH] Try to keep semantic highlighting colors stable across open files. --- src/lru_cache.h | 14 ++++++ src/semantic_highlight_symbol_cache.cc | 64 +++++++++++++++++++------- src/semantic_highlight_symbol_cache.h | 12 ++++- 3 files changed, 72 insertions(+), 18 deletions(-) diff --git a/src/lru_cache.h b/src/lru_cache.h index 88ffaaf4..5f9e525d 100644 --- a/src/lru_cache.h +++ b/src/lru_cache.h @@ -24,6 +24,11 @@ struct LruCache { // Inserts an entry. Evicts the oldest unused entry if there is no space. void Insert(const TKey& key, const std::shared_ptr& value); + // Call |func| on existing entries. If |func| returns false iteration + // temrinates early. + template + void IterateValues(TFunc func); + private: // There is a global score counter, when we access an element we increase // its score to the current global value, so it has the highest overall @@ -113,6 +118,15 @@ void LruCache::Insert(const TKey& key, entries_.push_back(entry); } +template +template +void LruCache::IterateValues(TFunc func) { + for (Entry& entry : entries_) { + if (!func(entry.value)) + break; + } +} + template void LruCache::IncrementScore() { next_score_ += 1; diff --git a/src/semantic_highlight_symbol_cache.cc b/src/semantic_highlight_symbol_cache.cc index cb60f7ef..60536f34 100644 --- a/src/semantic_highlight_symbol_cache.cc +++ b/src/semantic_highlight_symbol_cache.cc @@ -1,31 +1,60 @@ #include "semantic_highlight_symbol_cache.h" -SemanticHighlightSymbolCache::Entry::Entry(const std::string& path) - : path(path) {} +SemanticHighlightSymbolCache::Entry::Entry( + SemanticHighlightSymbolCache* all_caches, + const std::string& path) + : all_caches_(all_caches), path(path) {} + +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 nullopt; +} int SemanticHighlightSymbolCache::Entry::GetStableId( SymbolKind kind, const std::string& detailed_name) { - TNameToId* map = nullptr; + 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) { + 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) { switch (kind) { case SymbolKind::Type: - map = &detailed_type_name_to_stable_id; - break; + return &detailed_type_name_to_stable_id; case SymbolKind::Func: - map = &detailed_func_name_to_stable_id; - break; + return &detailed_func_name_to_stable_id; case SymbolKind::Var: - map = &detailed_var_name_to_stable_id; + return &detailed_var_name_to_stable_id; + case SymbolKind::File: + case SymbolKind::Invalid: break; - default: - assert(false); - return 0; } - assert(map); - auto it = map->find(detailed_name); - if (it != map->end()) - return it->second; - return (*map)[detailed_name] = map->size(); + assert(false); + return nullptr; } SemanticHighlightSymbolCache::SemanticHighlightSymbolCache() @@ -33,5 +62,6 @@ SemanticHighlightSymbolCache::SemanticHighlightSymbolCache() std::shared_ptr SemanticHighlightSymbolCache::GetCacheForFile(const std::string& path) { - return cache_.Get(path, [&]() { return std::make_shared(path); }); + return cache_.Get( + path, [&, this]() { return std::make_shared(this, path); }); } diff --git a/src/semantic_highlight_symbol_cache.h b/src/semantic_highlight_symbol_cache.h index 987f7fc3..e18ba5f6 100644 --- a/src/semantic_highlight_symbol_cache.h +++ b/src/semantic_highlight_symbol_cache.h @@ -6,10 +6,15 @@ #include #include +using std::experimental::nullopt; +using std::experimental::optional; + // 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. @@ -18,13 +23,18 @@ struct SemanticHighlightSymbolCache { TNameToId detailed_func_name_to_stable_id; TNameToId detailed_var_name_to_stable_id; - explicit Entry(const std::string& path); + Entry(SemanticHighlightSymbolCache* all_caches, const std::string& path); + 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; SemanticHighlightSymbolCache();