diff options
author | Karsten Heimrich <karsten.heimrich@qt.io> | 2019-11-08 14:38:30 +0100 |
---|---|---|
committer | Lucie GĂ©rard <lucie.gerard@qt.io> | 2020-02-18 15:05:41 +0100 |
commit | f685da95bd841c212142c9ba5ce9cad64640af2f (patch) | |
tree | a810899959baff697080859624eca38d03befaae | |
parent | 4bfea4e31f4a3deec673f519c83081b284f7c556 (diff) |
Add PP calls context and fill the information in translator
This is needed to get the context for translations present
in macros without a context in their argument and to apply
the argument-context in Q_DECLARE_TR_FUNCTIONS to the right
translation calls
Change-Id: I109f2bf963211dabcf293b772fa7d1d873f6ff60
Reviewed-by: Karsten Heimrich <karsten.heimrich@qt.io>
-rw-r--r-- | src/linguist/lupdate/clangtoolastreader.cpp | 261 | ||||
-rw-r--r-- | src/linguist/lupdate/clangtoolastreader.h | 50 | ||||
-rw-r--r-- | src/linguist/lupdate/cpp_clang.cpp | 174 | ||||
-rw-r--r-- | src/linguist/lupdate/cpp_clang.h | 14 |
4 files changed, 353 insertions, 146 deletions
diff --git a/src/linguist/lupdate/clangtoolastreader.cpp b/src/linguist/lupdate/clangtoolastreader.cpp index da0fcd5d8..8d384e89a 100644 --- a/src/linguist/lupdate/clangtoolastreader.cpp +++ b/src/linguist/lupdate/clangtoolastreader.cpp @@ -33,6 +33,34 @@ QT_BEGIN_NAMESPACE namespace LupdatePrivate { + /* + Retrieves the context for the NOOP macros using the context of + the NamedDeclaration within which the Macro is. + The context is stripped of the function or method part as it used not to be retrieved + in the previous cpp parser. + */ + QString contextForNoopMacro(clang::NamedDecl *namedDecl) + { + QStringList context; + const clang::DeclContext *decl = namedDecl->getDeclContext(); + while (decl) { + if (clang::isa<clang::NamedDecl>(decl) && !decl->isFunctionOrMethod()) { + if (const auto *namespaceDecl = clang::dyn_cast<clang::NamespaceDecl>(decl)) { + context.prepend(namespaceDecl->isAnonymousNamespace() + ? QStringLiteral("(anonymous namespace)") + : QString::fromStdString(namespaceDecl->getDeclName().getAsString())); + } else if (const auto *recordDecl = clang::dyn_cast<clang::RecordDecl>(decl)) { + static const QString anonymous = QStringLiteral("(anonymous %1)"); + context.prepend(recordDecl->getIdentifier() + ? QString::fromStdString(recordDecl->getDeclName().getAsString()) + : anonymous.arg(QLatin1String(recordDecl->getKindName().data()))); + } + } + decl = decl->getParent(); + } + return context.join(QStringLiteral("::")); + } + QString contextForFunctionDecl(clang::FunctionDecl *func, const std::string &funcName) { std::string context; @@ -104,6 +132,15 @@ namespace LupdatePrivate return true; return false; } + + bool isPointWithin(const clang::SourceRange &sourceRange, const clang::SourceLocation &point, + const clang::SourceManager &sm) + { + clang::SourceLocation start = sourceRange.getBegin(); + clang::SourceLocation end = sourceRange.getEnd(); + return point == start || point == end || (sm.isBeforeInTranslationUnit(start, point) + && sm.isBeforeInTranslationUnit(point, end)); + } } /* @@ -206,7 +243,7 @@ bool LupdateVisitor::VisitCallExpr(clang::CallExpr *callExpression) qCDebug(lcClang) << "Plural : " << store.lupdatePlural; break; } - m_translationStoresFromAST.push_back(store); + m_stores.AST.push_back(store); return true; } @@ -423,138 +460,136 @@ void LupdateVisitor::setInfoFromRawComment(const QString &commentString, } } -/* - Fill the Translator with the retrieved information after traversing the AST. -*/ -void LupdateVisitor::fillTranslator() +void LupdateVisitor::processPreprocessorCalls() { - for (const auto &store : qAsConst(m_translationStoresFromAST)) - fillTranslator(store); - // Here also need to fill the translator with the information retrieved from the PreProcessor + m_macro = (m_stores.Preprocessor.size() > 0); + for (const auto &store : qAsConst(m_stores.Preprocessor)) + processPreprocessorCall(store); } -void LupdateVisitor::fillTranslator(TranslationRelatedStore store) +void LupdateVisitor::processPreprocessorCall(TranslationRelatedStore store) { - bool forcePlural = false; - switch (trFunctionAliasManager.trFunctionByName(store.funcName)) { - case TrFunctionAliasManager::Function_Q_DECLARE_TR_FUNCTIONS: - // If there is a Q_DECLARE_TR_FUNCTION the context given takes priority - // over the retrieved context. - // The retrieved context for Q_DECLARE_TR_FUNCTION (where the macro was) - // has to fit the start of the retrieved context of the tr function or - // NOOP macro if there is already a argument giving the context, it has - // priority. - //handleDeclareTrFunctions(); // TODO: Implement. - break; - case TrFunctionAliasManager::Function_QT_TR_N_NOOP: - forcePlural = true; - Q_FALLTHROUGH(); - case TrFunctionAliasManager::Function_tr: - case TrFunctionAliasManager::Function_trUtf8: - case TrFunctionAliasManager::Function_QT_TR_NOOP: - case TrFunctionAliasManager::Function_QT_TR_NOOP_UTF8: - handleTr(store, forcePlural); - break; - case TrFunctionAliasManager::Function_QT_TRANSLATE_N_NOOP: - case TrFunctionAliasManager::Function_QT_TRANSLATE_N_NOOP3: - forcePlural = true; - Q_FALLTHROUGH(); - case TrFunctionAliasManager::Function_translate: - case TrFunctionAliasManager::Function_findMessage: - case TrFunctionAliasManager::Function_QT_TRANSLATE_NOOP: - case TrFunctionAliasManager::Function_QT_TRANSLATE_NOOP_UTF8: - case TrFunctionAliasManager::Function_QT_TRANSLATE_NOOP3: - case TrFunctionAliasManager::Function_QT_TRANSLATE_NOOP3_UTF8: - handleTranslate(store, forcePlural); - break; - case TrFunctionAliasManager::Function_QT_TRID_N_NOOP: - forcePlural = true; - Q_FALLTHROUGH(); - case TrFunctionAliasManager::Function_qtTrId: - case TrFunctionAliasManager::Function_QT_TRID_NOOP: - handleTrId(store, forcePlural); - break; - } -} + const std::vector<QString> rawComments = rawCommentsFromSourceLocation(store.callLocation); + for (const auto &rawComment : rawComments) + setInfoFromRawComment(rawComment, &store); -TranslatorMessage LupdateVisitor::fillTranslatorMessage(const TranslationRelatedStore &store, - bool forcePlural, bool isId) -{ - QString context; - if (!isId) { - context = ParserTool::transcode(store.contextArg.isEmpty() ? store.contextRetrieved - : store.contextArg); + if (store.isValid()) { + if (store.funcName.contains(QStringLiteral("Q_DECLARE_TR_FUNCTIONS"))) + m_qDeclareTrMacroAll.push_back(store); + else + m_noopTranslationMacroAll.push_back(store); + store.printStore(); } - - TranslatorMessage msg(context, - ParserTool::transcode(isId ? store.lupdateSourceWhenId - : store.lupdateSource), - ParserTool::transcode(store.lupdateComment), - QString(), - store.lupdateLocationFile, - store.lupdateLocationLine, - QStringList(), - TranslatorMessage::Type::Unfinished, - (forcePlural ? forcePlural : !store.lupdatePlural.isEmpty())); - - if (!store.lupdateAllMagicMetaData.empty()) - msg.setExtras(store.lupdateAllMagicMetaData); - msg.setExtraComment(ParserTool::transcode(store.lupdateExtraComment)); - return msg; } -void LupdateVisitor::handleTranslate(const TranslationRelatedStore &store, bool forcePlural) +bool LupdateVisitor::VisitNamedDecl(clang::NamedDecl *namedDeclaration) { - if (!store.lupdateSourceWhenId.isEmpty()) - qCDebug(lcClang) << "//% is ignored when using translate function\n"; + if (!m_macro) + return true; + auto fullLocation = m_context->getFullLoc(namedDeclaration->getBeginLoc()); + if (!fullLocation.isValid() || !fullLocation.getFileEntry()) + return true; + + if (fullLocation.getFileEntry()->getName() != m_inputFile) + return true; - TranslatorMessage msg = fillTranslatorMessage(store, forcePlural); - msg.setId(ParserTool::transcode(store.lupdateIdMetaData)); // //= NOT to be used with qTrId - m_tor->append(msg); + qCDebug(lcClang) << "NamedDecl Name: " << namedDeclaration->getQualifiedNameAsString(); + qCDebug(lcClang) << "NamedDecl source: " << namedDeclaration->getSourceRange().printToString( + m_context->getSourceManager()); + // Checks if there is a macro located within the range of this NamedDeclaration + // in order to find a context for the macro + findContextForTranslationStoresFromPP(namedDeclaration); + return true; } -void LupdateVisitor::handleTr(const TranslationRelatedStore &store, bool forcePlural) +void LupdateVisitor::findContextForTranslationStoresFromPP(clang::NamedDecl *namedDeclaration) { - if (!store.lupdateSourceWhenId.isEmpty()) - qCDebug(lcClang) << "//% is ignored when using tr function\n"; - if (store.contextRetrieved.isEmpty() && store.contextArg.isEmpty()) { - qCDebug(lcClang) << "tr() cannot be called without context \n"; - return; + qCDebug(lcClang) << "=================findContextForTranslationStoresFromPP==================="; + qCDebug(lcClang) << "m_noopTranslationMacroAll " << m_noopTranslationMacroAll.size(); + qCDebug(lcClang) << "m_qDeclareTrMacroAll " << m_qDeclareTrMacroAll.size(); + clang::SourceManager &sm = m_context->getSourceManager(); + + // Looking for NOOP context only in the input file + // because we are not interested in the NOOP from all related file + // Once QT_TR_NOOP are gone this step can be removes because the only + // QT_...NOOP left will have an context as argument + for (TranslationRelatedStore &store : m_noopTranslationMacroAll) { + if (!store.contextArg.isEmpty()) + continue; + clang::SourceLocation sourceLoc = store.callLocation; + if (!sourceLoc.isValid()) + continue; + if (LupdatePrivate::isPointWithin(namedDeclaration->getSourceRange(), sourceLoc, sm)) { + /* + void N3::C1::C12::C121::f2() + { + const char test_NOOP[] = QT_TR_NOOP("A QT_TR_NOOP N3::C1::C13"); + } + In such case namedDeclaration->getQualifiedNameAsString() will give only + test_NOOP as context. + This is why the following function is needed + */ + store.contextRetrievedTempNOOP = LupdatePrivate::contextForNoopMacro(namedDeclaration); + qCDebug(lcClang) << "------------------------------------------NOOP Macro in range ---"; + qCDebug(lcClang) << "Range " << namedDeclaration->getSourceRange().printToString(sm); + qCDebug(lcClang) << "Point " << sourceLoc.printToString(sm); + qCDebug(lcClang) << "=========== Visit Named Declaration ============================="; + qCDebug(lcClang) << " Declaration Location " << + namedDeclaration->getSourceRange().printToString(sm); + qCDebug(lcClang) << " Macro Location " + << store.callLocation.printToString(sm); + qCDebug(lcClang) << " Context namedDeclaration->getQualifiedNameAsString() " + << namedDeclaration->getQualifiedNameAsString(); + qCDebug(lcClang) << " Context LupdatePrivate::contextForNoopMacro " + << store.contextRetrievedTempNOOP; + qCDebug(lcClang) << " Context Retrieved " << store.contextRetrievedTempNOOP; + qCDebug(lcClang) << "================================================================="; + store.printStore(); + } } - TranslatorMessage msg = fillTranslatorMessage(store, forcePlural); - msg.setId(ParserTool::transcode(store.lupdateIdMetaData)); // //= NOT to be used with qTrId - m_tor->append(msg); + for (TranslationRelatedStore &store : m_qDeclareTrMacroAll) { + clang::SourceLocation sourceLoc = store.callLocation; + if (!sourceLoc.isValid()) + continue; + if (LupdatePrivate::isPointWithin(namedDeclaration->getSourceRange(), sourceLoc, sm)) { + store.contextRetrieved = QString::fromStdString( + namedDeclaration->getQualifiedNameAsString()); + qCDebug(lcClang) << "------------------------------------------DECL Macro in range ---"; + qCDebug(lcClang) << "Range " << namedDeclaration->getSourceRange().printToString(sm); + qCDebug(lcClang) << "Point " << sourceLoc.printToString(sm); + qCDebug(lcClang) << "=========== Visit Named Declaration ============================="; + qCDebug(lcClang) << " Declaration Location " << + namedDeclaration->getSourceRange().printToString(sm); + qCDebug(lcClang) << " Macro Location " + << store.callLocation.printToString(sm); + qCDebug(lcClang) << " Context namedDeclaration->getQualifiedNameAsString() " + << store.contextRetrieved; + qCDebug(lcClang) << " Context LupdatePrivate::contextForNoopMacro " + << LupdatePrivate::contextForNoopMacro(namedDeclaration); + qCDebug(lcClang) << " Context Retrieved " << store.contextRetrieved; + qCDebug(lcClang) << "================================================================="; + store.printStore(); + } + } } -void LupdateVisitor::handleTrId(const TranslationRelatedStore &store, bool forcePlural) +void LupdateVisitor::generateOuput() { - if (!store.lupdateIdMetaData.isEmpty()) - qCDebug(lcClang) << "//= is ignored when using qtTrId function \n"; + qCDebug(lcClang) << "===================generateOuput============================"; - TranslatorMessage msg = fillTranslatorMessage(store, forcePlural, true); - msg.setId(ParserTool::transcode(store.lupdateId)); - m_tor->append(msg); -} - -void LupdateVisitor::processPreprocessorCalls() -{ - for (const auto &store : qAsConst(m_translationStoresFromPP)) - processPreprocessorCall(store); -} - -void LupdateVisitor::processPreprocessorCall(TranslationRelatedStore store) -{ - const std::vector<QString> rawComments = rawCommentsFromSourceLocation(store.callLocation); - for (const auto &rawComment : rawComments) - setInfoFromRawComment(rawComment, &store); + for (TranslationRelatedStore &store : m_noopTranslationMacroAll) { + if (store.contextRetrievedTempNOOP.isEmpty() && store.contextArg.isEmpty()) + continue; + // only fill if a context has been retrieved in the file we're currently visiting + m_stores.QNoopTranlsationWithContext.push_back(store); + } - if (store.isValid()) { - if (store.funcName.contains(QStringLiteral("Q_DECLARE_TR_FUNCTIONS"))) - m_qDeclateTrFunctionContext.push_back(store); - else - m_noopTranslationStores.push_back(store); - store.printStore(); + for (TranslationRelatedStore &store : m_qDeclareTrMacroAll) { + if (store.contextRetrieved.isEmpty()) + continue; + // only fill if a context has been retrieved in the file we're currently visiting + m_stores.QDeclareTrWithContext.push_back(store); } } diff --git a/src/linguist/lupdate/clangtoolastreader.h b/src/linguist/lupdate/clangtoolastreader.h index ea544bdad..8f9a54565 100644 --- a/src/linguist/lupdate/clangtoolastreader.h +++ b/src/linguist/lupdate/clangtoolastreader.h @@ -57,17 +57,19 @@ class Translator; class LupdateVisitor : public clang::RecursiveASTVisitor<LupdateVisitor> { public: - explicit LupdateVisitor(clang::ASTContext *context, Translator *tor) - : m_context(context), - m_tor(tor) + explicit LupdateVisitor(clang::ASTContext *context, Stores &stores) + : m_context(context) + , m_stores(stores) { m_inputFile = m_context->getSourceManager().getFileEntryForID( m_context->getSourceManager().getMainFileID())->getName(); } bool VisitCallExpr(clang::CallExpr *callExpression); - void fillTranslator(); void processPreprocessorCalls(); + bool VisitNamedDecl(clang::NamedDecl *namedDeclaration); + void findContextForTranslationStoresFromPP(clang::NamedDecl *namedDeclaration); + void generateOuput(); private: std::vector<QString> rawCommentsForCallExpr(const clang::CallExpr *callExpr) const; @@ -75,30 +77,24 @@ private: void setInfoFromRawComment(const QString &commentString, TranslationRelatedStore *store); - void fillTranslator(TranslationRelatedStore store); - TranslatorMessage fillTranslatorMessage(const TranslationRelatedStore &store, - bool forcePlural, bool isID = false); - void handleTr(const TranslationRelatedStore &store, bool forcePlural); - void handleTrId(const TranslationRelatedStore &store, bool forcePlural); - void handleTranslate(const TranslationRelatedStore &store, bool forcePlural); - void processPreprocessorCall(TranslationRelatedStore store); clang::ASTContext *m_context { nullptr }; Translator *m_tor { nullptr }; std::string m_inputFile; - TranslationStores m_translationStoresFromAST; - TranslationStores m_qDeclateTrFunctionContext; - TranslationStores m_noopTranslationStores; - TranslationStores m_translationStoresFromPP; + Stores &m_stores; + + TranslationStores m_qDeclareTrMacroAll; + TranslationStores m_noopTranslationMacroAll; + bool m_macro = false; }; class LupdateASTConsumer : public clang::ASTConsumer { public: - explicit LupdateASTConsumer(clang::ASTContext *context, Translator *tor) - : m_visitor(context, tor) + explicit LupdateASTConsumer(clang::ASTContext *context, Stores &stores) + : m_visitor(context, stores) {} // This method is called when the ASTs for entire translation unit have been @@ -108,7 +104,7 @@ public: m_visitor.processPreprocessorCalls(); bool traverse = m_visitor.TraverseAST(context); qCDebug(lcClang) << "TraverseAST: " << traverse; - m_visitor.fillTranslator(); + m_visitor.generateOuput(); } private: @@ -118,42 +114,42 @@ private: class LupdateFrontendAction : public clang::ASTFrontendAction { public: - LupdateFrontendAction(Translator *tor) - : m_tor(tor) + LupdateFrontendAction(Stores &outputStoresWithContext) + : m_stores(outputStoresWithContext) {} std::unique_ptr<clang::ASTConsumer> CreateASTConsumer( clang::CompilerInstance &compiler, llvm::StringRef /* inFile */) override { - LupdateASTConsumer *consumer = new LupdateASTConsumer(&compiler.getASTContext(), m_tor); + auto consumer = new LupdateASTConsumer(&compiler.getASTContext(), m_stores); return std::unique_ptr<clang::ASTConsumer>(consumer); } private: - Translator *m_tor { nullptr }; + Stores &m_stores; }; class LupdateToolActionFactory : public clang::tooling::FrontendActionFactory { public: - LupdateToolActionFactory(Translator *tor) - : m_tor(tor) + LupdateToolActionFactory(Stores &stores) + : m_stores(stores) {} #if (LUPDATE_CLANG_VERSION >= LUPDATE_CLANG_VERSION_CHECK(10,0,0)) std::unique_ptr<clang::FrontendAction> create() override { - return std::make_unique<LupdateFrontendAction>(m_tor); + return std::make_unique<LupdateFrontendAction>(m_stores); } #else clang::FrontendAction *create() override { - return new LupdateFrontendAction(m_tor); + return new LupdateFrontendAction(m_stores); } #endif private: - Translator *m_tor { nullptr }; + Stores &m_stores; }; QT_END_NAMESPACE diff --git a/src/linguist/lupdate/cpp_clang.cpp b/src/linguist/lupdate/cpp_clang.cpp index 6b8162c59..fc11253bd 100644 --- a/src/linguist/lupdate/cpp_clang.cpp +++ b/src/linguist/lupdate/cpp_clang.cpp @@ -68,8 +68,6 @@ void ClangCppParser::loadCPP(Translator &translator, const QStringList &filename for (const QString &filename : filenames) sources.push_back(filename.toStdString()); - // The ClangTool is to be created and run from this function. - int argc = 4; // NEED 2 empty one to start!!! otherwise: LLVM::ERROR const QByteArray jsonPath = cd.m_compileCommandsPath.toLocal8Bit(); @@ -81,12 +79,10 @@ void ClangCppParser::loadCPP(Translator &translator, const QStringList &filename Stores stores; tool.run(new LupdatePreprocessorActionFactory(stores.Preprocessor)); + tool.run(new LupdateToolActionFactory(stores)); Translator *tor = new Translator(); - - // A ClangTool needs a new FrontendAction for each translation unit it runs on - // A Customized FrontendActionFactory is building a customized FrondendAction - tool.run(new LupdateToolActionFactory(tor)); + ClangCppParser::fillTranslator(tor, stores); if (QLoggingCategory("qt.lupdate.clang").isDebugEnabled()) tor->dump(); @@ -95,4 +91,170 @@ void ClangCppParser::loadCPP(Translator &translator, const QStringList &filename translator.extend(msg, cd); } +/* + Fill the Translator with the retrieved information after traversing the AST. +*/ +void ClangCppParser::fillTranslator(Translator *tor, Stores &stores) +{ + correctAstTranslationContext(stores); + for (auto &store : stores.AST) + fillTranslator(tor, store); + + correctNoopTanslationContext(stores); + for (auto &store : stores.QNoopTranlsationWithContext) + fillTranslator(tor, store); +} + +void ClangCppParser::fillTranslator(Translator *tor, TranslationRelatedStore store) +{ + bool plural = false; + switch (trFunctionAliasManager.trFunctionByName(store.funcName)) { + case TrFunctionAliasManager::Function_Q_DECLARE_TR_FUNCTIONS: + break; + case TrFunctionAliasManager::Function_QT_TR_N_NOOP: + plural = true; + Q_FALLTHROUGH(); + case TrFunctionAliasManager::Function_tr: + case TrFunctionAliasManager::Function_trUtf8: + case TrFunctionAliasManager::Function_QT_TR_NOOP: + case TrFunctionAliasManager::Function_QT_TR_NOOP_UTF8: + handleTr(tor, store, plural); + break; + case TrFunctionAliasManager::Function_QT_TRANSLATE_N_NOOP: + case TrFunctionAliasManager::Function_QT_TRANSLATE_N_NOOP3: + plural = true; + Q_FALLTHROUGH(); + case TrFunctionAliasManager::Function_translate: + case TrFunctionAliasManager::Function_findMessage: + case TrFunctionAliasManager::Function_QT_TRANSLATE_NOOP: + case TrFunctionAliasManager::Function_QT_TRANSLATE_NOOP_UTF8: + case TrFunctionAliasManager::Function_QT_TRANSLATE_NOOP3: + case TrFunctionAliasManager::Function_QT_TRANSLATE_NOOP3_UTF8: + handleTranslate(tor, store, plural); + break; + case TrFunctionAliasManager::Function_QT_TRID_N_NOOP: + plural = true; + Q_FALLTHROUGH(); + case TrFunctionAliasManager::Function_qtTrId: + case TrFunctionAliasManager::Function_QT_TRID_NOOP: + handleTrId(tor, store, plural); + break; + } +} + +TranslatorMessage ClangCppParser::fillTranslatorMessage(const TranslationRelatedStore &store, + const QString &id, bool plural, bool isId) +{ + QString context; + if (!isId) { + context = ParserTool::transcode(store.contextArg.isEmpty() ? store.contextRetrieved + : store.contextArg); + } + + TranslatorMessage msg(context, + ParserTool::transcode(isId ? store.lupdateSourceWhenId + : store.lupdateSource), + ParserTool::transcode(store.lupdateComment), + QString(), + store.lupdateLocationFile, + store.lupdateLocationLine, + QStringList(), + TranslatorMessage::Type::Unfinished, + (plural ? plural : !store.lupdatePlural.isEmpty())); + + if (!store.lupdateAllMagicMetaData.empty()) + msg.setExtras(store.lupdateAllMagicMetaData); + msg.setExtraComment(ParserTool::transcode(store.lupdateExtraComment)); + msg.setId(ParserTool::transcode(id)); + return msg; +} + +void ClangCppParser::handleTranslate(Translator *tor, const TranslationRelatedStore &store, + bool plural) +{ + if (!store.lupdateSourceWhenId.isEmpty()) + qCDebug(lcClang) << "//% is ignored when using translate function\n"; + tor->append(fillTranslatorMessage(store, store.lupdateIdMetaData, plural, false)); +} + +void ClangCppParser::handleTr(Translator *tor, const TranslationRelatedStore &store, bool plural) +{ + if (!store.lupdateSourceWhenId.isEmpty()) + qCDebug(lcClang) << "//% is ignored when using tr function\n"; + if (store.contextRetrieved.isEmpty() && store.contextArg.isEmpty()) { + qCDebug(lcClang) << "tr() cannot be called without context \n"; + return; + } + tor->append(fillTranslatorMessage(store, store.lupdateIdMetaData, plural, false)); +} + +void ClangCppParser::handleTrId(Translator *tor, const TranslationRelatedStore &store, bool plural) +{ + if (!store.lupdateIdMetaData.isEmpty()) + qCDebug(lcClang) << "//= is ignored when using qtTrId function \n"; + tor->append(fillTranslatorMessage(store, store.lupdateId, plural, true)); +} + +void ClangCppParser::correctAstTranslationContext(Stores &stores) +{ + for (auto &store : stores.AST) { + if (!store.contextArg.isEmpty()) + continue; + + // If there is a Q_DECLARE_TR_FUNCTION the context given there takes + // priority over the retrieved context. The retrieved context for + // Q_DECLARE_TR_FUNCTION (where the macro was) has to fit the retrieved + // context of the tr function if there is already a argument giving the + // context, it has priority + for (auto &declareStore : stores.QDeclareTrWithContext) { + qCDebug(lcClang) << "----------------------------"; + qCDebug(lcClang) << "Tr call context retrieved " << store.contextRetrieved; + qCDebug(lcClang) << "Tr call source " << store.lupdateSource; + qCDebug(lcClang) << "- DECLARE context retrieved " << declareStore.contextRetrieved; + qCDebug(lcClang) << "- DECLARE context Arg " << declareStore.contextArg; + if (declareStore.contextRetrieved.isEmpty()) + continue; + if (!declareStore.contextRetrieved.startsWith(store.contextRetrieved)) + continue; + if (store.contextRetrieved.size() == declareStore.contextRetrieved.size()) { + qCDebug(lcClang) << "* Tr call context retrieved " << store.contextRetrieved; + qCDebug(lcClang) << "* DECLARE context retrieved " << declareStore.contextRetrieved; + qCDebug(lcClang) << "* DECLARE context Arg " << declareStore.contextArg; + store.contextArg = declareStore.contextArg; + } + } + } +} + +void ClangCppParser::correctNoopTanslationContext(Stores &stores) +{ + for (auto &store : stores.QNoopTranlsationWithContext) { + if (!store.contextArg.isEmpty()) + continue; + qCDebug(lcClang) << "----------------------------"; + qCDebug(lcClang) << "NOOP call context retrieved Temp" << store.contextRetrievedTempNOOP; + qCDebug(lcClang) << "NOOP call source " << store.lupdateSource; + + for (const auto &qDeclare : stores.QDeclareTrWithContext) { + bool firstCheck = false; + bool secondCheck = false; + qCDebug(lcClang) << "- DECLARE context retrieved " << qDeclare.contextRetrieved; + qCDebug(lcClang) << "- DECLARE context Arg " << qDeclare.contextArg; + if (store.contextRetrievedTempNOOP.startsWith(qDeclare.contextRetrieved)) { + firstCheck = (store.contextRetrievedTempNOOP.size() == qDeclare.contextRetrieved.size() + || (store.contextRetrievedTempNOOP.at(qDeclare.contextRetrieved.size() + 1) + == QLatin1Char(':'))); + secondCheck = qDeclare.contextRetrieved.size() > store.contextRetrieved.size(); + if (firstCheck && secondCheck) { + store.contextRetrieved = qDeclare.contextRetrieved; + store.contextArg = qDeclare.contextArg; + qCDebug(lcClang) << "* NOOP call context retrieved " << store.contextRetrieved; + qCDebug(lcClang) << "* DECLARE context retrieved " << qDeclare.contextRetrieved; + qCDebug(lcClang) << "* DECLARE context Arg " << qDeclare.contextArg; + } + } + } + } +} + QT_END_NAMESPACE diff --git a/src/linguist/lupdate/cpp_clang.h b/src/linguist/lupdate/cpp_clang.h index c9d512c5e..acc0157da 100644 --- a/src/linguist/lupdate/cpp_clang.h +++ b/src/linguist/lupdate/cpp_clang.h @@ -72,6 +72,7 @@ struct TranslationRelatedStore qint64 locationCol = -1; QString contextArg; QString contextRetrieved; + QString contextRetrievedTempNOOP; QString lupdateSource; QString lupdateLocationFile; qint64 lupdateLocationLine = -1; @@ -189,6 +190,19 @@ namespace LupdatePrivate namespace ClangCppParser { void loadCPP(Translator &translator, const QStringList &filenames, ConversionData &cd); + + void fillTranslator(Translator *tor, Stores &stores); + void fillTranslator(Translator *tor, TranslationRelatedStore store); + + TranslatorMessage fillTranslatorMessage(const TranslationRelatedStore &store, + const QString &id, bool plural, bool isID); + + void handleTr(Translator *tor, const TranslationRelatedStore &store, bool plural); + void handleTrId(Translator *tor, const TranslationRelatedStore &store, bool plural); + void handleTranslate(Translator *tor, const TranslationRelatedStore &store, bool plural); + + void correctAstTranslationContext(Stores &stores); + void correctNoopTanslationContext(Stores &stores); } QT_END_NAMESPACE |