aboutsummaryrefslogtreecommitdiffstats
path: root/ApiExtractor/abstractmetabuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ApiExtractor/abstractmetabuilder.cpp')
-rw-r--r--ApiExtractor/abstractmetabuilder.cpp74
1 files changed, 60 insertions, 14 deletions
diff --git a/ApiExtractor/abstractmetabuilder.cpp b/ApiExtractor/abstractmetabuilder.cpp
index 8bac23cfc..0b9441490 100644
--- a/ApiExtractor/abstractmetabuilder.cpp
+++ b/ApiExtractor/abstractmetabuilder.cpp
@@ -55,6 +55,55 @@ static QString stripTemplateArgs(const QString &name)
return pos < 0 ? name : name.left(pos);
}
+static QStringList parseTemplateType(const QString& name) {
+ int n = name.indexOf('<');
+ if (n <= 0) {
+ // If name starts with '<' or contains an unmatched (i.e. any) '>', we
+ // reject it
+ if (n == 0 || name.count(">"))
+ return QStringList();
+ // Doesn't look like a template instantiation; just return the name
+ return QStringList() << name;
+ }
+
+ // Split the type name into the template name and template arguments; the
+ // part before the opening '<' is the template name
+ //
+ // Example:
+ // "foo<A, bar<B, C>, D>" -> ( "foo", "A", "bar<B, C>", "D" )
+ QStringList result;
+ result << name.left(n).trimmed();
+
+ // Extract template arguments
+ int i, depth = 1;
+ const int l = name.length();
+ for (i = n + 1; i < l; ++i) {
+ // Consume balanced '<'/'>' within a single argument so that we won't
+ // split on ',' as part of a single argument which is itself a
+ // multi-argument template type
+ if (name[i] == '<') {
+ ++depth;
+ } else if (name[i] == '>') {
+ if (--depth == 0)
+ break;
+ } else if (name[i] == ',' && depth == 1) {
+ // Encountered ',' in template argument list that is not within
+ // another template name; add current argument to result and start
+ // working on the next argument
+ result << name.mid(n + 1, i - n - 1).trimmed();
+ n = i;
+ }
+ }
+ if (i >= l) // arg list not closed
+ return QStringList();
+ if (i + 1 < l) // arg list closed before end of name
+ return QStringList();
+
+ // Add final argument and return result
+ result << name.mid(n + 1, i - n - 1).trimmed();
+ return result;
+}
+
AbstractMetaBuilder::AbstractMetaBuilder() : m_currentClass(0), m_logDirectory(QString('.')+QDir::separator())
{
}
@@ -2002,15 +2051,14 @@ AbstractMetaType* AbstractMetaBuilder::translateType(double vr, const AddedFunct
// test if the type is a template, like a container
bool isTemplate = false;
- QString templateArg;
- if (!type) {
- QRegExp r("(.*)<(.*)>$");
- if (r.indexIn(typeInfo.name) != -1) {
- templateArg = r.cap(2);
- if (templateArg.contains(','))
- ReportHandler::warning("add-function tag doesn't support container types with more than one argument or template arguments.");
- else
- isTemplate = (type = typeDb->findContainerType(r.cap(1)));
+ QStringList templateArgs;
+ if (!type && typeInfo.name.contains('<')) {
+ const QStringList& parsedType = parseTemplateType(typeInfo.name);
+ if (parsedType.isEmpty()) {
+ ReportHandler::warning(QString("Template type parsing failed for '%1'").arg(typeInfo.name));
+ } else {
+ templateArgs = parsedType.mid(1);
+ isTemplate = (type = typeDb->findContainerType(parsedType[0]));
}
}
@@ -2042,13 +2090,11 @@ AbstractMetaType* AbstractMetaBuilder::translateType(double vr, const AddedFunct
metaType->setReference(typeInfo.isReference);
metaType->setConstant(typeInfo.isConstant);
if (isTemplate) {
- type = typeDb->findType(templateArg);
- if (type) {
- AbstractMetaType* metaArgType = createMetaType();
- metaArgType->setTypeEntry(type);
+ foreach (const QString& templateArg, templateArgs) {
+ AbstractMetaType* metaArgType = translateType(vr, AddedFunction::TypeInfo::fromSignature(templateArg));
metaType->addInstantiation(metaArgType);
- metaType->setTypeUsagePattern(AbstractMetaType::ContainerPattern);
}
+ metaType->setTypeUsagePattern(AbstractMetaType::ContainerPattern);
}
return metaType;