qmake: Change source identifier type in ProString

The strings remember in which file they were created/assigned.

However, this used a non-counting reference to a ProFile, which could
become dangling. If a subsequent ProFile re-used the exact same address,
a string's source would be mis-identified, which would be fatal in
conjunction with discard_from().

Since we actually need only a unique id for comparison, let's use an
integer for that.

comment on cherry-pick: this is actually a lot more than a cherry-pick,
because the file ids need to be aware of the dual VFS which was
concurrently introduced on the qtc side.

Started-by: Simon Hausmann <simon.hausmann@qt.io>
Change-Id: I395153afaf7c835d0119690ee7f4b915e6f90d4a
(cherry picked from qtbase/190aa94be7f5e146bef44862b974d733755cec85)
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
Oswald Buddenhagen
2017-08-14 18:30:29 +02:00
parent 274726efb0
commit 60245e55d7
18 changed files with 248 additions and 190 deletions

View File

@@ -160,10 +160,13 @@ static void createTree(const QmakePriFile *pri, QmakePriFileNode *node, const Fi
QString errorMessage; QString errorMessage;
// Prefer the cumulative file if it's non-empty, based on the assumption // Prefer the cumulative file if it's non-empty, based on the assumption
// that it contains more "stuff". // that it contains more "stuff".
vfs->readFile(file.toString(), QMakeVfs::VfsCumulative, &contents, &errorMessage); int cid = vfs->idForFileName(file.toString(), QMakeVfs::VfsCumulative);
vfs->readFile(cid, &contents, &errorMessage);
// If the cumulative evaluation botched the file too much, try the exact one. // If the cumulative evaluation botched the file too much, try the exact one.
if (contents.isEmpty()) if (contents.isEmpty()) {
vfs->readFile(file.toString(), QMakeVfs::VfsExact, &contents, &errorMessage); int eid = vfs->idForFileName(file.toString(), QMakeVfs::VfsExact);
vfs->readFile(eid, &contents, &errorMessage);
}
auto resourceNode = new ResourceEditor::ResourceTopLevelNode(file, false, contents, vfolder); auto resourceNode = new ResourceEditor::ResourceTopLevelNode(file, false, contents, vfolder);
vfolder->addNode(resourceNode); vfolder->addNode(resourceNode);
} }

View File

@@ -237,7 +237,8 @@ QmakePriFile::~QmakePriFile()
void QmakePriFile::scheduleUpdate() void QmakePriFile::scheduleUpdate()
{ {
QtSupport::ProFileCacheManager::instance()->discardFile(filePath().toString()); QtSupport::ProFileCacheManager::instance()->discardFile(
filePath().toString(), m_project->qmakeVfs());
m_qmakeProFile->scheduleUpdate(QmakeProFile::ParseLater); m_qmakeProFile->scheduleUpdate(QmakeProFile::ParseLater);
} }
@@ -292,11 +293,11 @@ static QStringList fileListForVar(
} }
void QmakePriFile::extractSources( void QmakePriFile::extractSources(
QHash<const ProFile *, QmakePriFileEvalResult *> proToResult, QmakePriFileEvalResult *fallback, QHash<int, QmakePriFileEvalResult *> proToResult, QmakePriFileEvalResult *fallback,
QVector<ProFileEvaluator::SourceFile> sourceFiles, FileType type) QVector<ProFileEvaluator::SourceFile> sourceFiles, FileType type)
{ {
foreach (const ProFileEvaluator::SourceFile &source, sourceFiles) { foreach (const ProFileEvaluator::SourceFile &source, sourceFiles) {
QmakePriFileEvalResult *result = proToResult.value(source.proFile); auto *result = proToResult.value(source.proFileId);
if (!result) if (!result)
result = fallback; result = fallback;
result->foundFiles[type].insert(FileName::fromString(source.fileName)); result->foundFiles[type].insert(FileName::fromString(source.fileName));
@@ -304,12 +305,12 @@ void QmakePriFile::extractSources(
} }
void QmakePriFile::extractInstalls( void QmakePriFile::extractInstalls(
QHash<const ProFile *, QmakePriFileEvalResult *> proToResult, QmakePriFileEvalResult *fallback, QHash<int, QmakePriFileEvalResult *> proToResult, QmakePriFileEvalResult *fallback,
const InstallsList &installList) const InstallsList &installList)
{ {
for (const InstallsItem &item : installList.items) { for (const InstallsItem &item : installList.items) {
for (const ProFileEvaluator::SourceFile &source : item.files) { for (const ProFileEvaluator::SourceFile &source : item.files) {
auto *result = proToResult.value(source.proFile); auto *result = proToResult.value(source.proFileId);
if (!result) if (!result)
result = fallback; result = fallback;
result->folders.insert(FileName::fromString(source.fileName)); result->folders.insert(FileName::fromString(source.fileName));
@@ -621,7 +622,8 @@ bool QmakePriFile::saveModifiedEditors()
return false; return false;
// force instant reload of ourselves // force instant reload of ourselves
QtSupport::ProFileCacheManager::instance()->discardFile(filePath().toString()); QtSupport::ProFileCacheManager::instance()->discardFile(
filePath().toString(), m_project->qmakeVfs());
QmakeProject::notifyChanged(filePath()); QmakeProject::notifyChanged(filePath());
return true; return true;
} }
@@ -701,7 +703,7 @@ QPair<ProFile *, QStringList> QmakePriFile::readProFile(const QString &file)
QMakeVfs vfs; QMakeVfs vfs;
QtSupport::ProMessageHandler handler; QtSupport::ProMessageHandler handler;
QMakeParser parser(nullptr, &vfs, &handler); QMakeParser parser(nullptr, &vfs, &handler);
includeFile = parser.parsedProBlock(QStringRef(&contents), file, 1); includeFile = parser.parsedProBlock(QStringRef(&contents), 0, file, 1);
} }
return qMakePair(includeFile, lines); return qMakePair(includeFile, lines);
} }
@@ -738,7 +740,7 @@ bool QmakePriFile::renameFile(const QString &oldName,
QMakeParser parser(nullptr, nullptr, nullptr); QMakeParser parser(nullptr, nullptr, nullptr);
QString contents = lines.join(QLatin1Char('\n')); QString contents = lines.join(QLatin1Char('\n'));
includeFile = parser.parsedProBlock(QStringRef(&contents), includeFile = parser.parsedProBlock(QStringRef(&contents),
filePath().toString(), 1, QMakeParser::FullGrammar); 0, filePath().toString(), 1, QMakeParser::FullGrammar);
QTC_ASSERT(includeFile, return false); // The file should still be valid after what we did. QTC_ASSERT(includeFile, return false); // The file should still be valid after what we did.
ProWriter::addFiles(includeFile, &lines, ProWriter::addFiles(includeFile, &lines,
@@ -1294,7 +1296,7 @@ QmakeEvalResult *QmakeProFile::evaluate(const QmakeEvalInput &input)
result->includedFiles.proFile = pro; result->includedFiles.proFile = pro;
result->includedFiles.name = input.projectFilePath; result->includedFiles.name = input.projectFilePath;
QHash<const ProFile *, QmakePriFileEvalResult *> proToResult; QHash<int, QmakePriFileEvalResult *> proToResult;
result->projectType result->projectType
= proFileTemplateTypeToProjectType( = proFileTemplateTypeToProjectType(
@@ -1332,7 +1334,7 @@ QmakeEvalResult *QmakeProFile::evaluate(const QmakeEvalInput &input)
childTree->proFile = child; childTree->proFile = child;
childTree->name = childName; childTree->name = childName;
current->children.insert(childName, childTree); current->children.insert(childName, childTree);
proToResult[child] = &childTree->result; proToResult[child->id()] = &childTree->result;
} }
} }
toBuild.append(current->children.values()); toBuild.append(current->children.values());
@@ -1368,7 +1370,7 @@ QmakeEvalResult *QmakeProFile::evaluate(const QmakeEvalInput &input)
childTree->proFile = child; childTree->proFile = child;
childTree->name = childName; childTree->name = childName;
current->children.insert(childName, childTree); current->children.insert(childName, childTree);
proToResult[child] = &childTree->result; proToResult[child->id()] = &childTree->result;
} }
} }
toBuild.append(current->children.values()); toBuild.append(current->children.values());

