summaryrefslogtreecommitdiffstats
path: root/tools/linguist/lupdate
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@nokia.com>2009-09-23 12:47:45 +0200
committerOswald Buddenhagen <oswald.buddenhagen@nokia.com>2009-09-23 15:44:58 +0200
commit1c4dc6be0c5b6a730e5ae910afa8c4da986e37ee (patch)
treec0a7cbcfbd7801c37706d979c74976b171b59c2c /tools/linguist/lupdate
parent57df91e20b8e669f4833e1f11dc2474d8118e0c9 (diff)
drastically improve lupdate's scalability
do not import all data from included files into the current file (which turned out to be extremely expensive for 3rdparty/webkit), but do hierarchical lookups on demand. this makes the lookups as such much slower, of course, but it still pays off.
Diffstat (limited to 'tools/linguist/lupdate')
-rw-r--r--tools/linguist/lupdate/cpp.cpp477
1 files changed, 280 insertions, 197 deletions
diff --git a/tools/linguist/lupdate/cpp.cpp b/tools/linguist/lupdate/cpp.cpp
index d5d2e10a5f..c9b25f37c8 100644
--- a/tools/linguist/lupdate/cpp.cpp
+++ b/tools/linguist/lupdate/cpp.cpp
@@ -43,6 +43,7 @@
#include <translator.h>
+#include <QtCore/QBitArray>
#include <QtCore/QDebug>
#include <QtCore/QFileInfo>
#include <QtCore/QStack>
@@ -62,53 +63,110 @@ static QString MagicComment(QLatin1String("TRANSLATOR"));
//#define DIAGNOSE_RETRANSLATABILITY // FIXME: should make a runtime option of this
-uint qHash(const QStringList &qsl)
+class HashString {
+public:
+ HashString() : m_hashed(false) {}
+ explicit HashString(const QString &str) : m_str(str), m_hashed(false) {}
+ void setValue(const QString &str) { m_str = str; m_hashed = false; }
+ const QString &value() const { return m_str; }
+ bool operator==(const HashString &other) const { return m_str == other.m_str; }
+private:
+ QString m_str;
+ mutable uint m_hash;
+ mutable bool m_hashed;
+ friend uint qHash(const HashString &str);
+};
+
+uint qHash(const HashString &str)
+{
+ if (!str.m_hashed) {
+ str.m_hashed = true;
+ str.m_hash = qHash(str.m_str);
+ }
+ return str.m_hash;
+}
+
+class HashStringList {
+public:
+ explicit HashStringList(const QList<HashString> &list) : m_list(list), m_hashed(false) {}
+ const QList<HashString> &value() const { return m_list; }
+ bool operator==(const HashStringList &other) const { return m_list == other.m_list; }
+private:
+ QList<HashString> m_list;
+ mutable uint m_hash;
+ mutable bool m_hashed;
+ friend uint qHash(const HashStringList &list);
+};
+
+uint qHash(const HashStringList &list)
{
- uint hash = 0;
- foreach (const QString &qs, qsl) {
- hash ^= qHash(qs) ^ 0xa09df22f;
- hash = (hash << 13) | (hash >> 19);
+ if (!list.m_hashed) {
+ list.m_hashed = true;
+ uint hash = 0;
+ foreach (const HashString &qs, list.m_list) {
+ hash ^= qHash(qs) ^ 0xa09df22f;
+ hash = (hash << 13) | (hash >> 19);
+ }
+ list.m_hash = hash;
}
- return hash;
+ return list.m_hash;
}
+typedef QList<HashString> NamespaceList;
+
struct Namespace {
Namespace() :
- isClass(false),
+ classDef(0),
hasTrFunctions(false), complained(false)
{}
- QString name;
- QMap<QString, Namespace *> children;
- QMap<QString, QStringList> aliases;
- QSet<QStringList> usings;
-
- int fileId;
+ QHash<HashString, Namespace *> children;
+ QHash<HashString, NamespaceList> aliases;
+ QList<HashStringList> usings;
- bool isClass;
+ // Class declarations set no flags and create no namespaces, so they are ignored.
+ // Class definitions may appear multiple times - but only because we are trying to
+ // "compile" all sources irrespective of build configuration.
+ // Nested classes may be forward-declared inside a definition, and defined in another file.
+ // The latter will detach the class' child list, so clones need a backlink to the original
+ // definition (either one in case of multiple definitions).
+ Namespace *classDef;
bool hasTrFunctions;
bool complained; // ... that tr functions are missing.
};
-typedef QList<Namespace *> NamespaceList;
+static int nextFileId;
+
+class VisitRecorder {
+public:
+ VisitRecorder()
+ {
+ m_ba.resize(nextFileId);
+ }
+ bool tryVisit(int fileId)
+ {
+ if (m_ba.at(fileId))
+ return false;
+ m_ba[fileId] = true;
+ return true;
+ }
+private:
+ QBitArray m_ba;
+};
struct ParseResults {
ParseResults()
{
- static int nextFileId;
- rootNamespace.fileId = nextFileId++;
tor = 0;
}
- bool detachNamespace(Namespace **that);
- Namespace *include(Namespace *that, const Namespace *other);
- void unite(const ParseResults *other);
+ int fileId;
Namespace rootNamespace;
Translator *tor;
- QSet<QString> allIncludes;
+ QSet<const ParseResults *> includes;
};
typedef QHash<QString, const ParseResults *> ParseResultHash;
@@ -117,7 +175,7 @@ class CppFiles {
public:
static const ParseResults *getResults(const QString &cleanFile);
- static void setResults(const QString &cleanFile, const ParseResults *results);
+ static void setResults(const QString &cleanFile, ParseResults *results);
static bool isBlacklisted(const QString &cleanFile);
static void setBlacklisted(const QString &cleanFile);
@@ -135,13 +193,13 @@ public:
void setTranslator(Translator *tor) { results->tor = tor; }
void parse(const QString &initialContext, ConversionData &cd, QSet<QString> &inclusions);
void parseInternal(ConversionData &cd, QSet<QString> &inclusions);
- const ParseResults *getResults() const { return results; }
+ ParseResults *getResults() const { return results; }
void deleteResults() { delete results; }
struct SavedState {
- QStringList namespaces;
+ NamespaceList namespaces;
QStack<int> namespaceDepths;
- QStringList functionContext;
+ NamespaceList functionContext;
QString functionContextUnresolved;
QString pendingContext;
};
@@ -183,15 +241,28 @@ private:
static QString stringifyNamespace(const NamespaceList &namespaces);
static QStringList stringListifyNamespace(const NamespaceList &namespaces);
- void modifyNamespace(NamespaceList *namespaces);
- NamespaceList resolveNamespaces(const QStringList &segments);
- bool qualifyOne(const NamespaceList &namespaces, int nsIdx, const QString &segment,
- NamespaceList *resolved);
- bool fullyQualify(const NamespaceList &namespaces, const QStringList &segments,
+ typedef bool (CppParser::*VisitNamespaceCallback)(const Namespace *ns, void *context) const;
+ bool visitNamespace(const NamespaceList &namespaces, int nsCount,
+ VisitNamespaceCallback callback, void *context,
+ VisitRecorder &vr, const ParseResults *rslt) const;
+ bool visitNamespace(const NamespaceList &namespaces, int nsCount,
+ VisitNamespaceCallback callback, void *context) const;
+ static QStringList stringListifySegments(const QList<HashString> &namespaces);
+ bool qualifyOneCallbackOwn(const Namespace *ns, void *context) const;
+ bool qualifyOneCallbackUsing(const Namespace *ns, void *context) const;
+ bool qualifyOne(const NamespaceList &namespaces, int nsCnt, const HashString &segment,
+ NamespaceList *resolved) const;
+ bool fullyQualify(const NamespaceList &namespaces, const QList<HashString> &segments,
bool isDeclaration,
- NamespaceList *resolved, QStringList *unresolved);
- void enterNamespace(NamespaceList *namespaces, const QString &name);
+ NamespaceList *resolved, QStringList *unresolved) const;
+ bool fullyQualify(const NamespaceList &namespaces, const QString &segments,
+ bool isDeclaration,
+ NamespaceList *resolved, QStringList *unresolved) const;
+ bool findNamespaceCallback(const Namespace *ns, void *context) const;
+ const Namespace *findNamespace(const NamespaceList &namespaces, int nsCount = -1) const;
+ void enterNamespace(NamespaceList *namespaces, const HashString &name, bool isClass);
void truncateNamespaces(NamespaceList *namespaces, int lenght);
+ Namespace *modifyNamespace(NamespaceList *namespaces, bool tryOrigin = true);
enum {
Tok_Eof, Tok_class, Tok_friend, Tok_namespace, Tok_using, Tok_return,
@@ -837,85 +908,40 @@ uint CppParser::getToken()
void CppParser::saveState(SavedState *state)
{
- state->namespaces = stringListifyNamespace(namespaces);
+ state->namespaces = namespaces;
state->namespaceDepths = namespaceDepths;
- state->functionContext = stringListifyNamespace(functionContext);
+ state->functionContext = functionContext;
state->functionContextUnresolved = functionContextUnresolved;
state->pendingContext = pendingContext;
}
void CppParser::loadState(const SavedState *state)
{
- namespaces = resolveNamespaces(state->namespaces);
+ namespaces = state->namespaces;
namespaceDepths = state->namespaceDepths;
- functionContext = resolveNamespaces(state->functionContext);
+ functionContext = state->functionContext;
functionContextUnresolved = state->functionContextUnresolved;
pendingContext = state->pendingContext;
}
-bool ParseResults::detachNamespace(Namespace **that)
-{
- if ((*that)->fileId != rootNamespace.fileId) {
- Namespace *newThat = new Namespace;
- *newThat = **that;
- newThat->fileId = rootNamespace.fileId;
- *that = newThat;
- return true;
- }
- return false;
-}
-
-Namespace *ParseResults::include(Namespace *that, const Namespace *other)
+Namespace *CppParser::modifyNamespace(NamespaceList *namespaces, bool tryOrigin)
{
- Namespace *origThat = that;
- foreach (Namespace *otherSub, other->children) {
- if (Namespace *thisSub = that->children.value(otherSub->name)) {
- // Don't make these cause a detach - it's best
- // (though not necessary) if they are shared
- thisSub->isClass |= otherSub->isClass;
- thisSub->hasTrFunctions |= otherSub->hasTrFunctions;
- thisSub->complained |= otherSub->complained;
-
- if (Namespace *newSub = include(thisSub, otherSub)) {
- thisSub = newSub;
- detachNamespace(&that);
- that->children[thisSub->name] = thisSub;
- }
- } else {
- detachNamespace(&that);
- that->children[otherSub->name] = otherSub;
- }
- }
- if ((that->aliases != other->aliases && !other->aliases.isEmpty())
- || (that->usings != other->usings && !other->usings.isEmpty())) {
- detachNamespace(&that);
- that->aliases.unite(other->aliases);
- that->usings.unite(other->usings);
- }
- return (that != origThat) ? that : 0;
-}
-
-void ParseResults::unite(const ParseResults *other)
-{
- allIncludes.unite(other->allIncludes);
- include(&rootNamespace, &other->rootNamespace);
-}
-
-void CppParser::modifyNamespace(NamespaceList *namespaces)
-{
- Namespace *pns = 0;
- int i = namespaces->count();
- forever {
- --i;
- Namespace *ns = namespaces->at(i);
- bool detached = results->detachNamespace(&ns);
- if (pns)
- ns->children[pns->name] = pns;
- if (!detached) // Known to be true for root namespace
- return;
+ Namespace *pns, *ns = &results->rootNamespace;
+ for (int i = 1; i < namespaces->count(); ++i) {
pns = ns;
- namespaces->replace(i, ns);
+ if (!(ns = pns->children.value(namespaces->at(i)))) {
+ do {
+ ns = new Namespace;
+ if (tryOrigin)
+ if (const Namespace *ons = findNamespace(*namespaces, i + 1))
+ ns->classDef = ons->classDef;
+ pns->children.insert(namespaces->at(i), ns);
+ pns = ns;
+ } while (++i < namespaces->count());
+ break;
+ }
}
+ return ns;
}
QString CppParser::stringifyNamespace(const NamespaceList &namespaces)
@@ -924,7 +950,7 @@ QString CppParser::stringifyNamespace(const NamespaceList &namespaces)
for (int i = 1; i < namespaces.count(); ++i) {
if (i > 1)
ret += QLatin1String("::");
- ret += namespaces.at(i)->name;
+ ret += namespaces.at(i).value();
}
return ret;
}
@@ -933,58 +959,102 @@ QStringList CppParser::stringListifyNamespace(const NamespaceList &namespaces)
{
QStringList ret;
for (int i = 1; i < namespaces.count(); ++i)
- ret << namespaces.at(i)->name;
+ ret << namespaces.at(i).value();
return ret;
}
-// This function is called only with known-existing namespaces
-NamespaceList CppParser::resolveNamespaces(const QStringList &segments)
+bool CppParser::visitNamespace(const NamespaceList &namespaces, int nsCount,
+ VisitNamespaceCallback callback, void *context,
+ VisitRecorder &vr, const ParseResults *rslt) const
{
- NamespaceList ret;
- Namespace *ns = &results->rootNamespace;
- ret << ns;
- foreach (const QString &seg, segments) {
- ns = ns->children.value(seg);
- ret << ns;
- }
+ const Namespace *ns = &rslt->rootNamespace;
+ for (int i = 1; i < nsCount; ++i)
+ if (!(ns = ns->children.value(namespaces.at(i))))
+ goto supers;
+ if ((this->*callback)(ns, context))
+ return true;
+supers:
+ foreach (const ParseResults *sup, rslt->includes)
+ if (vr.tryVisit(sup->fileId)
+ && visitNamespace(namespaces, nsCount, callback, context, vr, sup))
+ return true;
+ return false;
+}
+
+bool CppParser::visitNamespace(const NamespaceList &namespaces, int nsCount,
+ VisitNamespaceCallback callback, void *context) const
+{
+ VisitRecorder vr;
+ return visitNamespace(namespaces, nsCount, callback, context, vr, results);
+}
+
+QStringList CppParser::stringListifySegments(const QList<HashString> &segments)
+{
+ QStringList ret;
+ for (int i = 0; i < segments.count(); ++i)
+ ret << segments.at(i).value();
return ret;
}
-bool CppParser::qualifyOne(const NamespaceList &namespaces, int nsIdx, const QString &segment,
- NamespaceList *resolved)
+struct QualifyOneData {
+ const NamespaceList &namespaces;
+ int nsCount;
+ const HashString &segment;
+ NamespaceList *resolved;
+ QSet<HashStringList> visitedUsings;
+};
+
+bool CppParser::qualifyOneCallbackOwn(const Namespace *ns, void *context) const
{
- const Namespace *ns = namespaces.at(nsIdx);
- QMap<QString, Namespace *>::ConstIterator cnsi = ns->children.constFind(segment);
- if (cnsi != ns->children.constEnd()) {
- *resolved = namespaces.mid(0, nsIdx + 1);
- *resolved << *cnsi;
+ QualifyOneData *data = (QualifyOneData *)context;
+ if (ns->children.contains(data->segment)) {
+ *data->resolved = data->namespaces.mid(0, data->nsCount);
+ *data->resolved << data->segment;
return true;
}
- QMap<QString, QStringList>::ConstIterator nsai = ns->aliases.constFind(segment);
+ QHash<HashString, NamespaceList>::ConstIterator nsai = ns->aliases.constFind(data->segment);
if (nsai != ns->aliases.constEnd()) {
- *resolved = resolveNamespaces(*nsai);
+ *data->resolved = *nsai;
return true;
}
- foreach (const QStringList &use, ns->usings) {
- NamespaceList usedNs = resolveNamespaces(use);
- if (qualifyOne(usedNs, usedNs.count() - 1, segment, resolved))
- return true;
- }
return false;
}
-bool CppParser::fullyQualify(const NamespaceList &namespaces, const QStringList &segments,
+bool CppParser::qualifyOneCallbackUsing(const Namespace *ns, void *context) const
+{
+ QualifyOneData *data = (QualifyOneData *)context;
+ foreach (const HashStringList &use, ns->usings)
+ if (!data->visitedUsings.contains(use)) {
+ data->visitedUsings.insert(use);
+ if (qualifyOne(use.value(), use.value().count(), data->segment, data->resolved))
+ return true;
+ }
+ return false;
+}
+
+bool CppParser::qualifyOne(const NamespaceList &namespaces, int nsCnt, const HashString &segment,
+ NamespaceList *resolved) const
+{
+ QualifyOneData data = { namespaces, nsCnt, segment, resolved, QSet<HashStringList>() };
+
+ if (visitNamespace(namespaces, nsCnt, &CppParser::qualifyOneCallbackOwn, &data))
+ return true;
+
+ return visitNamespace(namespaces, nsCnt, &CppParser::qualifyOneCallbackUsing, &data);
+}
+
+bool CppParser::fullyQualify(const NamespaceList &namespaces, const QList<HashString> &segments,
bool isDeclaration,
- NamespaceList *resolved, QStringList *unresolved)
+ NamespaceList *resolved, QStringList *unresolved) const
{
int nsIdx;
int initSegIdx;
- if (segments.first().isEmpty()) {
+ if (segments.first().value().isEmpty()) {
// fully qualified
if (segments.count() == 1) {
resolved->clear();
- *resolved << &results->rootNamespace;
+ *resolved << HashString(QString());
return true;
}
initSegIdx = 1;
@@ -995,12 +1065,12 @@ bool CppParser::fullyQualify(const NamespaceList &namespaces, const QStringList
}
do {
- if (qualifyOne(namespaces, nsIdx, segments[initSegIdx], resolved)) {
+ if (qualifyOne(namespaces, nsIdx + 1, segments[initSegIdx], resolved)) {
int segIdx = initSegIdx;
while (++segIdx < segments.count()) {
- if (!qualifyOne(*resolved, resolved->count() - 1, segments[segIdx], resolved)) {
+ if (!qualifyOne(*resolved, resolved->count(), segments[segIdx], resolved)) {
if (unresolved)
- *unresolved = segments.mid(segIdx);
+ *unresolved = stringListifySegments(segments.mid(segIdx));
return false;
}
}
@@ -1008,23 +1078,47 @@ bool CppParser::fullyQualify(const NamespaceList &namespaces, const QStringList
}
} while (!isDeclaration && --nsIdx >= 0);
resolved->clear();
- *resolved << &results->rootNamespace;
+ *resolved << HashString(QString());
if (unresolved)
- *unresolved = segments.mid(initSegIdx);
+ *unresolved = stringListifySegments(segments.mid(initSegIdx));
return false;
}
-void CppParser::enterNamespace(NamespaceList *namespaces, const QString &name)
+bool CppParser::fullyQualify(const NamespaceList &namespaces, const QString &quali,
+ bool isDeclaration,
+ NamespaceList *resolved, QStringList *unresolved) const
+{
+ static QString strColons(QLatin1String("::"));
+
+ QList<HashString> segments;
+ foreach (const QString &str, quali.split(strColons)) // XXX slow, but needs to be fast(?)
+ segments << HashString(str);
+ return fullyQualify(namespaces, segments, isDeclaration, resolved, unresolved);
+}
+
+bool CppParser::findNamespaceCallback(const Namespace *ns, void *context) const
{
- Namespace *ns = namespaces->last()->children.value(name);
- if (!ns) {
- ns = new Namespace;
- ns->fileId = results->rootNamespace.fileId;
- ns->name = name;
- modifyNamespace(namespaces);
- namespaces->last()->children[name] = ns;
+ *((const Namespace **)context) = ns;
+ return true;
+}
+
+const Namespace *CppParser::findNamespace(const NamespaceList &namespaces, int nsCount) const
+{
+ const Namespace *ns = 0;
+ if (nsCount == -1)
+ nsCount = namespaces.count();
+ visitNamespace(namespaces, nsCount, &CppParser::findNamespaceCallback, &ns);
+ return ns;
+}
+
+void CppParser::enterNamespace(NamespaceList *namespaces, const HashString &name, bool isClass)
+{
+ *namespaces << name;
+ if (!findNamespace(*namespaces)) {
+ Namespace *ns = modifyNamespace(namespaces, false);
+ if (isClass)
+ ns->classDef = ns;
}
- *namespaces << ns;
}
void CppParser::truncateNamespaces(NamespaceList *namespaces, int length)
@@ -1056,8 +1150,9 @@ const ParseResults *CppFiles::getResults(const QString &cleanFile)
return parsedFiles().value(cleanFile);
}
-void CppFiles::setResults(const QString &cleanFile, const ParseResults *results)
+void CppFiles::setResults(const QString &cleanFile, ParseResults *results)
{
+ results->fileId = nextFileId++;
parsedFiles().insert(cleanFile, results);
}
@@ -1093,12 +1188,8 @@ void CppParser::processInclude(const QString &file, ConversionData &cd,
QString fileExt = QFileInfo(cleanFile).suffix();
if (fileExt.isEmpty() || fileExt.startsWith(QLatin1Char('h'), Qt::CaseInsensitive)) {
- if (results->allIncludes.contains(cleanFile))
- return;
- results->allIncludes.insert(cleanFile);
-
if (const ParseResults *res = CppFiles::getResults(cleanFile)) {
- results->unite(res);
+ results->includes.insert(res);
return;
}
@@ -1128,8 +1219,8 @@ void CppParser::processInclude(const QString &file, ConversionData &cd,
}
parser.setInput(ts, cleanFile);
parser.parse(cd.m_defaultContext, cd, inclusions);
- CppFiles::setResults(cleanFile, parser.getResults());
- results->unite(parser.results);
+ CppFiles::setResults(cleanFile, parser.results);
+ results->includes.insert(parser.results);
} else {
CppParser parser(results);
parser.namespaces = namespaces;
@@ -1138,12 +1229,6 @@ void CppParser::processInclude(const QString &file, ConversionData &cd,
parser.pendingContext = pendingContext;
parser.setInput(ts, cleanFile);
parser.parseInternal(cd, inclusions);
- // Don't wreak havoc if not enough braces were found.
- truncateNamespaces(&parser.namespaces, namespaces.count());
- truncateNamespaces(&parser.functionContext, functionContext.count());
- // Copy them back - the pointers might have changed.
- namespaces = parser.namespaces;
- functionContext = parser.functionContext;
// Avoid that messages obtained by direct scanning are used
CppFiles::setBlacklisted(cleanFile);
}
@@ -1330,7 +1415,7 @@ void CppParser::parse(const QString &initialContext, ConversionData &cd,
if (results->tor)
yyCodecIsUtf8 = (results->tor->codecName() == "UTF-8");
- namespaces << &results->rootNamespace;
+ namespaces << HashString();
functionContext = namespaces;
functionContextUnresolved = initialContext;
@@ -1405,8 +1490,8 @@ void CppParser::parseInternal(ConversionData &cd, QSet<QString> &inclusions)
*/
yyTok = getToken();
if (yyBraceDepth == namespaceDepths.count() && yyParenDepth == 0) {
- QStringList quali;
- QString fct;
+ QList<HashString> quali;
+ HashString fct;
do {
/*
This code should execute only once, but we play
@@ -1414,8 +1499,9 @@ void CppParser::parseInternal(ConversionData &cd, QSet<QString> &inclusions)
'class Q_EXPORT QMessageBox', in which case
'QMessageBox' is the class name, not 'Q_EXPORT'.
*/
- fct = yyWord;
- fct.detach();
+ text = yyWord;
+ text.detach();
+ fct.setValue(text);
yyTok = getToken();
} while (yyTok == Tok_Ident);
while (yyTok == Tok_ColonColon) {
@@ -1423,8 +1509,9 @@ void CppParser::parseInternal(ConversionData &cd, QSet<QString> &inclusions)
if (yyTok != Tok_Ident)
break; // Oops ...
quali << fct;
- fct = yyWord;
- fct.detach();
+ text = yyWord;
+ text.detach();
+ fct.setValue(text);
yyTok = getToken();
}
while (yyTok == Tok_Comment)
@@ -1456,8 +1543,7 @@ void CppParser::parseInternal(ConversionData &cd, QSet<QString> &inclusions)
} else {
namespaceDepths.push(namespaces.count());
}
- enterNamespace(&namespaces, fct);
- namespaces.last()->isClass = true;
+ enterNamespace(&namespaces, fct, true);
functionContext = namespaces;
functionContextUnresolved.clear(); // Pointless
@@ -1469,34 +1555,33 @@ void CppParser::parseInternal(ConversionData &cd, QSet<QString> &inclusions)
yyTokColonSeen = false;
yyTok = getToken();
if (yyTok == Tok_Ident) {
- QString ns = yyWord;
- ns.detach();
+ text = yyWord;
+ text.detach();
+ HashString ns = HashString(text);
yyTok = getToken();
if (yyTok == Tok_LeftBrace) {
namespaceDepths.push(namespaces.count());
- enterNamespace(&namespaces, ns);
+ enterNamespace(&namespaces, ns, false);
yyTok = getToken();
} else if (yyTok == Tok_Equals) {
// e.g. namespace Is = OuterSpace::InnerSpace;
- QStringList fullName;
+ QList<HashString> fullName;
yyTok = getToken();
if (yyTok == Tok_ColonColon)
- fullName.append(QString());
+ fullName.append(HashString(QString()));
while (yyTok == Tok_ColonColon || yyTok == Tok_Ident) {
if (yyTok == Tok_Ident) {
text = yyWord;
text.detach();
- fullName.append(text);
+ fullName.append(HashString(text));
}
yyTok = getToken();
}
if (fullName.isEmpty())
break;
NamespaceList nsl;
- if (fullyQualify(namespaces, fullName, false, &nsl, 0)) {
- modifyNamespace(&namespaces);
- namespaces.last()->aliases.insert(ns, stringListifyNamespace(nsl));
- }
+ if (fullyQualify(namespaces, fullName, false, &nsl, 0))
+ modifyNamespace(&namespaces, false)->aliases[ns] = nsl;
}
} else if (yyTok == Tok_LeftBrace) {
// Anonymous namespace
@@ -1506,43 +1591,40 @@ void CppParser::parseInternal(ConversionData &cd, QSet<QString> &inclusions)
break;
case Tok_using:
yyTok = getToken();
+ // XXX this should affect only the current scope, not the entire current namespace
if (yyTok == Tok_namespace) {
- QStringList fullName;
+ QList<HashString> fullName;
yyTok = getToken();
if (yyTok == Tok_ColonColon)
- fullName.append(QString());
+ fullName.append(HashString(QString()));
while (yyTok == Tok_ColonColon || yyTok == Tok_Ident) {
if (yyTok == Tok_Ident) {
text = yyWord;
text.detach();
- fullName.append(text);
+ fullName.append(HashString(text));
}
yyTok = getToken();
}
NamespaceList nsl;
- if (fullyQualify(namespaces, fullName, false, &nsl, 0)) {
- modifyNamespace(&namespaces);
- namespaces.last()->usings.insert(stringListifyNamespace(nsl));
- }
+ if (fullyQualify(namespaces, fullName, false, &nsl, 0))
+ modifyNamespace(&namespaces, false)->usings << HashStringList(nsl);
} else {
- QStringList fullName;
+ QList<HashString> fullName;
if (yyTok == Tok_ColonColon)
- fullName.append(QString());
+ fullName.append(HashString(QString()));
while (yyTok == Tok_ColonColon || yyTok == Tok_Ident) {
if (yyTok == Tok_Ident) {
text = yyWord;
text.detach();
- fullName.append(text);
+ fullName.append(HashString(text));
}
yyTok = getToken();
}
if (fullName.isEmpty())
break;
NamespaceList nsl;
- if (fullyQualify(namespaces, fullName, false, &nsl, 0)) {
- modifyNamespace(&namespaces);
- namespaces.last()->aliases.insert(nsl.last()->name, stringListifyNamespace(nsl));
- }
+ if (fullyQualify(namespaces, fullName, false, &nsl, 0))
+ modifyNamespace(&namespaces, true)->aliases[nsl.last()] = nsl;
}
break;
case Tok_tr:
@@ -1570,8 +1652,7 @@ void CppParser::parseInternal(ConversionData &cd, QSet<QString> &inclusions)
}
if (!pendingContext.isEmpty()) {
QStringList unresolved;
- if (!fullyQualify(namespaces, pendingContext.split(strColons), true,
- &functionContext, &unresolved)) {
+ if (!fullyQualify(namespaces, pendingContext, true, &functionContext, &unresolved)) {
functionContextUnresolved = unresolved.join(strColons);
qWarning("%s:%d: Qualifying with unknown namespace/class %s::%s\n",
qPrintable(yyFileName), yyLineNo,
@@ -1588,14 +1669,15 @@ void CppParser::parseInternal(ConversionData &cd, QSet<QString> &inclusions)
qPrintable(yyFileName), yyLineNo);
break;
}
- while (!functionContext.at(idx - 1)->hasTrFunctions) {
- if (idx == 1 || !functionContext.at(idx - 2)->isClass) {
+ while (!findNamespace(functionContext, idx)->classDef->hasTrFunctions) {
+ if (idx == 1 || !findNamespace(functionContext, idx - 1)->classDef) {
context = stringifyNamespace(functionContext);
- if (!functionContext.last()->complained) {
+ Namespace *fctx = findNamespace(functionContext)->classDef;
+ if (!fctx->complained) {
qWarning("%s:%d: Class '%s' lacks Q_OBJECT macro\n",
qPrintable(yyFileName), yyLineNo,
qPrintable(context));
- functionContext.last()->complained = true;
+ fctx->complained = true;
}
goto gotctx;
}
@@ -1603,7 +1685,7 @@ void CppParser::parseInternal(ConversionData &cd, QSet<QString> &inclusions)
}
context.clear();
for (int i = 1;;) {
- context += functionContext.at(i)->name;
+ context += functionContext.at(i).value();
if (++i == idx)
break;
context += strColons;
@@ -1625,13 +1707,14 @@ void CppParser::parseInternal(ConversionData &cd, QSet<QString> &inclusions)
prefix.chop(2);
NamespaceList nsl;
QStringList unresolved;
- if (fullyQualify(functionContext, prefix.split(strColons), false, &nsl, &unresolved)) {
+ if (fullyQualify(functionContext, prefix, false, &nsl, &unresolved)) {
context = stringifyNamespace(nsl);
- if (!nsl.last()->hasTrFunctions && !nsl.last()->complained) {
+ Namespace *fctx = findNamespace(nsl)->classDef;
+ if (!fctx->hasTrFunctions && !fctx->complained) {
qWarning("%s:%d: Class '%s' lacks Q_OBJECT macro\n",
qPrintable(yyFileName), yyLineNo,
qPrintable(context));
- nsl.last()->complained = true;
+ fctx->complained = true;
}
} else {
context = (stringListifyNamespace(nsl) + unresolved).join(strColons);
@@ -1727,7 +1810,7 @@ void CppParser::parseInternal(ConversionData &cd, QSet<QString> &inclusions)
break;
case Tok_Q_DECLARE_TR_FUNCTIONS:
case Tok_Q_OBJECT:
- namespaces.last()->hasTrFunctions = true;
+ modifyNamespace(&namespaces, true)->hasTrFunctions = true;
yyTok = getToken();
break;
case Tok_Ident: