From d9aebed5c8520911f290da0d66b6cb849ccb9657 Mon Sep 17 00:00:00 2001 From: Lucie Gerard Date: Mon, 1 Apr 2019 10:23:38 +0200 Subject: Add forward looking after Colon Colons seen are remembered in order to identify a member or base class identifier. In case of declaration of a bit field, the colon should be ignored. If it is not, unexpected behaviors compromise the resolution of the context, when the context is not explicit in the tr() function. To differentiate between colons in a member or base class identifier, and colons in a bit field, this patch implements a heuristic: We parse forward to either a '{', or a ';'. If it is a semicolon we assume it's a bit field, if it is a curved open bracket we assume the colon is for a member or base class identifier. Related auto test in case of bitfields declaration added. Task-number: QTBUG-55479 Change-Id: I2ca1124c192e4ab16fd449afc634a5de5023f481 Reviewed-by: Kai Koehne --- src/linguist/lupdate/cpp.cpp | 25 ++++++++++++++++++++-- .../linguist/lupdate/testdata/good/prefix/main.cpp | 13 +++++++++++ .../lupdate/testdata/good/prefix/project.ts.result | 24 +++++++++++++++++++++ 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/linguist/lupdate/cpp.cpp b/src/linguist/lupdate/cpp.cpp index aac9a90ff..d8a4f9a37 100644 --- a/src/linguist/lupdate/cpp.cpp +++ b/src/linguist/lupdate/cpp.cpp @@ -239,6 +239,7 @@ private: std::ostream &yyMsg(int line = 0); int getChar(); + TokenType lookAheadToSemicolonOrLeftBrace(); TokenType getToken(); void processComment(); @@ -450,6 +451,23 @@ int CppParser::getChar() } } +CppParser::TokenType CppParser::lookAheadToSemicolonOrLeftBrace() +{ + if (*yyInPtr == 0) + return Tok_Eof; + const ushort *uc = yyInPtr + 1; + forever { + ushort c = *uc; + if (!c) + return Tok_Eof; + if (c == ';') + return Tok_Semicolon; + if (c == '{') + return Tok_LeftBrace; + ++uc; + } +} + STRING(Q_OBJECT); STRING(class); STRING(final); @@ -2182,8 +2200,11 @@ void CppParser::parseInternal(ConversionData &cd, const QStringList &includeStac pendingContext = prospectiveContext; prospectiveContext.clear(); } - if (yyTok == Tok_Colon) - yyTokColonSeen = true; + //ignore colons for bitfields (are usually followed by a semicolon) + if (yyTok == Tok_Colon) { + if (lookAheadToSemicolonOrLeftBrace() != Tok_Semicolon) + yyTokColonSeen = true; + } } metaExpected = true; yyTok = getToken(); diff --git a/tests/auto/linguist/lupdate/testdata/good/prefix/main.cpp b/tests/auto/linguist/lupdate/testdata/good/prefix/main.cpp index 772ebfb29..6cef7a28c 100644 --- a/tests/auto/linguist/lupdate/testdata/good/prefix/main.cpp +++ b/tests/auto/linguist/lupdate/testdata/good/prefix/main.cpp @@ -41,3 +41,16 @@ void Foo::bar() { tr("BAR"); } + +class BitFields : public QObject +{ + int bits : 20; + QString str = tr("text BitFields"); +}; + +Bibi::Bibi() +{ + int bits : 32; + tr("text Bibi"); + Babebi::tr("text Babebi"); +} diff --git a/tests/auto/linguist/lupdate/testdata/good/prefix/project.ts.result b/tests/auto/linguist/lupdate/testdata/good/prefix/project.ts.result index 7e7e27742..e4f347db2 100644 --- a/tests/auto/linguist/lupdate/testdata/good/prefix/project.ts.result +++ b/tests/auto/linguist/lupdate/testdata/good/prefix/project.ts.result @@ -1,6 +1,30 @@ + + Babebi + + + text Babebi + + + + + Bibi + + + text Bibi + + + + + BitFields + + + text BitFields + + + Foo -- cgit v1.2.3