View File

@@ -201,11 +201,11 @@ private:
static QStringList baseVPaths(QtSupport::ProFileReader *reader, const QString &projectDir, const QString &buildDir); static QStringList baseVPaths(QtSupport::ProFileReader *reader, const QString &projectDir, const QString &buildDir);
static QStringList fullVPaths(const QStringList &baseVPaths, QtSupport::ProFileReader *reader, const QString &qmakeVariable, const QString &projectDir); static QStringList fullVPaths(const QStringList &baseVPaths, QtSupport::ProFileReader *reader, const QString &qmakeVariable, const QString &projectDir);
static void extractSources( static void extractSources(
QHash<const ProFile *, Internal::QmakePriFileEvalResult *> proToResult, QHash<int, Internal::QmakePriFileEvalResult *> proToResult,
Internal::QmakePriFileEvalResult *fallback, Internal::QmakePriFileEvalResult *fallback,
QVector<ProFileEvaluator::SourceFile> sourceFiles, ProjectExplorer::FileType type); QVector<ProFileEvaluator::SourceFile> sourceFiles, ProjectExplorer::FileType type);
static void extractInstalls( static void extractInstalls(
QHash<const ProFile *, Internal::QmakePriFileEvalResult *> proToResult, QHash<int, Internal::QmakePriFileEvalResult *> proToResult,
Internal::QmakePriFileEvalResult *fallback, Internal::QmakePriFileEvalResult *fallback,
const InstallsList &installList); const InstallsList &installList);
static void processValues(Internal::QmakePriFileEvalResult &result); static void processValues(Internal::QmakePriFileEvalResult &result);

View File

