summaryrefslogtreecommitdiff
path: root/src/plugins/cpptools/cppmodelmanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/cpptools/cppmodelmanager.cpp')
-rw-r--r--src/plugins/cpptools/cppmodelmanager.cpp556
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 &macroName,
+ const QByteArray &macroText);
+ virtual void startExpandingMacro(unsigned offset,
+ const Macro &macro,
+ const QByteArray &originalText);
+ virtual void stopExpandingMacro(unsigned offset, const Macro &macro);
+ 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 &macroName, const QByteArray &macroText)
- {
- if (! m_currentDoc)
- return;
+ //qDebug() << "**** file" << fileName << "not found!";
+ return QByteArray();
+}
- m_currentDoc->appendMacro(macroName, macroText);
- }
+void CppPreprocessor::macroAdded(const QByteArray &macroName, const QByteArray &macroText)
+{
+ 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,