type-display(#985): implement extractor for simple type designator
using a heuristic approach on a merely lexical level
This commit is contained in:
parent
08c3d5d4c5
commit
21c02e3015
3 changed files with 77 additions and 18 deletions
|
|
@ -59,6 +59,7 @@
|
|||
//using util::_Fmt;
|
||||
using util::removePrefix;
|
||||
using util::removeSuffix;
|
||||
using util::isnil;
|
||||
using std::string;
|
||||
|
||||
using std::regex;
|
||||
|
|
@ -180,7 +181,11 @@ apologies for that."
|
|||
string
|
||||
humanReadableTypeID (Literal rawType)
|
||||
{
|
||||
string typeName = demangleCxx (rawType);
|
||||
|
||||
|
||||
static regex commonPrefixes {"std::"
|
||||
"|(\\w+::)+\\(anonymous namespace\\)::"
|
||||
"|lib::meta::"
|
||||
"|lib::time::"
|
||||
"|lib::test::"
|
||||
|
|
@ -199,28 +204,74 @@ apologies for that."
|
|||
static regex stdAllocator {"(\\w+<(\\w+)), allocator<\\2>\\s*"
|
||||
, regex::ECMAScript | regex::optimize};
|
||||
|
||||
static regex lumieraP {"P<(\\w+), shared_ptr<\\1>\\s*"
|
||||
, regex::ECMAScript | regex::optimize};
|
||||
|
||||
|
||||
string typeName = demangleCxx (rawType);
|
||||
auto pos = typeName.begin();
|
||||
auto end = typeName.end();
|
||||
|
||||
end = regex_replace(pos, pos, end, commonPrefixes, "");
|
||||
end = regex_replace(pos, pos, end, stdAllocator, "$1");
|
||||
end = regex_replace(pos, pos, end, lumieraP, "P<$1");
|
||||
|
||||
typeName.resize(end - typeName.begin());
|
||||
return typeName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** \par implementation notes
|
||||
* We want to get at the name of the _most relevant_ type entity.
|
||||
* This in itself is a heuristic. But we can work on the assumption,
|
||||
* that we get a sequence of nested namespaces and type names, and
|
||||
* we'll be interested in the last, the innermost of these types.
|
||||
* In the most general case, each type could be templated, and
|
||||
* thus will be followed by parameter specs enclosed in angle
|
||||
* braces. Behind this spec, only type adornments will follow.
|
||||
* Thus we'll inspect the string _from the back side_, skipping
|
||||
* over all type parameter contents, until we reach brace
|
||||
* level zero again. From this point, we have to search
|
||||
* backwards to the first namespace separator `::`
|
||||
* @warning we acknowledge this function can fail in various ways,
|
||||
* some of which will be indicated by returning the string "void".
|
||||
* But it may well happen that the returned string contains
|
||||
* whitespace, superfluous punctuation or even the whole
|
||||
* demangled type specification as is.
|
||||
*/
|
||||
string
|
||||
primaryTypeComponent (Literal rawType)
|
||||
{
|
||||
string typeStr = demangleCxx (rawType);
|
||||
size_t end = typeStr.rfind("<");
|
||||
size_t pos = typeStr.rfind("::", end);
|
||||
if (pos != string::npos)
|
||||
typeStr = (end==string::npos? typeStr.substr(pos+2)
|
||||
: typeStr.substr(pos+2, end-pos-2));
|
||||
|
||||
removeSuffix (typeStr, " const");
|
||||
removeSuffix (typeStr, " const *");
|
||||
removeSuffix (typeStr, "*");
|
||||
removeSuffix (typeStr, "&");
|
||||
|
||||
if (isnil (typeStr)) return VOID_INDICATOR;
|
||||
|
||||
auto end = typeStr.end();
|
||||
auto beg = typeStr.begin();
|
||||
int level=0;
|
||||
while (--end != beg)
|
||||
{
|
||||
if ('>' == *end)
|
||||
++level;
|
||||
else if ('<' == *end and level>0)
|
||||
--level;
|
||||
else
|
||||
if (level==0)
|
||||
{
|
||||
++end;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (end == beg) return VOID_INDICATOR;
|
||||
|
||||
auto pos = typeStr.rfind("::", end-beg);
|
||||
typeStr = (pos==string::npos? typeStr.substr(end-beg)
|
||||
: typeStr.substr(pos+2, (end-beg)-pos-2));
|
||||
return typeStr;
|
||||
}
|
||||
|
||||
|
|
@ -228,25 +279,20 @@ apologies for that."
|
|||
string
|
||||
sanitisedFullTypeName(lib::Literal rawName)
|
||||
{
|
||||
return util::sanitise (demangleCxx (rawName));
|
||||
return util::sanitise (humanReadableTypeID (rawName));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}}// namespace lib::meta
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* === formatting and pretty printing support uitls === */
|
||||
|
||||
namespace util {
|
||||
|
||||
|
||||
namespace { // implementation details...
|
||||
|
||||
}//(End) implementation details
|
||||
|
||||
using std::hex;
|
||||
using std::setw;
|
||||
using std::right;
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ namespace util {
|
|||
ChPredicate operator! (ChPredicate p) { return not bind(p,_1); }
|
||||
|
||||
// character classes used for sanitising a string
|
||||
ChPredicate isValid (is_alnum() or is_any_of("-_.:+$'()@")); ///< characters to be retained
|
||||
ChPredicate isPunct (is_space() or is_any_of(",;#*~´`?\\=/&%![]{}")); ///< punctuation to be replaced by '_'
|
||||
ChPredicate isValid (is_alnum() or is_any_of("-_.+$'()@")); ///< characters to be retained
|
||||
ChPredicate isPunct (is_space() or is_any_of(",;:#*~´`?\\=/&%![]{}<>")); ///< punctuation to be replaced by '_'
|
||||
|
||||
|
||||
string
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ namespace test{
|
|||
struct Inner { };
|
||||
|
||||
static const T*
|
||||
cloak (Inner const&&)
|
||||
cloak (Inner&&)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -60,9 +60,9 @@ namespace test{
|
|||
|
||||
struct Space { };
|
||||
|
||||
auto CHALLENGE_1 = "some::arbitrary::BullShit<oh::RLY>";
|
||||
auto CHALLENGE_1 = "some::arbitrary::BullShit<oh::RLY>*";
|
||||
auto CHALLENGE_2 = "lib::Contrived<lib::meta::Barely,true>::ClusterFuck<const std::string& (const std::vector<proc::mobject::oh::RLY* const>)>";
|
||||
auto CHALLENGE_3 = "std::function<special::(anonymous namespace)::Shit(lib::P<asset::Clip, std::shared_ptr<asset::Clip>>)>";
|
||||
auto CHALLENGE_3 = "std::function<special::(anonymous namespace)::Shit(lib::P<proc::asset::Clip, std::shared_ptr<proc::asset::Clip>>)>";
|
||||
|
||||
}//(end)fixture
|
||||
|
||||
|
|
@ -85,6 +85,11 @@ namespace test{
|
|||
void
|
||||
run (Arg)
|
||||
{
|
||||
cout << "-----input----------------------"<<endl;
|
||||
cout << CHALLENGE_1 <<endl;
|
||||
cout << CHALLENGE_2 <<endl;
|
||||
cout << CHALLENGE_3 <<endl;
|
||||
|
||||
cout << "-----human-readable-------------"<<endl;
|
||||
cout << humanReadableTypeID (CHALLENGE_1) <<endl;
|
||||
cout << humanReadableTypeID (CHALLENGE_2) <<endl;
|
||||
|
|
@ -99,6 +104,14 @@ namespace test{
|
|||
cout << sanitisedFullTypeName (CHALLENGE_1) <<endl;
|
||||
cout << sanitisedFullTypeName (CHALLENGE_2) <<endl;
|
||||
cout << sanitisedFullTypeName (CHALLENGE_3) <<endl;
|
||||
|
||||
|
||||
Outer<Space> ship;
|
||||
auto magic = ship.cloak;
|
||||
cout << typeStr(&magic) <<endl;
|
||||
cout << typeSymbol(&magic) <<endl;
|
||||
|
||||
cout << typeStr<Outer<typeof(this)>::Inner>() <<endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue