From 5de24b671c9051c42eff5f4ab2bc5263712fd2a3 Mon Sep 17 00:00:00 2001 From: Mirek Fidler Date: Mon, 5 Dec 2022 10:00:45 +0100 Subject: [PATCH] ide: Usage of virtual functions improved --- uppsrc/ide/Usage.cpp | 66 ++++++++++++++++++++++++++---------- uppsrc/ide/clang/Indexer.cpp | 17 +++++----- uppsrc/ide/clang/clang.h | 2 +- uppsrc/ide/idebar.cpp | 7 +++- 4 files changed, 64 insertions(+), 28 deletions(-) diff --git a/uppsrc/ide/Usage.cpp b/uppsrc/ide/Usage.cpp index 6c762c055..507fe6087 100644 --- a/uppsrc/ide/Usage.cpp +++ b/uppsrc/ide/Usage.cpp @@ -68,32 +68,45 @@ String ScopeWorkaround(const char *s) return r; } -void GatherVirtuals(const String& cls, const String& signature, Index& ids, Index& visited) -{ // find all virtual methods with the same signature +void GatherBaseVirtuals(const String& cls, const String& signature, Index& ids, Index& visited) +{ // find all ancestor classes that contain signature if(IsNull(cls) || visited.Find(cls) >= 0) return; visited.Add(cls); - for(const auto& f : ~CodeIndex()) // find base and derived classes + for(const auto& f : ~CodeIndex()) // check base classes for(const AnnotationItem& m : f.value.items) - if(IsStruct(m.kind)) { - if(m.id == cls) // Find base classes - // we cheat with With.. by splitting it to With... and TopWindow - for(String bcls : Split(m.bases, [](int c) { return iscid(c) || c == ':' ? 0 : 1; })) - GatherVirtuals(bcls, signature, ids, visited); - } + if(IsStruct(m.kind) && m.id == cls) + // we cheat with With.. by splitting it to With... and TopWindow as + // two bases + for(String bcls : Split(m.bases, [](int c) { return iscid(c) || c == ':' ? 0 : 1; })) + GatherBaseVirtuals(bcls, signature, ids, visited); - for(const auto& f : ~CodeIndex()) // now gather virtual methods of this class + for(const auto& f : ~CodeIndex()) // now check virtual methods of this cls + for(const AnnotationItem& m : f.value.items) { + if(m.nest == cls && IsFunction(m.kind) && m.isvirtual && ScopeWorkaround(m.id.Mid(m.nest.GetCount())) == signature) { + ids.FindAdd(cls); // found virtual method in the class + return; + } + } +} + +void GatherVirtuals(const VectorMap& bases, const String& cls, + const String& signature, Index& ids, Index& visited) +{ // find all virtual methods with the same signature + if(IsNull(cls) || visited.Find(cls) >= 0) + return; + + visited.Add(cls); + + for(int q = bases.Find(cls); q >= 0; q = bases.FindNext(q)) { + GatherVirtuals(bases, bases[q], signature, ids, visited); + } + + for(const auto& f : ~CodeIndex()) // now check virtual methods of this cls for(const AnnotationItem& m : f.value.items) { if(m.nest == cls && IsFunction(m.kind) && m.isvirtual && ScopeWorkaround(m.id.Mid(m.nest.GetCount())) == signature) { ids.FindAdd(m.id); // found virtual method in the class - for(const auto& f : ~CodeIndex()) // check derived classes for overrides - for(const AnnotationItem& m : f.value.items) - if(IsStruct(m.kind) && visited.Find(m.id) < 0) { - for(String bcls : Split(m.bases, [](int c) { return iscid(c) || c == ':' ? 0 : 1; })) - if(bcls == cls) // Find derived classes - GatherVirtuals(m.id, signature, ids, visited); - } return; } } @@ -148,7 +161,24 @@ void Ide::Usage(const String& id, const String& name, Point ref_pos) if(isvirtual) { Index visited; - GatherVirtuals(cls, ScopeWorkaround(id.Mid(cls.GetCount())), ids, visited); + String signature = ScopeWorkaround(id.Mid(cls.GetCount())); + Index base_id; + GatherBaseVirtuals(cls, signature, base_id, visited); + + + VectorMap bases; + for(const auto& f : ~CodeIndex()) // check derived classes + for(const AnnotationItem& m : f.value.items) + if(IsStruct(m.kind)) + for(String bcls : Split(m.bases, [](int c) { return iscid(c) || c == ':' ? 0 : 1; })) + bases.Add(bcls, m.id); + + + + visited.Clear(); + for(const String& cls : base_id) + GatherVirtuals(bases, cls, signature, ids, visited); + } SortByKey(CodeIndex()); diff --git a/uppsrc/ide/clang/Indexer.cpp b/uppsrc/ide/clang/Indexer.cpp index 61c5aec8e..684ba4d55 100644 --- a/uppsrc/ide/clang/Indexer.cpp +++ b/uppsrc/ide/clang/Indexer.cpp @@ -100,19 +100,20 @@ ArrayMap& CodeIndex() return m; } -void DumpIndex(const char *file) +void DumpIndex(const char *file, const String& what_file) { GuiLock __; FileOut out(file); out << GetSysTime() << "\n"; ArrayMap& x = CodeIndex(); - for(const auto& m : ~x) { - out << m.key << "\n"; - for(const auto& n : m.value.items) - out << '\t' << n.pos.y << ": " << n.id << " -> " << n.pretty << ", bases: " << n.bases << "\n"; - for(const auto& n : m.value.refs) - out << '\t' << n.pos << " " << n.id << " -> " << n.ref_pos << "\n"; - } + for(const auto& m : ~x) + if(IsNull(what_file) || m.key == what_file) { + out << m.key << "\n"; + for(const auto& n : m.value.items) + out << '\t' << n.pos.y << ": " << n.id << " -> " << n.pretty << ", bases: " << n.bases << "\n"; + for(const auto& n : m.value.refs) + out << '\t' << n.pos << " " << n.id << " -> " << n.ref_pos << "\n"; + } } CoEvent Indexer::event; diff --git a/uppsrc/ide/clang/clang.h b/uppsrc/ide/clang/clang.h index b6c21a510..6b48f5c8d 100644 --- a/uppsrc/ide/clang/clang.h +++ b/uppsrc/ide/clang/clang.h @@ -311,6 +311,6 @@ public: static double Progress(); }; -void DumpIndex(const char *file); +void DumpIndex(const char *file, const String& what = Null); #endif diff --git a/uppsrc/ide/idebar.cpp b/uppsrc/ide/idebar.cpp index 30ac3cee8..08ba2c50c 100644 --- a/uppsrc/ide/idebar.cpp +++ b/uppsrc/ide/idebar.cpp @@ -816,11 +816,16 @@ void Ide::BrowseMenu(Bar& menu) if(AssistDiagnostics) { menu.Separator(); - menu.Add("Dump and show current index", [=] { + menu.Add("Dump and show whole current index", [=] { String path = CacheFile("index_" + AsString(Random()) + AsString(Random())); DumpIndex(path); EditFile(path); }); + menu.Add("Dump and show current file index", [=] { + String path = CacheFile("index_" + AsString(Random()) + AsString(Random())); + DumpIndex(path, editfile); + EditFile(path); + }); menu.Add("Current file parse errors", [=] { EditFile(CacheFile("parse_errors")); }); menu.Add("Current file autocomplete errors", [=] { EditFile(CacheFile("autocomplete_errors")); }); menu.Add("Current parsed file content", [=] { EditFile(CacheFile("CurrentContext.txt")); });