From 178945342d0d46ddde460f230c22d2acb9f930a8 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 22 Sep 2009 20:27:26 +0200 Subject: actually use the argument of Q_DECLARE_TR_FUNCTIONS which means that one can set an arbitrary context. as a side effect, this caches the stringified context of Q_OBJECT-derived classes. --- .../lupdate/testdata/good/parsecontexts/main.cpp | 9 +++ .../testdata/good/parsecontexts/project.ts.result | 9 +++ tools/linguist/lupdate/cpp.cpp | 68 +++++++++++++++++++--- 3 files changed, 77 insertions(+), 9 deletions(-) diff --git a/tests/auto/linguist/lupdate/testdata/good/parsecontexts/main.cpp b/tests/auto/linguist/lupdate/testdata/good/parsecontexts/main.cpp index 7e81b84..25c2c0d 100644 --- a/tests/auto/linguist/lupdate/testdata/good/parsecontexts/main.cpp +++ b/tests/auto/linguist/lupdate/testdata/good/parsecontexts/main.cpp @@ -262,6 +262,15 @@ QString C2::foo() } +namespace Fooish { + Q_DECLARE_TR_FUNCTIONS(Bears::And::Spiders) +} + +void Fooish::bar() +{ + return tr("whatever the context", "Bears::And::Spiders"); +} + int main(int /*argc*/, char ** /*argv*/) { return 0; diff --git a/tests/auto/linguist/lupdate/testdata/good/parsecontexts/project.ts.result b/tests/auto/linguist/lupdate/testdata/good/parsecontexts/project.ts.result index 9b00d53..2f21de2 100644 --- a/tests/auto/linguist/lupdate/testdata/good/parsecontexts/project.ts.result +++ b/tests/auto/linguist/lupdate/testdata/good/parsecontexts/project.ts.result @@ -102,6 +102,15 @@ + Bears::And::Spiders + + + whatever the context + Bears::And::Spiders + + + + C1 diff --git a/tools/linguist/lupdate/cpp.cpp b/tools/linguist/lupdate/cpp.cpp index 81623ab..44a8feb 100644 --- a/tools/linguist/lupdate/cpp.cpp +++ b/tools/linguist/lupdate/cpp.cpp @@ -133,6 +133,8 @@ struct Namespace { // definition (either one in case of multiple definitions). Namespace *classDef; + QString trQualification; + bool hasTrFunctions; bool complained; // ... that tr functions are missing. }; @@ -221,6 +223,7 @@ private: uint getChar(); uint getToken(); + bool getMacroArgs(); bool match(uint t); bool matchString(QString *s); bool matchEncoding(bool *utf8); @@ -416,6 +419,34 @@ uint CppParser::getChar() } } +// This ignores commas, parens and comments. +// IOW, it understands only a single, simple argument. +bool CppParser::getMacroArgs() +{ + // Failing this assertion would mean losing the preallocated buffer. + Q_ASSERT(yyWord.isDetached()); + yyWord.resize(0); + + while (isspace(yyCh)) + yyCh = getChar(); + if (yyCh != '(') + return false; + do { + yyCh = getChar(); + } while (isspace(yyCh)); + ushort *ptr = (ushort *)yyWord.unicode(); + while (yyCh != ')') { + if (yyCh == EOF) + return false; + *ptr++ = yyCh; + yyCh = getChar(); + } + yyCh = getChar(); + for (; ptr != (ushort *)yyWord.unicode() && isspace(*(ptr - 1)); --ptr) ; + yyWord.resize(ptr - (ushort *)yyWord.unicode()); + return true; +} + STRING(Q_OBJECT); STRING(Q_DECLARE_TR_FUNCTIONS); STRING(QT_TR_NOOP); @@ -1666,10 +1697,11 @@ void CppParser::parseInternal(ConversionData &cd, QSet &inclusions) qPrintable(yyFileName), yyLineNo); break; } - while (!findNamespace(functionContext, idx)->classDef->hasTrFunctions) { + Namespace *fctx; + while (!(fctx = findNamespace(functionContext, idx)->classDef)->hasTrFunctions) { if (idx == 1) { context = stringifyNamespace(functionContext); - Namespace *fctx = findNamespace(functionContext)->classDef; + fctx = findNamespace(functionContext)->classDef; if (!fctx->complained) { qWarning("%s:%d: Class '%s' lacks Q_OBJECT macro\n", qPrintable(yyFileName), yyLineNo, @@ -1680,12 +1712,17 @@ void CppParser::parseInternal(ConversionData &cd, QSet &inclusions) } --idx; } - context.clear(); - for (int i = 1;;) { - context += functionContext.at(i).value(); - if (++i == idx) - break; - context += strColons; + if (fctx->trQualification.isEmpty()) { + context.clear(); + for (int i = 1;;) { + context += functionContext.at(i).value(); + if (++i == idx) + break; + context += strColons; + } + fctx->trQualification = context; + } else { + context = fctx->trQualification; } } else { context = (stringListifyNamespace(functionContext) @@ -1705,8 +1742,13 @@ void CppParser::parseInternal(ConversionData &cd, QSet &inclusions) NamespaceList nsl; QStringList unresolved; if (fullyQualify(functionContext, prefix, false, &nsl, &unresolved)) { - context = stringifyNamespace(nsl); Namespace *fctx = findNamespace(nsl)->classDef; + if (fctx->trQualification.isEmpty()) { + context = stringifyNamespace(nsl); + fctx->trQualification = context; + } else { + context = fctx->trQualification; + } if (!fctx->hasTrFunctions && !fctx->complained) { qWarning("%s:%d: Class '%s' lacks Q_OBJECT macro\n", qPrintable(yyFileName), yyLineNo, @@ -1806,6 +1848,14 @@ void CppParser::parseInternal(ConversionData &cd, QSet &inclusions) extra.clear(); break; case Tok_Q_DECLARE_TR_FUNCTIONS: + if (getMacroArgs()) { + Namespace *ns = modifyNamespace(&namespaces, true); + ns->hasTrFunctions = true; + ns->trQualification = yyWord; + ns->trQualification.detach(); + } + yyTok = getToken(); + break; case Tok_Q_OBJECT: modifyNamespace(&namespaces, true)->hasTrFunctions = true; yyTok = getToken(); -- cgit v0.12