forked from qt-creator/qt-creator
cache parsed pri & prf files
no point in re-parsing them over and over during the scan of a bigger project ... shaves off another 20% of the loading time of Qt 4.6.
This commit is contained in:
@@ -42,35 +42,27 @@ ProFileReader::ProFileReader(ProFileOption *option) : ProFileEvaluator(option)
|
|||||||
ProFileReader::~ProFileReader()
|
ProFileReader::~ProFileReader()
|
||||||
{
|
{
|
||||||
foreach (ProFile *pf, m_proFiles)
|
foreach (ProFile *pf, m_proFiles)
|
||||||
delete pf;
|
pf->deref();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProFileReader::readProFile(const QString &fileName)
|
bool ProFileReader::readProFile(const QString &fileName)
|
||||||
{
|
{
|
||||||
//disable caching -> list of include files is not updated otherwise
|
if (ProFile *pro = parsedProFile(fileName)) {
|
||||||
ProFile *pro = new ProFile(fileName);
|
aboutToEval(pro);
|
||||||
if (!queryProFile(pro)) {
|
bool ok = accept(pro);
|
||||||
delete pro;
|
pro->deref();
|
||||||
return false;
|
return ok;
|
||||||
}
|
}
|
||||||
m_includeFiles.insert(fileName, pro);
|
return false;
|
||||||
m_proFiles.append(pro);
|
|
||||||
return accept(pro);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ProFile *ProFileReader::parsedProFile(const QString &fileName)
|
void ProFileReader::aboutToEval(ProFile *pro)
|
||||||
{
|
{
|
||||||
ProFile *pro = ProFileEvaluator::parsedProFile(fileName);
|
if (!m_includeFiles.contains(pro->fileName())) {
|
||||||
if (pro) {
|
m_includeFiles.insert(pro->fileName(), pro);
|
||||||
m_includeFiles.insert(fileName, pro);
|
|
||||||
m_proFiles.append(pro);
|
m_proFiles.append(pro);
|
||||||
|
pro->ref();
|
||||||
}
|
}
|
||||||
return pro;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProFileReader::releaseParsedProFile(ProFile *)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<ProFile*> ProFileReader::includeFiles() const
|
QList<ProFile*> ProFileReader::includeFiles() const
|
||||||
@@ -117,3 +109,52 @@ ProFile *ProFileReader::proFileFor(const QString &name)
|
|||||||
{
|
{
|
||||||
return m_includeFiles.value(name);
|
return m_includeFiles.value(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ProFileCacheManager *ProFileCacheManager::s_instance = 0;
|
||||||
|
|
||||||
|
ProFileCacheManager::ProFileCacheManager(QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_cache(0)
|
||||||
|
{
|
||||||
|
s_instance = this;
|
||||||
|
m_timer.setSingleShot(true);
|
||||||
|
m_timer.setInterval(5000);
|
||||||
|
connect(&m_timer, SIGNAL(timeout()), SLOT(clear()));
|
||||||
|
}
|
||||||
|
|
||||||
|
ProFileCacheManager::~ProFileCacheManager()
|
||||||
|
{
|
||||||
|
s_instance = 0;
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
ProFileCache *ProFileCacheManager::cache()
|
||||||
|
{
|
||||||
|
m_timer.start();
|
||||||
|
if (!m_cache)
|
||||||
|
m_cache = new ProFileCache;
|
||||||
|
return m_cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProFileCacheManager::clear()
|
||||||
|
{
|
||||||
|
// Just deleting the cache will be safe as long as the sequence of
|
||||||
|
// obtaining a cache pointer and using it is atomic as far as the main
|
||||||
|
// loop is concerned. Use a shared pointer once this is not true anymore.
|
||||||
|
delete m_cache;
|
||||||
|
m_cache = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProFileCacheManager::discardFiles(const QString &prefix)
|
||||||
|
{
|
||||||
|
if (m_cache)
|
||||||
|
m_cache->discardFiles(prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProFileCacheManager::discardFile(const QString &fileName)
|
||||||
|
{
|
||||||
|
if (m_cache)
|
||||||
|
m_cache->discardFile(fileName);
|
||||||
|
}
|
||||||
|
@@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
#include <QtCore/QMap>
|
#include <QtCore/QMap>
|
||||||
|
#include <QtCore/QTimer>
|
||||||
|
|
||||||
namespace Qt4ProjectManager {
|
namespace Qt4ProjectManager {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
@@ -56,8 +57,7 @@ signals:
|
|||||||
void errorFound(const QString &error);
|
void errorFound(const QString &error);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual ProFile *parsedProFile(const QString &fileName);
|
virtual void aboutToEval(ProFile *proFile);
|
||||||
virtual void releaseParsedProFile(ProFile *proFile);
|
|
||||||
virtual void logMessage(const QString &msg);
|
virtual void logMessage(const QString &msg);
|
||||||
virtual void fileMessage(const QString &msg);
|
virtual void fileMessage(const QString &msg);
|
||||||
virtual void errorMessage(const QString &msg);
|
virtual void errorMessage(const QString &msg);
|
||||||
@@ -67,6 +67,28 @@ private:
|
|||||||
QList<ProFile *> m_proFiles;
|
QList<ProFile *> m_proFiles;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ProFileCacheManager : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
static ProFileCacheManager *instance() { return s_instance; }
|
||||||
|
ProFileCache *cache();
|
||||||
|
void discardFiles(const QString &prefix);
|
||||||
|
void discardFile(const QString &fileName);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ProFileCacheManager(QObject *parent);
|
||||||
|
~ProFileCacheManager();
|
||||||
|
Q_SLOT void clear();
|
||||||
|
QTimer m_timer;
|
||||||
|
ProFileCache *m_cache;
|
||||||
|
|
||||||
|
static ProFileCacheManager *s_instance;
|
||||||
|
|
||||||
|
friend class Qt4ProjectManagerPlugin;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace Qt4ProjectManager
|
} // namespace Qt4ProjectManager
|
||||||
|
|
||||||
|
@@ -115,6 +115,7 @@ Qt4PriFileNode::Qt4PriFileNode(Qt4Project *project, Qt4ProFileNode* qt4ProFileNo
|
|||||||
|
|
||||||
void Qt4PriFileNode::scheduleUpdate()
|
void Qt4PriFileNode::scheduleUpdate()
|
||||||
{
|
{
|
||||||
|
ProFileCacheManager::instance()->discardFile(m_projectFilePath);
|
||||||
m_qt4ProFileNode->scheduleUpdate();
|
m_qt4ProFileNode->scheduleUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -867,6 +867,8 @@ ProFileReader *Qt4Project::createProFileReader(Qt4ProFileNode *qt4ProFileNode)
|
|||||||
if (version->isValid())
|
if (version->isValid())
|
||||||
m_proFileOption->properties = version->versionInfo();
|
m_proFileOption->properties = version->versionInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_proFileOption->cache = ProFileCacheManager::instance()->cache();
|
||||||
}
|
}
|
||||||
++m_proFileOptionRefCnt;
|
++m_proFileOptionRefCnt;
|
||||||
|
|
||||||
@@ -883,6 +885,11 @@ void Qt4Project::destroyProFileReader(ProFileReader *reader)
|
|||||||
{
|
{
|
||||||
delete reader;
|
delete reader;
|
||||||
if (!--m_proFileOptionRefCnt) {
|
if (!--m_proFileOptionRefCnt) {
|
||||||
|
QString dir = QFileInfo(m_fileInfo->fileName()).absolutePath();
|
||||||
|
if (!dir.endsWith(QLatin1Char('/')))
|
||||||
|
dir += QLatin1Char('/');
|
||||||
|
m_proFileOption->cache->discardFiles(dir);
|
||||||
|
|
||||||
delete m_proFileOption;
|
delete m_proFileOption;
|
||||||
m_proFileOption = 0;
|
m_proFileOption = 0;
|
||||||
}
|
}
|
||||||
@@ -1040,8 +1047,10 @@ void Qt4Project::notifyChanged(const QString &name)
|
|||||||
if (files(Qt4Project::ExcludeGeneratedFiles).contains(name)) {
|
if (files(Qt4Project::ExcludeGeneratedFiles).contains(name)) {
|
||||||
QList<Qt4ProFileNode *> list;
|
QList<Qt4ProFileNode *> list;
|
||||||
findProFile(name, rootProjectNode(), list);
|
findProFile(name, rootProjectNode(), list);
|
||||||
foreach(Qt4ProFileNode *node, list)
|
foreach(Qt4ProFileNode *node, list) {
|
||||||
|
ProFileCacheManager::instance()->discardFile(name);
|
||||||
node->update();
|
node->update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -169,6 +169,8 @@ bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString *
|
|||||||
addAutoReleasedObject(MaemoManager::instance());
|
addAutoReleasedObject(MaemoManager::instance());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
new ProFileCacheManager(this);
|
||||||
|
|
||||||
// TODO reenable
|
// TODO reenable
|
||||||
//m_embeddedPropertiesPage = new EmbeddedPropertiesPage;
|
//m_embeddedPropertiesPage = new EmbeddedPropertiesPage;
|
||||||
//addObject(m_embeddedPropertiesPage);
|
//addObject(m_embeddedPropertiesPage);
|
||||||
|
@@ -1207,6 +1207,7 @@ void QtVersion::updateToolChainAndMkspec() const
|
|||||||
|
|
||||||
ProFileOption option;
|
ProFileOption option;
|
||||||
option.properties = versionInfo();
|
option.properties = versionInfo();
|
||||||
|
option.cache = ProFileCacheManager::instance()->cache();
|
||||||
ProFileReader *reader = new ProFileReader(&option);
|
ProFileReader *reader = new ProFileReader(&option);
|
||||||
reader->setCumulative(false);
|
reader->setCumulative(false);
|
||||||
reader->setParsePreAndPostFiles(false);
|
reader->setParsePreAndPostFiles(false);
|
||||||
|
@@ -83,13 +83,61 @@ static void clearFunctions(ProFileEvaluator::FunctionDefs *defs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// ProFileCache
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ProFileCache::~ProFileCache()
|
||||||
|
{
|
||||||
|
foreach (ProFile *pro, parsed_files)
|
||||||
|
pro->deref();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProFileCache::discardFile(const QString &fileName)
|
||||||
|
{
|
||||||
|
QHash<QString, ProFile *>::Iterator it = parsed_files.find(fileName);
|
||||||
|
if (it != parsed_files.end()) {
|
||||||
|
it.value()->deref();
|
||||||
|
parsed_files.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProFileCache::discardFiles(const QString &prefix)
|
||||||
|
{
|
||||||
|
QHash<QString, ProFile *>::Iterator
|
||||||
|
it = parsed_files.begin(),
|
||||||
|
end = parsed_files.end();
|
||||||
|
while (it != end)
|
||||||
|
if (it.key().startsWith(prefix)) {
|
||||||
|
it.value()->deref();
|
||||||
|
it = parsed_files.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProFileCache::addFile(ProFile *pro)
|
||||||
|
{
|
||||||
|
parsed_files[pro->fileName()] = pro;
|
||||||
|
pro->ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
ProFile *ProFileCache::getFile(const QString &fileName)
|
||||||
|
{
|
||||||
|
ProFile *pro = parsed_files.value(fileName);
|
||||||
|
if (pro)
|
||||||
|
pro->ref();
|
||||||
|
return pro;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// ProFileOption
|
// ProFileOption
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// ProFileOption
|
|
||||||
ProFileOption::ProFileOption()
|
ProFileOption::ProFileOption()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
@@ -112,6 +160,8 @@ ProFileOption::ProFileOption()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
field_sep = QLatin1String(" ");
|
field_sep = QLatin1String(" ");
|
||||||
|
|
||||||
|
cache = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProFileOption::~ProFileOption()
|
ProFileOption::~ProFileOption()
|
||||||
@@ -199,6 +249,8 @@ public:
|
|||||||
ProFile *currentProFile() const;
|
ProFile *currentProFile() const;
|
||||||
|
|
||||||
ProItem::ProItemReturn evaluateConditionalFunction(const QString &function, const QString &arguments);
|
ProItem::ProItemReturn evaluateConditionalFunction(const QString &function, const QString &arguments);
|
||||||
|
ProFile *parsedProFile(const QString &fileName, bool cache,
|
||||||
|
const QString &contents = QString());
|
||||||
bool evaluateFile(const QString &fileName);
|
bool evaluateFile(const QString &fileName);
|
||||||
bool evaluateFeatureFile(const QString &fileName,
|
bool evaluateFeatureFile(const QString &fileName,
|
||||||
QHash<QString, QStringList> *values = 0, FunctionDefs *defs = 0);
|
QHash<QString, QStringList> *values = 0, FunctionDefs *defs = 0);
|
||||||
@@ -2776,20 +2828,20 @@ QStringList ProFileEvaluator::Private::values(const QString &variableName, const
|
|||||||
return values(variableName, m_filevaluemap[pro], pro);
|
return values(variableName, m_filevaluemap[pro], pro);
|
||||||
}
|
}
|
||||||
|
|
||||||
// virtual
|
ProFile *ProFileEvaluator::Private::parsedProFile(const QString &fileName, bool cache,
|
||||||
ProFile *ProFileEvaluator::parsedProFile(const QString &fileName)
|
const QString &contents)
|
||||||
{
|
{
|
||||||
ProFile *pro = new ProFile(fileName);
|
ProFile *pro;
|
||||||
if (d->read(pro))
|
if (!m_option->cache || !(pro = m_option->cache->getFile(fileName))) {
|
||||||
return pro;
|
pro = new ProFile(fileName);
|
||||||
delete pro;
|
if (!(contents.isNull() ? read(pro) : read(pro, contents))) {
|
||||||
return 0;
|
delete pro;
|
||||||
}
|
return 0;
|
||||||
|
}
|
||||||
// virtual
|
if (m_option->cache && cache)
|
||||||
void ProFileEvaluator::releaseParsedProFile(ProFile *proFile)
|
m_option->cache->addFile(pro);
|
||||||
{
|
}
|
||||||
delete proFile;
|
return pro;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProFileEvaluator::Private::evaluateFile(const QString &fileName)
|
bool ProFileEvaluator::Private::evaluateFile(const QString &fileName)
|
||||||
@@ -2803,10 +2855,10 @@ bool ProFileEvaluator::Private::evaluateFile(const QString &fileName)
|
|||||||
errorMessage(format("circular inclusion of %1").arg(fn));
|
errorMessage(format("circular inclusion of %1").arg(fn));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ProFile *pro = q->parsedProFile(fn);
|
if (ProFile *pro = parsedProFile(fn, true)) {
|
||||||
if (pro) {
|
q->aboutToEval(pro);
|
||||||
bool ok = (pro->Accept(this) == ProItem::ReturnTrue);
|
bool ok = (pro->Accept(this) == ProItem::ReturnTrue);
|
||||||
q->releaseParsedProFile(pro);
|
pro->deref();
|
||||||
return ok;
|
return ok;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@@ -2857,12 +2909,13 @@ bool ProFileEvaluator::Private::evaluateFeatureFile(
|
|||||||
bool cumulative = m_cumulative;
|
bool cumulative = m_cumulative;
|
||||||
m_cumulative = false;
|
m_cumulative = false;
|
||||||
|
|
||||||
// Don't use evaluateFile() here to avoid the virtual parsedProFile().
|
// Don't use evaluateFile() here to avoid calling aboutToEval().
|
||||||
// The path is fully normalized already.
|
// The path is fully normalized already.
|
||||||
ProFile pro(fn);
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
if (read(&pro))
|
if (ProFile *pro = parsedProFile(fn, true)) {
|
||||||
ok = (pro.Accept(this) == ProItem::ReturnTrue);
|
ok = (pro->Accept(this) == ProItem::ReturnTrue);
|
||||||
|
pro->deref();
|
||||||
|
}
|
||||||
|
|
||||||
m_cumulative = cumulative;
|
m_cumulative = cumulative;
|
||||||
return ok;
|
return ok;
|
||||||
@@ -3019,14 +3072,9 @@ ProFileEvaluator::TemplateType ProFileEvaluator::templateType()
|
|||||||
return TT_Unknown;
|
return TT_Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProFileEvaluator::queryProFile(ProFile *pro)
|
ProFile *ProFileEvaluator::parsedProFile(const QString &fileName, const QString &contents)
|
||||||
{
|
{
|
||||||
return d->read(pro);
|
return d->parsedProFile(fileName, false, contents);
|
||||||
}
|
|
||||||
|
|
||||||
bool ProFileEvaluator::queryProFile(ProFile *pro, const QString &content)
|
|
||||||
{
|
|
||||||
return d->read(pro, content);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProFileEvaluator::accept(ProFile *pro)
|
bool ProFileEvaluator::accept(ProFile *pro)
|
||||||
@@ -3039,6 +3087,10 @@ QString ProFileEvaluator::propertyValue(const QString &name) const
|
|||||||
return d->propertyValue(name);
|
return d->propertyValue(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProFileEvaluator::aboutToEval(ProFile *)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void ProFileEvaluator::logMessage(const QString &message)
|
void ProFileEvaluator::logMessage(const QString &message)
|
||||||
{
|
{
|
||||||
qWarning("%s", qPrintable(message));
|
qWarning("%s", qPrintable(message));
|
||||||
|
@@ -42,6 +42,22 @@ QT_BEGIN_NAMESPACE
|
|||||||
|
|
||||||
class ProFileOption;
|
class ProFileOption;
|
||||||
|
|
||||||
|
class ProFileCache
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ProFileCache() {}
|
||||||
|
~ProFileCache();
|
||||||
|
|
||||||
|
void addFile(ProFile *pro);
|
||||||
|
ProFile *getFile(const QString &fileName);
|
||||||
|
|
||||||
|
void discardFile(const QString &fileName);
|
||||||
|
void discardFiles(const QString &prefix);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QHash<QString, ProFile *> parsed_files;
|
||||||
|
};
|
||||||
|
|
||||||
class ProFileEvaluator
|
class ProFileEvaluator
|
||||||
{
|
{
|
||||||
class Private;
|
class Private;
|
||||||
@@ -74,8 +90,8 @@ public:
|
|||||||
void setConfigCommandLineArguments(const QStringList &addUserConfigCmdArgs, const QStringList &removeUserConfigCmdArgs);
|
void setConfigCommandLineArguments(const QStringList &addUserConfigCmdArgs, const QStringList &removeUserConfigCmdArgs);
|
||||||
void setParsePreAndPostFiles(bool on); // Default is true
|
void setParsePreAndPostFiles(bool on); // Default is true
|
||||||
|
|
||||||
bool queryProFile(ProFile *pro);
|
// If contents is non-null, it will be used instead of the file's actual content
|
||||||
bool queryProFile(ProFile *pro, const QString &content); // the same as above but the content is read from "content" string, not from filesystem
|
ProFile *parsedProFile(const QString &fileName, const QString &contents = QString());
|
||||||
bool accept(ProFile *pro);
|
bool accept(ProFile *pro);
|
||||||
|
|
||||||
QStringList values(const QString &variableName) const;
|
QStringList values(const QString &variableName) const;
|
||||||
@@ -87,8 +103,7 @@ public:
|
|||||||
QString propertyValue(const QString &val) const;
|
QString propertyValue(const QString &val) const;
|
||||||
|
|
||||||
// for our descendents
|
// for our descendents
|
||||||
virtual ProFile *parsedProFile(const QString &fileName);
|
virtual void aboutToEval(ProFile *proFile); // only .pri, but not .prf. or .pro
|
||||||
virtual void releaseParsedProFile(ProFile *proFile);
|
|
||||||
virtual void logMessage(const QString &msg);
|
virtual void logMessage(const QString &msg);
|
||||||
virtual void errorMessage(const QString &msg); // .pro parse errors
|
virtual void errorMessage(const QString &msg); // .pro parse errors
|
||||||
virtual void fileMessage(const QString &msg); // error() and message() from .pro file
|
virtual void fileMessage(const QString &msg); // error() and message() from .pro file
|
||||||
@@ -130,6 +145,7 @@ struct ProFileOption
|
|||||||
QString qmakespec;
|
QString qmakespec;
|
||||||
QString cachefile;
|
QString cachefile;
|
||||||
QHash<QString, QString> properties;
|
QHash<QString, QString> properties;
|
||||||
|
ProFileCache *cache;
|
||||||
|
|
||||||
enum TARG_MODE { TARG_UNIX_MODE, TARG_WIN_MODE, TARG_MACX_MODE, TARG_MAC9_MODE, TARG_QNX6_MODE };
|
enum TARG_MODE { TARG_UNIX_MODE, TARG_WIN_MODE, TARG_MACX_MODE, TARG_MAC9_MODE, TARG_QNX6_MODE };
|
||||||
TARG_MODE target_mode;
|
TARG_MODE target_mode;
|
||||||
|
Reference in New Issue
Block a user