Merge branch 'llbm_ide' of https://github.com/ultimatepp/ultimatepp into llbm_ide

This commit is contained in:
Mirek Fidler 2022-07-09 18:37:45 +02:00
commit a4bd9e4283
11 changed files with 315 additions and 192 deletions

View file

@ -1,31 +1,5 @@
#include "ide.h"
void AssistEditor::Annotate(const String& filename)
{
CodeBaseLock __;
int fi = GetSourceFileIndex(filename);
CppBase& base = CodeBase();
ClearAnnotations();
#if 0
for(int j = 0; j < base.GetCount(); j++) {
String nest = base.GetKey(j);
if(*nest != '@') { // Annotations of anonymous structures not suported
const Array<CppItem>& n = base[j];
for(int k = 0; k < n.GetCount(); k++) {
const CppItem& m = n[k];
if(m.file == fi) {
String coderef = MakeCodeRef(nest, m.qitem);
SetAnnotation(m.line - 1,
GetRefLinks(coderef).GetCount() ? IdeImg::tpp_doc()
: IdeImg::tpp_pen(),
coderef);
}
}
}
}
#endif
}
bool IsCodeItem(const RichTxt& txt, int i)
{
static Uuid codeitem = CodeItemUuid();

View file

@ -482,22 +482,24 @@ void AssistEditor::SyncCurrentFile()
{
int line_delta;
CurrentFileContext cfx = CurrentContext(line_delta);
annotations_dirty = true;
if(cfx.content.GetCount())
SetCurrentFile(CurrentContext(line_delta), [=](const Vector<AnnotationItem>& annotations_) {
ClearAnnotations();
annotations = clone(annotations_);
for(auto& m : annotations) {
int l = m.line - line_delta - 1;
if(l >= 0) {
m.line -= line_delta + 1;
if(m.line >= 0) {
String mm = m.id;
if(line_delta)
FixItNamespace(mm);
SetAnnotation(l,
SetAnnotation(m.line,
GetRefLinks(mm).GetCount() ? IdeImg::tpp_doc()
: IdeImg::tpp_pen(),
mm);
}
}
annotations_dirty = false;
});
}
@ -803,6 +805,25 @@ bool isaid(int c)
bool AssistEditor::Key(dword key, int count)
{
#ifdef _DEBUG
if(key == K_F12) {
int l = GetLine(GetCursor());
for(const AnnotationItem& m : annotations)
if(m.line == l) {
PromptOK(String() <<
"kind: \1" << m.kind << "\1&" <<
"name: \1" << m.name << "\1&" <<
"id: \1" << m.id << "\1&" <<
"pretty: \1" << m.pretty << "\1&" <<
"nspace: \1" << m.nspace << "\1&" <<
"definition: \1" << m.definition << "\1&" <<
"extern: \1" << m.external << "\1&"
);
return true;
}
Exclamation("No annotation for this line.");
}
#endif
if(popup.IsOpen()) {
int k = key & ~K_CTRL;
ArrayCtrl& kt = key & K_CTRL ? type : assist;

View file

@ -151,6 +151,7 @@ struct AssistEditor : CodeEditor, Navigator {
} assist_display;
RichTextCtrl annotation_popup;
bool annotations_dirty = true;
Vector<AnnotationItem> annotations;
int assist_cursor;
@ -248,7 +249,6 @@ struct AssistEditor : CodeEditor, Navigator {
bool GetAnnotationRef(String& t, String& coderef, int q = -1);
void SyncAnnotationPopup();
void EditAnnotation(bool fastedit);
void Annotate(const String& filename);
void OpenTopic(String topic, String create, bool before);
void NewTopic(String group, String coderef);

View file

@ -403,7 +403,6 @@ String CreateQtf(const AnnotationItem& m, const String& lang, bool onlyhdr = fal
qtf << "[s4 &]";
String st = str ? "[s2;" : "[s1;";
String k = st + ":" + DeQtf(m.id) + ": ";
DDUMP(m.id);
if(IsTemplate(m.kind) && str) {
int q = 0;
int w = 0;
@ -450,8 +449,6 @@ String CreateQtf(const AnnotationItem& m, const String& lang, bool onlyhdr = fal
}
qtf << "&]";
qtf << "[s7 &]";
DDUMP(qtf);
DDUMP(AsQTF(ParseQTF(qtf)));
return qtf;
}

View file

@ -11,7 +11,92 @@
#endif
void AssistEditor::DCopy()
{
{ // changes declaration <-> definition
String r;
int l, h;
if(!GetSelection32(l, h))
l = h = GetCursor();
int first_line = GetLine(l);
int last_line = GetLine(h);
if(last_line - first_line > 10000) {
Exclamation("Too many lines.");
return;
}
if(annotations_dirty) {
Progress pi("Parsing");
while(annotations_dirty)
if(pi.StepCanceled())
return;
}
String result;
for(const AnnotationItem& m : annotations) {
if(first_line <= m.line && m.line <= last_line) {
String cls = m.id;
int q = FindId(cls, m.name);
if(q >= 0) {
cls.Trim(q);
if(m.nspace.GetCount())
cls.TrimStart(m.nspace + "::");
if(IsFunction(m.kind)) {
if(m.definition) {
if(cls.GetCount())
result << '\t';
result << m.pretty << ";\n";
}
else {
int q = FindId(m.pretty, m.name);
if(q < 0)
result << m.pretty;
else
result << m.pretty.Mid(0, q) << cls << m.pretty.Mid(q);
result << "\n{\n}\n\n";
}
}
if(m.kind == CXCursor_VarDecl) {
if(cls.GetCount()) { // class variable
if(m.definition) {
int q = FindId(m.pretty, m.name);
if(q >= 0) {
int w = m.pretty.ReverseFind(' ', q);
if(w >= 0)
result << "\tstatic " << m.pretty.Mid(0, w + 1) << m.pretty.Mid(q) << "\n";
}
}
else {
String h = m.pretty;
h.TrimStart("static ");
h = TrimLeft(h);
int q = FindId(h, m.name);
if(q >= 0)
result << h.Mid(0, q) << cls << h.Mid(q) << ";\n";
}
}
else { // just toggle extern
String h = m.pretty;
if(m.external)
h.TrimStart("extern ");
else
h = "extern " + h;
result << h << ";\n";
}
}
}
}
}
if(result.GetCount() == 0) {
PromptOK("No relevant declarations found.");
return;
}
WriteClipboardText(result);
#if 0
String r;
int l, h;
bool decla = false;
@ -42,7 +127,7 @@ void AssistEditor::DCopy()
}
else
decla = true;
ParserContext ctx;
Context(ctx, l);
String txt = Get(l, h - l);
@ -62,88 +147,74 @@ void AssistEditor::DCopy()
CppBase cpp;
SimpleParse(cpp, txt, cls);
if(cpp.GetCount() == 0) { // scan for THISBACKs
Index<String> id;
CParser p(txt);
try {
while(!p.IsEof()) {
if(p.Id("THISBACK") && p.Char('('))
id.FindAdd(p.ReadId());
p.SkipTerm();
}
}
catch(CParser::Error) {
}
for(int i = 0; i < id.GetCount(); i++)
r << "\tvoid " << id[i] << "();\n";
}
else
for(int i = 0; i < cpp.GetCount(); i++) {
const Array<CppItem>& n = cpp[i];
bool decl = decla;
for(int j = 0; j < n.GetCount(); j++)
if(n[j].impl)
decl = false;
for(int j = 0; j < n.GetCount(); j++) {
const CppItem& m = n[j];
if(m.IsCode()) {
if(decl)
r << MakeDefinition(cls, m.natural) << "\n{\n}\n\n";
else {
if(cpp.IsType(i))
r << String('\t', Split(cpp.GetKey(i), ':').GetCount());
r << m.natural << ";\n";
}
for(int i = 0; i < cpp.GetCount(); i++) {
const Array<CppItem>& n = cpp[i];
bool decl = decla;
for(int j = 0; j < n.GetCount(); j++)
if(n[j].impl)
decl = false;
for(int j = 0; j < n.GetCount(); j++) {
const CppItem& m = n[j];
if(m.IsCode()) {
if(decl)
r << MakeDefinition(cls, m.natural) << "\n{\n}\n\n";
else {
if(cpp.IsType(i))
r << String('\t', Split(cpp.GetKey(i), ':').GetCount());
r << m.natural << ";\n";
}
if(m.IsData()) {
String nat = m.natural;
if(cls.GetCount()) {
nat.Replace("static", "");
nat = TrimLeft(nat);
const char *s = nat;
while(*s) {
if(iscib(*s)) {
const char *b = s;
while(iscid(*s)) s++;
String id(b, s);
if(m.name == id) {
if(cls.GetCount())
r << cls << "::" << m.name << s;
else
r << m.name << s;
break;
}
r << id;
}
if(m.IsData()) {
String nat = m.natural;
if(cls.GetCount()) {
nat.Replace("static", "");
nat = TrimLeft(nat);
const char *s = nat;
while(*s) {
if(iscib(*s)) {
const char *b = s;
while(iscid(*s)) s++;
String id(b, s);
if(m.name == id) {
if(cls.GetCount())
r << cls << "::" << m.name << s;
else
r << m.name << s;
break;
}
else
r << *s++;
}
}
else {
int q = nat.ReverseFind("::");
if(q >= 0) { // Foo Class2 :: Class::variable; -> static Foo variable;
int e = q + 2;
for(;;) {
while(q >= 0 && nat[q - 1] == ' ')
q--;
if(q == 0 || !iscid(nat[q - 1]))
break;
while(q >= 0 && iscid(nat[q - 1]))
q--;
int w = nat.ReverseFind("::", q);
if(w < 0)
break;
q = w;
}
nat.Remove(q, e - q);
r << "static " << nat;
r << id;
}
else
r << "extern " << nat;
r << *s++;
}
r << ";\n";
}
else {
int q = nat.ReverseFind("::");
if(q >= 0) { // Foo Class2 :: Class::variable; -> static Foo variable;
int e = q + 2;
for(;;) {
while(q >= 0 && nat[q - 1] == ' ')
q--;
if(q == 0 || !iscid(nat[q - 1]))
break;
while(q >= 0 && iscid(nat[q - 1]))
q--;
int w = nat.ReverseFind("::", q);
if(w < 0)
break;
q = w;
}
nat.Remove(q, e - q);
r << "static " << nat;
}
else
r << "extern " << nat;
}
r << ";\n";
}
}
}
WriteClipboardText(r);
#endif
}

View file

@ -50,19 +50,18 @@ CXChildVisitResult current_file_visitor( CXCursor cursor, CXCursor p, CXClientDa
String name = GetCursorSpelling(cursor);
String type = GetTypeSpelling(cursor);
String id = FetchString(clang_getCursorPrettyPrinted(cursor, pp_id));
String scope = GetTypeSpelling(parent);
if(scope.GetCount() == 0) { // type is fully qualified, otherwise scan up for namespaces
CXCursor p = parent;
for(;;) {
CXCursorKind k = clang_getCursorKind(p);
if(findarg(k, CXCursor_Namespace, CXCursor_ClassTemplate) < 0)
break;
String q = GetCursorSpelling(p);
if(scope.GetCount())
q << "::" << scope;
scope = q;
p = clang_getCursorSemanticParent(p);
}
CXCursor p = parent;
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;
p = clang_getCursorSemanticParent(p);
}
int q = scope.Find('('); // 'Struct::(unnamed enum at C:\u\upp.src\upptst\Annotations\main.cpp:47:2)'
if(q >= 0)
@ -71,7 +70,7 @@ CXChildVisitResult current_file_visitor( CXCursor cursor, CXCursor p, CXClientDa
scope << "::";
auto Dump = [&] {
#if 0
#if 1
SourceLocation location(cxlocation);
LOG("=====================");
// DDUMP(location);
@ -82,6 +81,7 @@ CXChildVisitResult current_file_visitor( CXCursor cursor, CXCursor p, CXClientDa
DDUMP(id);
DDUMP(CleanupId(id));
DDUMP(scope);
DDUMP(nspace);
DDUMP(clang_isCursorDefinition(cursor));
static CXPrintingPolicy pp = clang_getCursorPrintingPolicy(cursor);
ONCELOCK {
@ -128,50 +128,52 @@ CXChildVisitResult current_file_visitor( CXCursor cursor, CXCursor p, CXClientDa
#endif
};
// Dump();
Dump();
switch(cursorKind) {
case CXCursor_StructDecl:
case CXCursor_UnionDecl:
case CXCursor_ClassDecl:
case CXCursor_FunctionTemplate:
case CXCursor_FunctionDecl:
case CXCursor_Constructor:
case CXCursor_Destructor:
case CXCursor_CXXMethod:
m = id;
break;
case CXCursor_VarDecl:
if(findarg(parentKind, CXCursor_FunctionTemplate, CXCursor_FunctionDecl, CXCursor_CXXMethod) >= 0) {
valid = false; // local variable
bool external = false;
if(findarg(parentKind, CXCursor_FunctionTemplate, CXCursor_FunctionDecl, CXCursor_CXXMethod,
CXCursor_Constructor, CXCursor_Destructor) >= 0)
valid = false; // local variable
else
switch(cursorKind) {
case CXCursor_StructDecl:
case CXCursor_UnionDecl:
case CXCursor_ClassDecl:
case CXCursor_FunctionTemplate:
case CXCursor_FunctionDecl:
case CXCursor_Constructor:
case CXCursor_Destructor:
case CXCursor_CXXMethod:
m = id;
break;
case CXCursor_VarDecl:
external = clang_Cursor_hasVarDeclExternalStorage(cursor);
case CXCursor_FieldDecl:
case CXCursor_ClassTemplate:
m << scope << name;
break;
case CXCursor_ConversionFunction:
m << scope << "operator " << type;
break;
case CXCursor_MacroDefinition:
m = name;
break;
case CXCursor_EnumConstantDecl:
m << scope << name;
break;
case CXCursor_EnumDecl:
// case CXCursor_ParmDecl:
case CXCursor_TypedefDecl:
case CXCursor_Namespace:
case CXCursor_UnexposedDecl:
// case CXCursor_NamespaceAlias:
break;
default:
valid = false;
break;
}
case CXCursor_ClassTemplate:
case CXCursor_FieldDecl:
m << scope << name;
break;
case CXCursor_ConversionFunction:
m << scope << "operator " << type;
break;
case CXCursor_MacroDefinition:
m = name;
break;
case CXCursor_EnumConstantDecl:
m << scope << name;
break;
case CXCursor_EnumDecl:
// case CXCursor_ParmDecl:
case CXCursor_TypedefDecl:
case CXCursor_Namespace:
case CXCursor_UnexposedDecl:
// case CXCursor_NamespaceAlias:
break;
default:
valid = false;
break;
}
if(valid) {
Dump();
// Dump();
if(m.GetCount()) {
CXFile file;
unsigned line_;
@ -183,6 +185,9 @@ CXChildVisitResult current_file_visitor( CXCursor cursor, CXCursor p, CXClientDa
r.name = name;
r.line = line_;
r.id = CleanupId(m);
r.definition = clang_isCursorDefinition(cursor);
r.external = external;
r.nspace = nspace;
static CXPrintingPolicy pp;
ONCELOCK {
pp = clang_getCursorPrintingPolicy(cursor);
@ -191,7 +196,7 @@ CXChildVisitResult current_file_visitor( CXCursor cursor, CXCursor p, CXClientDa
clang_PrintingPolicy_setProperty(pp, CXPrintingPolicy_TerseOutput, 1);
clang_PrintingPolicy_setProperty(pp, CXPrintingPolicy_SuppressScope, 1);
}
r.pretty = CleanupSignature(FetchString(clang_getCursorPrettyPrinted(cursor, pp)));
r.pretty = CleanupPretty(FetchString(clang_getCursorPrettyPrinted(cursor, pp)));
}
}
}
@ -239,7 +244,9 @@ void CurrentFileThread()
auto DoAnnotations = [&] {
if(!tu || !annotations_done) return;
Vector<AnnotationItem> item;
{ TIMESTOP("DoAnnotations");
clang_visitChildren(clang_getTranslationUnitCursor(tu), current_file_visitor, &item);
}
Ctrl::Call([&] {
if(parsed_file.filename == current_file.filename &&
parsed_file.real_filename == current_file.real_filename &&
@ -311,7 +318,7 @@ void CurrentFileThread()
AutoCompleteItem& m = item.Add();
m.name = name;
m.parent = FetchString(clang_getCompletionParent(string, NULL));
m.signature = CleanupSignature(signature);
m.signature = CleanupPretty(signature);
m.kind = kind;
m.priority = clang_getCompletionPriority(string);
}
@ -341,7 +348,7 @@ void StartCurrentFileParserThread()
{
MemoryIgnoreNonMainLeaks();
MemoryIgnoreNonUppThreadsLeaks(); // clangs leaks static memory in threads
Thread::StartNice([] { CurrentFileThread(); });
Thread::Start([] { CurrentFileThread(); });
}
void SetCurrentFile(const CurrentFileContext& ctx, Event<const Vector<AnnotationItem>&> done)

View file

@ -2,22 +2,6 @@
#define LTIMING(x)
bool IsStruct(int kind)
{
return findarg(kind, CXCursor_StructDecl, CXCursor_UnionDecl, CXCursor_ClassDecl, CXCursor_ClassTemplate) >= 0;
}
bool IsTemplate(int kind)
{
return findarg(kind, CXCursor_FunctionTemplate, CXCursor_ClassTemplate) >= 0;
}
bool IsSourceFile(const String& path)
{
String ext = ToLower(GetFileExt(path));
return findarg(ext, ".cpp", ".cc", ".cxx", ".icpp", ".c") >= 0;
}
bool IsCppKeyword(const String& id);
bool IsCppType(const String& id);
@ -50,8 +34,8 @@ String CleanupId(const char *s)
bool was_space = false;
bool was_name = false;
bool function = false;
static String operator_id1 = "operator";
static String operator_id2 = ":operator";
bool destructor = false;
int name_pos = 0; // to filter out eventual return value of function
bool operator_def = false; // between operator and ( - suppress < > handling
while(*s && *s != '{') {
if(iscid(*s)) {
@ -79,6 +63,7 @@ String CleanupId(const char *s)
was_param_type = true;
if(was_id)
mm.Cat(' ');
name_pos = mm.GetCount();
mm.Cat(id);
was_id = true;
was_name = true;
@ -89,7 +74,7 @@ String CleanupId(const char *s)
s++;
}
else
if(*s == '<' && !function && !operator_def) { // remove template stuff before params, e.g. Buffer<T>();
if(*s == '<' && !operator_def) { // remove template stuff e.g. Buffer<T>(Vector<T>) -> Buffer(Vector);
int lvl = 1;
s++;
while(*s && lvl) {
@ -102,10 +87,16 @@ String CleanupId(const char *s)
}
else {
was_id = was_space = false;
if(*s == '~' && !operator_def) // prevent culling of 'return value' in destructor
destructor = true;
if(*s == '(') {
function = true;
was_param_type = false;
operator_def = false;
if(name_pos && !destructor) {
String h = String(mm).Mid(name_pos);
mm = h;
}
}
if(*s == ',')
was_param_type = false;
@ -118,12 +109,26 @@ String CleanupId(const char *s)
return mm;
}
String CleanupSignature(const String& signature)
String CleanupPretty(const String& signature)
{
LTIMING("CleanupSignature");
LTIMING("CleanupPretty");
StringBuffer result;
const char *s = signature;
while(*s)
if(iscib(*s)) {
const char *b = s;
while(iscid(*s))
s++;
int len = s - b;
if(len == 5 && (memcmp(b, "class", 5) == 0 || memcmp(b, "union", 5) == 0) ||
len == 6 && (memcmp(b, "struct", 6) == 0 || memcmp(b, "extern", 6) == 0)) {
while(*s == ' ')
s++;
continue;
}
result.Cat(b, s);
}
else
if(s[0] == ' ' && s[1] == '*' && s[2] == ' ') {
result.Cat(' ');
result.Cat('*');

View file

@ -38,6 +38,9 @@ String SignatureQtf(const String& name, const String& signature, int pari);
bool IsStruct(int kind);
bool IsTemplate(int kind);
bool IsFunction(int kind);
bool IsVariable(int kind);
int FindId(const char *s, const String& id);
enum {
ITEM_TEXT,
@ -75,9 +78,12 @@ struct AutoCompleteItem : Moveable<AutoCompleteItem> {
struct AnnotationItem : Moveable<AnnotationItem> {
int kind;
int line;
bool definition;
bool external;
String name;
String id;
String pretty;
String nspace;
};
struct CurrentFileContext {
@ -93,8 +99,9 @@ void StartCurrentFileParserThread();
void DumpDiagnostics(CXTranslationUnit tu);
String CleanupSignature(const String& signature);
String CleanupId(const char *s);
String CleanupPretty(const String& signature);
bool IsSourceFile(const String& path);
void SetCurrentFile(const CurrentFileContext& ctx, Event<const Vector<AnnotationItem>&> done);

View file

@ -10,6 +10,7 @@ library(POSIX) clang;
file
clang.h,
help.txt,
util.cpp,
macros.cpp,
CxxIcon.cpp,
Signature.cpp,

42
uppsrc/ide/clang/util.cpp Normal file
View file

@ -0,0 +1,42 @@
#include "clang.h"
bool IsSourceFile(const String& path)
{
String ext = ToLower(GetFileExt(path));
return findarg(ext, ".cpp", ".cc", ".cxx", ".icpp", ".c") >= 0;
}
bool IsStruct(int kind)
{
return findarg(kind, CXCursor_StructDecl, CXCursor_UnionDecl, CXCursor_ClassDecl,
CXCursor_ClassTemplate) >= 0;
}
bool IsTemplate(int kind)
{
return findarg(kind, CXCursor_FunctionTemplate, CXCursor_ClassTemplate) >= 0;
}
bool IsFunction(int kind)
{
return findarg(kind, CXCursor_FunctionTemplate, CXCursor_FunctionDecl, CXCursor_Constructor,
CXCursor_Destructor, CXCursor_ConversionFunction, CXCursor_CXXMethod) >= 0;
}
bool IsVariable(int kind)
{
return findarg(kind, CXCursor_VarDecl, CXCursor_FieldDecl) >= 0;
}
int FindId(const char *s, const String& id)
{
CParser p(s);
while(!p.IsEof()) {
const char *q = p.GetPtr();
if(p.Id(id))
return q - s;
else
p.Skip();
}
return -1;
}

View file

@ -623,7 +623,6 @@ void Ide::EditFile0(const String& path, byte charset, int spellcheck_comments, c
editor.SyncNavigatorShow();
editor.assist_active = IsProjectFile(editfile) && IsCppBaseFile();
editor.CheckEdited(true);
editor.Annotate(editfile);
editor.SyncNavigator();
editor.SyncCurrentFile();
editfile_repo = GetRepoKind(editfile);
@ -666,8 +665,8 @@ void Ide::ScanFile(bool check_includes)
bool Ide::EditFileAssistSync2()
{
if(TryLockCodeBase()) {
editor.Annotate(editfile);
editor.SyncNavigator();
editor.SyncCurrentFile();
UnlockCodeBase();
return true;
}
@ -1026,7 +1025,6 @@ void Ide::PassEditor()
editor2.CheckEdited();
editor.SetFocus();
editor.ScrollIntoCursor();
editor2.Annotate(editfile2);
editor2.SpellcheckComments(editor.GetSpellcheckComments());
}