diff options
author | Matthew Woehlke <matthew.woehlke@kitware.com> | 2013-09-26 15:54:48 -0400 |
---|---|---|
committer | John Cummings <jcummings2@users.sf.net> | 2013-09-26 22:31:46 +0200 |
commit | 1aeeae8382cc9ed5d8c03dd168c8566b6594d399 (patch) | |
tree | 0d32fba97662a25d3474bb92515e5e2c3505544b /ApiExtractor | |
parent | 02c6e63ac8dbb8acde3bc19abd36fff0db65fd11 (diff) |
Refactor and improve added function resolving
Add a public function to create an AddedFunction::TypeInfo from a
signature string. Change translateType to use this to do full recursive
resolution on template arguments. Create a new helper function to do
more intelligent parsing of template type name signatures, and use this
in translateType.
Taken together, this means that we now recognize both multiple arguments
to template types of added functions, as well as template arguments that
are themselves template types. We couldn't do this before due to the use
of a regular expression to attempt to separate the template type name
from its arguments. The test cases are updated to test these new
features.
Note, however, that it is now a fatal error if the template argument
type cannot be determined. (Before we would just drop it and treat the
type as a non-container.) However, 1) this should not be happening in a
well formed type system, and 2) it's questionable if things wouldn't
have fallen apart anyway from treating the presumed container as
something else.
Change-Id: I23c3a7f7e311e046642d951d6ad2236571fda6b8
Reviewed-by: John Cummings <jcummings2@users.sf.net>
Diffstat (limited to 'ApiExtractor')
-rw-r--r-- | ApiExtractor/abstractmetabuilder.cpp | 74 | ||||
-rw-r--r-- | ApiExtractor/typesystem.cpp | 5 | ||||
-rw-r--r-- | ApiExtractor/typesystem.h | 2 |
3 files changed, 67 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; diff --git a/ApiExtractor/typesystem.cpp b/ApiExtractor/typesystem.cpp index 9a99ce5f5..9925a390f 100644 --- a/ApiExtractor/typesystem.cpp +++ b/ApiExtractor/typesystem.cpp @@ -2202,6 +2202,11 @@ AddedFunction::AddedFunction(QString signature, QString returnType, double vr) : } } +AddedFunction::TypeInfo AddedFunction::TypeInfo::fromSignature(const QString& signature) +{ + return parseType(signature); +} + QString ComplexTypeEntry::targetLangApiName() const { return strings_jobject; diff --git a/ApiExtractor/typesystem.h b/ApiExtractor/typesystem.h index 98f5cb76e..054967201 100644 --- a/ApiExtractor/typesystem.h +++ b/ApiExtractor/typesystem.h @@ -473,6 +473,8 @@ struct AddedFunction */ struct TypeInfo { TypeInfo() : isConstant(false), indirections(0), isReference(false) {} + static TypeInfo fromSignature(const QString& signature); + QString name; bool isConstant; int indirections; |