diff options
author | dt <qtc-commiter@nokia.com> | 2008-12-08 12:47:15 +0100 |
---|---|---|
committer | dt <qtc-commiter@nokia.com> | 2008-12-08 12:47:15 +0100 |
commit | 942363913cd907097703ecbbe4a9da98df9613d9 (patch) | |
tree | 04f2068b7588f0d084a938ea0e04da6e18ada5c2 /src/plugins/cpptools/cppmodelmanager.cpp | |
parent | 83d5461c7f083277ee5948b6b4bbbd93b63415dc (diff) | |
parent | f6fbb274ae715c05fcdee61cba5395b4fd4814b9 (diff) | |
download | qt-creator-942363913cd907097703ecbbe4a9da98df9613d9.tar.gz |
Merge branch '0.9.1-beta' of git@scm.dev.nokia.troll.no:creator/mainline into 0.9.1-beta
Conflicts:
src/plugins/qt4projectmanager/qtversionmanager.cpp
Diffstat (limited to 'src/plugins/cpptools/cppmodelmanager.cpp')
-rw-r--r-- | src/plugins/cpptools/cppmodelmanager.cpp | 556 |
1 files changed, 315 insertions, 241 deletions
diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 042b93cc74..af885de622 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -31,7 +31,6 @@ ** ***************************************************************************/ -#define _SCL_SECURE_NO_WARNINGS 1 #include "pp.h" #include "cppmodelmanager.h" @@ -66,14 +65,14 @@ #include <Token.h> #include <QPlainTextEdit> +#include <QMutexLocker> #include <QTime> #include <QDebug> +using namespace CppTools; +using namespace CppTools::Internal; using namespace CPlusPlus; -namespace CppTools { -namespace Internal { - static const char pp_configuration_file[] = "<configuration>"; static const char pp_configuration[] = @@ -105,299 +104,328 @@ static const char pp_configuration[] = "#define __declspec(a)\n" "#define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method\n"; -class CppPreprocessor: public rpp::Client +namespace CppTools { +namespace Internal { + +class CppPreprocessor: public CPlusPlus::Client { public: - CppPreprocessor(QPointer<CppModelManager> modelManager) - : m_modelManager(modelManager), - m_documents(modelManager->documents()), - m_proc(this, env) - { } + CppPreprocessor(QPointer<CppModelManager> modelManager); - void setWorkingCopy(const QMap<QString, QByteArray> &workingCopy) - { m_workingCopy = workingCopy; } + void setWorkingCopy(const QMap<QString, QByteArray> &workingCopy); + void setIncludePaths(const QStringList &includePaths); + void setFrameworkPaths(const QStringList &frameworkPaths); + void addIncludePath(const QString &path); + void setProjectFiles(const QStringList &files); + void run(QString &fileName); + void operator()(QString &fileName); - void setIncludePaths(const QStringList &includePaths) - { m_includePaths = includePaths; } +protected: + CPlusPlus::Document::Ptr switchDocument(CPlusPlus::Document::Ptr doc); - void setFrameworkPaths(const QStringList &frameworkPaths) - { m_frameworkPaths = frameworkPaths; } + bool includeFile(const QString &absoluteFilePath, QByteArray *result); + QByteArray tryIncludeFile(QString &fileName, IncludeType type); - void addIncludePath(const QString &path) - { m_includePaths.append(path); } + void mergeEnvironment(CPlusPlus::Document::Ptr doc); + void mergeEnvironment(CPlusPlus::Document::Ptr doc, QSet<QString> *processed); - void setProjectFiles(const QStringList &files) - { m_projectFiles = files; } + virtual void macroAdded(const QByteArray ¯oName, + const QByteArray ¯oText); + virtual void startExpandingMacro(unsigned offset, + const Macro ¯o, + const QByteArray &originalText); + virtual void stopExpandingMacro(unsigned offset, const Macro ¯o); + virtual void startSkippingBlocks(unsigned offset); + virtual void stopSkippingBlocks(unsigned offset); + virtual void sourceNeeded(QString &fileName, IncludeType type); - void run(QString &fileName) - { sourceNeeded(fileName, IncludeGlobal); } +private: + QPointer<CppModelManager> m_modelManager; + CppModelManager::DocumentTable m_documents; + Environment env; + pp m_proc; + QStringList m_includePaths; + QStringList m_systemIncludePaths; + QMap<QString, QByteArray> m_workingCopy; + QStringList m_projectFiles; + QStringList m_frameworkPaths; + QSet<QString> m_included; + CPlusPlus::Document::Ptr m_currentDoc; +}; - void operator()(QString &fileName) - { run(fileName); } +} // namespace Internal +} // namespace CppTools -protected: - bool includeFile(const QString &absoluteFilePath, QByteArray *result) - { - if (absoluteFilePath.isEmpty() || m_included.contains(absoluteFilePath)) { - return true; - } +CppPreprocessor::CppPreprocessor(QPointer<CppModelManager> modelManager) + : m_modelManager(modelManager), + m_documents(modelManager->documents()), + m_proc(this, env) +{ } - if (m_workingCopy.contains(absoluteFilePath)) { - m_included.insert(absoluteFilePath); - *result = m_workingCopy.value(absoluteFilePath); - return true; - } +void CppPreprocessor::setWorkingCopy(const QMap<QString, QByteArray> &workingCopy) +{ m_workingCopy = workingCopy; } - QFileInfo fileInfo(absoluteFilePath); - if (! fileInfo.isFile()) - return false; - - QFile file(absoluteFilePath); - if (file.open(QFile::ReadOnly)) { - m_included.insert(absoluteFilePath); - QTextStream stream(&file); - const QString contents = stream.readAll(); - *result = contents.toUtf8(); - file.close(); - return true; - } +void CppPreprocessor::setIncludePaths(const QStringList &includePaths) +{ m_includePaths = includePaths; } + +void CppPreprocessor::setFrameworkPaths(const QStringList &frameworkPaths) +{ m_frameworkPaths = frameworkPaths; } + +void CppPreprocessor::addIncludePath(const QString &path) +{ m_includePaths.append(path); } + +void CppPreprocessor::setProjectFiles(const QStringList &files) +{ m_projectFiles = files; } + +void CppPreprocessor::run(QString &fileName) +{ sourceNeeded(fileName, IncludeGlobal); } + +void CppPreprocessor::operator()(QString &fileName) +{ run(fileName); } + +bool CppPreprocessor::includeFile(const QString &absoluteFilePath, QByteArray *result) +{ + if (absoluteFilePath.isEmpty() || m_included.contains(absoluteFilePath)) { + return true; + } + + if (m_workingCopy.contains(absoluteFilePath)) { + m_included.insert(absoluteFilePath); + *result = m_workingCopy.value(absoluteFilePath); + return true; + } + QFileInfo fileInfo(absoluteFilePath); + if (! fileInfo.isFile()) return false; + + QFile file(absoluteFilePath); + if (file.open(QFile::ReadOnly)) { + m_included.insert(absoluteFilePath); + QTextStream stream(&file); + const QString contents = stream.readAll(); + *result = contents.toUtf8(); + file.close(); + return true; } - QByteArray tryIncludeFile(QString &fileName, IncludeType type) - { - QFileInfo fileInfo(fileName); - if (fileName == QLatin1String(pp_configuration_file) || fileInfo.isAbsolute()) { - QByteArray contents; - includeFile(fileName, &contents); + return false; +} + +QByteArray CppPreprocessor::tryIncludeFile(QString &fileName, IncludeType type) +{ + QFileInfo fileInfo(fileName); + if (fileName == QLatin1String(pp_configuration_file) || fileInfo.isAbsolute()) { + QByteArray contents; + includeFile(fileName, &contents); + return contents; + } + + if (type == IncludeLocal && m_currentDoc) { + QFileInfo currentFileInfo(m_currentDoc->fileName()); + QString path = currentFileInfo.absolutePath(); + path += QLatin1Char('/'); + path += fileName; + path = QDir::cleanPath(path); + QByteArray contents; + if (includeFile(path, &contents)) { + fileName = path; return contents; } + } - if (type == IncludeLocal && m_currentDoc) { - QFileInfo currentFileInfo(m_currentDoc->fileName()); - QString path = currentFileInfo.absolutePath(); - path += QLatin1Char('/'); - path += fileName; - path = QDir::cleanPath(path); - QByteArray contents; - if (includeFile(path, &contents)) { - fileName = path; - return contents; - } + foreach (const QString &includePath, m_includePaths) { + QString path = includePath; + path += QLatin1Char('/'); + path += fileName; + path = QDir::cleanPath(path); + QByteArray contents; + if (includeFile(path, &contents)) { + fileName = path; + return contents; } + } - foreach (const QString &includePath, m_includePaths) { - QString path = includePath; - path += QLatin1Char('/'); - path += fileName; - path = QDir::cleanPath(path); - QByteArray contents; - if (includeFile(path, &contents)) { - fileName = path; - return contents; - } + // look in the system include paths + foreach (const QString &includePath, m_systemIncludePaths) { + QString path = includePath; + path += QLatin1Char('/'); + path += fileName; + path = QDir::cleanPath(path); + QByteArray contents; + if (includeFile(path, &contents)) { + fileName = path; + return contents; } + } + + int index = fileName.indexOf(QLatin1Char('/')); + if (index != -1) { + QString frameworkName = fileName.left(index); + QString name = fileName.mid(index + 1); - // look in the system include paths - foreach (const QString &includePath, m_systemIncludePaths) { - QString path = includePath; + foreach (const QString &frameworkPath, m_frameworkPaths) { + QString path = frameworkPath; path += QLatin1Char('/'); - path += fileName; - path = QDir::cleanPath(path); + path += frameworkName; + path += QLatin1String(".framework/Headers/"); + path += name; QByteArray contents; if (includeFile(path, &contents)) { fileName = path; return contents; } } + } - int index = fileName.indexOf(QLatin1Char('/')); - if (index != -1) { - QString frameworkName = fileName.left(index); - QString name = fileName.mid(index + 1); - - foreach (const QString &frameworkPath, m_frameworkPaths) { - QString path = frameworkPath; - path += QLatin1Char('/'); - path += frameworkName; - path += QLatin1String(".framework/Headers/"); - path += name; - QByteArray contents; - if (includeFile(path, &contents)) { - fileName = path; - return contents; - } - } - } - - QString path = fileName; - if (path.at(0) != QLatin1Char('/')) - path.prepend(QLatin1Char('/')); + QString path = fileName; + if (path.at(0) != QLatin1Char('/')) + path.prepend(QLatin1Char('/')); - foreach (const QString &projectFile, m_projectFiles) { - if (projectFile.endsWith(path)) { - fileName = projectFile; - QByteArray contents; - includeFile(fileName, &contents); - return contents; - } + foreach (const QString &projectFile, m_projectFiles) { + if (projectFile.endsWith(path)) { + fileName = projectFile; + QByteArray contents; + includeFile(fileName, &contents); + return contents; } - - //qDebug() << "**** file" << fileName << "not found!"; - return QByteArray(); } - virtual void macroAdded(const QByteArray ¯oName, const QByteArray ¯oText) - { - if (! m_currentDoc) - return; + //qDebug() << "**** file" << fileName << "not found!"; + return QByteArray(); +} - m_currentDoc->appendMacro(macroName, macroText); - } +void CppPreprocessor::macroAdded(const QByteArray ¯oName, const QByteArray ¯oText) +{ + if (! m_currentDoc) + return; - virtual void startExpandingMacro(unsigned offset, - const rpp::Macro &, - const QByteArray &originalText) - { - if (! m_currentDoc) - return; - - //qDebug() << "start expanding:" << macro.name << "text:" << originalText; - m_currentDoc->addMacroUse(offset, originalText.length()); - } + m_currentDoc->appendMacro(macroName, macroText); +} - virtual void stopExpandingMacro(unsigned, const rpp::Macro &) - { - if (! m_currentDoc) - return; +void CppPreprocessor::startExpandingMacro(unsigned offset, + const Macro &, + const QByteArray &originalText) +{ + if (! m_currentDoc) + return; - //qDebug() << "stop expanding:" << macro.name; - } + //qDebug() << "start expanding:" << macro.name << "text:" << originalText; + m_currentDoc->addMacroUse(offset, originalText.length()); +} - void mergeEnvironment(Document::Ptr doc) - { - QSet<QString> processed; - mergeEnvironment(doc, &processed); - } +void CppPreprocessor::stopExpandingMacro(unsigned, const Macro &) +{ + if (! m_currentDoc) + return; - void mergeEnvironment(Document::Ptr doc, QSet<QString> *processed) - { - if (! doc) - return; + //qDebug() << "stop expanding:" << macro.name; +} - const QString fn = doc->fileName(); +void CppPreprocessor::mergeEnvironment(Document::Ptr doc) +{ + QSet<QString> processed; + mergeEnvironment(doc, &processed); +} - if (processed->contains(fn)) - return; +void CppPreprocessor::mergeEnvironment(Document::Ptr doc, QSet<QString> *processed) +{ + if (! doc) + return; - processed->insert(fn); + const QString fn = doc->fileName(); - foreach (QString includedFile, doc->includedFiles()) - mergeEnvironment(m_documents.value(includedFile), processed); + if (processed->contains(fn)) + return; - const QByteArray macros = doc->definedMacros(); - QByteArray localFileName = doc->fileName().toUtf8(); + processed->insert(fn); - QByteArray dummy; - m_proc(localFileName, macros, &dummy); - } + foreach (QString includedFile, doc->includedFiles()) + mergeEnvironment(m_documents.value(includedFile), processed); - virtual void startSkippingBlocks(unsigned offset) - { - //qDebug() << "start skipping blocks:" << offset; - if (m_currentDoc) - m_currentDoc->startSkippingBlocks(offset); - } + const QByteArray macros = doc->definedMacros(); + QByteArray localFileName = doc->fileName().toUtf8(); - virtual void stopSkippingBlocks(unsigned offset) - { - //qDebug() << "stop skipping blocks:" << offset; - if (m_currentDoc) - m_currentDoc->stopSkippingBlocks(offset); - } + QByteArray dummy; + m_proc(localFileName, macros, &dummy); +} - virtual void sourceNeeded(QString &fileName, IncludeType type) - { - if (fileName.isEmpty()) - return; - - QByteArray contents = tryIncludeFile(fileName, type); - - if (m_currentDoc) { - m_currentDoc->addIncludeFile(fileName); - if (contents.isEmpty() && ! QFileInfo(fileName).isAbsolute()) { - QString msg; - msg += fileName; - msg += QLatin1String(": No such file or directory"); - Document::DiagnosticMessage d(Document::DiagnosticMessage::Warning, - m_currentDoc->fileName(), - env.currentLine, /*column = */ 0, - msg); - m_currentDoc->addDiagnosticMessage(d); - //qWarning() << "file not found:" << fileName << m_currentDoc->fileName() << env.current_line; - } +void CppPreprocessor::startSkippingBlocks(unsigned offset) +{ + //qDebug() << "start skipping blocks:" << offset; + if (m_currentDoc) + m_currentDoc->startSkippingBlocks(offset); +} + +void CppPreprocessor::stopSkippingBlocks(unsigned offset) +{ + //qDebug() << "stop skipping blocks:" << offset; + if (m_currentDoc) + m_currentDoc->stopSkippingBlocks(offset); +} + +void CppPreprocessor::sourceNeeded(QString &fileName, IncludeType type) +{ + if (fileName.isEmpty()) + return; + + QByteArray contents = tryIncludeFile(fileName, type); + + if (m_currentDoc) { + m_currentDoc->addIncludeFile(fileName); + if (contents.isEmpty() && ! QFileInfo(fileName).isAbsolute()) { + QString msg; + msg += fileName; + msg += QLatin1String(": No such file or directory"); + Document::DiagnosticMessage d(Document::DiagnosticMessage::Warning, + m_currentDoc->fileName(), + env.currentLine, /*column = */ 0, + msg); + m_currentDoc->addDiagnosticMessage(d); + //qWarning() << "file not found:" << fileName << m_currentDoc->fileName() << env.current_line; } + } - if (! contents.isEmpty()) { - Document::Ptr cachedDoc = m_documents.value(fileName); - if (cachedDoc && m_currentDoc) { - mergeEnvironment(cachedDoc); - } else { - Document::Ptr previousDoc = switchDocument(Document::create(fileName)); + if (! contents.isEmpty()) { + Document::Ptr cachedDoc = m_documents.value(fileName); + if (cachedDoc && m_currentDoc) { + mergeEnvironment(cachedDoc); + } else { + Document::Ptr previousDoc = switchDocument(Document::create(fileName)); - const QByteArray previousFile = env.current_file; - const unsigned previousLine = env.currentLine; + const QByteArray previousFile = env.current_file; + const unsigned previousLine = env.currentLine; - env.current_file = QByteArray(m_currentDoc->translationUnit()->fileName(), - m_currentDoc->translationUnit()->fileNameLength()); + env.current_file = QByteArray(m_currentDoc->translationUnit()->fileName(), + m_currentDoc->translationUnit()->fileNameLength()); - QByteArray preprocessedCode; - m_proc(contents, &preprocessedCode); - //qDebug() << preprocessedCode; + QByteArray preprocessedCode; + m_proc(contents, &preprocessedCode); + //qDebug() << preprocessedCode; - env.current_file = previousFile; - env.currentLine = previousLine; + env.current_file = previousFile; + env.currentLine = previousLine; - m_currentDoc->setSource(preprocessedCode); - m_currentDoc->parse(); - m_currentDoc->check(); - m_currentDoc->releaseTranslationUnit(); // release the AST and the token stream. + m_currentDoc->setSource(preprocessedCode); + m_currentDoc->parse(); + m_currentDoc->check(); + m_currentDoc->releaseTranslationUnit(); // release the AST and the token stream. - if (m_modelManager) - m_modelManager->emitDocumentUpdated(m_currentDoc); - (void) switchDocument(previousDoc); - } + if (m_modelManager) + m_modelManager->emitDocumentUpdated(m_currentDoc); + (void) switchDocument(previousDoc); } } +} - Document::Ptr switchDocument(Document::Ptr doc) - { - Document::Ptr previousDoc = m_currentDoc; - m_currentDoc = doc; - return previousDoc; - } - -private: - QPointer<CppModelManager> m_modelManager; - CppModelManager::DocumentTable m_documents; - rpp::Environment env; - rpp::pp m_proc; - QStringList m_includePaths; - QStringList m_systemIncludePaths; - QMap<QString, QByteArray> m_workingCopy; - QStringList m_projectFiles; - QStringList m_frameworkPaths; - QSet<QString> m_included; - Document::Ptr m_currentDoc; -}; - -} // namespace Internal -} // namespace CppTools +Document::Ptr CppPreprocessor::switchDocument(Document::Ptr doc) +{ + Document::Ptr previousDoc = m_currentDoc; + m_currentDoc = doc; + return previousDoc; +} -using namespace CppTools; -using namespace CppTools::Internal; /*! \class CppTools::CppModelManager @@ -450,12 +478,25 @@ CppModelManager::CppModelManager(QObject *parent) : CppModelManager::~CppModelManager() { } -Document::Ptr CppModelManager::document(const QString &fileName) +Document::Ptr CppModelManager::document(const QString &fileName) const { return m_documents.value(fileName); } -CppModelManager::DocumentTable CppModelManager::documents() +CppModelManager::DocumentTable CppModelManager::documents() const { return m_documents; } +void CppModelManager::ensureUpdated() +{ + QMutexLocker locker(&mutex); + if (! m_dirty) + return; + + m_projectFiles = updateProjectFiles(); + m_includePaths = updateIncludePaths(); + m_frameworkPaths = updateFrameworkPaths(); + m_definedMacros = updateDefinedMacros(); + m_dirty = false; +} + QStringList CppModelManager::updateProjectFiles() const { QStringList files; @@ -527,8 +568,29 @@ QMap<QString, QByteArray> CppModelManager::buildWorkingCopyList() void CppModelManager::updateSourceFiles(const QStringList &sourceFiles) { (void) refreshSourceFiles(sourceFiles); } -CppModelManager::ProjectInfo *CppModelManager::projectInfo(ProjectExplorer::Project *project) -{ return &m_projects[project]; } +QList<CppModelManager::ProjectInfo> CppModelManager::projectInfos() const +{ + QMutexLocker locker(&mutex); + + return m_projects.values(); +} + +CppModelManager::ProjectInfo CppModelManager::projectInfo(ProjectExplorer::Project *project) const +{ + QMutexLocker locker(&mutex); + + return m_projects.value(project, ProjectInfo(project)); +} + +void CppModelManager::updateProjectInfo(const ProjectInfo &pinfo) +{ + QMutexLocker locker(&mutex); + + if (! pinfo.isValid()) + return; + + m_projects.insert(pinfo.project, pinfo); +} QFuture<void> CppModelManager::refreshSourceFiles(const QStringList &sourceFiles) { @@ -691,13 +753,18 @@ void CppModelManager::onDocumentUpdated(Document::Ptr doc) void CppModelManager::onProjectAdded(ProjectExplorer::Project *) { + QMutexLocker locker(&mutex); m_dirty = true; } void CppModelManager::onAboutToRemoveProject(ProjectExplorer::Project *project) { - m_dirty = true; - m_projects.remove(project); + do { + QMutexLocker locker(&mutex); + m_dirty = true; + m_projects.remove(project); + } while (0); + GC(); } @@ -705,8 +772,15 @@ void CppModelManager::onSessionUnloaded() { if (m_core->progressManager()) { m_core->progressManager()->cancelTasks(CppTools::Constants::TASK_INDEX); - m_dirty = true; } + + do { + QMutexLocker locker(&mutex); + m_projects.clear(); + m_dirty = true; + } while (0); + + GC(); } void CppModelManager::parse(QFutureInterface<void> &future, |