Developing indexer

This commit is contained in:
Mirek Fidler 2022-07-20 16:14:13 +02:00
parent b16713e74c
commit 78dc90e9c2
34 changed files with 1059 additions and 219 deletions

View file

@ -25,10 +25,10 @@ public:
};
struct TimeStopper {
const char *name;
String name;
TimeStop tm;
TimeStopper(const char *name) : name(name) {}
TimeStopper(const String& name) : name(name) {}
~TimeStopper() { RLOG(name << " " << tm); }
};

View file

@ -1068,8 +1068,10 @@ EditField& EditField::SetFont(Font _font)
EditField& EditField::SetColor(Color c)
{
SetColorAttr(ATTR_TEXTCOLOR, c);
Refresh();
if(GetColorAttr(ATTR_TEXTCOLOR) != c) {
SetColorAttr(ATTR_TEXTCOLOR, c);
Refresh();
}
return *this;
}

View file

@ -69,7 +69,8 @@ AssistEditor::AssistEditor()
NoFindReplace();
WhenUpdate << [=] {
annotate_trigger.KillSet(100, [=] { SyncCurrentFile(); });
annotating = true;
annotate_trigger.KillSet(500, [=] { SyncCurrentFile(); });
};
}
@ -460,6 +461,10 @@ CurrentFileContext AssistEditor::CurrentContext(int& line_delta)
cfx.content.Clear();
}
}
#ifdef _DEBUG
if(cfx.content.GetCount())
SaveFile(ConfigFile("pseudo_header_src.cpp"), cfx.content);
#endif
return cfx;
}
@ -478,6 +483,9 @@ void AssistEditor::SyncCurrentFile(CurrentFileContext& cfx, int line_delta)
m.id);
}
}
annotating = false;
if(!navigator_global)
Search();
});
}
@ -490,11 +498,11 @@ void AssistEditor::SyncCurrentFile()
void AssistEditor::NewFile()
{
SyncHeaders();
int line_delta;
CurrentFileContext cfx = CurrentContext(line_delta);
SyncCurrentFile(cfx, line_delta);
SetAutoCompleteFile(cfx);
SyncHeaders();
}
void AssistEditor::Assist(bool macros)
@ -744,7 +752,7 @@ void AssistEditor::AssistInsert()
else {
String txt = f.name;
int param_count;
ParseSignature(f.name, f.signature, &param_count);
ParsePretty(f.name, f.signature, &param_count);
if(param_count >= 0)
txt << "()";
if(f.signature.EndsWith("::"))
@ -803,21 +811,7 @@ bool AssistEditor::Key(dword key, int count)
Exclamation("No annotation for this line.");
}
if(key == K_F11) {
HdependTimeDirty();
VectorMap<String, Vector<String>> deps;
{
TIMESTOP("Scan");
const Workspace& wspc = GetIdeWorkspace();
for(int i = 0; i < wspc.GetCount(); i++) {
const Package& pk = wspc.GetPackage(i);
String n = wspc[i];
for(int i = 0; i < pk.file.GetCount(); i++) {
String path = SourcePath(n, pk.file[i]);
deps.GetAdd(path) = pick(HdependGetDependencies(path));
}
}
}
DDUMPM(deps);
StartIndexing(theide->GetCurrentIncludePath(), theide->GetCurrentDefines());
}
#endif
if(popup.IsOpen()) {

View file

@ -9,7 +9,13 @@ struct Navigator {
bool operator<(const NavLine& b) const;
};
struct NavItem {
enum KindEnum { KIND_LINE = -4000, KIND_NEST, KIND_FILE, KIND_SRCFILE };
struct NavItem : AnnotationItem {
// int priority = 0; // for sorting based on search accuracy
/* int decl_line = 0;
int decl_file = 0;
String nest;
String qitem;
String name;
@ -30,13 +36,11 @@ struct Navigator {
bool impl;
bool decl;
int8 pass;
Vector<NavLine> linefo;
void Set(const CppItem& m);
*/
};
enum KindEnum { KIND_LINE = 123, KIND_NEST, KIND_FILE, KIND_SRCFILE };
struct ScopeDisplay : Display {
Navigator *navigator;
@ -52,23 +56,22 @@ struct Navigator {
};
struct NavigatorDisplay : Display {
const Vector<NavItem *>& item;
const Vector<const NavItem *>& item;
int DoPaint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const;
virtual void PaintBackground(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const;
virtual void Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const;
virtual Size GetStdSize(const Value& q) const;
NavigatorDisplay(const Vector<NavItem *>& item) : item(item) {}
NavigatorDisplay(const Vector<const NavItem *>& item) : item(item) {}
};
Ide *theide;
Array<NavItem> nitem;
VectorMap<String, Vector<NavItem *> > gitem;
Vector<NavItem *> litem;
Array<NavItem> nest_item;
VectorMap<int, SortedVectorMap<int, int> > linefo;
Vector<const NavItem *> litem;
Array<NavItem> nest_item; // list separators with nest (scope) or file
VectorMap<int, SortedVectorMap<int, int> > linefo; // TODO remove?
NavigatorDisplay navidisplay;
bool navigating;
TimeCallback search_trigger;
@ -86,7 +89,6 @@ struct Navigator {
ScopeDisplay scope_display;
void TriggerSearch();
void NavGroup(bool local);
void Search();
void Scope();
void ListLineEnabled(int i, bool& b);
@ -103,9 +105,6 @@ struct Navigator {
void GoToNavLine();
void SyncCursor();
static bool SortByLines(const NavItem *a, const NavItem *b);
static bool SortByNames(const NavItem *a, const NavItem *b);
typedef Navigator CLASSNAME;
Navigator();
@ -152,6 +151,7 @@ struct AssistEditor : CodeEditor, Navigator {
} assist_display;
RichTextCtrl annotation_popup;
bool annotating = false;
Vector<AnnotationItem> annotations;
int assist_cursor;

View file

@ -27,6 +27,38 @@ Image CxxIcon(int kind)
return BrowserImg::unknown();
}
int PaintCpp(Draw& w, const Rect& r, int kind, const String& name, const String& pretty, Color ink, bool focuscursor, bool retval_last)
{
int x = r.left;
Image img = CxxIcon(kind);
Size isz = img.GetSize();
w.DrawImage(x + (DPI(16) - isz.cx) / 2, r.top + (r.GetHeight() - isz.cy) / 2, img);
x += DPI(16);
int y = r.top + (r.GetHeight() - Draw::GetStdFontCy()) / 2;
#ifdef _DEBUG
String ks = " [" + AsString(kind) + "] ";
w.DrawText(x, y, ks);
x += GetTextSize(ks, StdFont()).cx;
#endif
Vector<ItemTextPart> n = ParsePretty(name, pretty);
int count = n.GetCount();
if(retval_last)
for(int i = 0; i < n.GetCount(); i++)
if(n[i].type == ITEM_NAME) {
PaintText(w, x, y, pretty, n, i, count - i, focuscursor, ink, false);
w.DrawText(x, y, "", StdFont(), SGray());
x += GetTextSize("", StdFont()).cx;
count = i;
break;
}
PaintText(w, x, y, pretty, n, 0, count, focuscursor, ink, false);
return x;
}
void AssistEditor::AssistDisplay::Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
{
int ii = q;
@ -34,26 +66,7 @@ void AssistEditor::AssistDisplay::Paint(Draw& w, const Rect& r, const Value& q,
AutoCompleteItem& m = editor->assist_item[editor->assist_item_ndx[ii]];
w.DrawRect(r, paper);
bool focuscursor = (style & (FOCUS|CURSOR)) == (FOCUS|CURSOR) || (style & SELECT);
int x = r.left;
int ry = r.top + r.GetHeight() / 2;
Image img = CxxIcon(m.kind);
Size isz = img.GetSize();
w.DrawImage(x + (DPI(16) - isz.cx) / 2, r.top + (r.GetHeight() - isz.cy) / 2, img);
x += DPI(16);
int y = ry - Draw::GetStdFontCy() / 2;
#ifdef _DEBUG
String ks = " [" + AsString(m.kind) + "] ";
w.DrawText(x, y, ks);
x += GetTextSize(ks, StdFont()).cx;
#endif
int x0 = x;
Vector<ItemTextPart> n = ParseSignature(m.name, m.signature);
int starti = 0;
PaintText(w, x, y, m.signature, n, starti, n.GetCount(), focuscursor, ink, false);
PaintCpp(w, r, m.kind, m.name, m.signature, ink, (style & (FOCUS|CURSOR)) == (FOCUS|CURSOR) || (style & SELECT));
}
}

View file

@ -1,4 +1,4 @@
#include "Browser.h"
#include <ide/ide.h>
#include <plugin/lz4/lz4.h>

View file

@ -1,4 +1,4 @@
#include "Browser.h"
#include <ide/ide.h>
bool MatchCib(const String& s, const String& match)
{

View file

@ -346,7 +346,7 @@ void TopicEditor::InsertItem()
String DecoratedItem(const String& name, const String& pretty)
{
String qtf = "[%00-00K ";
Vector<ItemTextPart> n = ParseSignature(name, pretty);
Vector<ItemTextPart> n = ParsePretty(name, pretty);
/* TODO
if(pari < 0) {
if(m.virt)
@ -435,7 +435,7 @@ String CreateQtf(const AnnotationItem& m, const String& lang, bool onlyhdr = fal
qtf << "[s3%" << lang << " ";
if(!str) {
Vector<ItemTextPart> n = ParseSignature(m.name, m.pretty);
Vector<ItemTextPart> n = ParsePretty(m.name, m.pretty);
if(!str) {
bool was;
for(const auto& h : n)

View file

@ -4,8 +4,8 @@ void PaintText(Draw& w, int& x, int y, const char *text, const Vector<ItemTextPa
int starti, int count, bool focuscursor, Color _ink, bool italic)
{
static int maxascent = MaxAscent(BrowserFont());
for(int i = starti; i < count; i++) {
const ItemTextPart& p = n[i];
for(int i = 0; i < count; i++) {
const ItemTextPart& p = n[starti + i];
Font f = BrowserFont();
Color ink = SColorText;
switch(p.type) {

View file

@ -1,4 +1,4 @@
#include "Browser.h"
#include <ide/ide.h>
struct MoveTopicDlg : public WithMoveTopicLayout<TopWindow> {
typedef MoveTopicDlg CLASSNAME;

View file

@ -239,6 +239,7 @@ void SyncRefs()
SyncRefsShowProgress = true;
return;
}
TIMESTOP("SyncRefs");
Progress pi;
pi.AlignText(ALIGN_LEFT);
Vector<String> upp = GetUppDirs();

View file

@ -1,4 +1,4 @@
#include "Browser.h"
#include <ide/ide.h>
bool IsTopicFile(const char *path)
{

View file

@ -58,7 +58,7 @@ class Hdepend {
ArrayMap<String, Info> map;
Vector<String> incdir; // include directories
VectorMap<String, Index<String> > depends; // externally forced dependecies
bool cache_time = false;
bool console = true;
void Include(const char *trm, Info& info, const String& filedir, bool bydefine);
void ScanFile(const String& path, int map_index);
@ -69,8 +69,8 @@ class Hdepend {
void GetMacroIndex(Index<String>& dest, int ix);
public:
void SetDirs(Vector<String>&& id) { incdir = pick(id); map.Clear(); }
void SetDirs(const String& includes) { incdir = pick(Split(includes, ';')); map.Clear(); }
void SetDirs(Vector<String>&& id);
void SetDirs(const String& includes);
void TimeDirty();
void ClearDependencies() { depends.Clear(); }
@ -85,7 +85,7 @@ public:
const Vector<String>& GetDefines(const String& path);
Vector<String> GetDependencies(const String& path, bool bydefine_too = true);
const Vector<String>& GetAllFiles() { return map.GetKeys(); }
void CacheTime() { cache_time = true; }
void NoConsole() { console = false; }
};
class IdeContext
@ -153,8 +153,8 @@ public:
virtual ~IdeContext() {}
};
IdeContext *TheIde();
void TheIde(IdeContext *context);
Ide *TheIde();
void TheIde(Ide *context);
bool IsVerbose();
void PutConsole(const char *s);
@ -391,7 +391,6 @@ public:
File() { Init(); }
File(const String& s) : String(s) { Init(); }
rval_default(File);
};
struct Config {
String name;

View file

@ -85,7 +85,7 @@ void Hdepend::ScanFile(const String& path, int map_index)
auto Id = [&](const char *id) {
int n = strlen(id);
if(memcmp(term, id, n) == 0 && findarg(term[n], ' ', '\t')) {
if(memcmp(term, id, n) == 0 && findarg(term[n], ' ', '\t') >= 0) {
term += n + 1;
return true;
}
@ -160,6 +160,7 @@ void Hdepend::ScanFile(const String& path, int map_index)
if(p.Char('#') && p.Id("define") && p.IsId() && id == p.ReadId())
info.guarded = true;
}
term = p.GetPtr();
}
catch(CParser::Error) {}
}
@ -268,29 +269,19 @@ int Hdepend::File(const String& f)
Info& info = map[ii];
if(info.flag) return ii;
info.flag = true;
if(cache_time) {
Time file_time = FileGetTime(path);
if(IsNull(file_time) || file_time == info.time) {
if(info.timedirty) {
info.time = FileGetTime(path);
for(int i = 0; i < info.depend.GetCount(); i++)
File(map.GetKey(info.depend[i]));
info.timedirty = false;
}
}
else {
Time file_time = FileGetTime(path);
if(IsNull(file_time) || file_time == info.time) {
if(info.timedirty) {
for(int i = 0; i < info.depend.GetCount(); i++)
File(map.GetKey(info.depend[i]));
info.timedirty = false;
}
}
else {
info.time = file_time;
if(info.time > GetSysTime() + 10)
PutConsole(String().Cat() << "WARNING: " << path << " has invalid (future) time " << info.time);
ScanFile(path, ii);
}
info.time = file_time;
if(console && info.time > GetSysTime() + 10)
PutConsole(String().Cat() << "WARNING: " << path << " has invalid (future) time " << info.time);
ScanFile(path, ii);
}
return ii;
}
@ -355,6 +346,19 @@ void Hdepend::ClearMacroFlag()
map[i].macroflag = false;
}
void Hdepend::SetDirs(Vector<String>&& id)
{
if(incdir != id) {
incdir = pick(id);
map.Clear();
}
}
void Hdepend::SetDirs(const String& includes)
{
SetDirs(pick(Split(includes, ';')));
}
void Hdepend::TimeDirty()
{
for(int i = 0; i < map.GetCount(); i++)
@ -376,7 +380,7 @@ Time Hdepend::FileTime(const String& path)
FindFile ff(dep[i]);
if(ff) {
Time tm = ff.GetLastWriteTime();
if(tm > GetSysTime() + 10)
if(console && tm > GetSysTime() + 10)
PutConsole(String().Cat() << "WARNING: " << dep[i] << " has invalid (future) time " << tm);
if(tm > h)
h = tm;
@ -398,8 +402,9 @@ bool Hdepend::BlitzApproved(const String& path)
return true;
for(int i = 0; i < info.depend.GetCount(); i++)
if(!info.bydefine[i] && !map[info.depend[i]].CanBlitz()) {
PutVerbose(String().Cat() << map.GetKey(info.depend[i])
<< "(1) : blocks BLITZ of " << path);
if(console)
PutVerbose(String().Cat() << map.GetKey(info.depend[i])
<< "(1) : blocks BLITZ of " << path);
return false;
}
return true;

View file

@ -1,9 +1,9 @@
#include "Core.h"
#include <ide/ide.h>
static IdeContext *the_ide;
static Ide *the_ide;
IdeContext *TheIde() { return the_ide; }
void TheIde(IdeContext *context) { the_ide = context; }
Ide *TheIde() { return the_ide; }
void TheIde(Ide *context) { the_ide = context; }
bool IsVerbose() { return the_ide ? the_ide->IsVerbose() : false; }
void PutConsole(const char *s) { if(the_ide) the_ide->PutConsole(s); }

View file

@ -10,7 +10,7 @@ bool IsCSourceFile(const char *path)
bool IsCHeaderFile(const char *path)
{
String ext = ToLower(GetFileExt(path));
return ext == ".h" || ext == ".hpp" || ext == ".hh" || ext == ".hxx";
return ext == ".h" || ext == ".hpp" || ext == ".hh" || ext == ".hxx" || ext == ".i";
}
bool IsFullDirectory(const String& d) {

View file

@ -5,11 +5,12 @@
void AssistEditor::SyncHeaders()
{
// hdepend.CacheTime();
TIMESTOP("SyncHeaders");
hdepend.TimeDirty();
hdepend.SetDirs(theide->GetCurrentIncludePath() + ";" + GetClangInternalIncludes());
master_source.Clear();
String editfile = NormalizePath(theide->editfile);
if(editfile.GetCount() && !IsSourceFile(editfile)) {
if(editfile.GetCount() && IsCHeaderFile(editfile)) {
for(int pass = 0; pass < 2; pass++) { // all packages in second pass
const Workspace& wspc = GetIdeWorkspace();
for(int i = 0; i < wspc.GetCount(); i++) { // find package of included file

View file

@ -1,3 +1,7 @@
#if 0
// TODO: remove
#include "ide.h"
#define LTIMING(x) // RTIMING(x)
@ -750,3 +754,5 @@ void Navigator::NaviSort()
sorting = !sorting;
Search();
}
#endif

596
uppsrc/ide/Navigator2.cpp Normal file
View file

@ -0,0 +1,596 @@
#include "ide.h"
#define LTIMING(x) // RTIMING(x)
String FormatNest(String nest)
{
int q = nest.Find("@");
if(q >= 0) {
nest.Trim(q);
nest << "[anonymous]";
}
return nest;
}
int CharFilterNavigator(int c)
{
return c == ':' ? '.' : IsAlNum(c) || c == '_' || c == '.' ? c : 0;
}
void PaintTeXt(Draw& w, int& x, int y, const String& text, Font font, Color ink)
{
static int maxascent = MaxAscent(StdFont());
Size sz = GetTextSize(text, font);
w.DrawText(x, y + maxascent - font.GetAscent(), text, font, ink);
x += sz.cx;
}
int DrawFileName0(Draw& w, const Rect& r, const String& h, Color ink, int x)
{
if(h.GetCount() == 0)
return 0;
int q = h.Find("\xff");
String ns;
String fn = h;
if(q >= 0) {
ns = h.Mid(0, q) + ' ';
fn = h.Mid(q + 1);
}
String s = GetFileName(GetFileFolder(h)) + "/";
x += r.left;
if(ns.GetCount()) {
PaintTeXt(w, x, r.top, ns, StdFont().Bold(), ink);
PaintTeXt(w, x, r.top, "(", StdFont(), ink);
}
PaintTeXt(w, x, r.top, s, StdFont(), ink);
s = GetFileName(h);
PaintTeXt(w, x, r.top, s, StdFont().Bold(), ink);
if(ns.GetCount())
PaintTeXt(w, x, r.top, ")", StdFont(), ink);
return x - r.left;
}
Size GetDrawFileNameSize(const String& h)
{
NilDraw w;
return Size(DrawFileName0(w, Size(999999, 999999), h, Null, 0), StdFont().Bold().GetCy());
}
void DrawFileName(Draw& w, const Rect& r, const String& h, Color ink)
{
DrawFileName0(w, r, h, ink, min(r.GetWidth() - GetDrawFileNameSize(h).cx, 0));
}
int PaintFileName(Draw& w, const Rect& r, String h, Color ink)
{
if(*h == '\xff')
h.Remove(0, 1);
return DrawFileName0(w, r, h, ink, 0);
}
Navigator::Navigator()
: navidisplay(litem)
{
scope_display.navigator = this;
scope.NoHeader();
scope.AddColumn().SetDisplay(scope_display);
scope.NoWantFocus();
scope.WhenSel = THISBACK(Scope);
scope.WhenLeftDouble = THISBACK(ScopeDblClk);
list.NoHeader();
list.AddRowNumColumn().SetDisplay(navidisplay);
list.SetLineCy(max(16, GetStdFontCy()));
list.NoWantFocus();
list.WhenLeftClick = THISBACK(NavigatorClick);
list.WhenSel = THISBACK(SyncNavLines);
list.WhenLineEnabled = THISBACK(ListLineEnabled);
navlines.NoHeader().NoWantFocus();
navlines.WhenLeftClick = THISBACK(GoToNavLine);
navlines.AddColumn().SetDisplay(Single<LineDisplay>());
search <<= THISBACK(TriggerSearch);
search.SetFilter(CharFilterNavigator);
search.WhenEnter = THISBACK(NavigatorEnter);
sortitems.Image(BrowserImg::Sort());
sortitems <<= THISBACK(NaviSort);
sorting = false;
dlgmode = false;
}
void Navigator::SyncCursor()
{
String k = "(" + GetKeyDesc(IdeKeys::AK_GOTO().key[0]) + ") ";
search.NullText("Symbol/lineno " + k);
search.Tip(IsNull(search) ? String() : "Clear " + k);
if(!navigating && theide->editfile.GetCount()) {
navlines.KillCursor();
int q = linefo.Find(GetSourceFileIndex(theide->editfile));
if(q < 0)
return;
navigating = true;
SortedVectorMap<int, int>& m = linefo[q];
q = m.FindUpperBound(GetCurrentLine() + 1) - 1;
if(q >= 0 && q < m.GetCount())
list.SetCursor(m[q]);
navigating = false;
}
SyncLines();
if(scope.IsCursor())
scope.RefreshRow(scope.GetCursor());
}
void Navigator::SyncLines()
{
if(IsNull(theide->editfile) || navigating)
return;
int ln = GetCurrentLine() + 1;
int fi = GetSourceFileIndex(theide->editfile);
int q = -1;
for(int i = 0; i < navlines.GetCount(); i++) {
const NavLine& l = navlines.Get(i, 0).To<NavLine>();
if(l.file == fi && l.line <= ln && i < navlines.GetCount())
q = i;
}
if(dlgmode)
navlines.GoBegin();
else
if(q >= 0)
navlines.SetCursor(q);
}
void Navigator::SyncNavLines()
{
int sc = navlines.GetScroll();
navlines.Clear();
int ii = list.GetCursor();
if(ii >= 0 && ii < litem.GetCount()) {
Vector<NavLine> l = GetNavLines(*litem[ii]);
for(int i = 0; i < l.GetCount(); i++) {
String p = GetSourceFilePath(l[i].file);
navlines.Add(RawToValue(l[i]));
}
navlines.ScrollTo(sc);
SyncLines();
}
}
int Navigator::LineDisplay::DoPaint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style, int x) const
{
w.DrawRect(r, paper);
const NavLine& l = q.To<NavLine>();
x += r.left;
String p = GetSourceFilePath(l.file);
int y = r.top + (r.GetHeight() - StdFont().GetCy()) / 2;
PaintTeXt(w, x, y, GetFileName(GetFileFolder(p)) + "/", StdFont(), ink);
PaintTeXt(w, x, y, GetFileName(p), StdFont().Bold(), ink);
PaintTeXt(w, x, y, " (", StdFont(), ink);
PaintTeXt(w, x, y, AsString(l.line), StdFont().Bold(), ink);
PaintTeXt(w, x, y, ")", StdFont(), ink);
return x - r.left;
}
void Navigator::LineDisplay::Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
{
DoPaint(w, r, q, ink, paper, style, min(r.GetWidth() - GetStdSize(q).cx, 0));
}
Size Navigator::LineDisplay::GetStdSize(const Value& q) const
{
NilDraw w;
return Size(DoPaint(w, Size(999999, 999999), q, White(), White(), 0, 0), StdFont().Bold().GetCy());
}
void Navigator::GoToNavLine()
{
if(dlgmode)
return;
int ii = navlines.GetClickPos().y;
if(ii >= 0 && ii < navlines.GetCount() && theide) {
const NavLine& l = navlines.Get(ii, 0).To<NavLine>();
theide->GotoPos(GetSourceFilePath(l.file), l.line);
}
}
bool Navigator::NavLine::operator<(const NavLine& b) const
{
String p1 = GetSourceFilePath(file);
String p2 = GetSourceFilePath(b.file);
return CombineCompare/*(!impl, !b.impl)*/
(GetFileExt(p2), GetFileExt(p1)) // .h > .c
(GetFileName(p1), GetFileName(p2))
(p1, p2)
(line, b.line) < 0;
}
Vector<Navigator::NavLine> Navigator::GetNavLines(const NavItem& m)
{
_DBG_
Vector<NavLine> l;
/*
CodeBaseLock __;
int q = CodeBase().Find(m.nest);
if(q < 0 || IsNull(m.qitem))
return l;
const Array<CppItem>& a = CodeBase()[q];
for(int i = 0; i < a.GetCount(); i++) {
const CppItem& mm = a[i];
if(mm.qitem == m.qitem) {
NavLine& nl = l.Add();
nl.impl = mm.impl;
nl.file = mm.file;
nl.line = mm.line;
}
}
Sort(l);
*/
return l;
}
void Navigator::Navigate()
{
if(navigating)
return;
navigating = true;
int ii = list.GetCursor();
if(theide && ii >= 0 && ii < litem.GetCount()) {
int ln = GetCurrentLine() + 1;
const NavItem& m = *litem[ii];
if(m.kind == KIND_LINE || IsNull(search)) {
theide->GotoPos(Null, m.line);
if(m.kind == KIND_LINE) { // Go to line - restore file view
search.Clear();
Search();
navigating = false;
}
SyncCursor();
}
else
if(m.kind == KIND_SRCFILE) {
theide->AddHistory();
theide->EditFile(m.id);
theide->AddHistory();
}
else {
Vector<NavLine> l = GetNavLines(m);
int q = l.GetCount() - 1;
for(int i = 0; i < l.GetCount(); i++)
if(GetSourceFilePath(l[i].file) == NormalizeSourcePath(theide->editfile) && l[i].line == ln) {
q = (i + l.GetCount() + 1) % l.GetCount();
break;
}
if(q >= 0 && q < l.GetCount()) {
String path = GetSourceFilePath(l[q].file);
// TODO:
_DBG_
// if(!theide->GotoDesignerFile(path, m.nest, m.name, l[q].line))
// theide->GotoPos(path, l[q].line);
}
}
}
navigating = false;
}
void Navigator::ScopeDblClk()
{
if(!scope.IsCursor())
return;
String h = scope.GetKey();
if((byte)*h == 0xff)
theide->GotoPos(h.Mid(1), 1);
else {
list.GoBegin();
Navigate();
}
}
void Navigator::NavigatorClick()
{
if(dlgmode)
return;
int q = list.GetClickPos().y;
if(q >= 0 && q < list.GetCount())
Navigate();
}
void Navigator::NavigatorEnter()
{
if(list.GetCount()) {
list.GoBegin();
Navigate();
}
}
void Ide::ToggleNavigator()
{
editor.Navigator(!editor.navigator);
}
void Ide::SearchCode()
{
if(!editor.navigator)
editor.Navigator(true);
if(!IsNull(~editor.search)) {
editor.search.Clear();
editor.Search();
editor.SetFocus();
}
else {
String h = editor.GetWord();
if(h.GetCount()) {
editor.search <<= h;
editor.search.SelectAll();
editor.Search();
}
editor.search.SetFocus();
}
}
//TODO: What is this?
void Ide::SwitchHeader() {
int c = filelist.GetCursor();
if(c < 0) return;
String currfile = filelist[c];
const char *ext = GetFileExtPos(currfile);
if(!stricmp(ext, ".h") || !stricmp(ext, ".hpp")
|| !stricmp(ext, ".lay") || !stricmp(ext, ".iml")) {
int f = filelist.Find(ForceExt(currfile, ".cpp"));
if(f < 0) f = filelist.Find(ForceExt(currfile, ".c"));
if(f < 0) f = filelist.Find(ForceExt(currfile, ".cc"));
if(f >= 0) filelist.SetCursor(f);
}
}
void Navigator::NavigatorDisplay::PaintBackground(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
{
int ii = q;
if(ii < 0 || ii >= item.GetCount())
return;
const NavItem& m = *item[ii];
bool focuscursor = (style & (FOCUS|CURSOR)) == (FOCUS|CURSOR) || (style & SELECT);
if(findarg(m.kind, KIND_FILE, KIND_NEST) >= 0)
w.DrawRect(r, focuscursor ? paper : m.kind == KIND_NEST ? Blend(SColorMark, SColorPaper, 220)
: SColorFace);
else
w.DrawRect(r, paper);
}
int Navigator::NavigatorDisplay::DoPaint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
{
int ii = q;
if(ii < 0 || ii >= item.GetCount())
return 0;
const NavItem& m = *item[ii];
bool focuscursor = (style & (FOCUS|CURSOR)) == (FOCUS|CURSOR) || (style & SELECT);
int x = r.left;
int y = (r.GetHeight() - Draw::GetStdFontCy()) / 2;
if(findarg(m.kind, KIND_FILE, KIND_NEST) >= 0) {
w.DrawRect(r, focuscursor ? paper : m.kind == KIND_NEST ? Blend(SColorMark, SColorPaper, 220)
: SColorFace);
if(findarg(m.kind, KIND_FILE) >= 0)
return PaintFileName(w, r, m.pretty, ink);
String h = FormatNest(m.pretty);
w.DrawText(x, y, h, StdFont().Bold(), ink);
return GetTextSize(h, StdFont().Bold()).cx;
}
w.DrawRect(r, paper);
if(m.kind == KIND_SRCFILE)
return PaintFileName(w, r, m.pretty, ink);
if(m.kind == KIND_LINE) {
w.DrawText(x, y, m.pretty, StdFont().Bold(), ink);
return GetTextSize(m.pretty, StdFont().Bold()).cx;
}
return PaintCpp(w, r, m.kind, m.name, m.pretty, ink, focuscursor, true);
}
void Navigator::NavigatorDisplay::Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
{
DoPaint(w, r, q, ink, paper, style);
}
Size Navigator::NavigatorDisplay::GetStdSize(const Value& q) const
{
NilDraw w;
return Size(DoPaint(w, Size(999999, 999999), q, White(), White(), 0), Draw::GetStdFontCy());
}
void Navigator::TriggerSearch()
{
search_trigger.KillSet(100, THISBACK(Search));
}
void Navigator::Search()
{
sortitems.Check(sorting);
int sc = scope.GetScroll();
String key = scope.GetKey();
String s = TrimBoth(~search);
String search_name, search_nest;
bool wholeclass = false;
bool both = false;
navigator_global = false;
if(s.Find('.') >= 0) {
Vector<String> h = Split((String)~search, '.');
if(*s.Last() == '.')
search_nest = Join(h, "::");
else {
search_name = h.Pop();
if(h.GetCount())
search_nest = Join(h, "::");
}
wholeclass = *s == '.' && search_nest.GetCount();
}
else {
search_name = search_nest = ~search;
both = true;
}
s = Join(Split(s, '.'), "::") + (s.EndsWith(".") ? "::" : "");
int lineno = StrInt(s);
nitem.Clear();
Index<String> nests;
if(IsNull(theide->editfile))
return;
int fileii = GetSourceFileIndex(theide->editfile);
if(!IsNull(lineno)) {
NavItem& m = nitem.Add();
m.pretty = "Go to line " + AsString(lineno);
m.kind = KIND_LINE;
m.line = lineno;
nests.Add(Null);
}
else
if(IsNull(s) && !sorting) {
bool sch = GetFileExt(theide->editfile) == ".sch";
Ide *theide = TheIde();
if(theide)
for(const AnnotationItem& m : theide->editor.annotations) {
NavItem& n = nitem.Add();
(AnnotationItem&)n = m;
nests.FindAdd(n.nest);
}
SortIndex(nests);
}
else { // TODO: Sort codeindex paths, add files in that order to make things stable
navigator_global = true;
String usearch_nest = ToUpper(search_nest);
String usearch_name = ToUpper(search_name);
Index<String> visited;
for(int pass = 0; pass < 2; pass++)
for(const auto& f : ~CodeIndex())
for(const AnnotationItem& m : f.value.items) {
int q = visited.Find(m.id);
if(q >= 0) { // replace definition (.cpp) with declaration (.h)
AnnotationItem& n = nitem[q];
if(n.definition && !m.definition) { // file: make it stable
(AnnotationItem&)n = m;
}
}
else
if((pass == 0 ? m.name.StartsWith(search_name) : m.uname.Find(usearch_name) >= 0) &&
(pass == 0 ? m.nest.Find(search_nest) >= 0 : m.unest.Find(usearch_nest) >= 0)) {
visited.Add(m.id);
NavItem& n = nitem.Add();
(AnnotationItem&)n = m;
nests.FindAdd(n.nest);
}
}
SortIndex(nests);
const Workspace& wspc = GetIdeWorkspace();
String s = ToUpper(TrimBoth(~search));
for(int i = 0; i < wspc.GetCount(); i++) {
const Package& p = wspc.GetPackage(i);
for(int j = 0; j < p.GetCount(); j++) {
if(!p[j].separator && ToUpper(p[j]).Find(s) >= 0) {
NavItem& m = nitem.Add();
m.kind = KIND_SRCFILE;
m.pretty = wspc[i] + "/" + p[j];
m.id = SourcePath(wspc[i], p[j]);
m.line = 0;
nests.FindAdd("<files>");
}
}
}
}
scope.Clear();
scope.Add(Null);
for(String n : nests)
scope.Add(n);
scope.ScrollTo(sc);
if(!navigator_global || !scope.FindSetCursor(key))
scope.GoBegin();
}
int Navigator::ScopeDisplay::DoPaint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
{
w.DrawRect(r, paper);
if(IsNull(q)) {
const char *txt = "* ";
int x = 0;
w.DrawText(r.left, r.top, txt, StdFont().Bold().Italic(),
style & CURSOR ? ink : HighlightSetup::GetHlStyle(HighlightSetup::INK_KEYWORD).color);
x += GetTextSize(txt, StdFont().Bold().Italic()).cx;
int ii = navigator->list.GetCursor();
if(ii >= 0 && ii < navigator->litem.GetCount()) {
const NavItem& m = *navigator->litem[ii];
String txt = m.nest;
if(IsCppCode(m.kind))
txt << "::" << m.name;
w.DrawText(r.left + x, r.top, txt, StdFont().Bold(), ink);
x += GetTextSize(txt, StdFont().Bold()).cx;
}
return x;
}
String h = q;
if(*h == '\xff') // TODO
return PaintFileName(w, r, h, ink);
else
h = FormatNest(h);
w.DrawText(r.left, r.top, h, StdFont(), ink);
return GetTextSize(h, StdFont()).cx;
}
void Navigator::ScopeDisplay::Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
{
DoPaint(w, r, q, ink, paper, style);
}
Size Navigator::ScopeDisplay::GetStdSize(const Value& q) const
{
NilDraw w;
return Size(DoPaint(w, Size(999999, 999999), q, White(), White(), 0), StdFont().Bold().GetCy());
}
void Navigator::Scope()
{
LTIMING("FINALIZE");
litem.Clear();
nest_item.Clear();
linefo.Clear();
String sc = scope.GetKey();
String nest;
for(const NavItem& n : nitem) {
if(IsNull(sc) || n.nest == sc) {
if(!sorting && n.nest != nest) {
NavItem& m = nest_item.Add();
m.kind = KIND_NEST; // TODO: KIND_FILE
nest = m.pretty = n.nest;
litem.Add(&m);
}
litem.Add(&n);
}
}
// TODO sorting
int lsc = list.GetScroll();
list.Clear();
list.SetVirtualCount(litem.GetCount());
list.ScrollTo(lsc);
}
void Navigator::ListLineEnabled(int i, bool& b)
{
if(i >= 0 && i < litem.GetCount()) {
int kind = litem[i]->kind;
if(findarg(kind, KIND_FILE, KIND_NEST) >= 0)
b = false;
}
}
void Navigator::NaviSort()
{
sorting = !sorting;
Search();
}

View file

@ -62,7 +62,6 @@ void AutocompleteThread()
f.includes != parsed_file.includes || f.defines != parsed_file.defines ||
!clang.tu) {
parsed_file = f;
clang.Dispose();
TIMESTOP("Autocomplete parse");
autocomplete_parsing = true;
clang.Parse(fn, f.content, f.includes, f.defines,
@ -79,10 +78,10 @@ void AutocompleteThread()
CXCodeCompleteResults *results;
{
TIMESTOP("clang_codeCompleteAt");
autocomplete_parsing = false;
autocomplete_parsing = true;
results = clang_codeCompleteAt(clang.tu, fn, autocomplete_pos.y, autocomplete_pos.x, &ufile, 1,
macros ? CXCodeComplete_IncludeMacros : 0);
autocomplete_parsing = true;
autocomplete_parsing = false;
}
DumpDiagnostics(clang.tu);
if(results) {

View file

@ -9,20 +9,6 @@ int64 current_file_serial;
int64 current_file_done_serial;
Event<const Vector<AnnotationItem>&> annotations_done;
struct CurrentFileVisitor : ClangVisitor {
Vector<AnnotationItem> item;
virtual void Item() {
AnnotationItem& r = item.Add();
r.kind = GetKind();
r.name = GetName();
r.line = GetLine();
r.id = GetId();
r.pretty = GetPretty();
r.definition = IsDefinition();
r.nspace = GetNamespace();
}
};
void CurrentFileThread()
{
MemoryIgnoreLeaksBlock __;
@ -34,7 +20,7 @@ void CurrentFileThread()
auto DoAnnotations = [&] {
if(!clang.tu || !annotations_done) return;
CurrentFileVisitor v;
ClangVisitor v;
v.Do(clang.tu);
// DumpDiagnostics(clang.tu);
Ctrl::Call([&] {
@ -42,7 +28,7 @@ void CurrentFileThread()
parsed_file.real_filename == current_file.real_filename &&
parsed_file.includes == current_file.includes &&
serial == current_file_serial)
annotations_done(v.item);
annotations_done(v.item[0]);
current_file_done_serial = serial;
});
};
@ -64,7 +50,6 @@ void CurrentFileThread()
f.includes != parsed_file.includes || f.defines != parsed_file.defines ||
!clang.tu) { // TODO: same is in autocomplete
parsed_file = f;
clang.Dispose();
{
TIMESTOP("CurrentFile parse");
current_file_parsing = true;

View file

@ -0,0 +1,169 @@
#include "clang.h"
#define LTIMING(x)
#define LTIMESTOP(x)
#define LLOG(x)
struct BlitzMaker {
Time time;
String blitz;
Vector<String> individual;
void Do(const String& pk_name, const Vector<Tuple<String, bool>>& file, Hdepend& hdepend);
};
void BlitzFile(String& blitz, const String& sourceFile, Hdepend& hdepend, int index)
{
blitz << "\r\n"
<< "#define BLITZ_INDEX__ F" << index << "\r\n"
<< "#include \"" << sourceFile << "\"\r\n";
const Vector<String>& d = hdepend.GetDefines(sourceFile);
for(int i = 0; i < d.GetCount(); i++)
blitz << "#ifdef " << d[i] << "\r\n"
<< "#undef " << d[i] << "\r\n"
<< "#endif\r\n";
blitz << "#undef BLITZ_INDEX__\r\n";
}
void BlitzMaker::Do(const String& pk_name, const Vector<Tuple<String, bool>>& file, Hdepend& hdepend)
{
blitz.Clear();
individual.Clear();
time = Null;
int index = 1;
for(const auto& m : file) {
if(IsCSourceFile(m.a)) {
Time filetime = hdepend.FileTime(m.a);
time = max(Nvl(time, filetime), filetime);
if(hdepend.BlitzApproved(m.a) && !m.b)
BlitzFile(blitz, m.a, hdepend, index++);
else
individual.Add(m.a);
}
}
}
ArrayMap<String, FileAnnotation>& WriteCodeIndex()
{
DTIMING("WriteCodeIndex");
static ArrayMap<String, FileAnnotation> m;
return m;
}
const ArrayMap<String, FileAnnotation>& CodeIndex()
{
return WriteCodeIndex();
}
static std::atomic<int> indexer_pkgi;
static std::atomic<int> running_indexers;
static Index<String> visited_files;
static Mutex visited_files_mutex;
bool IsIndexing()
{
return running_indexers;
}
void Indexer(const String& includes, const String& defines)
{
static Hdepend hdepend; // shared between threads
static Mutex hdepend_mutex;
ONCELOCK {
hdepend.NoConsole();
};
Clang clang;
int tm0 = msecs();
running_indexers++;
for(;;) {
BlitzMaker m;
String pk_name;
Vector<Tuple<String, bool>> pk_files;
Index<String> pk_files_index;
{
GuiLock __;
const Workspace& wspc = GetIdeWorkspace();
int pkgi = indexer_pkgi++;
if(pkgi >= wspc.GetCount())
break;
LTIMING("Indexer Fetch");
pk_name = wspc[pkgi];
const Package& pk = wspc.GetPackage(pkgi);
for(int i = 0; i < pk.GetCount(); i++) {
String path = SourcePath(pk_name, pk[i]);
pk_files.Add({ path, pk[i].noblitz });
pk_files_index.Add(path);
}
}
{
Mutex::Lock __(hdepend_mutex);
m.Do(pk_name, pk_files, hdepend);
}
// TODO: Check time
auto ProcessResults = [&] {
ClangVisitor v;
Index<String> doing_files;
v.WhenFile = [&](const String& path) {
return pk_files_index.Find(path) >= 0;
};
{
DTIMING("Visitor");
v.Do(clang.tu);
}
{
GuiLock __;
DTIMING("Process files");
for(int i = 0; i < v.item.GetCount(); i++) {
DTIMING("Process file");
FileAnnotation& f = WriteCodeIndex().GetAdd(v.item.GetKey(i));
f.defines = defines;
f.includes = includes;
DTIMING("Process file pick");
f.items = pick(v.item[i]);
}
}
};
LTIMESTOP("======= Indexing " + pk_name);
for(const String& fn : m.individual) {
LTIMESTOP("Indexing " + fn);
clang.Parse(fn, Null, includes, defines,
CXTranslationUnit_DetailedPreprocessingRecord|
CXTranslationUnit_KeepGoing|
PARSE_FILE);
if(clang.tu)
ProcessResults();
if(Thread::IsShutdownThreads())
break;
}
if(Thread::IsShutdownThreads())
break;
LTIMESTOP("Indexing BLITZ " + pk_name);
clang.Parse(ConfigFile(pk_name + "$$$blitz.cpp"), m.blitz, includes, defines,
CXTranslationUnit_DetailedPreprocessingRecord|
CXTranslationUnit_KeepGoing);
if(clang.tu)
ProcessResults();
if(Thread::IsShutdownThreads())
break;
}
if(--running_indexers == 0)
LLOG("Done everything " << (msecs() - tm0) / 1000.0 << " s");
LLOG("Done");
}
void StartIndexing(const String& includes, const String& defines)
{
{
Mutex::Lock __(visited_files_mutex);
visited_files.Clear();
}
indexer_pkgi = 0;
if(!IsIndexing()) {
for(int i = 0; i < CPU_Cores(); i++) // TODO: CPU_Cores?
Thread::StartNice([=] { Indexer(includes, defines); });
}
}

View file

@ -177,7 +177,7 @@ String CleanupPretty(const String& signature)
return r;
}
Vector<ItemTextPart> ParseSignature(const String& name, const String& signature, int *fn_info)
Vector<ItemTextPart> ParsePretty(const String& name, const String& signature, int *fn_info)
{
Vector<ItemTextPart> part;
int name_len = name.GetLength();
@ -233,15 +233,13 @@ Vector<ItemTextPart> ParseSignature(const String& name, const String& signature,
p.type = ITEM_CPP_TYPE;
}
else
if(IsCppType(id)) {
p.type = ITEM_CPP_TYPE;
if(lastidi >= 0 && par == 0)
was_type = true;
if(IsCppKeyword(id)) {
if(id == "virtual")
part.Drop();
else
p.type = ITEM_CPP;
}
else
if(IsCppKeyword(id))
p.type = ITEM_CPP;
else
if(param) {
if(lastidi >= 0 && par == 0)
was_type = true;
@ -301,10 +299,10 @@ Vector<ItemTextPart> ParseSignature(const String& name, const String& signature,
Image CxxIcon(int kind);
String SignatureQtf(const String& name, const String& signature, int pari)
String SignatureQtf(const String& name, const String& pretty, int pari)
{
String qtf = "[%00-00K ";
Vector<ItemTextPart> n = ParseSignature(name, signature);
Vector<ItemTextPart> n = ParsePretty(name, pretty);
for(int i = 0; i < n.GetCount(); i++) {
ItemTextPart& p = n[i];
qtf << "[";
@ -331,7 +329,7 @@ String SignatureQtf(const String& name, const String& signature, int pari)
break;
}
qtf << ' ';
qtf << '\1' << signature.Mid(p.pos, p.len) << '\1';
qtf << '\1' << pretty.Mid(p.pos, p.len) << '\1';
qtf << ']';
}
return qtf + "]";

View file

@ -2,9 +2,8 @@
// #define DUMPTREE
bool ClangVisitor::ProcessNode(CXCursor c)
bool ClangVisitor::ProcessNode(CXCursor cursor)
{
cursor = c;
CXSourceLocation cxlocation = clang_getCursorLocation(cursor);
CXCursorKind cursorKind = clang_getCursorKind(cursor);
@ -16,23 +15,40 @@ bool ClangVisitor::ProcessNode(CXCursor c)
DDUMP(SourceLocation(cxlocation));
#endif
if(!clang_Location_isFromMainFile(cxlocation))
bool position_loaded = false;
unsigned line;
unsigned column;
unsigned offset;
String path;
auto LoadPosition = [&] {
if(position_loaded) return;
CXFile file;
clang_getExpansionLocation(cxlocation, &file, &line, &column, &offset);
path = FetchString(clang_getFileName(file));
position_loaded = true;
};
if(WhenFile)
LoadPosition();
if(!(WhenFile ? WhenFile(path) : clang_Location_isFromMainFile(cxlocation))) {
return findarg(cursorKind, CXCursor_StructDecl, CXCursor_UnionDecl, CXCursor_ClassDecl,
CXCursor_FunctionTemplate, CXCursor_FunctionDecl, CXCursor_Constructor,
CXCursor_Destructor, CXCursor_CXXMethod, CXCursor_ClassTemplate,
CXCursor_ClassTemplatePartialSpecialization, CXCursor_UnexposedDecl,
CXCursor_UsingDeclaration, CXCursor_VarDecl, CXCursor_EnumConstantDecl,
CXCursor_TypeAliasTemplateDecl, CXCursor_EnumDecl, CXCursor_ConversionFunction) < 0;
}
String m;
CXCursor parent = clang_getCursorSemanticParent(cursor);
CXCursorKind parentKind = clang_getCursorKind(parent);
name = GetCursorSpelling(cursor);
type = GetTypeSpelling(cursor);
String name = GetCursorSpelling(cursor);
String type = GetTypeSpelling(cursor);
String pid = FetchString(clang_getCursorPrettyPrinted(cursor, pp_id));
#ifdef DUMPTREE
_DBG_
CXCursor ref = clang_getCursorReferenced(cursor);
@ -49,16 +65,18 @@ bool ClangVisitor::ProcessNode(CXCursor c)
#endif
CXCursor p = parent;
scope.Clear();
nspace.Clear();
String scope;
String nspace;
for(;;) {
CXCursorKind k = clang_getCursorKind(p);
if(findarg(k, CXCursor_Namespace, CXCursor_ClassTemplate, CXCursor_StructDecl, CXCursor_UnionDecl, CXCursor_ClassDecl) < 0)
break;
String q = GetCursorSpelling(p);
scope = scope.GetCount() ? q + "::" + scope : q;
if(k == CXCursor_Namespace)
nspace = nspace.GetCount() ? q + "::" + nspace : q;
if(k != CXCursor_EnumDecl) {
if(findarg(k, CXCursor_Namespace, CXCursor_ClassTemplate, CXCursor_StructDecl, CXCursor_UnionDecl, CXCursor_ClassDecl) < 0)
break;
String q = GetCursorSpelling(p);
scope = scope.GetCount() ? q + "::" + scope : q;
if(k == CXCursor_Namespace)
nspace = nspace.GetCount() ? q + "::" + nspace : q;
}
p = clang_getCursorSemanticParent(p);
}
int q = scope.Find('('); // 'Struct::(unnamed enum at C:\u\upp.src\upptst\Annotations\main.cpp:47:2)'
@ -67,7 +85,7 @@ bool ClangVisitor::ProcessNode(CXCursor c)
if(scope.GetCount() && *scope.Last() != ':')
scope << "::";
annotation = true;
bool annotation = true;
if(findarg(parentKind, CXCursor_FunctionTemplate, CXCursor_FunctionDecl, CXCursor_CXXMethod,
CXCursor_Constructor, CXCursor_Destructor) >= 0)
annotation = false; // local variable
@ -76,6 +94,8 @@ bool ClangVisitor::ProcessNode(CXCursor c)
case CXCursor_StructDecl:
case CXCursor_UnionDecl:
case CXCursor_ClassDecl:
m = type;
break;
case CXCursor_FunctionTemplate:
case CXCursor_FunctionDecl:
case CXCursor_Constructor:
@ -109,17 +129,22 @@ bool ClangVisitor::ProcessNode(CXCursor c)
break;
}
if(annotation && m.GetCount()) {
CXFile file;
unsigned line_;
unsigned column_;
unsigned offset_;
clang_getExpansionLocation(cxlocation, &file, &line_, &column_, &offset_);
line = line_;
column = column_;
kind = cursorKind;
pretty = CleanupPretty(FetchString(clang_getCursorPrettyPrinted(cursor, pp_pretty)));
id = CleanupId(m);
Item();
LoadPosition();
AnnotationItem& r = item.GetAdd(path).Add();
r.kind = cursorKind;
r.name = name;
r.line = line;
r.id = CleanupId(m);
r.pretty = CleanupPretty(FetchString(clang_getCursorPrettyPrinted(cursor, pp_pretty)));
r.definition = clang_isCursorDefinition(cursor);
r.nspace = nspace;
int q = FindId(r.id, r.name);
if(q >= 0) {
r.nest = r.id.Mid(0, q);
r.nest.TrimEnd("::");
}
r.uname = ToUpper(name);
r.unest = ToUpper(r.nest);
}
return true;
}

View file

@ -0,0 +1 @@
#include "clang.h"

View file

@ -77,6 +77,8 @@ void Clang::Dispose()
bool Clang::Parse(const String& filename, const String& content, const String& includes_, const String& defines, dword options)
{
if(!index) return false;
Dispose();
String cmdline;
@ -99,10 +101,12 @@ bool Clang::Parse(const String& filename, const String& content, const String& i
for(const String& s : args)
argv.Add(~s);
CXUnsavedFile ufile = { ~filename, ~content, (unsigned)content.GetCount() };
tu = clang_parseTranslationUnit(index, nullptr, argv, argv.GetCount(), &ufile, 1, options);
CXUnsavedFile ufile = { ~filename, ~content, (unsigned)content.GetCount() };
tu = clang_parseTranslationUnit(index, nullptr, argv, argv.GetCount(),
options & PARSE_FILE ? nullptr : &ufile,
options & PARSE_FILE ? 0 : 1,
options);
// DumpDiagnostics(tu);

View file

@ -32,8 +32,9 @@ enum AdditionalKinds {
KIND_COMPLETE,
};
Image CxxIcon(int kind); // TODO: Move here
String SignatureQtf(const String& name, const String& signature, int pari);
Image CxxIcon(int kind); // TODO: Move here
int PaintCpp(Draw& w, const Rect& r, int kind, const String& name, const String& pretty, Color ink, bool focuscursor, bool retval_last = false);
String SignatureQtf(const String& name, const String& pretty, int pari);
bool IsStruct(int kind);
bool IsTemplate(int kind);
@ -64,12 +65,12 @@ struct ItemTextPart : Moveable<ItemTextPart> {
int pari;
};
Vector<ItemTextPart> ParseSignature(const String& name, const String& signature, int *fn_info = NULL);
Vector<ItemTextPart> ParsePretty(const String& name, const String& signature, int *fn_info = NULL);
struct AutoCompleteItem : Moveable<AutoCompleteItem> {
String parent;
String name;
String signature;
String signature; // TODO: rename to pretty
int kind;
int priority;
};
@ -78,10 +79,15 @@ struct AnnotationItem : Moveable<AnnotationItem> {
int kind;
int line;
bool definition;
String name;
String id;
String pretty;
String nspace;
String name; // Method
String id; // Upp::Class::Method(Upp::Point p)
String pretty; // void Class::Method(Point p)
String nspace; // Upp
String uname; // METHOD
String nest; // Upp::Class
String unest; // UPP::CLASS
~AnnotationItem() { DHITCOUNT("AnnotationItem"); }
};
struct CurrentFileContext {
@ -92,6 +98,8 @@ struct CurrentFileContext {
String content;
};
enum { PARSE_FILE = 0x80000000 };
struct Clang {
CXIndex index = nullptr;
CXTranslationUnit tu = nullptr;
@ -121,36 +129,14 @@ class ClangVisitor {
bool initialized = false;
CXPrintingPolicy pp_id, pp_pretty;
CXCursor cursor;
int kind;
String name;
String id;
String type;
String scope;
String nspace;
String pretty;
bool annotation;
int line;
int column;
bool ProcessNode(CXCursor c);
friend CXChildVisitResult clang_visitor(CXCursor cursor, CXCursor p, CXClientData clientData);
public:
virtual void Item() = 0;
int GetKind() const { return kind; }
String GetId() const { return id; }
String GetName() const { return name; }
String GetType() const { return type; }
String GetScope() const { return scope; }
String GetNamespace() const { return nspace; }
String GetPretty() const { return pretty; }
bool IsDefinition() const { return clang_isCursorDefinition(cursor); }
bool IsAnnotation() const { return annotation; }
int GetLine() const { return line; }
int GetColumn() const { return column; }
VectorMap<String, Vector<AnnotationItem>> item;
Gate<const String&> WhenFile;
void Do(CXTranslationUnit tu);
~ClangVisitor();
@ -167,4 +153,18 @@ void StartAutoComplete(const CurrentFileContext& ctx, int line, int column, bool
Event<const Vector<AutoCompleteItem>&> done);
void CancelAutoComplete();
struct FileAnnotation {
String defines;
String includes;
Time time;
Vector<AnnotationItem> items;
};
bool IsIndexing();
void StartIndexing(const String& includes, const String& defines);
const ArrayMap<String, FileAnnotation>& CodeIndex();
#endif

View file

@ -11,6 +11,7 @@ file
clang.h,
todo.txt,
help.txt,
blitz.cpp,
util.cpp,
macros.cpp,
CxxIcon.cpp,
@ -19,5 +20,6 @@ file
Codebase.cpp,
Visitor.cpp,
AutoComplete.cpp,
CurrentFile.cpp;
CurrentFile.cpp,
Indexer.cpp;

View file

@ -8,14 +8,10 @@
- failed AC keeps running (sites[i]. instead of ->)
- writing to text is slow (IsSource detection?)
- background thread problem
- MSVC
- Enum annotations
- optimise loading
- TPP HELP WINDOW->EDITOR - go to active label
@ -36,6 +32,61 @@
- this is just a test
- OpenWind.h autocomplete
- server_methods.i
- fixups?
- enum annotation popup (Ctrl::)
- .txt is pulsing all time
- Remove template < > in autocomplete
- newly created file looks like parsing until first function(?)
- current file indexing
- check editor mode
- navlines
- navigator - GotoDesignerFile
- i < items crash at start occassionally
- * nest in navigator local file
- remove $blitz items
- constructor/destructor name is not bold (check destructor in navigator display)
- PaintCpp ending spaces in navigator
- Error output: (): x += GetTextSize(" Ôćĺ ", StdFont());
- x += GetTextSize(" Ôćĺ ", StdFont()) - autocomplete fails on UTF8
LATER:
- slow .txt
- optimise hdepend (then maybe remove .h limitation for syncheaders)
DONE:
- Upp:: missing from Vector
- class Ctrl
- class Logc
- writing to text is slow (IsSource detection?)
- .txt keeps syncing
- Enum annotations

View file

@ -361,7 +361,6 @@ void Ide::DeactivateBy(Ctrl *new_focus)
DeactivationSave(true);
SaveFile();
DeactivationSave(false);
editor.SyncHeaders();
}
TopWindow::DeactivateBy(new_focus);
}
@ -657,32 +656,19 @@ void Ide::SyncClang()
auto Animate = [=](int& animator, int& dir, bool animate) -> Color {
if(animator <= 0 && !animate) return Null;
if(animate)
dir = clamp(dir, -1, 1);
animator = 20;
else
dir = -3;
if(animator >= 15)
dir = -1;
if(animator <= 0)
dir = 1;
if(phase != animate_phase)
animator = max(animator + dir, 0);
Color bg;
if(IsDarkTheme())
bg = GrayColor(70 + animator);
else {
bg = SColorLtFace();
auto C = [&](int c) { return clamp(c - animator, 0, 255); };
bg = Color(C(bg.GetR()), C(bg.GetG()), C(bg.GetG()));
}
return bg;
animator -= 3;
return Blend(IsDarkTheme() ? GrayColor(70) : SColorLtFace(), Color(198, 170, 0), animator);
};
Color bg = Animate(animate_current_file, animate_current_file_dir, IsCurrentFileParsing());
Color bg = Animate(animate_current_file, animate_current_file_dir, editor.annotating || IsCurrentFileParsing());
if(!IsNull(bg)) {
int cx = editor.GetBarSize().cx;
for(int i = 0; i < cx; i++)
a.Add(bg);
a.Add(i > cx - DPI(6) ? bg : Null);
}
editor.AnimateBar(pick(a));
editor.search.SetColor(Animate(animate_indexer, animate_indexer_dir, IsIndexing()));
display.Animate(Animate(animate_autocomplete, animate_autocomplete_dir, IsAutocompleteParsing()));
animate_phase = phase;
}

View file

@ -724,6 +724,7 @@ public:
int animate_current_file = 0, animate_current_file_dir = 0;
int animate_autocomplete = 0, animate_autocomplete_dir = 0;
int animate_indexer = 0, animate_indexer_dir = 0;
int animate_phase = 0;
// ------------------------------------

View file

@ -54,6 +54,7 @@ file
GoToLine.cpp,
Swaps.cpp,
ParamInfo.cpp,
Navigator2.cpp,
Navigator.cpp,
Annotations.cpp,
Virtuals.cpp,

View file

@ -303,7 +303,6 @@ void Ide::SaveFile(bool always)
{
issaving++;
SaveFile0(always);
editor.SyncHeaders();
issaving--;
}

View file

@ -333,8 +333,10 @@ void AppMain___()
ide.SaveLastMain();
ide.isscanning++;
ide.MakeTitle();
if(!ide.IsEditorMode())
if(!ide.IsEditorMode()) {
SyncRefs();
StartIndexing(ide.GetCurrentIncludePath(), ide.GetCurrentDefines());
}
ide.FileSelected();
ide.isscanning--;
ide.MakeTitle();