type-display(#985): implement extractor for simple type designator

using a heuristic approach on a merely lexical level
This commit is contained in:
Fischlurch 2016-01-10 02:02:18 +01:00
parent 08c3d5d4c5
commit 21c02e3015
3 changed files with 77 additions and 18 deletions

View file

@ -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;

View file

@ -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

View file

@ -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;
}
};