tools/linguist/lupdate/cpp.cpp
changeset 37 758a864f9613
parent 33 3e2da88830cd
equal deleted inserted replaced
36:ef0373b55136 37:758a864f9613
    48 #include <QtCore/QFileInfo>
    48 #include <QtCore/QFileInfo>
    49 #include <QtCore/QStack>
    49 #include <QtCore/QStack>
    50 #include <QtCore/QString>
    50 #include <QtCore/QString>
    51 #include <QtCore/QTextCodec>
    51 #include <QtCore/QTextCodec>
    52 #include <QtCore/QTextStream>
    52 #include <QtCore/QTextStream>
       
    53 #include <QtCore/QCoreApplication>
    53 
    54 
    54 #include <iostream>
    55 #include <iostream>
    55 
    56 
    56 #include <ctype.h>              // for isXXX()
    57 #include <ctype.h>              // for isXXX()
    57 
    58 
    58 QT_BEGIN_NAMESPACE
    59 QT_BEGIN_NAMESPACE
       
    60 
       
    61 class LU {
       
    62     Q_DECLARE_TR_FUNCTIONS(LUpdate)
       
    63 };
    59 
    64 
    60 /* qmake ignore Q_OBJECT */
    65 /* qmake ignore Q_OBJECT */
    61 
    66 
    62 static QString MagicComment(QLatin1String("TRANSLATOR"));
    67 static QString MagicComment(QLatin1String("TRANSLATOR"));
    63 
    68 
   622                         if (is.elseLine != -1) {
   627                         if (is.elseLine != -1) {
   623                             if (yyBracketDepth != is.bracketDepth1st
   628                             if (yyBracketDepth != is.bracketDepth1st
   624                                 || yyBraceDepth != is.braceDepth1st
   629                                 || yyBraceDepth != is.braceDepth1st
   625                                 || yyParenDepth != is.parenDepth1st)
   630                                 || yyParenDepth != is.parenDepth1st)
   626                                 yyMsg(is.elseLine)
   631                                 yyMsg(is.elseLine)
   627                                     << "Parenthesis/bracket/brace mismatch between "
   632                                     << qPrintable(LU::tr("Parenthesis/bracket/brace mismatch between "
   628                                        "#if and #else branches; using #if branch\n";
   633                                                          "#if and #else branches; using #if branch\n"));
   629                         } else {
   634                         } else {
   630                             is.bracketDepth1st = yyBracketDepth;
   635                             is.bracketDepth1st = yyBracketDepth;
   631                             is.braceDepth1st = yyBraceDepth;
   636                             is.braceDepth1st = yyBraceDepth;
   632                             is.parenDepth1st = yyParenDepth;
   637                             is.parenDepth1st = yyParenDepth;
   633                             saveState(&is.state);
   638                             saveState(&is.state);
   645                         if (is.elseLine != -1) {
   650                         if (is.elseLine != -1) {
   646                             if (yyBracketDepth != is.bracketDepth1st
   651                             if (yyBracketDepth != is.bracketDepth1st
   647                                 || yyBraceDepth != is.braceDepth1st
   652                                 || yyBraceDepth != is.braceDepth1st
   648                                 || yyParenDepth != is.parenDepth1st)
   653                                 || yyParenDepth != is.parenDepth1st)
   649                                 yyMsg(is.elseLine)
   654                                 yyMsg(is.elseLine)
   650                                     << "Parenthesis/brace mismatch between "
   655                                     << qPrintable(LU::tr("Parenthesis/brace mismatch between "
   651                                        "#if and #else branches; using #if branch\n";
   656                                                          "#if and #else branches; using #if branch\n"));
   652                             yyBracketDepth = is.bracketDepth1st;
   657                             yyBracketDepth = is.bracketDepth1st;
   653                             yyBraceDepth = is.braceDepth1st;
   658                             yyBraceDepth = is.braceDepth1st;
   654                             yyParenDepth = is.parenDepth1st;
   659                             yyParenDepth = is.parenDepth1st;
   655                             loadState(&is.state);
   660                             loadState(&is.state);
   656                         }
   661                         }
   672                         bool metAster = false;
   677                         bool metAster = false;
   673 
   678 
   674                         forever {
   679                         forever {
   675                             yyCh = getChar();
   680                             yyCh = getChar();
   676                             if (yyCh == EOF) {
   681                             if (yyCh == EOF) {
   677                                 yyMsg() << "Unterminated C++ comment\n";
   682                                 yyMsg() << qPrintable(LU::tr("Unterminated C++ comment\n"));
   678                                 break;
   683                                 break;
   679                             }
   684                             }
   680 
   685 
   681                             if (yyCh == '*') {
   686                             if (yyCh == '*') {
   682                                 metAster = true;
   687                                 metAster = true;
   802                     ushort *ptr = (ushort *)yyWord.unicode() + yyWord.length();
   807                     ushort *ptr = (ushort *)yyWord.unicode() + yyWord.length();
   803 
   808 
   804                     forever {
   809                     forever {
   805                         yyCh = getChar();
   810                         yyCh = getChar();
   806                         if (yyCh == EOF) {
   811                         if (yyCh == EOF) {
   807                             yyMsg() << "Unterminated C++ comment\n";
   812                             yyMsg() << qPrintable(LU::tr("Unterminated C++ comment\n"));
   808                             break;
   813                             break;
   809                         }
   814                         }
   810                         *ptr++ = yyCh;
   815                         *ptr++ = yyCh;
   811 
   816 
   812                         if (yyCh == '*')
   817                         if (yyCh == '*')
   835                     yyCh = getChar();
   840                     yyCh = getChar();
   836                 }
   841                 }
   837                 yyWord.resize(ptr - (ushort *)yyWord.unicode());
   842                 yyWord.resize(ptr - (ushort *)yyWord.unicode());
   838 
   843 
   839                 if (yyCh != '"')
   844                 if (yyCh != '"')
   840                     yyMsg() << "Unterminated C++ string\n";
   845                     yyMsg() << qPrintable(LU::tr("Unterminated C++ string\n"));
   841                 else
   846                 else
   842                     yyCh = getChar();
   847                     yyCh = getChar();
   843                 return Tok_String;
   848                 return Tok_String;
   844             }
   849             }
   845             case '-':
   850             case '-':
   892                 return Tok_LeftBrace;
   897                 return Tok_LeftBrace;
   893             case '}':
   898             case '}':
   894                 if (yyBraceDepth == yyMinBraceDepth) {
   899                 if (yyBraceDepth == yyMinBraceDepth) {
   895                     if (!inDefine)
   900                     if (!inDefine)
   896                         yyMsg(yyCurLineNo)
   901                         yyMsg(yyCurLineNo)
   897                             << "Excess closing brace in C++ code"
   902                             << qPrintable(LU::tr("Excess closing brace in C++ code"
   898                                " (or abuse of the C++ preprocessor)\n";
   903                                                  " (or abuse of the C++ preprocessor)\n"));
   899                     // Avoid things getting messed up even more
   904                     // Avoid things getting messed up even more
   900                     yyCh = getChar();
   905                     yyCh = getChar();
   901                     return Tok_Semicolon;
   906                     return Tok_Semicolon;
   902                 }
   907                 }
   903                 yyBraceDepth--;
   908                 yyBraceDepth--;
   910                 yyCh = getChar();
   915                 yyCh = getChar();
   911                 return Tok_LeftParen;
   916                 return Tok_LeftParen;
   912             case ')':
   917             case ')':
   913                 if (yyParenDepth == 0)
   918                 if (yyParenDepth == 0)
   914                     yyMsg(yyCurLineNo)
   919                     yyMsg(yyCurLineNo)
   915                         << "Excess closing parenthesis in C++ code"
   920                         << qPrintable(LU::tr("Excess closing parenthesis in C++ code"
   916                            " (or abuse of the C++ preprocessor)\n";
   921                                              " (or abuse of the C++ preprocessor)\n"));
   917                 else
   922                 else
   918                     yyParenDepth--;
   923                     yyParenDepth--;
   919                 yyCh = getChar();
   924                 yyCh = getChar();
   920                 return Tok_RightParen;
   925                 return Tok_RightParen;
   921             case '[':
   926             case '[':
   925                 yyCh = getChar();
   930                 yyCh = getChar();
   926                 return Tok_LeftBracket;
   931                 return Tok_LeftBracket;
   927             case ']':
   932             case ']':
   928                 if (yyBracketDepth == 0)
   933                 if (yyBracketDepth == 0)
   929                     yyMsg(yyCurLineNo)
   934                     yyMsg(yyCurLineNo)
   930                         << "Excess closing bracket in C++ code"
   935                         << qPrintable(LU::tr("Excess closing bracket in C++ code"
   931                            " (or abuse of the C++ preprocessor)\n";
   936                                              " (or abuse of the C++ preprocessor)\n"));
   932                 else
   937                 else
   933                     yyBracketDepth--;
   938                     yyBracketDepth--;
   934                 yyCh = getChar();
   939                 yyCh = getChar();
   935                 return Tok_RightBracket;
   940                 return Tok_RightBracket;
   936             case ',':
   941             case ',':
  1294                                QSet<QString> &inclusions)
  1299                                QSet<QString> &inclusions)
  1295 {
  1300 {
  1296     QString cleanFile = QDir::cleanPath(file);
  1301     QString cleanFile = QDir::cleanPath(file);
  1297 
  1302 
  1298     if (inclusions.contains(cleanFile)) {
  1303     if (inclusions.contains(cleanFile)) {
  1299         yyMsg() << "circular inclusion of " << qPrintable(cleanFile) << std::endl;
  1304         yyMsg() << qPrintable(LU::tr("circular inclusion of %1\n").arg(cleanFile));
  1300         return;
  1305         return;
  1301     }
  1306     }
  1302 
  1307 
  1303     // If the #include is in any kind of namespace, has been blacklisted previously,
  1308     // If the #include is in any kind of namespace, has been blacklisted previously,
  1304     // or is not a header file (stdc++ extensionless or *.h*), then really include
  1309     // or is not a header file (stdc++ extensionless or *.h*), then really include
  1318         isIndirect = true;
  1323         isIndirect = true;
  1319     }
  1324     }
  1320 
  1325 
  1321     QFile f(cleanFile);
  1326     QFile f(cleanFile);
  1322     if (!f.open(QIODevice::ReadOnly)) {
  1327     if (!f.open(QIODevice::ReadOnly)) {
  1323         yyMsg()
  1328         yyMsg() << qPrintable(LU::tr("Cannot open %1: %2\n").arg(cleanFile, f.errorString()));
  1324             << "Cannot open " << qPrintable(cleanFile) << ": "
       
  1325             << qPrintable(f.errorString()) << std::endl;
       
  1326         return;
  1329         return;
  1327     }
  1330     }
  1328 
  1331 
  1329     QTextStream ts(&f);
  1332     QTextStream ts(&f);
  1330     ts.setCodec(yySourceCodec);
  1333     ts.setCodec(yySourceCodec);
  1764         case Tok_tr:
  1767         case Tok_tr:
  1765         case Tok_trUtf8:
  1768         case Tok_trUtf8:
  1766             if (!tor)
  1769             if (!tor)
  1767                 goto case_default;
  1770                 goto case_default;
  1768             if (!sourcetext.isEmpty())
  1771             if (!sourcetext.isEmpty())
  1769                 yyMsg() << "//% cannot be used with tr() / QT_TR_NOOP(). Ignoring\n";
  1772                 yyMsg() << qPrintable(LU::tr("//% cannot be used with tr() / QT_TR_NOOP(). Ignoring\n"));
  1770             utf8 = (yyTok == Tok_trUtf8);
  1773             utf8 = (yyTok == Tok_trUtf8);
  1771             line = yyLineNo;
  1774             line = yyLineNo;
  1772             yyTok = getToken();
  1775             yyTok = getToken();
  1773             if (match(Tok_LeftParen) && matchString(&text) && !text.isEmpty()) {
  1776             if (match(Tok_LeftParen) && matchString(&text) && !text.isEmpty()) {
  1774                 comment.clear();
  1777                 comment.clear();
  1785                 }
  1788                 }
  1786                 if (!pendingContext.isEmpty() && !prefix.startsWith(strColons)) {
  1789                 if (!pendingContext.isEmpty() && !prefix.startsWith(strColons)) {
  1787                     QStringList unresolved;
  1790                     QStringList unresolved;
  1788                     if (!fullyQualify(namespaces, pendingContext, true, &functionContext, &unresolved)) {
  1791                     if (!fullyQualify(namespaces, pendingContext, true, &functionContext, &unresolved)) {
  1789                         functionContextUnresolved = unresolved.join(strColons);
  1792                         functionContextUnresolved = unresolved.join(strColons);
  1790                         yyMsg() << "Qualifying with unknown namespace/class "
  1793                         yyMsg() << qPrintable(LU::tr("Qualifying with unknown namespace/class %1::%2\n")
  1791                                 << qPrintable(stringifyNamespace(functionContext)) << "::"
  1794                                               .arg(stringifyNamespace(functionContext)).arg(unresolved.first()));
  1792                                 << qPrintable(unresolved.first()) << std::endl;
       
  1793                     }
  1795                     }
  1794                     pendingContext.clear();
  1796                     pendingContext.clear();
  1795                 }
  1797                 }
  1796                 if (prefix.isEmpty()) {
  1798                 if (prefix.isEmpty()) {
  1797                     if (functionContextUnresolved.isEmpty()) {
  1799                     if (functionContextUnresolved.isEmpty()) {
  1798                         int idx = functionContext.length();
  1800                         int idx = functionContext.length();
  1799                         if (idx < 2) {
  1801                         if (idx < 2) {
  1800                             yyMsg() << "tr() cannot be called without context\n";
  1802                             yyMsg() << qPrintable(LU::tr("tr() cannot be called without context\n"));
  1801                             break;
  1803                             break;
  1802                         }
  1804                         }
  1803                         Namespace *fctx;
  1805                         Namespace *fctx;
  1804                         while (!(fctx = findNamespace(functionContext, idx)->classDef)->hasTrFunctions) {
  1806                         while (!(fctx = findNamespace(functionContext, idx)->classDef)->hasTrFunctions) {
  1805                             if (idx == 1) {
  1807                             if (idx == 1) {
  1806                                 context = stringifyNamespace(functionContext);
  1808                                 context = stringifyNamespace(functionContext);
  1807                                 fctx = findNamespace(functionContext)->classDef;
  1809                                 fctx = findNamespace(functionContext)->classDef;
  1808                                 if (!fctx->complained) {
  1810                                 if (!fctx->complained) {
  1809                                     yyMsg() << "Class '" << qPrintable(context)
  1811                                     yyMsg() << qPrintable(LU::tr("Class '%1' lacks Q_OBJECT macro\n")
  1810                                             << "' lacks Q_OBJECT macro\n";
  1812                                                          .arg(context));
  1811                                     fctx->complained = true;
  1813                                     fctx->complained = true;
  1812                                 }
  1814                                 }
  1813                                 goto gotctx;
  1815                                 goto gotctx;
  1814                             }
  1816                             }
  1815                             --idx;
  1817                             --idx;
  1833                 } else {
  1835                 } else {
  1834 #ifdef DIAGNOSE_RETRANSLATABILITY
  1836 #ifdef DIAGNOSE_RETRANSLATABILITY
  1835                     int last = prefix.lastIndexOf(strColons);
  1837                     int last = prefix.lastIndexOf(strColons);
  1836                     QString className = prefix.mid(last == -1 ? 0 : last + 2);
  1838                     QString className = prefix.mid(last == -1 ? 0 : last + 2);
  1837                     if (!className.isEmpty() && className == functionName) {
  1839                     if (!className.isEmpty() && className == functionName) {
  1838                         yyMsg() << "It is not recommended to call tr() from within a constructor '"
  1840                         yyMsg() << qPrintable(LU::tr("It is not recommended to call tr() from within a constructor '%1::%2'\n")
  1839                                 << qPrintable(className) << "::" << qPrintable(functionName) << "'\n";
  1841                                 .arg(className).arg(functionName));
  1840                     }
  1842                     }
  1841 #endif
  1843 #endif
  1842                     prefix.chop(2);
  1844                     prefix.chop(2);
  1843                     NamespaceList nsl;
  1845                     NamespaceList nsl;
  1844                     QStringList unresolved;
  1846                     QStringList unresolved;
  1849                             fctx->trQualification = context;
  1851                             fctx->trQualification = context;
  1850                         } else {
  1852                         } else {
  1851                             context = fctx->trQualification;
  1853                             context = fctx->trQualification;
  1852                         }
  1854                         }
  1853                         if (!fctx->hasTrFunctions && !fctx->complained) {
  1855                         if (!fctx->hasTrFunctions && !fctx->complained) {
  1854                             yyMsg() << "Class '" << qPrintable(context) << "' lacks Q_OBJECT macro\n";
  1856                             yyMsg() << qPrintable(LU::tr("Class '%1' lacks Q_OBJECT macro\n").arg(context));
  1855                             fctx->complained = true;
  1857                             fctx->complained = true;
  1856                         }
  1858                         }
  1857                     } else {
  1859                     } else {
  1858                         context = (stringListifyNamespace(nsl) + unresolved).join(strColons);
  1860                         context = (stringListifyNamespace(nsl) + unresolved).join(strColons);
  1859                     }
  1861                     }
  1871         case Tok_translateUtf8:
  1873         case Tok_translateUtf8:
  1872         case Tok_translate:
  1874         case Tok_translate:
  1873             if (!tor)
  1875             if (!tor)
  1874                 goto case_default;
  1876                 goto case_default;
  1875             if (!sourcetext.isEmpty())
  1877             if (!sourcetext.isEmpty())
  1876                 yyMsg() << "//% cannot be used with translate() / QT_TRANSLATE_NOOP(). Ignoring\n";
  1878                 yyMsg() << qPrintable(LU::tr("//% cannot be used with translate() / QT_TRANSLATE_NOOP(). Ignoring\n"));
  1877             utf8 = (yyTok == Tok_translateUtf8);
  1879             utf8 = (yyTok == Tok_translateUtf8);
  1878             line = yyLineNo;
  1880             line = yyLineNo;
  1879             yyTok = getToken();
  1881             yyTok = getToken();
  1880             if (match(Tok_LeftParen)
  1882             if (match(Tok_LeftParen)
  1881                 && matchString(&context)
  1883                 && matchString(&context)
  1926             break;
  1928             break;
  1927         case Tok_trid:
  1929         case Tok_trid:
  1928             if (!tor)
  1930             if (!tor)
  1929                 goto case_default;
  1931                 goto case_default;
  1930             if (!msgid.isEmpty())
  1932             if (!msgid.isEmpty())
  1931                 yyMsg() << "//= cannot be used with qtTrId() / QT_TRID_NOOP(). Ignoring\n";
  1933                 yyMsg() << qPrintable(LU::tr("//= cannot be used with qtTrId() / QT_TRID_NOOP(). Ignoring\n"));
  1932             //utf8 = false; // Maybe use //%% or something like that
  1934             //utf8 = false; // Maybe use //%% or something like that
  1933             line = yyLineNo;
  1935             line = yyLineNo;
  1934             yyTok = getToken();
  1936             yyTok = getToken();
  1935             if (match(Tok_LeftParen) && matchString(&msgid) && !msgid.isEmpty()) {
  1937             if (match(Tok_LeftParen) && matchString(&msgid) && !msgid.isEmpty()) {
  1936                 bool plural = match(Tok_Comma);
  1938                 bool plural = match(Tok_Comma);
  1993                         break;
  1995                         break;
  1994                     c = yyWord.unicode()[p++].unicode();
  1996                     c = yyWord.unicode()[p++].unicode();
  1995                     if (isspace(c))
  1997                     if (isspace(c))
  1996                         continue;
  1998                         continue;
  1997                     if (c != '"') {
  1999                     if (c != '"') {
  1998                         yyMsg() << "Unexpected character in meta string\n";
  2000                         yyMsg() << qPrintable(LU::tr("Unexpected character in meta string\n"));
  1999                         break;
  2001                         break;
  2000                     }
  2002                     }
  2001                     forever {
  2003                     forever {
  2002                         if (p >= yyWord.length()) {
  2004                         if (p >= yyWord.length()) {
  2003                           whoops:
  2005                           whoops:
  2004                             yyMsg() << "Unterminated meta string\n";
  2006                             yyMsg() << qPrintable(LU::tr("Unterminated meta string\n"));
  2005                             break;
  2007                             break;
  2006                         }
  2008                         }
  2007                         c = yyWord.unicode()[p++].unicode();
  2009                         c = yyWord.unicode()[p++].unicode();
  2008                         if (c == '"')
  2010                         if (c == '"')
  2009                             break;
  2011                             break;
  2052             break;
  2054             break;
  2053         }
  2055         }
  2054         case Tok_Arrow:
  2056         case Tok_Arrow:
  2055             yyTok = getToken();
  2057             yyTok = getToken();
  2056             if (yyTok == Tok_tr || yyTok == Tok_trUtf8)
  2058             if (yyTok == Tok_tr || yyTok == Tok_trUtf8)
  2057                 yyMsg() << "Cannot invoke tr() like this\n";
  2059                 yyMsg() << qPrintable(LU::tr("Cannot invoke tr() like this\n"));
  2058             break;
  2060             break;
  2059         case Tok_ColonColon:
  2061         case Tok_ColonColon:
  2060             if (yyBraceDepth == namespaceDepths.count() && yyParenDepth == 0 && !yyTokColonSeen)
  2062             if (yyBraceDepth == namespaceDepths.count() && yyParenDepth == 0 && !yyTokColonSeen)
  2061                 prospectiveContext = prefix;
  2063                 prospectiveContext = prefix;
  2062             prefix += strColons;
  2064             prefix += strColons;
  2085             // fallthrough
  2087             // fallthrough
  2086         case Tok_Semicolon:
  2088         case Tok_Semicolon:
  2087             prospectiveContext.clear();
  2089             prospectiveContext.clear();
  2088             prefix.clear();
  2090             prefix.clear();
  2089             if (!sourcetext.isEmpty() || !extracomment.isEmpty() || !msgid.isEmpty() || !extra.isEmpty()) {
  2091             if (!sourcetext.isEmpty() || !extracomment.isEmpty() || !msgid.isEmpty() || !extra.isEmpty()) {
  2090                 yyMsg() << "Discarding unconsumed meta data\n";
  2092                 yyMsg() << qPrintable(LU::tr("Discarding unconsumed meta data\n"));
  2091                 sourcetext.clear();
  2093                 sourcetext.clear();
  2092                 extracomment.clear();
  2094                 extracomment.clear();
  2093                 msgid.clear();
  2095                 msgid.clear();
  2094                 extra.clear();
  2096                 extra.clear();
  2095             }
  2097             }
  2125         }
  2127         }
  2126     }
  2128     }
  2127 
  2129 
  2128     if (yyBraceDepth != 0)
  2130     if (yyBraceDepth != 0)
  2129         yyMsg(yyBraceLineNo)
  2131         yyMsg(yyBraceLineNo)
  2130             << "Unbalanced opening brace in C++ code"
  2132             << qPrintable(LU::tr("Unbalanced opening brace in C++ code"
  2131                " (or abuse of the C++ preprocessor)\n";
  2133                                  " (or abuse of the C++ preprocessor)\n"));
  2132     else if (yyParenDepth != 0)
  2134     else if (yyParenDepth != 0)
  2133         yyMsg(yyParenLineNo)
  2135         yyMsg(yyParenLineNo)
  2134             << "Unbalanced opening parenthesis in C++ code"
  2136             << qPrintable(LU::tr("Unbalanced opening parenthesis in C++ code"
  2135                " (or abuse of the C++ preprocessor)\n";
  2137                                  " (or abuse of the C++ preprocessor)\n"));
  2136     else if (yyBracketDepth != 0)
  2138     else if (yyBracketDepth != 0)
  2137         yyMsg(yyBracketLineNo)
  2139         yyMsg(yyBracketLineNo)
  2138             << "Unbalanced opening bracket in C++ code"
  2140             << qPrintable(LU::tr("Unbalanced opening bracket in C++ code"
  2139                " (or abuse of the C++ preprocessor)\n";
  2141                                  " (or abuse of the C++ preprocessor)\n"));
  2140 }
  2142 }
  2141 
  2143 
  2142 const ParseResults *CppParser::recordResults(bool isHeader)
  2144 const ParseResults *CppParser::recordResults(bool isHeader)
  2143 {
  2145 {
  2144     if (tor) {
  2146     if (tor) {
  2195         if (CppFiles::getResults(filename) || CppFiles::isBlacklisted(filename))
  2197         if (CppFiles::getResults(filename) || CppFiles::isBlacklisted(filename))
  2196             continue;
  2198             continue;
  2197 
  2199 
  2198         QFile file(filename);
  2200         QFile file(filename);
  2199         if (!file.open(QIODevice::ReadOnly)) {
  2201         if (!file.open(QIODevice::ReadOnly)) {
  2200             cd.appendError(QString::fromLatin1("Cannot open %1: %2")
  2202             cd.appendError(LU::tr("Cannot open %1: %2").arg(filename, file.errorString()));
  2201                 .arg(filename, file.errorString()));
       
  2202             continue;
  2203             continue;
  2203         }
  2204         }
  2204 
  2205 
  2205         CppParser parser;
  2206         CppParser parser;
  2206         QTextStream ts(&file);
  2207         QTextStream ts(&file);