summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@nokia.com>2009-07-13 14:20:44 (GMT)
committerOswald Buddenhagen <oswald.buddenhagen@nokia.com>2009-07-13 14:51:21 (GMT)
commite2f381365bf2158095c5c7236fc4b2f842b9fa8c (patch)
tree5bf317515ed903054c1f2df5bfb41b2356f76273
parent45efa082135cbf97820a5ce7025685d22bd926ce (diff)
downloadQt-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
-rw-r--r--tests/auto/linguist/lupdate/testdata/good/proparsingpaths/file1.cpp9
-rw-r--r--tests/auto/linguist/lupdate/testdata/good/proparsingpaths/filter.cpp9
-rw-r--r--tests/auto/linguist/lupdate/testdata/good/proparsingpaths/project.pro10
-rw-r--r--tests/auto/linguist/lupdate/testdata/good/proparsingpaths/project.ts.result31
-rw-r--r--tests/auto/linguist/lupdate/testdata/good/proparsingpaths/sub/sub.pri3
-rw-r--r--tests/auto/linguist/lupdate/testdata/good/proparsingpaths/sub/subfile1.cpp9
-rw-r--r--tests/auto/linguist/lupdate/testdata/good/proparsingpaths/sub/subfilter.cpp9
-rw-r--r--tools/linguist/lupdate/main.cpp2
-rw-r--r--tools/linguist/shared/profileevaluator.cpp155
-rw-r--r--tools/linguist/shared/profileevaluator.h4
-rw-r--r--tools/linguist/shared/proreader.cpp43
-rw-r--r--tools/linguist/shared/proreader.h3
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