Source

Target

Commits (17)
Showing with 187 additions and 102 deletions
......@@ -52,10 +52,12 @@
#include <QtGui/QKeyEvent>
#include <QtWidgets/QMenu>
#ifndef QT_NO_PRINTER
#include <QtPrintSupport/QPageSetupDialog>
#include <QtPrintSupport/QPrintDialog>
#include <QtPrintSupport/QPrintPreviewDialog>
#include <QtPrintSupport/QPrinter>
#endif
#include <QtWidgets/QStackedWidget>
#include <QtWidgets/QTextBrowser>
#include <QtWidgets/QVBoxLayout>
......
......@@ -403,7 +403,15 @@ void MainWindow::lookForNewQtDocumentation()
<< QLatin1String("qtwebkitexamples")
<< QLatin1String("qtwidgets")
<< QLatin1String("qtxml")
<< QLatin1String("qtxmlpatterns");
<< QLatin1String("qtxmlpatterns")
<< QLatin1String("qdoc")
<< QLatin1String("qtsensors")
<< QLatin1String("qtx11extras")
<< QLatin1String("qtserialport")
<< QLatin1String("qtscripttools")
<< QLatin1String("qtquickcontrols")
<< QLatin1String("qtquicklayouts")
<< QLatin1String("qtmultimediawidgets");
QList<QtDocInstaller::DocInfo> qtDocInfos;
foreach (const QString &doc, docs)
......
......@@ -85,7 +85,9 @@
#include <QtGui/QImage>
#include <QtGui/QPixmap>
#include <QtWidgets/QMdiSubWindow>
#ifndef QT_NO_PRINTER
#include <QtPrintSupport/QPrintDialog>
#endif
#include <QtGui/QPainter>
#include <QtGui/QTransform>
#include <QtGui/QCursor>
......@@ -1044,7 +1046,7 @@ QAction *QDesignerActions::minimizeAction() const
void QDesignerActions::showDesignerHelp()
{
QString url = AssistantClient::designerManualUrl();
url += QStringLiteral("qtdesigner-index.html");
url += QStringLiteral("qtdesigner-manual.html");
showHelp(url);
}
......
......@@ -47,7 +47,9 @@
#include <QtCore/QObject>
#include <QtCore/QPointer>
#ifndef QT_NO_PRINTER
#include <QtPrintSupport/QPrinter>
#endif
QT_BEGIN_NAMESPACE
......
......@@ -365,7 +365,6 @@ void WidgetDataBase::loadPlugins()
{
typedef QMap<QString, int> NameIndexMap;
typedef QList<QDesignerWidgetDataBaseItemInterface*> ItemList;
typedef QMap<QString, QDesignerWidgetDataBaseItemInterface*> NameItemMap;
typedef QSet<QString> NameSet;
// 1) create a map of existing custom classes
NameIndexMap existingCustomClasses;
......
......@@ -215,12 +215,16 @@ const QMetaObject *QDesignerAxPluginWidget::metaObject() const
return QDesignerAxWidget::metaObject();
}
#ifndef QT_NO_EXCEPTIONS
static QString msgComException(const QObject *o, const QMetaObject::Call call, int index)
{
return QDesignerAxWidget::tr("A COM exception occurred when executing a meta call of type %1, index %2 of \"%3\".").
arg(call).arg(index).arg(o->objectName());
}
#endif // QT_NO_EXCEPTIONS
int QDesignerAxPluginWidget::qt_metacall(QMetaObject::Call call, int signal, void **argv)
{
QAxWidget *aw = axobject();
......
......@@ -307,6 +307,9 @@ enum ProToken {
TokTestCall, // previous literal/expansion is a test function call
// - ((nested expansion + TokArgSeparator)* + nested expansion)?
// - TokFuncTerminator
TokReturn, // previous literal/expansion is a return value
TokBreak, // break loop
TokNext, // shortcut to next loop iteration
TokNot, // '!' operator
TokAnd, // ':' operator
TokOr, // '|' operator
......
......@@ -96,7 +96,7 @@ enum ExpandFunc {
enum TestFunc {
T_INVALID = 0, T_REQUIRES, T_GREATERTHAN, T_LESSTHAN, T_EQUALS,
T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM,
T_RETURN, T_BREAK, T_NEXT, T_DEFINED, T_CONTAINS, T_INFILE,
T_DEFINED, T_CONTAINS, T_INFILE,
T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, T_DEBUG, T_LOG, T_MESSAGE, T_WARNING, T_ERROR, T_IF,
T_MKPATH, T_WRITE_FILE, T_TOUCH, T_CACHE
};
......@@ -168,9 +168,6 @@ void QMakeEvaluator::initFunctionStatics()
{ "if", T_IF },
{ "isActiveConfig", T_CONFIG },
{ "system", T_SYSTEM },
{ "return", T_RETURN },
{ "break", T_BREAK },
{ "next", T_NEXT },
{ "defined", T_DEFINED },
{ "contains", T_CONTAINS },
{ "infile", T_INFILE },
......@@ -470,8 +467,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
QString tmp = args.at(0).toQString(m_tmp1);
for (int i = 1; i < args.count(); ++i)
tmp = tmp.arg(args.at(i).toQString(m_tmp2));
// Note: this depends on split_value_list() making a deep copy
ret = split_value_list(tmp);
ret << ProString(tmp);
}
break;
case E_FORMAT_NUMBER:
......@@ -564,7 +560,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
src = s;
break;
}
ret = split_value_list(before + var.join(glue) + after, src);
ret << ProString(before + var.join(glue) + after).setSource(src);
}
}
break;
......@@ -1071,17 +1067,6 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return returnBool(m_functionDefs.replaceFunctions.contains(var)
|| m_functionDefs.testFunctions.contains(var));
}
case T_RETURN:
m_returnValue = args;
// It is "safe" to ignore returns - due to qmake brokeness
// they cannot be used to terminate loops anyway.
if (m_cumulative)
return ReturnTrue;
if (m_valuemapStack.size() == 1) {
evalError(fL1S("unexpected return()."));
return ReturnFalse;
}
return ReturnReturn;
case T_EXPORT: {
if (args.count() != 1) {
evalError(fL1S("export(variable) requires one argument."));
......@@ -1132,11 +1117,11 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
}
}
return ReturnFalse;
#ifdef PROEVALUATOR_FULL
case T_REQUIRES:
#ifdef PROEVALUATOR_FULL
checkRequirements(args);
return ReturnFalse; // Another qmake breakage
#endif
return ReturnFalse; // Another qmake breakage
case T_EVAL: {
VisitReturn ret = ReturnFalse;
ProFile *pro = m_parser->parsedProBlock(args.join(statics.field_sep),
......@@ -1152,20 +1137,6 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
}
return ret;
}
case T_BREAK:
if (m_skipLevel)
return ReturnFalse;
if (m_loopLevel)
return ReturnBreak;
evalError(fL1S("Unexpected break()."));
return ReturnFalse;
case T_NEXT:
if (m_skipLevel)
return ReturnFalse;
if (m_loopLevel)
return ReturnNext;
evalError(fL1S("Unexpected next()."));
return ReturnFalse;
case T_IF: {
if (args.count() != 1) {
evalError(fL1S("if(condition) requires one argument."));
......@@ -1412,14 +1383,14 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
}
return (func_t == T_ERROR && !m_cumulative) ? ReturnError : ReturnTrue;
}
#ifdef PROEVALUATOR_FULL
case T_SYSTEM: {
if (m_cumulative) // Anything else would be insanity
return ReturnFalse;
if (args.count() != 1) {
evalError(fL1S("system(exec) requires one argument."));
return ReturnFalse;
}
#ifdef PROEVALUATOR_FULL
if (m_cumulative) // Anything else would be insanity
return ReturnFalse;
#ifndef QT_BOOTSTRAPPED
QProcess proc;
proc.setProcessChannelMode(QProcess::ForwardedChannels);
......@@ -1430,8 +1401,10 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
+ IoUtils::shellQuote(QDir::toNativeSeparators(currentDirectory()))
+ QLatin1String(" && ") + args.at(0)).toLocal8Bit().constData()) == 0);
#endif
}
#else
return ReturnTrue;
#endif
}
case T_ISEMPTY: {
if (args.count() != 1) {
evalError(fL1S("isEmpty(var) requires one argument."));
......@@ -1458,17 +1431,18 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return ReturnFalse;
}
#ifdef PROEVALUATOR_FULL
case T_MKPATH: {
if (args.count() != 1) {
evalError(fL1S("mkpath(file) requires one argument."));
return ReturnFalse;
}
#ifdef PROEVALUATOR_FULL
const QString &fn = resolvePath(args.at(0).toQString(m_tmp1));
if (!QDir::current().mkpath(fn)) {
evalError(fL1S("Cannot create directory %1.").arg(QDir::toNativeSeparators(fn)));
return ReturnFalse;
}
#endif
return ReturnTrue;
}
case T_WRITE_FILE: {
......@@ -1476,6 +1450,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
evalError(fL1S("write_file(name, [content var, [append]]) requires one to three arguments."));
return ReturnFalse;
}
#ifdef PROEVALUATOR_FULL
QIODevice::OpenMode mode = QIODevice::Truncate;
QString contents;
if (args.count() >= 2) {
......@@ -1487,12 +1462,16 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
mode = QIODevice::Append;
}
return writeFile(QString(), resolvePath(args.at(0).toQString(m_tmp1)), mode, contents);
#else
return ReturnTrue;
#endif
}
case T_TOUCH: {
if (args.count() != 2) {
evalError(fL1S("touch(file, reffile) requires two arguments."));
return ReturnFalse;
}
#ifdef PROEVALUATOR_FULL
const QString &tfn = resolvePath(args.at(0).toQString(m_tmp1));
const QString &rfn = resolvePath(args.at(1).toQString(m_tmp2));
#ifdef Q_OS_UNIX
......@@ -1528,6 +1507,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
}
SetFileTime(wHand, 0, 0, &ft);
CloseHandle(wHand);
#endif
#endif
return ReturnTrue;
}
......@@ -1536,6 +1516,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
evalError(fL1S("cache(var, [set|add|sub] [transient] [super], [srcvar]) requires one to three arguments."));
return ReturnFalse;
}
#ifdef PROEVALUATOR_FULL
bool persist = true;
bool super = false;
enum { CacheSet, CacheAdd, CacheSub } mode = CacheSet;
......@@ -1661,8 +1642,10 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
fn = m_cachefile;
}
return writeFile(fL1S("cache "), fn, QIODevice::Append, varstr);
}
#else
return ReturnTrue;
#endif
}
default:
evalError(fL1S("Function '%1' is not implemented.").arg(function.toQString(m_tmp1)));
return ReturnFalse;
......
......@@ -126,6 +126,7 @@ void QMakeEvaluator::initStatics()
statics.strforever = QLatin1String("forever");
statics.strhost_build = QLatin1String("host_build");
statics.strTEMPLATE = ProKey("TEMPLATE");
statics.strQMAKE_PLATFORM = ProKey("QMAKE_PLATFORM");
#ifdef PROEVALUATOR_FULL
statics.strREQUIRES = ProKey("REQUIRES");
#endif
......@@ -195,7 +196,6 @@ QMakeEvaluator::QMakeEvaluator(QMakeGlobals *option,
#ifdef PROEVALUATOR_CUMULATIVE
m_skipLevel = 0;
#endif
m_loopLevel = 0;
m_listCount = 0;
m_valuemapStack.push(ProValueMap());
m_valuemapInited = false;
......@@ -264,48 +264,55 @@ ProStringList QMakeEvaluator::split_value_list(const QString &vals, const ProFil
{
QString build;
ProStringList ret;
QStack<char> quote;
const ushort SPACE = ' ';
const ushort LPAREN = '(';
const ushort RPAREN = ')';
const ushort SINGLEQUOTE = '\'';
const ushort DOUBLEQUOTE = '"';
const ushort BACKSLASH = '\\';
if (!source)
source = currentProFile();
ushort unicode;
const QChar *vals_data = vals.data();
const int vals_len = vals.length();
int parens = 0;
ushort quote = 0;
bool hadWord = false;
for (int x = 0; x < vals_len; x++) {
unicode = vals_data[x].unicode();
if (x != (int)vals_len-1 && unicode == BACKSLASH &&
(vals_data[x+1].unicode() == SINGLEQUOTE || vals_data[x+1].unicode() == DOUBLEQUOTE)) {
build += vals_data[x++]; //get that 'escape'
} else if (!quote.isEmpty() && unicode == quote.top()) {
quote.pop();
} else if (unicode == SINGLEQUOTE || unicode == DOUBLEQUOTE) {
quote.push(unicode);
} else if (unicode == RPAREN) {
--parens;
} else if (unicode == LPAREN) {
++parens;
ushort unicode = vals_data[x].unicode();
if (unicode == quote) {
quote = 0;
continue;
}
if (!parens && quote.isEmpty() && vals_data[x] == SPACE) {
ret << ProString(build).setSource(source);
build.clear();
} else {
build += vals_data[x];
switch (unicode) {
case '"':
case '\'':
quote = unicode;
hadWord = true;
continue;
case ' ':
case '\t':
if (!quote) {
if (hadWord) {
ret << ProString(build).setSource(source);
build.clear();
hadWord = false;
}
continue;
}
build += QChar(unicode);
break;
case '\\':
if (x + 1 != vals_len) {
ushort next = vals_data[++x].unicode();
if (next == '\'' || next == '"' || next == '\\')
unicode = next;
else
--x;
}
// fallthrough
default:
hadWord = true;
build += QChar(unicode);
break;
}
}
if (!build.isEmpty())
if (hadWord)
ret << ProString(build).setSource(source);
if (parens)
deprecationWarning(fL1S("Unmatched parentheses are deprecated."));
return ret;
}
......@@ -454,9 +461,9 @@ void QMakeEvaluator::evaluateExpression(
break; }
case TokEnvVar: {
const ProString &var = getStr(tokPtr);
const ProStringList &val = split_value_list(m_option->getEnv(var.toQString(m_tmp1)));
debugMsg(2, "env var %s => %s", dbgStr(var), dbgStrList(val));
addStrList(val, tok, ret, pending, joined);
const ProString &val = ProString(m_option->getEnv(var.toQString(m_tmp1)));
debugMsg(2, "env var %s => %s", dbgStr(var), dbgStr(val));
addStr(val, ret, pending, joined);
break; }
case TokFuncName: {
const ProKey &func = getHashStr(tokPtr);
......@@ -683,6 +690,24 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProBlock(
invert = false;
curr.clear();
continue;
case TokReturn:
m_returnValue = curr;
curr.clear();
ret = ReturnReturn;
goto ctrlstm;
case TokBreak:
ret = ReturnBreak;
goto ctrlstm;
case TokNext:
ret = ReturnNext;
ctrlstm:
if (!m_skipLevel && okey != or_op) {
traceMsg("flow control statement '%s', aborting block", dbgReturn(ret));
return ret;
}
traceMsg("skipped flow control statement '%s'", dbgReturn(ret));
okey = false, or_op = true; // force next evaluation
continue;
default: {
const ushort *oTokPtr = --tokPtr;
evaluateExpression(tokPtr, &curr, false);
......@@ -762,7 +787,6 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProLoop(
else
traceMsg("entering loop for %s over %s", dbgKey(variable), dbgStrList(list));
m_loopLevel++;
forever {
if (infinite) {
if (!variable.isEmpty())
......@@ -799,7 +823,6 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProLoop(
}
}
do_break:
m_loopLevel--;
traceMsg("done looping");
......@@ -909,6 +932,8 @@ void QMakeEvaluator::visitProVariable(
if (varName == statics.strTEMPLATE)
setTemplate();
else if (varName == statics.strQMAKE_PLATFORM)
updateFeaturePaths();
#ifdef PROEVALUATOR_FULL
else if (varName == statics.strREQUIRES)
checkRequirements(values(varName));
......@@ -1037,7 +1062,7 @@ bool QMakeEvaluator::prepareProject(const QString &inDir)
forever {
QString superfile = superdir + QLatin1String("/.qmake.super");
if (IoUtils::exists(superfile)) {
m_superfile = superfile;
m_superfile = QDir::cleanPath(superfile);
break;
}
QFileInfo qdfi(superdir);
......@@ -1074,8 +1099,8 @@ bool QMakeEvaluator::prepareProject(const QString &inDir)
} else {
m_buildRoot = QFileInfo(cachefile).path();
}
m_conffile = conffile;
m_cachefile = cachefile;
m_conffile = QDir::cleanPath(conffile);
m_cachefile = QDir::cleanPath(cachefile);
}
no_cache:
......@@ -1199,7 +1224,6 @@ bool QMakeEvaluator::loadSpec()
}
if (!loadSpecInternal())
return false;
updateFeaturePaths(); // The spec extends the feature search path, so rebuild the cache.
if (!m_conffile.isEmpty()
&& !evaluateFile(m_conffile, QMakeHandler::EvalConfigFile, LoadProOnly)) {
return false;
......@@ -1589,8 +1613,6 @@ ProStringList QMakeEvaluator::evaluateFunction(
} else {
m_valuemapStack.push(ProValueMap());
m_locationStack.push(m_current);
int loopLevel = m_loopLevel;
m_loopLevel = 0;
ProStringList args;
for (int i = 0; i < argumentsList.count(); ++i) {
......@@ -1603,7 +1625,6 @@ ProStringList QMakeEvaluator::evaluateFunction(
ret = m_returnValue;
m_returnValue.clear();
m_loopLevel = loopLevel;
m_current = m_locationStack.pop();
m_valuemapStack.pop();
}
......
......@@ -233,7 +233,6 @@ public:
static void removeEach(ProStringList *varlist, const ProStringList &value);
QMakeEvaluator *m_caller;
int m_loopLevel; // To report unexpected break() and next()s
#ifdef PROEVALUATOR_CUMULATIVE
bool m_cumulative;
int m_skipLevel;
......
......@@ -89,6 +89,7 @@ struct QMakeStatics {
QString strforever;
QString strhost_build;
ProKey strTEMPLATE;
ProKey strQMAKE_PLATFORM;
#ifdef PROEVALUATOR_FULL
ProKey strREQUIRES;
#endif
......
......@@ -115,7 +115,6 @@ QMakeGlobals::QMakeGlobals()
dirlist_sep = QLatin1Char(':');
dir_sep = QLatin1Char('/');
#endif
qmakespec = getEnv(QLatin1String("QMAKESPEC"));
}
QMakeGlobals::~QMakeGlobals()
......
......@@ -108,6 +108,9 @@ static struct {
QString strdefineTest;
QString strdefineReplace;
QString stroption;
QString strreturn;
QString strnext;
QString strbreak;
QString strhost_build;
QString strLINE;
QString strFILE;
......@@ -128,6 +131,9 @@ void QMakeParser::initialize()
statics.strdefineTest = QLatin1String("defineTest");
statics.strdefineReplace = QLatin1String("defineReplace");
statics.stroption = QLatin1String("option");
statics.strreturn = QLatin1String("return");
statics.strnext = QLatin1String("next");
statics.strbreak = QLatin1String("break");
statics.strhost_build = QLatin1String("host_build");
statics.strLINE = QLatin1String("_LINE_");
statics.strFILE = QLatin1String("_FILE_");
......@@ -874,9 +880,11 @@ void QMakeParser::putLineMarker(ushort *&tokPtr)
void QMakeParser::enterScope(ushort *&tokPtr, bool special, ScopeState state)
{
uchar nest = m_blockstack.top().nest;
m_blockstack.resize(m_blockstack.size() + 1);
m_blockstack.top().special = special;
m_blockstack.top().start = tokPtr;
m_blockstack.top().nest = nest;
tokPtr += 2;
m_state = state;
m_canElse = false;
......@@ -1017,13 +1025,14 @@ void QMakeParser::finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int arg
const QString *defName;
ushort defType;
if (m_tmp == statics.strfor) {
flushCond(tokPtr);
putLineMarker(tokPtr);
if (m_invert || m_operator == OrOperator) {
// '|' could actually work reasonably, but qmake does nonsense here.
parseError(fL1S("Unexpected operator in front of for()."));
bogusTest(tokPtr);
return;
}
flushCond(tokPtr);
putLineMarker(tokPtr);
if (*uce == (TokLiteral|TokNewStr)) {
nlen = uce[1];
uc = uce + 2 + nlen;
......@@ -1037,6 +1046,7 @@ void QMakeParser::finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int arg
didFor:
putTok(tokPtr, TokValueTerminator);
enterScope(tokPtr, true, StCtrl);
m_blockstack.top().nest |= NestLoop;
return;
} else if (*uc == TokArgSeparator && argc == 2) {
// for(var, something)
......@@ -1066,12 +1076,13 @@ void QMakeParser::finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int arg
defName = &statics.strdefineTest;
defType = TokTestDef;
deffunc:
flushScopes(tokPtr);
putLineMarker(tokPtr);
if (m_invert) {
parseError(fL1S("Unexpected operator in front of function definition."));
bogusTest(tokPtr);
return;
}
flushScopes(tokPtr);
putLineMarker(tokPtr);
if (*uce == (TokLiteral|TokNewStr)) {
uint nlen = uce[1];
if (uce[nlen + 2] == TokFuncTerminator) {
......@@ -1082,15 +1093,59 @@ void QMakeParser::finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int arg
putTok(tokPtr, defType);
putHashStr(tokPtr, uce + 2, nlen);
enterScope(tokPtr, true, StCtrl);
m_blockstack.top().nest = NestFunction;
return;
}
}
parseError(fL1S("%1(function) requires one literal argument.").arg(*defName));
return;
} else if (m_tmp == statics.strreturn) {
if (m_blockstack.top().nest & NestFunction) {
if (argc > 1) {
parseError(fL1S("return() requires zero or one argument."));
bogusTest(tokPtr);
return;
}
} else {
if (*uce != TokFuncTerminator) {
parseError(fL1S("Top-level return() requires zero arguments."));
bogusTest(tokPtr);
return;
}
}
defType = TokReturn;
goto ctrlstm2;
} else if (m_tmp == statics.strnext) {
defType = TokNext;
goto ctrlstm;
} else if (m_tmp == statics.strbreak) {
defType = TokBreak;
ctrlstm:
if (*uce != TokFuncTerminator) {
parseError(fL1S("%1() requires zero arguments.").arg(m_tmp));
bogusTest(tokPtr);
return;
}
if (!(m_blockstack.top().nest & NestLoop)) {
parseError(fL1S("Unexpected %1().").arg(m_tmp));
bogusTest(tokPtr);
return;
}
ctrlstm2:
if (m_invert) {
parseError(fL1S("Unexpected NOT operator in front of %1().").arg(m_tmp));
bogusTest(tokPtr);
return;
}
finalizeTest(tokPtr);
putBlock(tokPtr, uce, ptr - uce - 1); // Only for TokReturn
putTok(tokPtr, defType);
return;
} else if (m_tmp == statics.stroption) {
if (m_state != StNew || m_blockstack.top().braceLevel || m_blockstack.size() > 1
|| m_invert || m_operator != NoOperator) {
parseError(fL1S("option() must appear outside any control structures."));
bogusTest(tokPtr);
return;
}
if (*uce == (TokLiteral|TokNewStr)) {
......
......@@ -97,13 +97,20 @@ public:
void discardFileFromCache(const QString &fileName);
private:
enum ScopeNesting {
NestNone = 0,
NestLoop = 1,
NestFunction = 2
};
struct BlockScope {
BlockScope() : start(0), braceLevel(0), special(false), inBranch(false) {}
BlockScope() : start(0), braceLevel(0), special(false), inBranch(false), nest(NestNone) {}
BlockScope(const BlockScope &other) { *this = other; }
ushort *start; // Where this block started; store length here
int braceLevel; // Nesting of braces in scope
bool special; // Single-line conditionals inside loops, etc. cannot have else branches
bool inBranch; // The 'else' branch of the previous TokBranch is still open
uchar nest; // Into what control structures we are nested
};
enum ScopeState {
......
......@@ -47,7 +47,9 @@
#include <QtGui/QMouseEvent>
#include <QtGui/QRegion>
#ifndef _USE_MATH_DEFINES
#define _USE_MATH_DEFINES
#endif
#include "math.h"
......
......@@ -2,3 +2,4 @@ tst_lupdate
testdata/*/*.ts
testdata/*/*/*.ts
testdata/*/*/*/*.ts
testdata/good/*/.qmake.cache
......@@ -122,19 +122,12 @@ static bool prepareMatch(const QString &expect, QString *tmpl, int *require, int
return true;
}
void tst_lupdate::doCompare(const QStringList &_actual, const QString &expectedFn, bool err)
void tst_lupdate::doCompare(const QStringList &actual, const QString &expectedFn, bool err)
{
QFile file(expectedFn);
QVERIFY2(file.open(QIODevice::ReadOnly | QIODevice::Text), qPrintable(expectedFn));
QStringList expected = QString(file.readAll()).split('\n');
QStringList actual;
actual.reserve(_actual.size());
QRegExp niRx(".*:(Function '\\w+' is not implemented|'\\w+' is not a recognized replace function)");
foreach (const QString &a, _actual)
if (!niRx.exactMatch(a))
actual << a;
int ei = 0, ai = 0, em = expected.size(), am = actual.size();
int oei = 0, oai = 0, oem = em, oam = am;
int require = 0, accept = 0;
......@@ -287,6 +280,10 @@ void tst_lupdate::good()
QVERIFY2(QFile::copy(beforetsfile, genTs), qPrintable(beforetsfile));
}
file.setFileName(workDir + QStringLiteral("/.qmake.cache"));
QVERIFY(file.open(QIODevice::WriteOnly));
file.close();
if (lupdatecmd.isEmpty())
lupdatecmd = QLatin1String("project.pro");
lupdatecmd.prepend("-silent ");
......