mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 06:05:58 -06:00
developing usage tree
This commit is contained in:
parent
d2d07bd834
commit
ea3443a4c6
9 changed files with 140 additions and 81 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ void GatherBaseVirtuals(const String& cls, const String& signature, Index<String
|
|||
// 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 check virtual methods of this cls
|
||||
for(const AnnotationItem& m : f.value.items) {
|
||||
|
|
@ -115,89 +115,93 @@ void GatherVirtuals(const VectorMap<String, String>& bases, const String& cls,
|
|||
}
|
||||
}
|
||||
|
||||
void Ide::GetGlobalUsageIds(const String& id, bool& isvirtual, bool& isstatic, bool& istype, Index<String>& 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<String> visited;
|
||||
String signature = ScopeWorkaround(id.Mid(cls.GetCount()));
|
||||
Index<String> base_id;
|
||||
GatherBaseVirtuals(cls, signature, base_id, visited);
|
||||
|
||||
VectorMap<String, String> 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<String> 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<String> ids;
|
||||
ids.FindAdd(id);
|
||||
|
||||
if(isvirtual) {
|
||||
Index<String> visited;
|
||||
String signature = ScopeWorkaround(id.Mid(cls.GetCount()));
|
||||
Index<String> base_id;
|
||||
GatherBaseVirtuals(cls, signature, base_id, visited);
|
||||
|
||||
|
||||
VectorMap<String, String> 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<String>& 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<String>& 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<String>& unique, int& lvl, String& current, Index<String>& 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<String> 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<String> 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)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -508,4 +508,4 @@ String MakeDefinition(const AnnotationItem& m, const String& klass)
|
|||
String MakeDefinition(const AnnotationItem& m)
|
||||
{
|
||||
return MakeDefinition(m, GetClass(m));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -144,6 +144,8 @@ struct AnnotationItem : Moveable<AnnotationItem> {
|
|||
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<ReferenceItem> {
|
||||
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<String, CppFileInfo> info;
|
||||
|
|
|
|||
|
|
@ -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<Ptr<TopWindow>> window;
|
||||
|
||||
void NewWindow(TopWindow *win);
|
||||
|
|
@ -1001,7 +1001,12 @@ public:
|
|||
void UsageId(const String& name, const String& id, const Index<String>& ids, bool istype, bool isstatic, Index<String>& 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<String>& 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<String>& unique,
|
||||
int& lvl, String& current, Index<String>& done);
|
||||
void UsageTree();
|
||||
bool OpenLink(const String& s, int pos);
|
||||
String GetRefId(int pos, String& name, Point& ref_pos);
|
||||
void ContextGoto0(int pos);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue