implement qmake language and deprecation warnings

Change-Id: Ia5dd0c408ace4e779da898ffb60e9ca12a383225
Reviewed-by: Daniel Teske <daniel.teske@nokia.com>
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
This commit is contained in:
Oswald Buddenhagen
2012-07-06 20:34:29 +02:00
parent 0af96c128a
commit a93e24fd0d
6 changed files with 85 additions and 32 deletions

View File

@@ -216,8 +216,11 @@ ProStringList QMakeEvaluator::evaluateExpandFunction(
if (func_t == 0) {
const QString &fn = func.toQString(m_tmp1);
const QString &lfn = fn.toLower();
if (!fn.isSharedWith(lfn))
if (!fn.isSharedWith(lfn)) {
func_t = ExpandFunc(statics.expands.value(ProString(lfn)));
if (func_t)
deprecationWarning(fL1S("Using uppercased builtin functions is deprecated."));
}
}
ProStringList ret;
@@ -974,23 +977,25 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditionalFunction(
case T_INCLUDE: {
if (m_skipLevel && !m_cumulative)
return ReturnFalse;
QString parseInto;
// the third optional argument to include() controls warnings
// and is not used here
if ((args.count() == 2) || (args.count() == 3) ) {
parseInto = args.at(1).toQString(m_tmp2);
} else if (args.count() != 1) {
evalError(fL1S("include(file, into, silent) requires one, two or three arguments."));
if (args.count() < 1 || args.count() > 3) {
evalError(fL1S("include(file, [into, [silent]]) requires one, two or three arguments."));
return ReturnFalse;
}
QString parseInto;
LoadFlags flags = 0;
if (args.count() >= 2) {
parseInto = args.at(1).toQString(m_tmp2);
if (args.count() >= 3 && isTrue(args.at(2), m_tmp3))
flags = LoadSilent;
}
QString fn = resolvePath(m_option->expandEnvVars(args.at(0).toQString(m_tmp1)));
fn.detach();
bool ok;
if (parseInto.isEmpty()) {
ok = evaluateFile(fn, QMakeHandler::EvalIncludeFile, LoadProOnly);
ok = evaluateFile(fn, QMakeHandler::EvalIncludeFile, LoadProOnly | flags);
} else {
ProValueMap symbols;
if ((ok = evaluateFileInto(fn, QMakeHandler::EvalAuxFile, &symbols, LoadAll))) {
if ((ok = evaluateFileInto(fn, QMakeHandler::EvalAuxFile, &symbols, LoadAll | flags))) {
ProValueMap newMap;
for (ProValueMap::ConstIterator
it = m_valuemapStack.top().constBegin(),
@@ -1011,20 +1016,20 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditionalFunction(
m_valuemapStack.top() = newMap;
}
}
return returnBool(ok);
return returnBool(ok || (flags & LoadSilent));
}
case T_LOAD: {
if (m_skipLevel && !m_cumulative)
return ReturnFalse;
// bool ignore_error = false;
bool ignore_error = false;
if (args.count() == 2) {
// ignore_error = isTrue(args.at(1), m_tmp2);
ignore_error = isTrue(args.at(1), m_tmp2);
} else if (args.count() != 1) {
evalError(fL1S("load(feature) requires one or two arguments."));
return ReturnFalse;
}
// XXX ignore_error unused
return returnBool(evaluateFeatureFile(m_option->expandEnvVars(args.at(0).toQString())));
return returnBool(evaluateFeatureFile(m_option->expandEnvVars(args.at(0).toQString()),
ignore_error) || ignore_error);
}
case T_DEBUG:
// Yup - do nothing. Nothing is going to enable debug output anyway.

View File

@@ -138,7 +138,11 @@ void QMakeEvaluator::initStatics()
const ProString &QMakeEvaluator::map(const ProString &var)
{
QHash<ProString, ProString>::ConstIterator it = statics.varMap.constFind(var);
return (it != statics.varMap.constEnd()) ? it.value() : var;
if (it == statics.varMap.constEnd())
return var;
deprecationWarning(fL1S("Variable %s is deprecated; use %s instead.")
.arg(var.toQString(), it.value().toQString()));
return it.value();
}
@@ -239,7 +243,8 @@ ProStringList QMakeEvaluator::split_value_list(const QString &vals, const ProFil
ushort unicode;
const QChar *vals_data = vals.data();
const int vals_len = vals.length();
for (int x = 0, parens = 0; x < vals_len; x++) {
int parens = 0;
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)) {
@@ -263,6 +268,8 @@ ProStringList QMakeEvaluator::split_value_list(const QString &vals, const ProFil
}
if (!build.isEmpty())
ret << ProString(build, NoHash).setSource(source);
if (parens)
deprecationWarning(fL1S("Unmatched parentheses are deprecated."));
return ret;
}
@@ -780,6 +787,8 @@ void QMakeEvaluator::visitProVariable(
if (!m_cumulative) {
if (!m_skipLevel) {
zipEmpty(&varVal);
// FIXME: add check+warning about accidental value removal.
// This may be a bit too noisy, though.
m_valuemapStack.top()[varName] = varVal;
}
} else {
@@ -1210,7 +1219,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProFile(
if (!processed.contains(config)) {
config.detach();
processed.insert(config);
if (evaluateFeatureFile(config)) {
if (evaluateFeatureFile(config, true)) {
finished = false;
break;
}
@@ -1892,6 +1901,8 @@ bool QMakeEvaluator::evaluateFileDirect(
#endif
return ok;
} else {
if (!(flags & LoadSilent) && IoUtils::exists(fileName))
languageWarning(fL1S("Include file %1 not found").arg(fileName));
return false;
}
}
@@ -1909,7 +1920,7 @@ bool QMakeEvaluator::evaluateFile(
return evaluateFileDirect(fileName, type, flags);
}
bool QMakeEvaluator::evaluateFeatureFile(const QString &fileName)
bool QMakeEvaluator::evaluateFeatureFile(const QString &fileName, bool silent)
{
QString fn = fileName;
if (!fn.endsWith(QLatin1String(".prf")))
@@ -1938,13 +1949,18 @@ bool QMakeEvaluator::evaluateFeatureFile(const QString &fileName)
if (QFileInfo(fn).exists())
goto cool;
#endif
if (!silent)
languageWarning(fL1S("Cannot find feature %1").arg(fileName));
return false;
cool:
ProStringList &already = valuesRef(ProString("QMAKE_INTERNAL_INCLUDED_FEATURES"));
ProString afn(fn, NoHash);
if (already.contains(afn))
if (already.contains(afn)) {
if (!silent)
languageWarning(fL1S("Feature %1 already included").arg(fileName));
return true;
}
already.append(afn);
#ifdef PROEVALUATOR_CUMULATIVE

View File

@@ -53,6 +53,9 @@ public:
enum {
SourceEvaluator = 0x10,
EvalWarnLanguage = SourceEvaluator | WarningMessage | WarnLanguage,
EvalWarnDeprecated = SourceEvaluator | WarningMessage | WarnDeprecated,
EvalError = ErrorMessage | SourceEvaluator
};
@@ -71,7 +74,8 @@ public:
LoadProOnly = 0,
LoadPreFiles = 1,
LoadPostFiles = 2,
LoadAll = LoadPreFiles|LoadPostFiles
LoadAll = LoadPreFiles|LoadPostFiles,
LoadSilent = 0x10
};
Q_DECLARE_FLAGS(LoadFlags, LoadFlag)
@@ -120,7 +124,7 @@ public:
void visitProFunctionDef(ushort tok, const ProString &name, const ushort *tokPtr);
void visitProVariable(ushort tok, const ProStringList &curr, const ushort *&tokPtr);
static const ProString &map(const ProString &var);
const ProString &map(const ProString &var);
ProValueMap *findValues(const ProString &variableName, ProValueMap::Iterator *it);
void setTemplate();
@@ -139,13 +143,17 @@ public:
LoadFlags flags);
bool evaluateFile(const QString &fileName, QMakeHandler::EvalFileType type,
LoadFlags flags);
bool evaluateFeatureFile(const QString &fileName);
bool evaluateFeatureFile(const QString &fileName, bool silent = false);
bool evaluateFileInto(const QString &fileName, QMakeHandler::EvalFileType type,
ProValueMap *values, // output-only
LoadFlags flags);
void message(int type, const QString &msg) const;
void evalError(const QString &msg) const
{ message(QMakeHandler::EvalError, msg); }
void languageWarning(const QString &msg) const
{ message(QMakeHandler::EvalWarnLanguage, msg); }
void deprecationWarning(const QString &msg) const
{ message(QMakeHandler::EvalWarnDeprecated, msg); }
QList<ProStringList> prepareFunctionArgs(const ushort *&tokPtr);
QList<ProStringList> prepareFunctionArgs(const ProString &arguments);

View File

@@ -309,6 +309,7 @@ bool QMakeParser::read(ProFile *pro, const QString &in)
int parens = 0; // Braces in value context
int argc = 0;
int wordCount = 0; // Number of words in currently accumulated expression
int lastIndent = 0; // Previous line's indentation, to detect accidental continuation abuse
bool putSpace = false; // Only ever true inside quoted string
bool lineMarked = true; // For in-expression markers
ushort needSep = TokNewStr; // Complementary to putSpace: separator outside quotes
@@ -372,7 +373,8 @@ bool QMakeParser::read(ProFile *pro, const QString &in)
ushort c;
// First, skip leading whitespace
for (;; ++cur) {
int indent;
for (indent = 0; ; ++cur, ++indent) {
c = *cur;
if (c == '\n') {
++cur;
@@ -556,12 +558,14 @@ bool QMakeParser::read(ProFile *pro, const QString &in)
needSep = 0;
goto nextChr;
}
} else if (c == '\\' && cur != end) {
} else if (c == '\\') {
static const char symbols[] = "[]{}()$\\'\"";
ushort c2 = *cur;
if (!(c2 & 0xff00) && strchr(symbols, c2)) {
ushort c2;
if (cur != end && !((c2 = *cur) & 0xff00) && strchr(symbols, c2)) {
c = c2;
cur++;
} else {
deprecationWarning(fL1S("Unescaped backslashes are deprecated"));
}
} else if (quote) {
if (c == quote) {
@@ -722,6 +726,9 @@ bool QMakeParser::read(ProFile *pro, const QString &in)
goto closeScope;
}
--parens;
} else if (c == '=') {
if (indent < lastIndent)
languageWarning(fL1S("Possible accidental line continuation"));
}
}
if (putSpace) {
@@ -771,6 +778,8 @@ bool QMakeParser::read(ProFile *pro, const QString &in)
}
} else if (context == CtxValue) {
FLUSH_VALUE_LIST();
if (parens)
languageWarning(fL1S("Possible braces mismatch"));
} else {
finalizeCond(tokPtr, buf, ptr, wordCount);
}
@@ -780,6 +789,7 @@ bool QMakeParser::read(ProFile *pro, const QString &in)
goto freshLine;
}
lastIndent = indent;
lineMarked = false;
ignore:
cur = cptr;

View File

@@ -46,11 +46,19 @@ class QMAKE_EXPORT QMakeParserHandler
public:
enum {
CategoryMask = 0xf00,
WarningMessage = 0x000,
ErrorMessage = 0x100,
SourceMask = 0xf0,
SourceParser = 0,
CodeMask = 0xf,
WarnLanguage = 0,
WarnDeprecated,
ParserWarnLanguage = SourceParser | WarningMessage | WarnLanguage,
ParserWarnDeprecated = SourceParser | WarningMessage | WarnDeprecated,
ParserIoError = ErrorMessage | SourceParser,
ParserError
};
@@ -123,6 +131,10 @@ private:
void message(int type, const QString &msg) const;
void parseError(const QString &msg) const
{ message(QMakeParserHandler::ParserError, msg); }
void languageWarning(const QString &msg) const
{ message(QMakeParserHandler::ParserWarnLanguage, msg); }
void deprecationWarning(const QString &msg) const
{ message(QMakeParserHandler::ParserWarnDeprecated, msg); }
// Current location
ProFile *m_proFile;

View File

@@ -43,18 +43,20 @@
#include <QStringList>
#include <QTextCodec>
static void print(const QString &fileName, int lineNo, const QString &msg)
static void print(const QString &fileName, int lineNo, int type, const QString &msg)
{
QString pfx = ((type & QMakeHandler::CategoryMask) == QMakeHandler::WarningMessage)
? QString::fromLatin1("WARNING: ") : QString();
if (lineNo)
qWarning("%s(%d): %s", qPrintable(fileName), lineNo, qPrintable(msg));
qWarning("%s%s:%d: %s", qPrintable(pfx), qPrintable(fileName), lineNo, qPrintable(msg));
else
qWarning("%s", qPrintable(msg));
qWarning("%s%s", qPrintable(pfx), qPrintable(msg));
}
class EvalHandler : public QMakeHandler {
public:
virtual void message(int /* type */, const QString &msg, const QString &fileName, int lineNo)
{ print(fileName, lineNo, msg); }
virtual void message(int type, const QString &msg, const QString &fileName, int lineNo)
{ print(fileName, lineNo, type, msg); }
virtual void fileMessage(const QString &msg)
{ qWarning("%s", qPrintable(msg)); }