diff options
author | Oswald Buddenhagen <oswald.buddenhagen@nokia.com> | 2009-07-13 14:20:44 (GMT) |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@nokia.com> | 2009-07-13 14:51:21 (GMT) |
commit | e2f381365bf2158095c5c7236fc4b2f842b9fa8c (patch) | |
tree | 5bf317515ed903054c1f2df5bfb41b2356f76273 | |
parent | 45efa082135cbf97820a5ce7025685d22bd926ce (diff) | |
download | Qt-e2f381365bf2158095c5c7236fc4b2f842b9fa8c.zip Qt-e2f381365bf2158095c5c7236fc4b2f842b9fa8c.tar.gz Qt-e2f381365bf2158095c5c7236fc4b2f842b9fa8c.tar.bz2 |
implement proper vpath handling
this also removes the bogus special casing of various
filename-containing variables inside the pro parser.
while this is a feature as such, it restores backwards compatibility
without damaging the correct behavior again, so it qualifies for 4.5.
based on a2f40fce2a1cf3c19a13fa27eea08192493ab76e from creator
Task-number: 254098
12 files changed, 173 insertions, 114 deletions
diff --git a/tests/auto/linguist/lupdate/testdata/good/proparsingpaths/file1.cpp b/tests/auto/linguist/lupdate/testdata/good/proparsingpaths/file1.cpp new file mode 100644 index 0000000..ad87e70 --- /dev/null +++ b/tests/auto/linguist/lupdate/testdata/good/proparsingpaths/file1.cpp @@ -0,0 +1,9 @@ +// IMPORTANT!!!! If you want to add testdata to this file, +// always add it to the end in order to not change the linenumbers of translations!!! + + +void func1() { + QApplication::tr("Hello world", "top-level wildcard"); +} + + diff --git a/tests/auto/linguist/lupdate/testdata/good/proparsingpaths/filter.cpp b/tests/auto/linguist/lupdate/testdata/good/proparsingpaths/filter.cpp new file mode 100644 index 0000000..912963d --- /dev/null +++ b/tests/auto/linguist/lupdate/testdata/good/proparsingpaths/filter.cpp @@ -0,0 +1,9 @@ +// IMPORTANT!!!! If you want to add testdata to this file, +// always add it to the end in order to not change the linenumbers of translations!!! + + +void func1() { + QApplication::tr("Hello world", "top-level direct"); +} + + diff --git a/tests/auto/linguist/lupdate/testdata/good/proparsingpaths/project.pro b/tests/auto/linguist/lupdate/testdata/good/proparsingpaths/project.pro new file mode 100644 index 0000000..820b4fa --- /dev/null +++ b/tests/auto/linguist/lupdate/testdata/good/proparsingpaths/project.pro @@ -0,0 +1,10 @@ +SOURCES += file*.cpp filter.cpp non-existing.cpp + +include(sub/sub.pri) + +TRANSLATIONS = project.ts + +exists( $$TRANSLATIONS ) { + win32: system(del $$TRANSLATIONS) + unix: system(rm -f $$TRANSLATIONS) +} diff --git a/tests/auto/linguist/lupdate/testdata/good/proparsingpaths/project.ts.result b/tests/auto/linguist/lupdate/testdata/good/proparsingpaths/project.ts.result new file mode 100644 index 0000000..470d6eb --- /dev/null +++ b/tests/auto/linguist/lupdate/testdata/good/proparsingpaths/project.ts.result @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.0"> +<context> + <name>QApplication</name> + <message> + <location filename="file1.cpp" line="6"/> + <source>Hello world</source> + <comment>top-level wildcard</comment> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="filter.cpp" line="6"/> + <source>Hello world</source> + <comment>top-level direct</comment> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="sub/subfile1.cpp" line="6"/> + <source>Hello world</source> + <comment>nested wildcard</comment> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="sub/subfilter.cpp" line="6"/> + <source>Hello world</source> + <comment>nested direct</comment> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/tests/auto/linguist/lupdate/testdata/good/proparsingpaths/sub/sub.pri b/tests/auto/linguist/lupdate/testdata/good/proparsingpaths/sub/sub.pri new file mode 100644 index 0000000..a6079f9 --- /dev/null +++ b/tests/auto/linguist/lupdate/testdata/good/proparsingpaths/sub/sub.pri @@ -0,0 +1,3 @@ +VPATH += $$PWD + +SOURCES += sub/subfile?.cpp subfilter.cpp diff --git a/tests/auto/linguist/lupdate/testdata/good/proparsingpaths/sub/subfile1.cpp b/tests/auto/linguist/lupdate/testdata/good/proparsingpaths/sub/subfile1.cpp new file mode 100644 index 0000000..807d296 --- /dev/null +++ b/tests/auto/linguist/lupdate/testdata/good/proparsingpaths/sub/subfile1.cpp @@ -0,0 +1,9 @@ +// IMPORTANT!!!! If you want to add testdata to this file, +// always add it to the end in order to not change the linenumbers of translations!!! + + +void func1() { + QApplication::tr("Hello world", "nested wildcard"); +} + + diff --git a/tests/auto/linguist/lupdate/testdata/good/proparsingpaths/sub/subfilter.cpp b/tests/auto/linguist/lupdate/testdata/good/proparsingpaths/sub/subfilter.cpp new file mode 100644 index 0000000..6e5dd25 --- /dev/null +++ b/tests/auto/linguist/lupdate/testdata/good/proparsingpaths/sub/subfilter.cpp @@ -0,0 +1,9 @@ +// IMPORTANT!!!! If you want to add testdata to this file, +// always add it to the end in order to not change the linenumbers of translations!!! + + +void func1() { + QApplication::tr("Hello world", "nested direct"); +} + + diff --git a/tools/linguist/lupdate/main.cpp b/tools/linguist/lupdate/main.cpp index 6e8b941..78e5b5f 100644 --- a/tools/linguist/lupdate/main.cpp +++ b/tools/linguist/lupdate/main.cpp @@ -452,7 +452,7 @@ int main(int argc, char **argv) continue; } - evaluateProFile(visitor, &variables); + evaluateProFile(visitor, &variables, pfi.absolutePath()); sourceFiles = variables.value("SOURCES"); diff --git a/tools/linguist/shared/profileevaluator.cpp b/tools/linguist/shared/profileevaluator.cpp index 54c5d9a..3b8a1b8 100644 --- a/tools/linguist/shared/profileevaluator.cpp +++ b/tools/linguist/shared/profileevaluator.cpp @@ -107,9 +107,6 @@ public: QString propertyValue(const QString &val) const; bool isActiveConfig(const QString &config, bool regex = false); - QStringList expandPattern(const QString &pattern); - void expandPatternHelper(const QString &relName, const QString &absName, - QStringList &sources_out); QStringList expandVariableReferences(const QString &value); QStringList evaluateExpandFunction(const QString &function, const QString &arguments); QString format(const char *format) const; @@ -559,29 +556,6 @@ bool ProFileEvaluator::Private::visitProValue(ProValue *value) m_prevLineNo = m_lineNo; m_prevProFile = currentProFile(); - // The following two blocks fix bug 180128 by making all "interesting" - // file name absolute in each .pro file, not just the top most one - if (varName == QLatin1String("SOURCES") - || varName == QLatin1String("HEADERS") - || varName == QLatin1String("INTERFACES") - || varName == QLatin1String("FORMS") - || varName == QLatin1String("FORMS3") - || varName == QLatin1String("RESOURCES")) { - // matches only existent files, expand certain(?) patterns - QStringList vv; - for (int i = v.count(); --i >= 0; ) - vv << expandPattern(v[i]); - v = vv; - } - - if (varName == QLatin1String("TRANSLATIONS")) { - // also matches non-existent files, but does not expand pattern - QString dir = QFileInfo(currentFileName()).absolutePath(); - dir += QLatin1Char('/'); - for (int i = v.count(); --i >= 0; ) - v[i] = QFileInfo(dir, v[i]).absoluteFilePath(); - } - switch (m_variableOperator) { case ProVariable::UniqueAddOperator: // * insertUnique(&m_valuemap, varName, v, true); @@ -1537,82 +1511,6 @@ bool ProFileEvaluator::Private::evaluateFeatureFile(const QString &fileName, boo return fn.isEmpty() ? false : evaluateFile(fn, result); } -void ProFileEvaluator::Private::expandPatternHelper(const QString &relName, const QString &absName, - QStringList &sources_out) -{ - const QStringList vpaths = values(QLatin1String("VPATH")) - + values(QLatin1String("QMAKE_ABSOLUTE_SOURCE_PATH")) - + values(QLatin1String("DEPENDPATH")) - + values(QLatin1String("VPATH_SOURCES")); - - QFileInfo fi(absName); - bool found = fi.exists(); - // Search in all vpaths - if (!found) { - foreach (const QString &vpath, vpaths) { - fi.setFile(vpath + QDir::separator() + relName); - if (fi.exists()) { - found = true; - break; - } - } - } - - if (found) { - sources_out += fi.absoluteFilePath(); // Not resolving symlinks - } else { - QString val = relName; - QString dir; - QString wildcard = val; - QString real_dir; - if (wildcard.lastIndexOf(QLatin1Char('/')) != -1) { - dir = wildcard.left(wildcard.lastIndexOf(QLatin1Char('/')) + 1); - real_dir = dir; - wildcard = wildcard.right(wildcard.length() - dir.length()); - } - - if (real_dir.isEmpty() || QFileInfo(real_dir).exists()) { - QStringList files = QDir(real_dir).entryList(QStringList(wildcard)); - if (files.isEmpty()) { - q->logMessage(format("Failure to find %1").arg(val)); - } else { - QString a; - for (int i = files.count() - 1; i >= 0; --i) { - if (files[i] == QLatin1String(".") || files[i] == QLatin1String("..")) - continue; - a = dir + files[i]; - sources_out += a; - } - } - } else { - q->logMessage(format("Cannot match %1/%2, as %3 does not exist.") - .arg(real_dir).arg(wildcard).arg(real_dir)); - } - } -} - - -/* - * Lookup of files are done in this order: - * 1. look in pwd - * 2. look in vpaths - * 3. expand wild card files relative from the profiles folder - **/ - -// FIXME: This code supports something that I'd consider a flaw in .pro file syntax -// which is not even documented. So arguably this can be ditched completely... -QStringList ProFileEvaluator::Private::expandPattern(const QString& pattern) -{ - if (!currentProFile()) - return QStringList(); - - QStringList sources_out; - const QString absName = QDir::cleanPath(QDir::current().absoluteFilePath(pattern)); - - expandPatternHelper(pattern, absName, sources_out); - return sources_out; -} - QString ProFileEvaluator::Private::format(const char *fmt) const { ProFile *pro = currentProFile(); @@ -1654,6 +1552,59 @@ QStringList ProFileEvaluator::values(const QString &variableName, const ProFile return d->values(variableName, pro); } +QStringList ProFileEvaluator::absolutePathValues( + const QString &variable, const QString &baseDirectory) const +{ + QStringList result; + foreach (const QString &el, values(variable)) { + const QFileInfo info = QFileInfo(baseDirectory, el); + if (info.isDir()) + result << QDir::cleanPath(info.absoluteFilePath()); + } + return result; +} + +QStringList ProFileEvaluator::absoluteFileValues( + const QString &variable, const QString &baseDirectory, const QStringList &searchDirs, + const ProFile *pro) const +{ + QStringList result; + foreach (const QString &el, pro ? values(variable, pro) : values(variable)) { + QFileInfo info(el); + if (info.isAbsolute()) { + if (info.exists()) { + result << QDir::cleanPath(el); + goto next; + } + } else { + foreach (const QString &dir, searchDirs) { + QFileInfo info(dir, el); + if (info.isFile()) { + result << QDir::cleanPath(info.filePath()); + goto next; + } + } + if (baseDirectory.isEmpty()) + goto next; + info = QFileInfo(baseDirectory, el); + } + { + QFileInfo baseInfo(info.absolutePath()); + if (baseInfo.exists()) { + QString wildcard = info.fileName(); + if (wildcard.contains(QLatin1Char('*')) || wildcard.contains(QLatin1Char('?'))) { + QDir theDir(QDir::cleanPath(baseInfo.filePath())); + foreach (const QString &fn, theDir.entryList(QStringList(wildcard))) + if (fn != QLatin1String(".") && fn != QLatin1String("..")) + result << theDir.absoluteFilePath(fn); + } + } + } + next: ; + } + return result; +} + ProFileEvaluator::TemplateType ProFileEvaluator::templateType() { QStringList templ = values(QLatin1String("TEMPLATE")); diff --git a/tools/linguist/shared/profileevaluator.h b/tools/linguist/shared/profileevaluator.h index 78d8fce..ae09a59 100644 --- a/tools/linguist/shared/profileevaluator.h +++ b/tools/linguist/shared/profileevaluator.h @@ -76,6 +76,10 @@ public: void addProperties(const QHash<QString, QString> &properties); QStringList values(const QString &variableName) const; QStringList values(const QString &variableName, const ProFile *pro) const; + QStringList absolutePathValues(const QString &variable, const QString &baseDirectory) const; + QStringList absoluteFileValues( + const QString &variable, const QString &baseDirectory, const QStringList &searchDirs, + const ProFile *pro) const; QString propertyValue(const QString &val) const; // for our descendents diff --git a/tools/linguist/shared/proreader.cpp b/tools/linguist/shared/proreader.cpp index 492c2ef..3400f20 100644 --- a/tools/linguist/shared/proreader.cpp +++ b/tools/linguist/shared/proreader.cpp @@ -41,21 +41,49 @@ #include "profileevaluator.h" +#include <QtCore/QDir> #include <QtCore/QFileInfo> QT_BEGIN_NAMESPACE -void evaluateProFile(const ProFileEvaluator &visitor, QHash<QByteArray, QStringList> *varMap) +static QStringList getSources(const char *var, const char *vvar, const QStringList &baseVPaths, + const QString &projectDir, const ProFileEvaluator &visitor) { + QStringList vPaths = + visitor.absolutePathValues(QLatin1String(vvar), projectDir); + vPaths += baseVPaths; + vPaths.removeDuplicates(); + return visitor.absoluteFileValues(QLatin1String(var), projectDir, vPaths, 0); +} + +void evaluateProFile(const ProFileEvaluator &visitor, QHash<QByteArray, QStringList> *varMap, + const QString &projectDir) +{ + QStringList baseVPaths; + baseVPaths += visitor.absolutePathValues(QLatin1String("VPATH"), projectDir); + baseVPaths << projectDir; // QMAKE_ABSOLUTE_SOURCE_PATH + baseVPaths += visitor.absolutePathValues(QLatin1String("DEPENDPATH"), projectDir); + baseVPaths.removeDuplicates(); + QStringList sourceFiles; QString codecForTr; QString codecForSource; QStringList tsFileNames; // app/lib template - sourceFiles += visitor.values(QLatin1String("SOURCES")); - sourceFiles += visitor.values(QLatin1String("HEADERS")); - tsFileNames = visitor.values(QLatin1String("TRANSLATIONS")); + sourceFiles += getSources("SOURCES", "VPATH_SOURCES", baseVPaths, projectDir, visitor); + + sourceFiles += getSources("FORMS", "VPATH_FORMS", baseVPaths, projectDir, visitor); + sourceFiles += getSources("FORMS3", "VPATH_FORMS3", baseVPaths, projectDir, visitor); + + QStringList vPathsInc = baseVPaths; + vPathsInc += visitor.absolutePathValues(QLatin1String("INCLUDEPATH"), projectDir); + vPathsInc.removeDuplicates(); + sourceFiles += visitor.absoluteFileValues(QLatin1String("HEADERS"), projectDir, vPathsInc, 0); + + QDir proDir(projectDir); + foreach (const QString &tsFile, visitor.values(QLatin1String("TRANSLATIONS"))) + tsFileNames << QFileInfo(proDir, tsFile).filePath(); QStringList trcodec = visitor.values(QLatin1String("CODEC")) + visitor.values(QLatin1String("DEFAULTCODEC")) @@ -67,11 +95,6 @@ void evaluateProFile(const ProFileEvaluator &visitor, QHash<QByteArray, QStringL if (!srccodec.isEmpty()) codecForSource = srccodec.last(); - QStringList forms = visitor.values(QLatin1String("INTERFACES")) - + visitor.values(QLatin1String("FORMS")) - + visitor.values(QLatin1String("FORMS3")); - sourceFiles << forms; - sourceFiles.sort(); sourceFiles.removeDuplicates(); tsFileNames.sort(); @@ -100,7 +123,7 @@ bool evaluateProFile(const QString &fileName, bool verbose, QHash<QByteArray, QS if (!visitor.accept(&pro)) return false; - evaluateProFile(visitor, varMap); + evaluateProFile(visitor, varMap, fi.absolutePath()); return true; } diff --git a/tools/linguist/shared/proreader.h b/tools/linguist/shared/proreader.h index 31e2e6f..f663e23 100644 --- a/tools/linguist/shared/proreader.h +++ b/tools/linguist/shared/proreader.h @@ -48,7 +48,8 @@ QT_BEGIN_NAMESPACE class ProFileEvaluator; -void evaluateProFile(const ProFileEvaluator &visitor, QHash<QByteArray, QStringList> *varMap); +void evaluateProFile(const ProFileEvaluator &visitor, QHash<QByteArray, QStringList> *varMap, + const QString &projectDir); bool evaluateProFile(const QString &fileName, bool verbose, QHash<QByteArray, QStringList> *varMap); QT_END_NAMESPACE |