@@ -372,12 +372,14 @@ void QmakeProject::updateQmlJSCodeModel()
QString errorMessage; QString errorMessage;
foreach (const QString &rc, exactResources) { foreach (const QString &rc, exactResources) {
QString contents; QString contents;
if (m_qmakeVfs->readFile(rc, QMakeVfs::VfsExact, &contents, &errorMessage) == QMakeVfs::ReadOk) int id = m_qmakeVfs->idForFileName(rc, QMakeVfs::VfsExact);
if (m_qmakeVfs->readFile(id, &contents, &errorMessage) == QMakeVfs::ReadOk)
projectInfo.resourceFileContents[rc] = contents; projectInfo.resourceFileContents[rc] = contents;
} }
foreach (const QString &rc, cumulativeResources) { foreach (const QString &rc, cumulativeResources) {
QString contents; QString contents;
if (m_qmakeVfs->readFile(rc, QMakeVfs::VfsCumulative, &contents, &errorMessage) == QMakeVfs::ReadOk) int id = m_qmakeVfs->idForFileName(rc, QMakeVfs::VfsCumulative);
if (m_qmakeVfs->readFile(id, &contents, &errorMessage) == QMakeVfs::ReadOk)
projectInfo.resourceFileContents[rc] = contents; projectInfo.resourceFileContents[rc] = contents;
} }
if (!hasQmlLib) { if (!hasQmlLib) {
@@ -734,7 +736,7 @@ void QmakeProject::destroyProFileReader(QtSupport::ProFileReader *reader)
QString dir = projectFilePath().toString(); QString dir = projectFilePath().toString();
if (!dir.endsWith(QLatin1Char('/'))) if (!dir.endsWith(QLatin1Char('/')))
dir += QLatin1Char('/'); dir += QLatin1Char('/');
QtSupport::ProFileCacheManager::instance()->discardFiles(dir); QtSupport::ProFileCacheManager::instance()->discardFiles(dir, qmakeVfs());
QtSupport::ProFileCacheManager::instance()->decRefCount(); QtSupport::ProFileCacheManager::instance()->decRefCount();
m_qmakeGlobals.reset(); m_qmakeGlobals.reset();
@@ -840,7 +842,8 @@ void QmakeProject::setAllBuildConfigurationsEnabled(bool enabled)
static void notifyChangedHelper(const FileName &fileName, QmakeProFile *file) static void notifyChangedHelper(const FileName &fileName, QmakeProFile *file)
{ {
if (file->filePath() == fileName) { if (file->filePath() == fileName) {
QtSupport::ProFileCacheManager::instance()->discardFile(fileName.toString()); QtSupport::ProFileCacheManager::instance()->discardFile(
fileName.toString(), file->project()->qmakeVfs());
file->scheduleUpdate(QmakeProFile::ParseNow); file->scheduleUpdate(QmakeProFile::ParseNow);
} }

View File

@@ -166,16 +166,17 @@ void ProFileCacheManager::clear()
// loop is concerned. Use a shared pointer once this is not true anymore. // loop is concerned. Use a shared pointer once this is not true anymore.
delete m_cache; delete m_cache;
m_cache = 0; m_cache = 0;
QMakeVfs::clearIds();
} }
void ProFileCacheManager::discardFiles(const QString &prefix) void ProFileCacheManager::discardFiles(const QString &prefix, QMakeVfs *vfs)
{ {
if (m_cache) if (m_cache)
m_cache->discardFiles(prefix); m_cache->discardFiles(prefix, vfs);
} }
void ProFileCacheManager::discardFile(const QString &fileName) void ProFileCacheManager::discardFile(const QString &fileName, QMakeVfs *vfs)
{ {
if (m_cache) if (m_cache)
m_cache->discardFile(fileName); m_cache->discardFile(fileName, vfs);
} }

View File

@@ -93,8 +93,8 @@ class QTSUPPORT_EXPORT ProFileCacheManager : public QObject
public: public:
static ProFileCacheManager *instance() { return s_instance; } static ProFileCacheManager *instance() { return s_instance; }
ProFileCache *cache(); ProFileCache *cache();
void discardFiles(const QString &prefix); void discardFiles(const QString &prefix, QMakeVfs *vfs);
void discardFile(const QString &fileName); void discardFile(const QString &fileName, QMakeVfs *vfs);
void incRefCount(); void incRefCount();
void decRefCount(); void decRefCount();

View File

@@ -55,7 +55,7 @@ public:
struct SourceFile { struct SourceFile {
QString fileName; QString fileName;
const ProFile *proFile; int proFileId;
}; };
// Call this from a concurrency-free context // Call this from a concurrency-free context

View File

@@ -474,9 +474,10 @@ bool ProStringList::contains(const char *str, Qt::CaseSensitivity cs) const
return false; return false;
} }
ProFile::ProFile(const QString &fileName) ProFile::ProFile(int id, const QString &fileName)
: m_refCount(1), : m_refCount(1),
m_fileName(fileName), m_fileName(fileName),
m_id(id),
m_ok(true), m_ok(true),
m_hostBuild(false) m_hostBuild(false)
{ {
@@ -493,7 +494,7 @@ ProString ProFile::getStr(const ushort *&tPtr)
{ {
uint len = *tPtr++; uint len = *tPtr++;
ProString ret(items(), tPtr - tokPtr(), len); ProString ret(items(), tPtr - tokPtr(), len);
ret.setSource(this); ret.setSource(m_id);
tPtr += len; tPtr += len;
return ret; return ret;
} }

View File

@@ -69,8 +69,8 @@ public:
void setValue(const QString &str); void setValue(const QString &str);
void clear() { m_string.clear(); m_length = 0; } void clear() { m_string.clear(); m_length = 0; }
ProString &setSource(const ProString &other) { m_file = other.m_file; return *this; } ProString &setSource(const ProString &other) { m_file = other.m_file; return *this; }
ProString &setSource(const ProFile *pro) { m_file = pro; return *this; } ProString &setSource(int id) { m_file = id; return *this; }
const ProFile *sourceFile() const { return m_file; } int sourceFile() const { return m_file; }
ProString &prepend(const ProString &other); ProString &prepend(const ProString &other);
ProString &append(const ProString &other, bool *pending = 0); ProString &append(const ProString &other, bool *pending = 0);
@@ -159,7 +159,7 @@ private:
QString m_string; QString m_string;
int m_offset, m_length; int m_offset, m_length;
const ProFile *m_file; int m_file;
mutable uint m_hash; mutable uint m_hash;
QChar *prepareExtend(int extraLen, int thisTarget, int extraTarget); QChar *prepareExtend(int extraLen, int thisTarget, int extraTarget);
uint updatedHash() const; uint updatedHash() const;
@@ -332,9 +332,10 @@ enum ProToken {
class QMAKE_EXPORT ProFile class QMAKE_EXPORT ProFile
{ {
public: public:
explicit ProFile(const QString &fileName); ProFile(int id, const QString &fileName);
~ProFile(); ~ProFile();
int id() const { return m_id; }
QString fileName() const { return m_fileName; } QString fileName() const { return m_fileName; }
QString directoryName() const { return m_directoryName; } QString directoryName() const { return m_directoryName; }
const QString &items() const { return m_proitems; } const QString &items() const { return m_proitems; }
@@ -359,6 +360,7 @@ private:
QString m_proitems; QString m_proitems;
QString m_fileName; QString m_fileName;
QString m_directoryName; QString m_directoryName;
int m_id;
bool m_ok; bool m_ok;
bool m_hostBuild; bool m_hostBuild;
}; };

View File

@@ -176,7 +176,7 @@ QString ProWriter::compileScope(const QString &scope)
if (scope.isEmpty()) if (scope.isEmpty())
return QString(); return QString();
QMakeParser parser(0, 0, 0); QMakeParser parser(0, 0, 0);
ProFile *includeFile = parser.parsedProBlock(QStringRef(&scope), QLatin1String("no-file"), 1); ProFile *includeFile = parser.parsedProBlock(QStringRef(&scope), 0, QLatin1String("no-file"), 1);
if (!includeFile) if (!includeFile)
return QString(); return QString();
QString result = includeFile->items(); QString result = includeFile->items();

View File

@@ -436,13 +436,16 @@ QMakeEvaluator::VisitReturn
QMakeEvaluator::writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode, QMakeEvaluator::writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode,
QMakeVfs::VfsFlags flags, const QString &contents) QMakeVfs::VfsFlags flags, const QString &contents)
{ {
int oldId = m_vfs->idForFileName(fn, flags | QMakeVfs::VfsAccessedOnly);
int id = m_vfs->idForFileName(fn, flags | QMakeVfs::VfsCreate);
QString errStr; QString errStr;
if (!m_vfs->writeFile(fn, mode, flags, contents, &errStr)) { if (!m_vfs->writeFile(id, mode, flags, contents, &errStr)) {
evalError(fL1S("Cannot write %1file %2: %3") evalError(fL1S("Cannot write %1file %2: %3")
.arg(ctx, QDir::toNativeSeparators(fn), errStr)); .arg(ctx, QDir::toNativeSeparators(fn), errStr));
return ReturnFalse; return ReturnFalse;
} }
m_parser->discardFileFromCache(fn); if (oldId)
m_parser->discardFileFromCache(oldId);
return ReturnTrue; return ReturnTrue;
} }
@@ -709,9 +712,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
after = args[3]; after = args[3];
const ProStringList &var = values(map(args.at(0))); const ProStringList &var = values(map(args.at(0)));
if (!var.isEmpty()) { if (!var.isEmpty()) {
const ProFile *src = currentProFile(); int src = currentFileId();
for (const ProString &v : var) for (const ProString &v : var)
if (const ProFile *s = v.sourceFile()) { if (int s = v.sourceFile()) {
src = s; src = s;
break; break;
} }
@@ -1062,7 +1065,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
dirs.append(fname + QLatin1Char('/')); dirs.append(fname + QLatin1Char('/'));
} }
if (regex.exactMatch(qdir[i])) if (regex.exactMatch(qdir[i]))
ret += ProString(fname).setSource(currentProFile()); ret += ProString(fname).setSource(currentFileId());
} }
} }
} }
@@ -1329,7 +1332,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return ReturnFalse; return ReturnFalse;
} }
QString fn = resolvePath(args.at(0).toQString(m_tmp1)); QString fn = resolvePath(args.at(0).toQString(m_tmp1));
ProFile *pro = m_parser->parsedProFile(fn, QMakeParser::ParseOnlyCached); QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
int pro = m_vfs->idForFileName(fn, flags | QMakeVfs::VfsAccessedOnly);
if (!pro) if (!pro)
return ReturnFalse; return ReturnFalse;
ProValueMap &vmap = m_valuemapStack.first(); ProValueMap &vmap = m_valuemapStack.first();
@@ -1349,18 +1353,17 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
++vit; ++vit;
} }
for (auto fit = m_functionDefs.testFunctions.begin(); fit != m_functionDefs.testFunctions.end(); ) { for (auto fit = m_functionDefs.testFunctions.begin(); fit != m_functionDefs.testFunctions.end(); ) {
if (fit->pro() == pro) if (fit->pro()->id() == pro)
fit = m_functionDefs.testFunctions.erase(fit); fit = m_functionDefs.testFunctions.erase(fit);
else else
++fit; ++fit;
} }
for (auto fit = m_functionDefs.replaceFunctions.begin(); fit != m_functionDefs.replaceFunctions.end(); ) { for (auto fit = m_functionDefs.replaceFunctions.begin(); fit != m_functionDefs.replaceFunctions.end(); ) {
if (fit->pro() == pro) if (fit->pro()->id() == pro)
fit = m_functionDefs.replaceFunctions.erase(fit); fit = m_functionDefs.replaceFunctions.erase(fit);
else else
++fit; ++fit;
} }
pro->deref();
ProStringList &iif = m_valuemapStack.first()[ProKey("QMAKE_INTERNAL_INCLUDED_FILES")]; ProStringList &iif = m_valuemapStack.first()[ProKey("QMAKE_INTERNAL_INCLUDED_FILES")];
int idx = iif.indexOf(ProString(fn)); int idx = iif.indexOf(ProString(fn));
if (idx >= 0) if (idx >= 0)
@@ -1405,7 +1408,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
VisitReturn ret = ReturnFalse; VisitReturn ret = ReturnFalse;
QString contents = args.join(statics.field_sep); QString contents = args.join(statics.field_sep);
ProFile *pro = m_parser->parsedProBlock(QStringRef(&contents), ProFile *pro = m_parser->parsedProBlock(QStringRef(&contents),
m_current.pro->fileName(), m_current.line); 0, m_current.pro->fileName(), m_current.line);
if (m_cumulative || pro->isOk()) { if (m_cumulative || pro->isOk()) {
m_locationStack.push(m_current); m_locationStack.push(m_current);
visitProBlock(pro, pro->tokPtr()); visitProBlock(pro, pro->tokPtr());

View File

@@ -268,13 +268,13 @@ void QMakeEvaluator::skipHashStr(const ushort *&tokPtr)
// FIXME: this should not build new strings for direct sections. // FIXME: this should not build new strings for direct sections.
// Note that the E_SPRINTF and E_LIST implementations rely on the deep copy. // Note that the E_SPRINTF and E_LIST implementations rely on the deep copy.
ProStringList QMakeEvaluator::split_value_list(const QStringRef &vals, const ProFile *source) ProStringList QMakeEvaluator::split_value_list(const QStringRef &vals, int source)
{ {
QString build; QString build;
ProStringList ret; ProStringList ret;
if (!source) if (!source)
source = currentProFile(); source = currentFileId();
const QChar *vals_data = vals.data(); const QChar *vals_data = vals.data();
const int vals_len = vals.length(); const int vals_len = vals.length();
@@ -1311,7 +1311,7 @@ void QMakeEvaluator::setupProject()
{ {
setTemplate(); setTemplate();
ProValueMap &vars = m_valuemapStack.top(); ProValueMap &vars = m_valuemapStack.top();
ProFile *proFile = currentProFile(); int proFile = currentFileId();
vars[ProKey("TARGET")] << ProString(QFileInfo(currentFileName()).baseName()).setSource(proFile); vars[ProKey("TARGET")] << ProString(QFileInfo(currentFileName()).baseName()).setSource(proFile);
vars[ProKey("_PRO_FILE_")] << ProString(currentFileName()).setSource(proFile); vars[ProKey("_PRO_FILE_")] << ProString(currentFileName()).setSource(proFile);
vars[ProKey("_PRO_FILE_PWD_")] << ProString(currentDirectory()).setSource(proFile); vars[ProKey("_PRO_FILE_PWD_")] << ProString(currentDirectory()).setSource(proFile);
@@ -1321,7 +1321,7 @@ void QMakeEvaluator::setupProject()
void QMakeEvaluator::evaluateCommand(const QString &cmds, const QString &where) void QMakeEvaluator::evaluateCommand(const QString &cmds, const QString &where)
{ {
if (!cmds.isEmpty()) { if (!cmds.isEmpty()) {
ProFile *pro = m_parser->parsedProBlock(QStringRef(&cmds), where, -1); ProFile *pro = m_parser->parsedProBlock(QStringRef(&cmds), 0, where, -1);
if (pro->isOk()) { if (pro->isOk()) {
m_locationStack.push(m_current); m_locationStack.push(m_current);
visitProBlock(pro, pro->tokPtr()); visitProBlock(pro, pro->tokPtr());
@@ -1605,6 +1605,14 @@ ProFile *QMakeEvaluator::currentProFile() const
return 0; return 0;
} }
int QMakeEvaluator::currentFileId() const
{
ProFile *pro = currentProFile();
if (pro)
return pro->id();
return 0;
}
QString QMakeEvaluator::currentFileName() const QString QMakeEvaluator::currentFileName() const
{ {
ProFile *pro = currentProFile(); ProFile *pro = currentProFile();
@@ -1819,7 +1827,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditional(
const QStringRef &cond, const QString &where, int line) const QStringRef &cond, const QString &where, int line)
{ {
VisitReturn ret = ReturnFalse; VisitReturn ret = ReturnFalse;
ProFile *pro = m_parser->parsedProBlock(cond, where, line, QMakeParser::TestGrammar); ProFile *pro = m_parser->parsedProBlock(cond, 0, where, line, QMakeParser::TestGrammar);
if (pro->isOk()) { if (pro->isOk()) {
m_locationStack.push(m_current); m_locationStack.push(m_current);
ret = visitProBlock(pro, pro->tokPtr()); ret = visitProBlock(pro, pro->tokPtr());

View File

@@ -173,12 +173,13 @@ public:
void setTemplate(); void setTemplate();
ProStringList split_value_list(const QStringRef &vals, const ProFile *source = 0); ProStringList split_value_list(const QStringRef &vals, int source = 0);
VisitReturn expandVariableReferences(const ushort *&tokPtr, int sizeHint, ProStringList *ret, bool joined); VisitReturn expandVariableReferences(const ushort *&tokPtr, int sizeHint, ProStringList *ret, bool joined);
QString currentFileName() const; QString currentFileName() const;
QString currentDirectory() const; QString currentDirectory() const;
ProFile *currentProFile() const; ProFile *currentProFile() const;
int currentFileId() const;
QString resolvePath(const QString &fileName) const QString resolvePath(const QString &fileName) const
{ return QMakeInternal::IoUtils::resolvePath(currentDirectory(), fileName); } { return QMakeInternal::IoUtils::resolvePath(currentDirectory(), fileName); }

View File

@@ -49,12 +49,22 @@ ProFileCache::~ProFileCache()
ent.pro->deref(); ent.pro->deref();
} }
void ProFileCache::discardFile(const QString &fileName) void ProFileCache::discardFile(const QString &fileName, QMakeVfs *vfs)
{
int eid = vfs->idForFileName(fileName, QMakeVfs::VfsExact | QMakeVfs::VfsAccessedOnly);
if (eid)
discardFile(eid);
int cid = vfs->idForFileName(fileName, QMakeVfs::VfsCumulative | QMakeVfs::VfsAccessedOnly);
if (cid && cid != eid)
discardFile(cid);
}
void ProFileCache::discardFile(int id)
{ {
#ifdef PROPARSER_THREAD_SAFE #ifdef PROPARSER_THREAD_SAFE
QMutexLocker lck(&mutex); QMutexLocker lck(&mutex);
#endif #endif
QHash<QString, Entry>::Iterator it = parsed_files.find(fileName); auto it = parsed_files.find(id);
if (it != parsed_files.end()) { if (it != parsed_files.end()) {
#ifdef PROPARSER_THREAD_SAFE #ifdef PROPARSER_THREAD_SAFE
if (it->locker) { if (it->locker) {
@@ -74,16 +84,16 @@ void ProFileCache::discardFile(const QString &fileName)
} }
} }
void ProFileCache::discardFiles(const QString &prefix) void ProFileCache::discardFiles(const QString &prefix, QMakeVfs *vfs)
{ {
#ifdef PROPARSER_THREAD_SAFE #ifdef PROPARSER_THREAD_SAFE
QMutexLocker lck(&mutex); QMutexLocker lck(&mutex);
#endif #endif
QHash<QString, Entry>::Iterator auto it = parsed_files.begin(), end = parsed_files.end();
it = parsed_files.begin(), while (it != end) {
end = parsed_files.end(); // Note: this is empty for virtual files from other VFSes.
while (it != end) QString fn = vfs->fileNameForId(it.key());
if (it.key().startsWith(prefix)) { if (fn.startsWith(prefix)) {
#ifdef PROPARSER_THREAD_SAFE #ifdef PROPARSER_THREAD_SAFE
if (it->locker) { if (it->locker) {
if (!it->locker->done) { if (!it->locker->done) {
@@ -103,6 +113,7 @@ void ProFileCache::discardFiles(const QString &prefix)
++it; ++it;
} }
} }
}
////////// Parser /////////// ////////// Parser ///////////
@@ -164,18 +175,15 @@ QMakeParser::QMakeParser(ProFileCache *cache, QMakeVfs *vfs, QMakeParserHandler
ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags) ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
{ {
ProFile *pro; ProFile *pro;
if ((flags & (ParseUseCache|ParseOnlyCached)) && m_cache) { QMakeVfs::VfsFlags vfsFlags = ((flags & ParseCumulative) ? QMakeVfs::VfsCumulative
: QMakeVfs::VfsExact);
int id = m_vfs->idForFileName(fileName, vfsFlags);
if ((flags & ParseUseCache) && m_cache) {
ProFileCache::Entry *ent; ProFileCache::Entry *ent;
#ifdef PROPARSER_THREAD_SAFE #ifdef PROPARSER_THREAD_SAFE
QMutexLocker locker(&m_cache->mutex); QMutexLocker locker(&m_cache->mutex);
#endif #endif
QHash<QString, ProFileCache::Entry>::Iterator it; auto it = m_cache->parsed_files.find(id);
#ifdef PROEVALUATOR_DUAL_VFS
QString virtFileName = ((flags & ParseCumulative) ? '-' : '+') + fileName;
it = m_cache->parsed_files.find(virtFileName);
if (it == m_cache->parsed_files.end())
#endif
it = m_cache->parsed_files.find(fileName);
if (it != m_cache->parsed_files.end()) { if (it != m_cache->parsed_files.end()) {
ent = &*it; ent = &*it;
#ifdef PROPARSER_THREAD_SAFE #ifdef PROPARSER_THREAD_SAFE
@@ -192,24 +200,15 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
#endif #endif
if ((pro = ent->pro)) if ((pro = ent->pro))
pro->ref(); pro->ref();
} else if (!(flags & ParseOnlyCached)) { } else {
QString contents; ent = &m_cache->parsed_files[id];
QMakeVfs::VfsFlags vfsFlags =
((flags & ParseCumulative) ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
bool virt = false;
#ifdef PROEVALUATOR_DUAL_VFS
virt = m_vfs->readVirtualFile(fileName, vfsFlags, &contents);
if (virt)
ent = &m_cache->parsed_files[virtFileName];
else
#endif
ent = &m_cache->parsed_files[fileName];
#ifdef PROPARSER_THREAD_SAFE #ifdef PROPARSER_THREAD_SAFE
ent->locker = new ProFileCache::Entry::Locker; ent->locker = new ProFileCache::Entry::Locker;
locker.unlock(); locker.unlock();
#endif #endif
if (virt || readFile(fileName, vfsFlags | QMakeVfs::VfsNoVirtual, flags, &contents)) { QString contents;
pro = parsedProBlock(QStringRef(&contents), fileName, 1, FullGrammar); if (readFile(id, flags, &contents)) {
pro = parsedProBlock(QStringRef(&contents), id, fileName, 1, FullGrammar);
pro->itemsRef()->squeeze(); pro->itemsRef()->squeeze();
pro->ref(); pro->ref();
} else { } else {
@@ -226,46 +225,39 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
ent->locker = 0; ent->locker = 0;
} }
#endif #endif
} else {
pro = 0;
} }
} else if (!(flags & ParseOnlyCached)) {
QString contents;
QMakeVfs::VfsFlags vfsFlags =
((flags & ParseCumulative) ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
if (readFile(fileName, vfsFlags, flags, &contents))
pro = parsedProBlock(QStringRef(&contents), fileName, 1, FullGrammar);
else
pro = 0;
} else { } else {
QString contents;
if (readFile(id, flags, &contents))
pro = parsedProBlock(QStringRef(&contents), id, fileName, 1, FullGrammar);
else
pro = 0; pro = 0;
} }
return pro; return pro;
} }
ProFile *QMakeParser::parsedProBlock( ProFile *QMakeParser::parsedProBlock(
const QStringRef &contents, const QString &name, int line, SubGrammar grammar) const QStringRef &contents, int id, const QString &name, int line, SubGrammar grammar)
{ {
ProFile *pro = new ProFile(name); ProFile *pro = new ProFile(id, name);
read(pro, contents, line, grammar); read(pro, contents, line, grammar);
return pro; return pro;
} }
void QMakeParser::discardFileFromCache(const QString &fileName) void QMakeParser::discardFileFromCache(int id)
{ {
if (m_cache) if (m_cache)
m_cache->discardFile(fileName); m_cache->discardFile(id);
} }
bool QMakeParser::readFile( bool QMakeParser::readFile(int id, ParseFlags flags, QString *contents)
const QString &fn, QMakeVfs::VfsFlags vfsFlags, ParseFlags flags, QString *contents)
{ {
QString errStr; QString errStr;
QMakeVfs::ReadResult result = m_vfs->readFile(fn, vfsFlags, contents, &errStr); QMakeVfs::ReadResult result = m_vfs->readFile(id, contents, &errStr);
if (result != QMakeVfs::ReadOk) { if (result != QMakeVfs::ReadOk) {
if (m_handler && ((flags & ParseReportMissing) || result != QMakeVfs::ReadNotFound)) if (m_handler && ((flags & ParseReportMissing) || result != QMakeVfs::ReadNotFound))
m_handler->message(QMakeParserHandler::ParserIoError, m_handler->message(QMakeParserHandler::ParserIoError,
fL1S("Cannot read %1: %2").arg(fn, errStr)); fL1S("Cannot read %1: %2").arg(m_vfs->fileNameForId(id), errStr));
return false; return false;
} }
return true; return true;

View File

@@ -75,7 +75,6 @@ public:
enum ParseFlag { enum ParseFlag {
ParseDefault = 0, ParseDefault = 0,
ParseUseCache = 1, ParseUseCache = 1,
ParseOnlyCached = 2,
ParseReportMissing = 4, ParseReportMissing = 4,
#ifdef PROEVALUATOR_DUAL_VFS #ifdef PROEVALUATOR_DUAL_VFS
ParseCumulative = 8 ParseCumulative = 8
@@ -90,10 +89,10 @@ public:
enum SubGrammar { FullGrammar, TestGrammar, ValueGrammar }; enum SubGrammar { FullGrammar, TestGrammar, ValueGrammar };
// fileName is expected to be absolute and cleanPath()ed. // fileName is expected to be absolute and cleanPath()ed.
ProFile *parsedProFile(const QString &fileName, ParseFlags flags = ParseDefault); ProFile *parsedProFile(const QString &fileName, ParseFlags flags = ParseDefault);
ProFile *parsedProBlock(const QStringRef &contents, const QString &name, int line = 0, ProFile *parsedProBlock(const QStringRef &contents, int id, const QString &name, int line = 0,
SubGrammar grammar = FullGrammar); SubGrammar grammar = FullGrammar);
void discardFileFromCache(const QString &fileName); void discardFileFromCache(int id);
#ifdef PROPARSER_DEBUG #ifdef PROPARSER_DEBUG
static QString formatProBlock(const QString &block); static QString formatProBlock(const QString &block);
@@ -132,7 +131,7 @@ private:
ushort terminator; // '}' if replace function call is braced, ':' if test function ushort terminator; // '}' if replace function call is braced, ':' if test function
}; };
bool readFile(const QString &fn, QMakeVfs::VfsFlags vfsFlags, QMakeParser::ParseFlags flags, QString *contents); bool readFile(int id, QMakeParser::ParseFlags flags, QString *contents);
void read(ProFile *pro, const QStringRef &content, int line, SubGrammar grammar); void read(ProFile *pro, const QStringRef &content, int line, SubGrammar grammar);
ALWAYS_INLINE void putTok(ushort *&tokPtr, ushort tok); ALWAYS_INLINE void putTok(ushort *&tokPtr, ushort tok);
@@ -201,8 +200,9 @@ public:
ProFileCache() {} ProFileCache() {}
~ProFileCache(); ~ProFileCache();
void discardFile(const QString &fileName); void discardFile(int id);
void discardFiles(const QString &prefix); void discardFile(const QString &fileName, QMakeVfs *vfs);
void discardFiles(const QString &prefix, QMakeVfs *vfs);
private: private:
struct Entry { struct Entry {
@@ -218,7 +218,7 @@ private:
#endif #endif
}; };
QHash<QString, Entry> parsed_files; QHash<int, Entry> parsed_files;
#ifdef PROPARSER_THREAD_SAFE #ifdef PROPARSER_THREAD_SAFE
QMutex mutex; QMutex mutex;
#endif #endif

View File

@@ -51,19 +51,85 @@ QMakeVfs::QMakeVfs()
#endif #endif
} }
bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, VfsFlags flags, #ifdef PROPARSER_THREAD_SAFE
QMutex QMakeVfs::s_mutex;
#endif
QAtomicInt QMakeVfs::s_fileIdCounter;
QHash<QString, int> QMakeVfs::s_fileIdMap;
QHash<int, QString> QMakeVfs::s_idFileMap;
int QMakeVfs::idForFileName(const QString &fn, VfsFlags flags)
{
#ifdef PROEVALUATOR_DUAL_VFS
{
# ifdef PROPARSER_THREAD_SAFE
QMutexLocker locker(&m_vmutex);
# endif
int idx = (flags & VfsCumulative) ? 1 : 0;
if (flags & VfsCreate) {
int &id = m_virtualFileIdMap[idx][fn];
if (!id) {
id = ++s_fileIdCounter;
m_virtualIdFileMap[id] = fn;
}
return id;
}
int id = m_virtualFileIdMap[idx].value(fn);
if (id || (flags & VfsCreatedOnly))
return id;
}
#endif
if (!(flags & VfsAccessedOnly)) {
#ifdef PROPARSER_THREAD_SAFE
QMutexLocker locker(&s_mutex);
#endif
int &id = s_fileIdMap[fn];
if (!id) {
id = ++s_fileIdCounter;
s_idFileMap[id] = fn;
}
return id;
}
return s_fileIdMap.value(fn);
}
QString QMakeVfs::fileNameForId(int id)
{
#ifdef PROEVALUATOR_DUAL_VFS
{
# ifdef PROPARSER_THREAD_SAFE
QMutexLocker locker(&m_vmutex);
# endif
const QString &fn = m_virtualIdFileMap.value(id);
if (!fn.isEmpty())
return fn;
}
#endif
#ifdef PROPARSER_THREAD_SAFE
QMutexLocker locker(&s_mutex);
#endif
return s_idFileMap.value(id);
}
void QMakeVfs::clearIds()
{
#ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&s_mutex);
#endif
s_fileIdCounter = 0;
s_fileIdMap.clear();
s_idFileMap.clear();
}
bool QMakeVfs::writeFile(int id, QIODevice::OpenMode mode, VfsFlags flags,
const QString &contents, QString *errStr) const QString &contents, QString *errStr)
{ {
#ifndef PROEVALUATOR_FULL #ifndef PROEVALUATOR_FULL
# ifdef PROEVALUATOR_THREAD_SAFE # ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
# endif # endif
#ifdef PROEVALUATOR_DUAL_VFS QString *cont = &m_files[id];
QString *cont = &m_files[((flags & VfsCumulative) ? '-' : '+') + fn];
#else
QString *cont = &m_files[fn];
Q_UNUSED(flags) Q_UNUSED(flags)
#endif
if (mode & QIODevice::Append) if (mode & QIODevice::Append)
*cont += contents; *cont += contents;
else else
@@ -71,13 +137,13 @@ bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, VfsFlags f
Q_UNUSED(errStr) Q_UNUSED(errStr)
return true; return true;
#else #else
QFileInfo qfi(fn); QFileInfo qfi(fileNameForId(id));
if (!QDir::current().mkpath(qfi.path())) { if (!QDir::current().mkpath(qfi.path())) {
*errStr = fL1S("Cannot create parent directory"); *errStr = fL1S("Cannot create parent directory");
return false; return false;
} }
QByteArray bytes = contents.toLocal8Bit(); QByteArray bytes = contents.toLocal8Bit();
QFile cfile(fn); QFile cfile(qfi.filePath());
if (!(mode & QIODevice::Append) && cfile.open(QIODevice::ReadOnly | QIODevice::Text)) { if (!(mode & QIODevice::Append) && cfile.open(QIODevice::ReadOnly | QIODevice::Text)) {
if (cfile.readAll() == bytes) { if (cfile.readAll() == bytes) {
if (flags & VfsExecutable) { if (flags & VfsExecutable) {
@@ -108,53 +174,13 @@ bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, VfsFlags f
#endif #endif
} }
#ifndef PROEVALUATOR_FULL QMakeVfs::ReadResult QMakeVfs::readFile(int id, QString *contents, QString *errStr)
bool QMakeVfs::readVirtualFile(const QString &fn, VfsFlags flags, QString *contents)
{
# ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&m_mutex);
# endif
QHash<QString, QString>::ConstIterator it;
# ifdef PROEVALUATOR_DUAL_VFS
it = m_files.constFind(((flags & VfsCumulative) ? '-' : '+') + fn);
if (it != m_files.constEnd()) {
*contents = *it;
return true;
}
# else
it = m_files.constFind(fn);
if (it != m_files.constEnd()
&& it->constData() != m_magicMissing.constData()
&& it->constData() != m_magicExisting.constData()) {
*contents = *it;
return true;
}
Q_UNUSED(flags)
# endif
return false;
}
#endif
QMakeVfs::ReadResult QMakeVfs::readFile(
const QString &fn, VfsFlags flags, QString *contents, QString *errStr)
{ {
#ifndef PROEVALUATOR_FULL #ifndef PROEVALUATOR_FULL
# ifdef PROEVALUATOR_THREAD_SAFE # ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
# endif # endif
QHash<QString, QString>::ConstIterator it; auto it = m_files.constFind(id);
# ifdef PROEVALUATOR_DUAL_VFS
if (!(flags & VfsNoVirtual)) {
it = m_files.constFind(((flags & VfsCumulative) ? '-' : '+') + fn);
if (it != m_files.constEnd()) {
*contents = *it;
return ReadOk;
}
}
# else
Q_UNUSED(flags)
# endif
it = m_files.constFind(fn);
if (it != m_files.constEnd()) { if (it != m_files.constEnd()) {
if (it->constData() == m_magicMissing.constData()) { if (it->constData() == m_magicMissing.constData()) {
*errStr = fL1S("No such file or directory"); *errStr = fL1S("No such file or directory");
@@ -165,15 +191,13 @@ QMakeVfs::ReadResult QMakeVfs::readFile(
return ReadOk; return ReadOk;
} }
} }
#else
Q_UNUSED(flags)
#endif #endif
QFile file(fn); QFile file(fileNameForId(id));
if (!file.open(QIODevice::ReadOnly)) { if (!file.open(QIODevice::ReadOnly)) {
if (!file.exists()) { if (!file.exists()) {
#ifndef PROEVALUATOR_FULL #ifndef PROEVALUATOR_FULL
m_files[fn] = m_magicMissing; m_files[id] = m_magicMissing;
#endif #endif
*errStr = fL1S("No such file or directory"); *errStr = fL1S("No such file or directory");
return ReadNotFound; return ReadNotFound;
@@ -182,7 +206,7 @@ QMakeVfs::ReadResult QMakeVfs::readFile(
return ReadOtherError; return ReadOtherError;
} }
#ifndef PROEVALUATOR_FULL #ifndef PROEVALUATOR_FULL
m_files[fn] = m_magicExisting; m_files[id] = m_magicExisting;
#endif #endif
QByteArray bcont = file.readAll(); QByteArray bcont = file.readAll();
@@ -205,15 +229,8 @@ bool QMakeVfs::exists(const QString &fn, VfsFlags flags)
# ifdef PROEVALUATOR_THREAD_SAFE # ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
# endif # endif
QHash<QString, QString>::ConstIterator it; int id = idForFileName(fn, flags);
# ifdef PROEVALUATOR_DUAL_VFS auto it = m_files.constFind(id);
it = m_files.constFind(((flags & VfsCumulative) ? '-' : '+') + fn);
if (it != m_files.constEnd())
return true;
# else
Q_UNUSED(flags)
# endif
it = m_files.constFind(fn);
if (it != m_files.constEnd()) if (it != m_files.constEnd())
return it->constData() != m_magicMissing.constData(); return it->constData() != m_magicMissing.constData();
#else #else
@@ -221,7 +238,7 @@ bool QMakeVfs::exists(const QString &fn, VfsFlags flags)
#endif #endif
bool ex = IoUtils::fileType(fn) == IoUtils::FileIsRegular; bool ex = IoUtils::fileType(fn) == IoUtils::FileIsRegular;
#ifndef PROEVALUATOR_FULL #ifndef PROEVALUATOR_FULL
m_files[fn] = ex ? m_magicExisting : m_magicMissing; m_files[id] = ex ? m_magicExisting : m_magicMissing;
#endif #endif
return ex; return ex;
} }
@@ -233,7 +250,7 @@ void QMakeVfs::invalidateCache()
# ifdef PROEVALUATOR_THREAD_SAFE # ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
# endif # endif
QHash<QString, QString>::Iterator it = m_files.begin(), eit = m_files.end(); auto it = m_files.begin(), eit = m_files.end();
while (it != eit) { while (it != eit) {
if (it->constData() == m_magicMissing.constData() if (it->constData() == m_magicMissing.constData()
||it->constData() == m_magicExisting.constData()) ||it->constData() == m_magicExisting.constData())

View File

@@ -28,13 +28,11 @@
#include "qmake_global.h" #include "qmake_global.h"
#include <qiodevice.h> #include <qiodevice.h>
#ifndef PROEVALUATOR_FULL
#include <qhash.h> #include <qhash.h>
#include <qstring.h> #include <qstring.h>
#ifdef PROEVALUATOR_THREAD_SAFE #ifdef PROEVALUATOR_THREAD_SAFE
# include <qmutex.h> # include <qmutex.h>
#endif #endif
#endif
#ifndef QT_NO_TEXTCODEC #ifndef QT_NO_TEXTCODEC
QT_FORWARD_DECLARE_CLASS(QTextCodec) QT_FORWARD_DECLARE_CLASS(QTextCodec)
@@ -62,23 +60,27 @@ public:
VfsExact = 0, VfsExact = 0,
#ifdef PROEVALUATOR_DUAL_VFS #ifdef PROEVALUATOR_DUAL_VFS
VfsCumulative = 2, VfsCumulative = 2,
VfsNoVirtual = 4 VfsCreate = 4,
VfsCreatedOnly = 8,
#else #else
VfsCumulative = 0, VfsCumulative = 0,
VfsNoVirtual = 0 VfsCreate = 0,
VfsCreatedOnly = 0,
#endif #endif
VfsAccessedOnly = 16
}; };
Q_DECLARE_FLAGS(VfsFlags, VfsFlag) Q_DECLARE_FLAGS(VfsFlags, VfsFlag)
QMakeVfs(); QMakeVfs();
bool writeFile(const QString &fn, QIODevice::OpenMode mode, VfsFlags flags, const QString &contents, QString *errStr); int idForFileName(const QString &fn, VfsFlags flags);
ReadResult readFile(const QString &fn, VfsFlags flags, QString *contents, QString *errStr); QString fileNameForId(int id);
bool exists(const QString &fn, VfsFlags flags); static void clearIds();
bool writeFile(int id, QIODevice::OpenMode mode, VfsFlags flags, const QString &contents, QString *errStr);
ReadResult readFile(int id, QString *contents, QString *errStr);
bool exists(const QString &fn, QMakeVfs::VfsFlags flags);
#ifndef PROEVALUATOR_FULL #ifndef PROEVALUATOR_FULL
bool readVirtualFile(const QString &fn, VfsFlags flags, QString *contents);
void invalidateCache(); void invalidateCache();
void invalidateContents(); void invalidateContents();
#endif #endif
@@ -88,11 +90,34 @@ public:
#endif #endif
private: private:
#ifdef PROEVALUATOR_THREAD_SAFE
static QMutex s_mutex;
#endif
static QAtomicInt s_fileIdCounter;
// Qt Creator's ProFile cache is a singleton to maximize its cross-project
// effectiveness (shared prf files from QtVersions).
// For this to actually work, real files need a global mapping.
// This is fine, because the namespace of real files is indeed global.
static QHash<QString, int> s_fileIdMap;
static QHash<int, QString> s_idFileMap;
#ifdef PROEVALUATOR_DUAL_VFS
# ifdef PROEVALUATOR_THREAD_SAFE
// The simple way to avoid recursing m_mutex.
QMutex m_vmutex;
# endif
// Virtual files are bound to the project context they were created in,
// so their ids need to be local as well.
// We violate that rule in lupdate (which has a non-dual VFS), but that
// does not matter, because it has only one project context anyway.
QHash<QString, int> m_virtualFileIdMap[2]; // Exact and cumulative
QHash<int, QString> m_virtualIdFileMap; // Only one map, as ids are unique across realms.
#endif
#ifndef PROEVALUATOR_FULL #ifndef PROEVALUATOR_FULL
# ifdef PROEVALUATOR_THREAD_SAFE # ifdef PROEVALUATOR_THREAD_SAFE
QMutex m_mutex; QMutex m_mutex;
# endif # endif
QHash<QString, QString> m_files; QHash<int, QString> m_files;
QString m_magicMissing; QString m_magicMissing;
QString m_magicExisting; QString m_magicExisting;
#endif #endif

View File

@@ -448,7 +448,7 @@ void tst_ProFileWriter::adds()
QMakeVfs vfs; QMakeVfs vfs;
QMakeParser parser(0, &vfs, &parseHandler); QMakeParser parser(0, &vfs, &parseHandler);
ProFile *proFile = parser.parsedProBlock(QStringRef(&input), QLatin1String(BASE_DIR "/test.pro"), 1); ProFile *proFile = parser.parsedProBlock(QStringRef(&input), 0, QLatin1String(BASE_DIR "/test.pro"), 1);
QVERIFY(proFile); QVERIFY(proFile);
PW::putVarValues(proFile, &lines, values, var, PW::PutFlags(flags), scope); PW::putVarValues(proFile, &lines, values, var, PW::PutFlags(flags), scope);
proFile->deref(); proFile->deref();
@@ -619,7 +619,7 @@ void tst_ProFileWriter::removes()
QMakeVfs vfs; QMakeVfs vfs;
QMakeParser parser(0, &vfs, &parseHandler); QMakeParser parser(0, &vfs, &parseHandler);
ProFile *proFile = parser.parsedProBlock(QStringRef(&input), QLatin1String(BASE_DIR "/test.pro"), 1); ProFile *proFile = parser.parsedProBlock(QStringRef(&input), 0, QLatin1String(BASE_DIR "/test.pro"), 1);
QVERIFY(proFile); QVERIFY(proFile);
QmakeProjectManager::Internal::ProWriter::removeVarValues(proFile, &lines, values, vars); QmakeProjectManager::Internal::ProWriter::removeVarValues(proFile, &lines, values, vars);
proFile->deref(); proFile->deref();
@@ -648,7 +648,7 @@ void tst_ProFileWriter::multiVar()
QMakeVfs vfs; QMakeVfs vfs;
QMakeParser parser(0, &vfs, &parseHandler); QMakeParser parser(0, &vfs, &parseHandler);
ProFile *proFile = parser.parsedProBlock(QStringRef(&input), QLatin1String(BASE_DIR "/test.pro"), 1); ProFile *proFile = parser.parsedProBlock(QStringRef(&input), 0, QLatin1String(BASE_DIR "/test.pro"), 1);
QVERIFY(proFile); QVERIFY(proFile);
QmakeProjectManager::Internal::ProWriter::removeFiles(proFile, &lines, baseDir, files, vars); QmakeProjectManager::Internal::ProWriter::removeFiles(proFile, &lines, baseDir, files, vars);
proFile->deref(); proFile->deref();
@@ -669,7 +669,7 @@ void tst_ProFileWriter::addFiles()
QMakeVfs vfs; QMakeVfs vfs;
QMakeParser parser(0, &vfs, &parseHandler); QMakeParser parser(0, &vfs, &parseHandler);
ProFile *proFile = parser.parsedProBlock(QStringRef(&input), QLatin1String(BASE_DIR "/test.pro"), 1); ProFile *proFile = parser.parsedProBlock(QStringRef(&input), 0, QLatin1String(BASE_DIR "/test.pro"), 1);
QVERIFY(proFile); QVERIFY(proFile);
QmakeProjectManager::Internal::ProWriter::addFiles(proFile, &lines, QmakeProjectManager::Internal::ProWriter::addFiles(proFile, &lines,
QStringList() << QString::fromLatin1(BASE_DIR "/sub/bar.cpp"), QStringList() << QString::fromLatin1(BASE_DIR "/sub/bar.cpp"),
@@ -691,7 +691,7 @@ void tst_ProFileWriter::removeFiles()
QMakeVfs vfs; QMakeVfs vfs;
QMakeParser parser(0, &vfs, &parseHandler); QMakeParser parser(0, &vfs, &parseHandler);
ProFile *proFile = parser.parsedProBlock(QStringRef(&input), QLatin1String(BASE_DIR "/test.pro"), 1); ProFile *proFile = parser.parsedProBlock(QStringRef(&input), 0, QLatin1String(BASE_DIR "/test.pro"), 1);
QVERIFY(proFile); QVERIFY(proFile);
QmakeProjectManager::Internal::ProWriter::removeFiles(proFile, &lines, QDir(BASE_DIR), QmakeProjectManager::Internal::ProWriter::removeFiles(proFile, &lines, QDir(BASE_DIR),
QStringList() << QString::fromLatin1(BASE_DIR "/sub/bar.cpp"), QStringList() << QString::fromLatin1(BASE_DIR "/sub/bar.cpp"),