From 5a45cede81df31a10dddc896eadcf62dac7a1f98 Mon Sep 17 00:00:00 2001 From: Mirek Fidler Date: Wed, 18 Jun 2025 15:42:48 +0200 Subject: [PATCH] ide: Fixed problems in CleanupId --- autotest/ide_CleanupId/Etalon.log | 50 +++++++++ autotest/ide_CleanupId/ide_CleanupId.cpp | 36 +++++++ autotest/ide_CleanupId/ide_CleanupId.upp | 11 ++ uppsrc/ide/Core/Core.h | 29 +++++ uppsrc/ide/Core/Core.upp | 1 + uppsrc/ide/{clang => Core}/Signature.cpp | 131 +++++------------------ uppsrc/ide/Usage.cpp | 4 + uppsrc/ide/clang/clang.h | 29 ----- uppsrc/ide/clang/clang.upp | 1 - uppsrc/ide/clang/util.cpp | 90 ++++++++++++++++ upptst/ide_CleanupId/ide_CleanupId.cpp | 4 +- 11 files changed, 251 insertions(+), 135 deletions(-) create mode 100644 autotest/ide_CleanupId/Etalon.log create mode 100644 autotest/ide_CleanupId/ide_CleanupId.cpp create mode 100644 autotest/ide_CleanupId/ide_CleanupId.upp rename uppsrc/ide/{clang => Core}/Signature.cpp (84%) diff --git a/autotest/ide_CleanupId/Etalon.log b/autotest/ide_CleanupId/Etalon.log new file mode 100644 index 000000000..106c59904 --- /dev/null +++ b/autotest/ide_CleanupId/Etalon.log @@ -0,0 +1,50 @@ +* C:\upp\out\autotest\CLANGx64.Debug.Debug_Full\ide_CleanupId.exe 18.06.2025 15:41:39, user: mirek + +====== +Foo1::operator<<(int) +id: Foo1::operator<<(int) +pretty: Foo1::operator<<(int) +====== +Foo1::operator<(int) +id: Foo1::operator<(int) +pretty: Foo1::operator<(int) +====== +Upp::Index::Find(const Upp::String &k) const +id: Upp::Index::Find(const String&)const +pretty: Upp::Index::Find(const Upp::String& k) const +====== +clang_PrintingPolicy_setProperty(CXPrintingPolicy Policy, enum CXPrintingPolicyProperty Property, unsigned int Value) __attribute__((dllimport)) +id: clang_PrintingPolicy_setProperty(CXPrintingPolicy,CXPrintingPolicyProperty,unsigned int) +pretty: clang_PrintingPolicy_setProperty(CXPrintingPolicy Policy, enum CXPrintingPolicyProperty Property, unsigned int Value) +====== +Foo1::Method() +id: Foo1::Method() +pretty: Foo1::Method() +====== +Foo3::Foo3() noexcept +id: Foo3::Foo3() +pretty: Foo3::Foo3() +====== +Foo1::operator*(int) +id: Foo1::operator*(int) +pretty: Foo1::operator*(int) +====== +main(int argc, const char *argv[]) +id: main(int,const char*[]) +pretty: main(int argc, const char *argv[]) +====== +Ns::EditText(int &s, const char *title, const char *label, int (*f)(int), int maxlen, bool notnull) +id: Ns::EditText(int&,const char*,const char*,int(*)(int),int,bool) +pretty: Ns::EditText(int& s, const char *title, const char *label, int (*f)(int), int maxlen, bool notnull) +====== +template auto SubRange(C&& c, int pos, int count) -> decltype(SubRange(c.begin() + pos, count)) +id: SubRange(C&&,int,int) +pretty: template auto SubRange(C&& c, int pos, int count) +====== +inline void Foo() +id: Foo() +pretty: void Foo() +====== +int (*test)(int (*test)()) +id: int(*test)(int(*)()) +pretty: int (*test)(int (*test)()) diff --git a/autotest/ide_CleanupId/ide_CleanupId.cpp b/autotest/ide_CleanupId/ide_CleanupId.cpp new file mode 100644 index 000000000..91adda4b4 --- /dev/null +++ b/autotest/ide_CleanupId/ide_CleanupId.cpp @@ -0,0 +1,36 @@ +#include + +using namespace Upp; + +CONSOLE_APP_MAIN +{ + StdLogSetup(LOG_COUT|LOG_FILE); + +#if 0 + String s = CleanupId("int (*test)(int (*test)())"); + DDUMP(s); + return; +#endif + + for(String s : { + "Foo1::operator<<(int)", + "Foo1::operator<(int)", + "Upp::Index::Find(const Upp::String &k) const", + "clang_PrintingPolicy_setProperty(CXPrintingPolicy Policy, enum CXPrintingPolicyProperty Property, unsigned int Value) __attribute__((dllimport))", + "Foo1::Method()", + "Foo3::Foo3() noexcept", + "Foo1::operator*(int)", + "main(int argc, const char *argv[])", + "Ns::EditText(int &s, const char *title, const char *label, int (*f)(int), int maxlen, bool notnull)", + "template auto SubRange(C&& c, int pos, int count) -> decltype(SubRange(c.begin() + pos, count))", + "inline void Foo()", + "int (*test)(int (*test)())" + }) { + DLOG("======"); + DLOG(s); + DLOG("id: " << CleanupId(s)); + DLOG("pretty: " << CleanupPretty(s)); + } + + CheckLogEtalon(); +} diff --git a/autotest/ide_CleanupId/ide_CleanupId.upp b/autotest/ide_CleanupId/ide_CleanupId.upp new file mode 100644 index 000000000..a7f38ddd2 --- /dev/null +++ b/autotest/ide_CleanupId/ide_CleanupId.upp @@ -0,0 +1,11 @@ +uses + Core, + ide/Core; + +file + Etalon.log, + ide_CleanupId.cpp; + +mainconfig + "" = ""; + diff --git a/uppsrc/ide/Core/Core.h b/uppsrc/ide/Core/Core.h index e244f5ca9..4acafe2b2 100644 --- a/uppsrc/ide/Core/Core.h +++ b/uppsrc/ide/Core/Core.h @@ -667,4 +667,33 @@ int GetRepoKind(const String& p); int GetRepo(String& path); String GetGitPath(); +enum { + ITEM_TEXT, + ITEM_NAME, + ITEM_OPERATOR, + ITEM_CPP_TYPE, + ITEM_CPP, + ITEM_PNAME, + ITEM_TNAME, + ITEM_NUMBER, + ITEM_SIGN, + ITEM_UPP, + ITEM_TYPE, + + ITEM_PTYPE = ITEM_TYPE + 10000, +}; + +struct ItemTextPart : Moveable { + int pos; + int len; + int type; + int ii; + int pari; +}; + +String CleanupId(const char *s); +String CleanupPretty(const String& signature); + +Vector ParsePretty(const String& name, const String& signature, int *fn_info = NULL); + #endif \ No newline at end of file diff --git a/uppsrc/ide/Core/Core.upp b/uppsrc/ide/Core/Core.upp index 2768dea85..8eaa6b5f9 100644 --- a/uppsrc/ide/Core/Core.upp +++ b/uppsrc/ide/Core/Core.upp @@ -20,6 +20,7 @@ file Workspace.cpp, usc.cpp, BinObj.cpp, + Signature.cpp, Host readonly separator, Host.h, Host.cpp, diff --git a/uppsrc/ide/clang/Signature.cpp b/uppsrc/ide/Core/Signature.cpp similarity index 84% rename from uppsrc/ide/clang/Signature.cpp rename to uppsrc/ide/Core/Signature.cpp index 9d96387f5..e12d8b38d 100644 --- a/uppsrc/ide/clang/Signature.cpp +++ b/uppsrc/ide/Core/Signature.cpp @@ -1,4 +1,4 @@ -#include "clang.h" +#include "Core.h" #define LTIMING(x) @@ -47,12 +47,12 @@ bool IsBasicType(const String& id) bool IsIgnored(const String& id) { - static Index kt = { "class", "struct", "union", "noexcept", "override", "final", "template", "enum" }; + static Index kt = { "class", "struct", "union", "noexcept", "override", "final", "template", "enum", "__attribute__" }; return kt.Find(id) >= 0; } String CleanupId(const char *s) -{ // removes unnecessary spaces, removes parameter names +{ // removes unnecessary spaces, removes parameter names, makes clang ids consistent StringBuffer mm; bool was_param_type = false; bool was_id = false; @@ -82,18 +82,32 @@ String CleanupId(const char *s) }; String id; - while(iscid(*s) || *s == ':') { - id.Cat(*s++); - if(*s == '<') { - if(id.GetCount() == 8 && IsOperator(id)) - break; - if(id.GetCount() > 8) { - const char *s = ~id + id.GetCount() - 8; - if(IsOperator(s) && !iscid(s[-1])) + for(;;) { + if(iscid(*s)) { + id.Cat(*s++); + if(*s == '<') { + if(id.GetCount() == 8 && IsOperator(id)) break; + if(id.GetCount() > 8) { + const char *s = ~id + id.GetCount() - 8; + if(IsOperator(s) && !iscid(s[-1])) + break; + } + SkipT(); // Skip template arguments like in Foo::Method() -> Foo::Method } - SkipT(); // Skip template arguments like in Foo::Method() -> Foo::Method } + else + if(*s == ':' && s[1] == ':') { + if(inparams) + id.Clear(); // remove qualification from parameters (it is inconsistent with libclang) + else { + id.Cat(':'); + id.Cat(':'); + } + s += 2; + } + else + break; } if(id == s_attribute) { while(*s == ' ') @@ -160,8 +174,9 @@ String CleanupId(const char *s) was_param_type = false; operator_def = false; } - if(s[1] == '*') { // function pointer, e.g. int(*)(int) + if(s[1] == '*' && inparams) { // function pointer, e.g. int(*)(int) was_param_type = false; // prevent skipping ^^^ + mm.Cat('('); while(*s && *s != ')') { if(*s == '*') // exclude any names mm.Cat(*s); @@ -467,93 +482,3 @@ String SignatureQtf(const String& name, const String& pretty, int pari) } return qtf + "]"; } - -String GetClass(const AnnotationItem& m) -{ - String cls = m.id; - int q; - if(m.kind == CXCursor_Constructor) { - q = cls.Find("::" + m.name + "("); - if(q >= 0) - q += 2; - } - else - if(m.kind == CXCursor_Destructor) { - q = cls.Find('~'); - } - else - q = FindId(cls, m.name); - - if(q >= 0) { - cls.Trim(q); - if(m.nspace.GetCount()) - cls.TrimStart(m.nspace + "::"); - return cls; - } - - return Null; -} - -String GetNameFromId(const String& id) -{ - String name; - try { - CParser p(id); - while(!p.IsEof()) - if(p.IsId()) - name = p.ReadId(); - else - if(!p.Char(':')) - break; - } - catch(CParser::Error) {} - return name; -} - -String MakeDefinition(const AnnotationItem& m, const String& klass) -{ - String result; - String pretty = m.pretty; - pretty.TrimStart("static "); - int q = FindId(pretty, m.name); - if(q < 0) - result << pretty; - else - result << pretty.Mid(0, q) << klass << pretty.Mid(q); - - const char *s = result; - int lvl = 0; - String r; - while(*s) { - if(*s == '(') - lvl++; - if(*s == ')') - lvl--; - if(lvl == 1 && *s == '=') { // skip default parameter - while(r.GetCount() && s[-1] == ' ') { - s--; - r.TrimLast(); - } - while(*s) { - if((*s == ',' || *s == ')') && lvl == 1) { - r.Cat(*s++); - break; - } - if(*s == '(') - lvl++; - if(*s == ')') - lvl--; - s++; - } - } - else - r.Cat(*s++); - } - r << "\n{\n}\n\n"; - return r; -} - -String MakeDefinition(const AnnotationItem& m) -{ - return MakeDefinition(m, GetClass(m)); -} \ No newline at end of file diff --git a/uppsrc/ide/Usage.cpp b/uppsrc/ide/Usage.cpp index af66f081f..800533c81 100644 --- a/uppsrc/ide/Usage.cpp +++ b/uppsrc/ide/Usage.cpp @@ -120,6 +120,10 @@ void Ide::Usage(const String& id, const String& name, Point ref_pos) if(IsNull(id)) return; + DDUMP(name); + DDUMP(id); + DDUMP(ref_pos); + ResetFileLine(); int li = editor.GetCursorLine(); diff --git a/uppsrc/ide/clang/clang.h b/uppsrc/ide/clang/clang.h index c32a08ecf..341c25498 100644 --- a/uppsrc/ide/clang/clang.h +++ b/uppsrc/ide/clang/clang.h @@ -100,32 +100,6 @@ bool IsFunction(int kind); bool IsVariable(int kind); int FindId(const String& s, const String& id); -enum { - ITEM_TEXT, - ITEM_NAME, - ITEM_OPERATOR, - ITEM_CPP_TYPE, - ITEM_CPP, - ITEM_PNAME, - ITEM_TNAME, - ITEM_NUMBER, - ITEM_SIGN, - ITEM_UPP, - ITEM_TYPE, - - ITEM_PTYPE = ITEM_TYPE + 10000, -}; - -struct ItemTextPart : Moveable { - int pos; - int len; - int type; - int ii; - int pari; -}; - -Vector ParsePretty(const String& name, const String& signature, int *fn_info = NULL); - struct AutoCompleteItem : Moveable { String parent; String name; @@ -211,9 +185,6 @@ void Diagnostics(CXTranslationUnit tu, Stream& out); inline bool IsWarning(int q) { return q == CXDiagnostic_Warning; } inline bool IsError(int q) { return findarg(q, CXDiagnostic_Error, CXDiagnostic_Fatal) >= 0; } -String CleanupId(const char *s); -String CleanupPretty(const String& signature); - bool IsCppSourceFile(const String& path); bool IsSourceFile(const String& path); bool IsHeaderFile(const String& path); diff --git a/uppsrc/ide/clang/clang.upp b/uppsrc/ide/clang/clang.upp index ffa13892a..5f60232c4 100644 --- a/uppsrc/ide/clang/clang.upp +++ b/uppsrc/ide/clang/clang.upp @@ -14,7 +14,6 @@ file libclang.cpp, util.cpp, macros.cpp, - Signature.cpp, clang.cpp, Visitor.cpp, CurrentFile.cpp, diff --git a/uppsrc/ide/clang/util.cpp b/uppsrc/ide/clang/util.cpp index 90d27a172..e590beb60 100644 --- a/uppsrc/ide/clang/util.cpp +++ b/uppsrc/ide/clang/util.cpp @@ -104,3 +104,93 @@ int FindId(const String& s, const String& id) { q++; } }; + +String GetClass(const AnnotationItem& m) +{ + String cls = m.id; + int q; + if(m.kind == CXCursor_Constructor) { + q = cls.Find("::" + m.name + "("); + if(q >= 0) + q += 2; + } + else + if(m.kind == CXCursor_Destructor) { + q = cls.Find('~'); + } + else + q = FindId(cls, m.name); + + if(q >= 0) { + cls.Trim(q); + if(m.nspace.GetCount()) + cls.TrimStart(m.nspace + "::"); + return cls; + } + + return Null; +} + +String GetNameFromId(const String& id) +{ + String name; + try { + CParser p(id); + while(!p.IsEof()) + if(p.IsId()) + name = p.ReadId(); + else + if(!p.Char(':')) + break; + } + catch(CParser::Error) {} + return name; +} + +String MakeDefinition(const AnnotationItem& m, const String& klass) +{ + String result; + String pretty = m.pretty; + pretty.TrimStart("static "); + int q = FindId(pretty, m.name); + if(q < 0) + result << pretty; + else + result << pretty.Mid(0, q) << klass << pretty.Mid(q); + + const char *s = result; + int lvl = 0; + String r; + while(*s) { + if(*s == '(') + lvl++; + if(*s == ')') + lvl--; + if(lvl == 1 && *s == '=') { // skip default parameter + while(r.GetCount() && s[-1] == ' ') { + s--; + r.TrimLast(); + } + while(*s) { + if((*s == ',' || *s == ')') && lvl == 1) { + r.Cat(*s++); + break; + } + if(*s == '(') + lvl++; + if(*s == ')') + lvl--; + s++; + } + } + else + r.Cat(*s++); + } + r << "\n{\n}\n\n"; + return r; +} + +String MakeDefinition(const AnnotationItem& m) +{ + return MakeDefinition(m, GetClass(m)); +} diff --git a/upptst/ide_CleanupId/ide_CleanupId.cpp b/upptst/ide_CleanupId/ide_CleanupId.cpp index 7bdcee14c..861104c85 100644 --- a/upptst/ide_CleanupId/ide_CleanupId.cpp +++ b/upptst/ide_CleanupId/ide_CleanupId.cpp @@ -27,8 +27,8 @@ CONSOLE_APP_MAIN }) { DLOG("======"); DLOG(s); - DLOG(CleanupId(s)); - DLOG(CleanupPretty(s)); + DLOG("id: " << CleanupId(s)); + DLOG("pretty: " << CleanupPretty(s)); } CheckLogEtalon();