diff --git a/uppsrc/ide/Builders/Builders.upp b/uppsrc/ide/Builders/Builders.upp index aa51fd879..9978016f7 100644 --- a/uppsrc/ide/Builders/Builders.upp +++ b/uppsrc/ide/Builders/Builders.upp @@ -13,7 +13,7 @@ uses(!NOSO) plugin/png; uses(!NOSO) Draw; file - Builders.h options(BUILDER_OPTION) PCH, + Builders.h, CppBuilder.cpp, MakeFile.cpp, CCJ.cpp, diff --git a/uppsrc/ide/Usage.cpp b/uppsrc/ide/Usage.cpp index af66f081f..d666ddffa 100644 --- a/uppsrc/ide/Usage.cpp +++ b/uppsrc/ide/Usage.cpp @@ -83,7 +83,7 @@ void GatherBaseVirtuals(const String& cls, const String& signature, Index& bases, const String& cls, } } +void Ide::GetGlobalUsageIds(const String& id, bool& isvirtual, bool& isstatic, bool& istype, Index& ids) +{ + isvirtual = false; + isstatic = false; // to limit file static variables to single file + istype = false; + String cls; + for(const auto& f : ~CodeIndex()) + for(const AnnotationItem& m : f.value.items) { + if(m.id == id) { + if(m.isvirtual) { + isvirtual = true; + cls = m.nest; + break; + } + if(IsStruct(m.kind)) { + istype = true; + cls = m.nest; + break; + } + if(m.id == id && m.isstatic && f.key == editfile && + m.nest.GetCount() == m.nspace.GetCount()) // ignore class variables + isstatic = true; + } + } + + ids.FindAdd(id); + + if(isvirtual) { + Index 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); + } +} + +bool Ide::IsLocalAtCursor(const String& id, Point ref_pos) +{ + int li = editor.GetCursorLine(); + bool local = false; + AnnotationItem cm = editor.FindCurrentAnnotation(); // what function body are we in? + if(IsFunction(cm.kind)) // do local variables + for(const AnnotationItem& lm : editor.locals) + if(lm.id == id && lm.pos.y >= cm.pos.y && lm.pos.y <= li && ref_pos == lm.pos) + return true; + return false; +} + void Ide::Usage(const String& id, const String& name, Point ref_pos) { if(IsNull(id)) return; - + ResetFileLine(); - - int li = editor.GetCursorLine(); - - bool local = false; - AnnotationItem cm = editor.FindCurrentAnnotation(); // what function body are we in? - if(IsFunction(cm.kind)) { // do local variables - for(const AnnotationItem& lm : editor.locals) - if(lm.id == id && lm.pos.y >= cm.pos.y && lm.pos.y <= li) { - if(ref_pos == lm.pos) { - local = true; - break; - } - } - } - NewFFound(); + Progress pi("Indexing files"); + while(Indexer::IsRunning()) { + if(pi.StepCanceled()) + break; + GuiSleep(10); + } + Index unique; - if(local) { + if(IsLocalAtCursor(id, ref_pos)) { AddReferenceLine(editfile, ref_pos, name, unique); for(const ReferenceItem& lm : editor.references) if(lm.id == id && lm.ref_pos == ref_pos) AddReferenceLine(editfile, lm.pos, name, unique); } else { - bool isvirtual = false; - bool isstatic = false; // to limit file static variables to single file - bool istype = false; - String cls; - Progress pi("Indexing files"); - while(Indexer::IsRunning()) { - if(pi.StepCanceled()) - break; - GuiSleep(10); - } - for(const auto& f : ~CodeIndex()) - for(const AnnotationItem& m : f.value.items) { - if(m.id == id) { - if(m.isvirtual) { - isvirtual = true; - cls = m.nest; - break; - } - if(IsStruct(m.kind)) { - istype = true; - cls = m.nest; - break; - } - if(m.id == id && m.isstatic && f.key == editfile && - m.nest.GetCount() == m.nspace.GetCount()) // ignore class variables - isstatic = true; - } - } - + bool isvirtual; + bool isstatic; // to limit file static variables to single file + bool istype; Index ids; - ids.FindAdd(id); - - if(isvirtual) { - Index 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); - } + + GetGlobalUsageIds(id, isvirtual, isstatic, istype, ids); UsageId(name, id, ids, istype, isstatic, unique); } @@ -211,7 +215,6 @@ void Ide::UsageId(const String& name, const String& id, const Index& ids int q = id.ReverseFind("::"); String constructor = id + "::" + (q >= 0 ? id.Mid(q + 2) : id) + "("; String destructor = id + "::~("; - SortByKey(CodeIndex()); int kind = Null; for(int src = 0; src < 2; src++) for(const auto& f : ~CodeIndex()) { @@ -231,7 +234,7 @@ void Ide::UsageId(const String& name, const String& id, const Index& ids Add(m.pos); } } - + if(!IsNull(kind)) FFoundSetIcon(CxxIcon(kind)); } @@ -261,6 +264,7 @@ void Ide::Usage() void Ide::IdUsage() { + SortByKey(CodeIndex()); if(designer) return; if(editfile.EndsWith(".lay")) { @@ -307,6 +311,43 @@ void Ide::IdUsage() Usage(ref_id, name, ref_pos); } +void Ide::DoUsageTree(String parent_id, String id, String fn, Point mpos, String name, Index& unique, int& lvl, String& current, Index& done) +{ +/* AddReferenceLine(fn, mpos, name, unique); + if(parent_id != current) { + current = parent_id; + if(lvl < 40 && !IsNull(parent_id) && done.Find(parent_id) < 0 && done.GetCount() < 100) { + done.Add(parent_id); + lvl++; + for(int pass = 0; pass < 2; pass++) + for(const auto& f : ~CodeIndex()) { + for(const AnnotationItem& m : f.value.items) { + if(m.id == parent_id && m.definition != (bool)pass) { + String current; + DLOG(lvl << " " << parent_id); + Usage(parent_id, m.name, m.pos, [&](String parent_id, String id, String fn, Point mpos, String name) { + DoUsageTree(parent_id, id, fn, mpos, name, unique, lvl, current, done); + }); + lvl--; + return; + } + } + } + lvl--; + } + } +*/} + +void Ide::UsageTree() +{ +/* Index unique, done; + int lvl = 0; + String current; + IdUsage([&](String parent_id, String id, String fn, Point mpos, String name) { + DoUsageTree(parent_id, id, fn, mpos, name, unique, lvl, current, done); + }); +*/} + void Ide::FindDesignerItemReferences(const String& id, const String& name) { SaveFile(); @@ -316,7 +357,7 @@ void Ide::FindDesignerItemReferences(const String& id, const String& name) int q = CodeIndex().Find(path); if(q < 0) return; - + auto DoUsage = [&](const AnnotationItem& m) { Index ids, unique; ids.Add(m.id); @@ -332,7 +373,7 @@ void Ide::FindDesignerItemReferences(const String& id, const String& name) return; } } - + // Probably untyped layout item, need to find all classes using the layout q = id.ReverseFind("::"); if(q < 0) return; @@ -358,3 +399,4 @@ void Ide::FindDesignerItemReferences(const String& id, const String& name) } } } + diff --git a/uppsrc/ide/clang/Indexer.cpp b/uppsrc/ide/clang/Indexer.cpp index 6fda2114a..63f4248bb 100644 --- a/uppsrc/ide/clang/Indexer.cpp +++ b/uppsrc/ide/clang/Indexer.cpp @@ -105,6 +105,7 @@ void AnnotationItem::Serialize(Stream& s) void ReferenceItem::Serialize(Stream& s) { s % id + % parent_id % pos % ref_pos ; @@ -131,6 +132,7 @@ String CachedAnnotationPath(const String& source_file, const String& defines, co #ifdef _DEBUG << "debug" // to have different codebase for development #endif + << "1" // version ; return CacheFile(GetFileTitle(source_file) + "$" + s.FinishString() + ".code_index"); } @@ -155,7 +157,7 @@ void DumpIndex(const char *file, const String& what_file) out << '\t' << n.pos.y << ": " << n.id << " -> " << n.pretty << ", bases: " << n.bases << "\n"; out << "\t=== References:\n"; for(const auto& n : m.value.refs) - out << '\t' << n.pos << " " << n.id << " -> " << n.ref_pos << "\n"; + out << '\t' << n.pos << " " << n.id << " -> " << n.ref_pos << ", parent: " << n.parent_id << "\n"; } } diff --git a/uppsrc/ide/clang/Signature.cpp b/uppsrc/ide/clang/Signature.cpp index b21f2f476..4b3192fa8 100644 --- a/uppsrc/ide/clang/Signature.cpp +++ b/uppsrc/ide/clang/Signature.cpp @@ -508,4 +508,4 @@ String MakeDefinition(const AnnotationItem& m, const String& klass) String MakeDefinition(const AnnotationItem& m) { return MakeDefinition(m, GetClass(m)); -} \ No newline at end of file +} diff --git a/uppsrc/ide/clang/Visitor.cpp b/uppsrc/ide/clang/Visitor.cpp index 27bb32465..c6574cabc 100644 --- a/uppsrc/ide/clang/Visitor.cpp +++ b/uppsrc/ide/clang/Visitor.cpp @@ -302,6 +302,7 @@ bool ClangVisitor::ProcessNode(CXCursor cursor) String id = ci.Id(); int kind = ci.Kind(); if(id.GetCount()) { + parent_id = id; LoadSourceLocation(); CppFileInfo& f = info.GetAdd(sl.path); AnnotationItem& r = locals ? f.locals.Add() : f.items.Add(); @@ -356,6 +357,7 @@ bool ClangVisitor::ProcessNode(CXCursor cursor) ReferenceItem rm; rm.pos = sl.pos; rm.id = ref_ci.Id(); + rm.parent_id = parent_id; rm.ref_pos = ref_loc.pos; #if 0 DLOG("======="); @@ -397,9 +399,11 @@ CXChildVisitResult clang_visitor(CXCursor cursor, CXCursor p, CXClientData clien #endif ClangVisitor *v = (ClangVisitor *)clientData; bool bak_locals = v->locals; + String bak_parent_id = v->parent_id; if(v->ProcessNode(cursor)) clang_visitChildren(cursor, clang_visitor, clientData); v->locals = bak_locals; + v->parent_id = bak_parent_id; #ifdef DUMPTREE LOGEND(); #endif diff --git a/uppsrc/ide/clang/clang.h b/uppsrc/ide/clang/clang.h index c1a7029f6..ff8bd19ba 100644 --- a/uppsrc/ide/clang/clang.h +++ b/uppsrc/ide/clang/clang.h @@ -144,6 +144,8 @@ struct AnnotationItem : Moveable { String nest; // Upp::Class String unest; // UPP::CLASS String bases; // base classes of struct/class + String parent_id; + Point pos = Null; int kind = Null; bool definition = false; @@ -160,6 +162,7 @@ String MakeDefinition(const AnnotationItem& m); struct ReferenceItem : Moveable { String id; + String parent_id; // function or struct that contains this item Point pos; Point ref_pos; @@ -243,7 +246,8 @@ class ClangVisitor { CXLocation GetLocation(CXSourceLocation cxlocation); SourceLocation GetSourceLocation(const CXLocation& p); - bool locals = false; + bool locals = false; + String parent_id; public: VectorMap info; diff --git a/uppsrc/ide/ide.h b/uppsrc/ide/ide.h index 7ad3ab709..55913c3f3 100644 --- a/uppsrc/ide/ide.h +++ b/uppsrc/ide/ide.h @@ -486,7 +486,7 @@ public: struct FoundList : ArrayCtrl { Button freplace; Image icon; - + FoundList(); }; @@ -667,7 +667,7 @@ public: true #endif ; - + // Formats editor's code with Ide format parameters void FormatJSON_XML(bool xml); @@ -716,7 +716,7 @@ public: int animate_autocomplete = 0, animate_autocomplete_dir = 0; int animate_indexer = 0, animate_indexer_dir = 0; int animate_phase = 0; - + Vector> window; void NewWindow(TopWindow *win); @@ -1001,7 +1001,12 @@ public: void UsageId(const String& name, const String& id, const Index& ids, bool istype, bool isstatic, Index& unique); void Usage(); void IdUsage(); + bool IsLocalAtCursor(const String& id, Point ref_pos); + void GetGlobalUsageIds(const String& id, bool& isvirtual, bool& isstatic, bool& istype, Index& ids); void Usage(const String& id, const String& name, Point ref_pos); + void DoUsageTree(String parent_id, String id, String fn, Point mpos, String name, Index& unique, + int& lvl, String& current, Index& done); + void UsageTree(); bool OpenLink(const String& s, int pos); String GetRefId(int pos, String& name, Point& ref_pos); void ContextGoto0(int pos); diff --git a/uppsrc/ide/ide.key b/uppsrc/ide/ide.key index ac7f73f65..3e6b240a0 100644 --- a/uppsrc/ide/ide.key +++ b/uppsrc/ide/ide.key @@ -106,6 +106,7 @@ KEY(THISBACKS, "Events..", K_ALT_T) KEY(SWAPS, "Go to definition/declaration", K_ALT_I) KEY(IDUSAGE, "Usage", K_ALT_U) KEY(USAGE, "Usage of current function", K_SHIFT|K_ALT_U) +KEY(USAGETREE, "Usage tree", K_ALT_O) KEY(JUMPS, "Context go to", K_ALT_J) KEY(TOGGLEINDEX, "File index", K_CTRL_F12) KEY(SEARCHINDEX, "File index search", K_F12) diff --git a/uppsrc/ide/idebar.cpp b/uppsrc/ide/idebar.cpp index f143c7a43..2c905560d 100644 --- a/uppsrc/ide/idebar.cpp +++ b/uppsrc/ide/idebar.cpp @@ -860,8 +860,9 @@ void Ide::AssistMenu(Bar& menu) menu.Add(!designer, AK_JUMPS, [=] { ContextGoto(); }); menu.Add(!designer, AK_SWAPS, THISBACK(SwapS)); menu.Add(!designer, AK_DCOPY, callback(&editor, &AssistEditor::DCopy)); - menu.Add(!designer, AK_IDUSAGE, THISBACK(IdUsage)); + menu.Add(!designer, AK_IDUSAGE, [=] { IdUsage(); }); menu.Add(!designer, AK_USAGE, [=] { Usage(); }); + menu.Add(!designer, AK_USAGETREE, [=] { UsageTree(); }); menu.Add(!designer, AK_GOTOGLOBAL, THISBACK(NavigatorDlg)); menu.Add(!designer, AK_VIRTUALS, callback(&editor, &AssistEditor::Virtuals)); menu.Add(!designer, AK_THISBACKS, callback(&editor, &AssistEditor::Events));