summaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/cpptools/builtinindexingsupport.cpp1
-rw-r--r--src/plugins/cpptools/cppcompletionassist.cpp2
-rw-r--r--src/plugins/cpptools/cppmodelmanager.cpp424
-rw-r--r--src/plugins/cpptools/cppmodelmanager.h76
-rw-r--r--src/plugins/cpptools/cppmodelmanager_test.cpp2
-rw-r--r--src/plugins/cpptools/cpppreprocessor.cpp425
-rw-r--r--src/plugins/cpptools/cpppreprocessor.h91
-rw-r--r--src/plugins/cpptools/cpptools.pro6
-rw-r--r--src/plugins/cpptools/cpptools.qbs4
-rw-r--r--src/plugins/cpptools/cpptoolsplugin.cpp2
-rw-r--r--src/plugins/cpptools/symbolsfindfilter.cpp2
11 files changed, 534 insertions, 501 deletions
diff --git a/src/plugins/cpptools/builtinindexingsupport.cpp b/src/plugins/cpptools/builtinindexingsupport.cpp
index 3def71feeb..e2b4ffb8ee 100644
--- a/src/plugins/cpptools/builtinindexingsupport.cpp
+++ b/src/plugins/cpptools/builtinindexingsupport.cpp
@@ -1,6 +1,7 @@
#include "builtinindexingsupport.h"
#include "cppmodelmanager.h"
+#include "cpppreprocessor.h"
#include "searchsymbols.h"
#include "cpptoolsconstants.h"
#include "cppprojectfile.h"
diff --git a/src/plugins/cpptools/cppcompletionassist.cpp b/src/plugins/cpptools/cppcompletionassist.cpp
index cae9114ef7..e27761f3a9 100644
--- a/src/plugins/cpptools/cppcompletionassist.cpp
+++ b/src/plugins/cpptools/cppcompletionassist.cpp
@@ -28,8 +28,8 @@
****************************************************************************/
#include "cppcompletionassist.h"
-
#include "cppmodelmanager.h"
+#include "cpptoolsconstants.h"
#include "cppdoxygen.h"
#include <coreplugin/icore.h>
diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp
index d09ac81655..26bdd65322 100644
--- a/src/plugins/cpptools/cppmodelmanager.cpp
+++ b/src/plugins/cpptools/cppmodelmanager.cpp
@@ -28,6 +28,8 @@
****************************************************************************/
#include "cppmodelmanager.h"
+#include "cpppreprocessor.h"
+#include "cpptoolsconstants.h"
#include "builtinindexingsupport.h"
#include "cppcompletionassist.h"
@@ -44,7 +46,6 @@
#include <projectexplorer/session.h>
#include <extensionsystem/pluginmanager.h>
-#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
#include <QCoreApplication>
@@ -53,9 +54,11 @@
#include <QTimer>
#include <QTextBlock>
-#include <functional>
+#if defined(QTCREATOR_WITH_DUMP_AST) && defined(Q_CC_GNU)
+#define WITH_AST_DUMP
#include <iostream>
#include <sstream>
+#endif
namespace CppTools {
@@ -96,7 +99,7 @@ using namespace CppTools;
using namespace CppTools::Internal;
using namespace CPlusPlus;
-#if defined(QTCREATOR_WITH_DUMP_AST) && defined(Q_CC_GNU)
+#ifdef WITH_AST_DUMP
#include <cxxabi.h>
@@ -169,421 +172,6 @@ static const char pp_configuration[] =
"#define __inline inline\n"
"#define __forceinline inline\n";
-CppPreprocessor::CppPreprocessor(QPointer<CppModelManager> modelManager, bool dumpFileNameWhileParsing)
- : m_snapshot(modelManager->snapshot()),
- m_modelManager(modelManager),
- m_dumpFileNameWhileParsing(dumpFileNameWhileParsing),
- m_preprocess(this, &m_env),
- m_revision(0)
-{
- m_preprocess.setKeepComments(true);
-}
-
-CppPreprocessor::~CppPreprocessor()
-{ }
-
-void CppPreprocessor::setRevision(unsigned revision)
-{ m_revision = revision; }
-
-void CppPreprocessor::setWorkingCopy(const CppModelManagerInterface::WorkingCopy &workingCopy)
-{ m_workingCopy = workingCopy; }
-
-void CppPreprocessor::setIncludePaths(const QStringList &includePaths)
-{
- m_includePaths.clear();
-
- for (int i = 0; i < includePaths.size(); ++i) {
- const QString &path = includePaths.at(i);
-
- if (Utils::HostOsInfo::isMacHost()) {
- if (i + 1 < includePaths.size() && path.endsWith(QLatin1String(".framework/Headers"))) {
- const QFileInfo pathInfo(path);
- const QFileInfo frameworkFileInfo(pathInfo.path());
- const QString frameworkName = frameworkFileInfo.baseName();
-
- const QFileInfo nextIncludePath = includePaths.at(i + 1);
- if (nextIncludePath.fileName() == frameworkName) {
- // We got a QtXXX.framework/Headers followed by $QTDIR/include/QtXXX.
- // In this case we prefer to include files from $QTDIR/include/QtXXX.
- continue;
- }
- }
- }
- m_includePaths.append(cleanPath(path));
- }
-}
-
-void CppPreprocessor::setFrameworkPaths(const QStringList &frameworkPaths)
-{
- m_frameworkPaths.clear();
-
- foreach (const QString &frameworkPath, frameworkPaths) {
- addFrameworkPath(frameworkPath);
- }
-}
-
-// Add the given framework path, and expand private frameworks.
-//
-// Example:
-// <framework-path>/ApplicationServices.framework
-// has private frameworks in:
-// <framework-path>/ApplicationServices.framework/Frameworks
-// if the "Frameworks" folder exists inside the top level framework.
-void CppPreprocessor::addFrameworkPath(const QString &frameworkPath)
-{
- // The algorithm below is a bit too eager, but that's because we're not getting
- // in the frameworks we're linking against. If we would have that, then we could
- // add only those private frameworks.
- QString cleanFrameworkPath = cleanPath(frameworkPath);
- if (!m_frameworkPaths.contains(cleanFrameworkPath))
- m_frameworkPaths.append(cleanFrameworkPath);
-
- const QDir frameworkDir(cleanFrameworkPath);
- const QStringList filter = QStringList() << QLatin1String("*.framework");
- foreach (const QFileInfo &framework, frameworkDir.entryInfoList(filter)) {
- if (!framework.isDir())
- continue;
- const QFileInfo privateFrameworks(framework.absoluteFilePath(), QLatin1String("Frameworks"));
- if (privateFrameworks.exists() && privateFrameworks.isDir())
- addFrameworkPath(privateFrameworks.absoluteFilePath());
- }
-}
-
-void CppPreprocessor::setTodo(const QStringList &files)
-{ m_todo = QSet<QString>::fromList(files); }
-
-namespace {
-class Process: public std::unary_function<Document::Ptr, void>
-{
- QPointer<CppModelManager> _modelManager;
- Document::Ptr _doc;
- Document::CheckMode _mode;
-
-public:
- Process(QPointer<CppModelManager> modelManager,
- Document::Ptr doc,
- const CppModelManager::WorkingCopy &workingCopy)
- : _modelManager(modelManager),
- _doc(doc),
- _mode(Document::FastCheck)
- {
-
- if (workingCopy.contains(_doc->fileName()))
- _mode = Document::FullCheck;
- }
-
- void operator()()
- {
- _doc->check(_mode);
-
- if (_modelManager)
- _modelManager->emitDocumentUpdated(_doc);
-
- _doc->releaseSourceAndAST();
- }
-};
-} // end of anonymous namespace
-
-void CppPreprocessor::run(const QString &fileName)
-{
- sourceNeeded(0, fileName, IncludeGlobal);
-}
-
-void CppPreprocessor::removeFromCache(const QString &fileName)
-{
- m_snapshot.remove(fileName);
-}
-
-void CppPreprocessor::resetEnvironment()
-{
- m_env.reset();
- m_processed.clear();
-}
-
-void CppPreprocessor::getFileContents(const QString &absoluteFilePath,
- QString *contents,
- unsigned *revision) const
-{
- if (absoluteFilePath.isEmpty())
- return;
-
- if (m_workingCopy.contains(absoluteFilePath)) {
- QPair<QString, unsigned> entry = m_workingCopy.get(absoluteFilePath);
- if (contents)
- *contents = entry.first;
- if (revision)
- *revision = entry.second;
- return;
- }
-
- QFile file(absoluteFilePath);
- if (file.open(QFile::ReadOnly | QFile::Text)) {
- QTextCodec *defaultCodec = Core::EditorManager::instance()->defaultTextCodec();
- QTextStream stream(&file);
- stream.setCodec(defaultCodec);
- if (contents)
- *contents = stream.readAll();
- if (revision)
- *revision = 0;
- file.close();
- }
-}
-
-bool CppPreprocessor::checkFile(const QString &absoluteFilePath) const
-{
- if (absoluteFilePath.isEmpty() || m_included.contains(absoluteFilePath))
- return true;
-
- QFileInfo fileInfo(absoluteFilePath);
- return fileInfo.isFile() && fileInfo.isReadable();
-}
-
-/// Resolve the given file name to its absolute path w.r.t. the include type.
-QString CppPreprocessor::resolveFile(const QString &fileName, IncludeType type)
-{
- if (type == IncludeGlobal) {
- QHash<QString, QString>::ConstIterator it = m_fileNameCache.find(fileName);
- if (it != m_fileNameCache.end())
- return it.value();
- const QString fn = resolveFile_helper(fileName, type);
- m_fileNameCache.insert(fileName, fn);
- return fn;
- }
-
- // IncludeLocal, IncludeNext
- return resolveFile_helper(fileName, type);
-}
-
-QString CppPreprocessor::cleanPath(const QString &path)
-{
- QString result = QDir::cleanPath(path);
- const QChar slash(QLatin1Char('/'));
- if (!result.endsWith(slash))
- result.append(slash);
- return result;
-}
-
-QString CppPreprocessor::resolveFile_helper(const QString &fileName, IncludeType type)
-{
- QFileInfo fileInfo(fileName);
- if (fileName == Preprocessor::configurationFileName || fileInfo.isAbsolute())
- return fileName;
-
- if (type == IncludeLocal && m_currentDoc) {
- QFileInfo currentFileInfo(m_currentDoc->fileName());
- QString path = cleanPath(currentFileInfo.absolutePath()) + fileName;
- if (checkFile(path))
- return path;
- }
-
- foreach (const QString &includePath, m_includePaths) {
- QString path = includePath + fileName;
- if (checkFile(path))
- return path;
- }
-
- int index = fileName.indexOf(QLatin1Char('/'));
- if (index != -1) {
- QString frameworkName = fileName.left(index);
- QString name = frameworkName + QLatin1String(".framework/Headers/") + fileName.mid(index + 1);
-
- foreach (const QString &frameworkPath, m_frameworkPaths) {
- QString path = frameworkPath + name;
- if (checkFile(path))
- return path;
- }
- }
-
- //qDebug() << "**** file" << fileName << "not found!";
- return QString();
-}
-
-void CppPreprocessor::macroAdded(const Macro &macro)
-{
- if (! m_currentDoc)
- return;
-
- m_currentDoc->appendMacro(macro);
-}
-
-static inline const Macro revision(const CppModelManagerInterface::WorkingCopy &s, const Macro &macro)
-{
- Macro newMacro(macro);
- newMacro.setFileRevision(s.get(macro.fileName()).second);
- return newMacro;
-}
-
-void CppPreprocessor::passedMacroDefinitionCheck(unsigned offset, unsigned line, const Macro &macro)
-{
- if (! m_currentDoc)
- return;
-
- m_currentDoc->addMacroUse(revision(m_workingCopy, macro), offset, macro.name().length(), line,
- QVector<MacroArgumentReference>());
-}
-
-void CppPreprocessor::failedMacroDefinitionCheck(unsigned offset, const ByteArrayRef &name)
-{
- if (! m_currentDoc)
- return;
-
- m_currentDoc->addUndefinedMacroUse(QByteArray(name.start(), name.size()), offset);
-}
-
-void CppPreprocessor::notifyMacroReference(unsigned offset, unsigned line, const Macro &macro)
-{
- if (! m_currentDoc)
- return;
-
- m_currentDoc->addMacroUse(revision(m_workingCopy, macro), offset, macro.name().length(), line,
- QVector<MacroArgumentReference>());
-}
-
-void CppPreprocessor::startExpandingMacro(unsigned offset, unsigned line,
- const Macro &macro,
- const QVector<MacroArgumentReference> &actuals)
-{
- if (! m_currentDoc)
- return;
-
- m_currentDoc->addMacroUse(revision(m_workingCopy, macro), offset, macro.name().length(), line, actuals);
-}
-
-void CppPreprocessor::stopExpandingMacro(unsigned, const Macro &)
-{
- if (! m_currentDoc)
- return;
-
- //qDebug() << "stop expanding:" << macro.name;
-}
-
-void CppPreprocessor::markAsIncludeGuard(const QByteArray &macroName)
-{
- if (!m_currentDoc)
- return;
-
- m_currentDoc->setIncludeGuardMacroName(macroName);
-}
-
-void CppPreprocessor::mergeEnvironment(Document::Ptr doc)
-{
- if (! doc)
- return;
-
- const QString fn = doc->fileName();
-
- if (m_processed.contains(fn))
- return;
-
- m_processed.insert(fn);
-
- foreach (const Document::Include &incl, doc->includes()) {
- QString includedFile = incl.fileName();
-
- if (Document::Ptr includedDoc = m_snapshot.document(includedFile))
- mergeEnvironment(includedDoc);
- else
- run(includedFile);
- }
-
- m_env.addMacros(doc->definedMacros());
-}
-
-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(unsigned line, const QString &fileName, IncludeType type)
-{
- if (fileName.isEmpty())
- return;
-
- QString absoluteFileName = resolveFile(fileName, type);
- absoluteFileName = QDir::cleanPath(absoluteFileName);
- if (m_currentDoc && !absoluteFileName.isEmpty())
- m_currentDoc->addIncludeFile(absoluteFileName, line);
- if (m_included.contains(absoluteFileName))
- return; // we've already seen this file.
- if (absoluteFileName != modelManager()->configurationFileName())
- m_included.insert(absoluteFileName);
-
- unsigned editorRevision = 0;
- QString contents;
- getFileContents(absoluteFileName, &contents, &editorRevision);
- if (m_currentDoc) {
- if (contents.isEmpty() && ! QFileInfo(absoluteFileName).isAbsolute()) {
- QString msg = QCoreApplication::translate(
- "CppPreprocessor", "%1: No such file or directory").arg(fileName);
-
- Document::DiagnosticMessage d(Document::DiagnosticMessage::Warning,
- m_currentDoc->fileName(),
- line, /*column = */ 0,
- msg);
-
- m_currentDoc->addDiagnosticMessage(d);
-
- //qWarning() << "file not found:" << fileName << m_currentDoc->fileName() << env.current_line;
-
- return;
- }
- }
-
- if (m_dumpFileNameWhileParsing) {
- qDebug() << "Parsing file:" << absoluteFileName
-// << "contents:" << contents.size()
- ;
- }
-
- Document::Ptr doc = m_snapshot.document(absoluteFileName);
- if (doc) {
- mergeEnvironment(doc);
- return;
- }
-
- doc = Document::create(absoluteFileName);
- doc->setRevision(m_revision);
- doc->setEditorRevision(editorRevision);
-
- QFileInfo info(absoluteFileName);
- if (info.exists())
- doc->setLastModified(info.lastModified());
-
- Document::Ptr previousDoc = switchDocument(doc);
-
- const QByteArray preprocessedCode = m_preprocess.run(absoluteFileName, contents);
-
-// { QByteArray b(preprocessedCode); b.replace("\n", "<<<\n"); qDebug("Preprocessed code for \"%s\": [[%s]]", fileName.toUtf8().constData(), b.constData()); }
-
- doc->setUtf8Source(preprocessedCode);
- doc->keepSourceAndAST();
- doc->tokenize();
-
- m_snapshot.insert(doc);
- m_todo.remove(absoluteFileName);
-
- Process process(m_modelManager, doc, m_workingCopy);
- process();
-
- (void) switchDocument(previousDoc);
-}
-
-Document::Ptr CppPreprocessor::switchDocument(Document::Ptr doc)
-{
- Document::Ptr previousDoc = m_currentDoc;
- m_currentDoc = doc;
- return previousDoc;
-}
-
void CppModelManager::updateModifiedSourceFiles()
{
const Snapshot snapshot = this->snapshot();
diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h
index d347b851e5..e78729958f 100644
--- a/src/plugins/cpptools/cppmodelmanager.h
+++ b/src/plugins/cpptools/cppmodelmanager.h
@@ -31,15 +31,11 @@
#define CPPMODELMANAGER_H
#include "cpptools_global.h"
-#include "cpptoolsconstants.h"
#include "cppmodelmanagerinterface.h"
#include <projectexplorer/project.h>
#include <texteditor/basetexteditor.h>
-#include <cplusplus/PreprocessorEnvironment.h>
-#include <cplusplus/pp-engine.h>
-
#include <QHash>
#include <QMutex>
@@ -51,7 +47,6 @@ class BaseTextEditorWidget;
namespace CppTools {
-class CppCompletionSupportFactory;
class CppEditorSupport;
class CppHighlightingSupportFactory;
@@ -205,77 +200,6 @@ private:
CppIndexingSupport *m_internalIndexingSupport;
};
-class CPPTOOLS_EXPORT CppPreprocessor: public CPlusPlus::Client
-{
- Q_DISABLE_COPY(CppPreprocessor)
-
-public:
- CppPreprocessor(QPointer<CppModelManager> modelManager, bool dumpFileNameWhileParsing = false);
- virtual ~CppPreprocessor();
-
- void setRevision(unsigned revision);
- void setWorkingCopy(const CppTools::CppModelManagerInterface::WorkingCopy &workingCopy);
- void setIncludePaths(const QStringList &includePaths);
- void setFrameworkPaths(const QStringList &frameworkPaths);
- void addFrameworkPath(const QString &frameworkPath);
- void setProjectFiles(const QStringList &files);
- void setTodo(const QStringList &files);
-
- void run(const QString &fileName);
- void removeFromCache(const QString &fileName);
-
- void resetEnvironment();
- static QString cleanPath(const QString &path);
-
- const QSet<QString> &todo() const
- { return m_todo; }
-
- CppModelManager *modelManager() const
- { return m_modelManager.data(); }
-
-protected:
- CPlusPlus::Document::Ptr switchDocument(CPlusPlus::Document::Ptr doc);
-
- void getFileContents(const QString &absoluteFilePath, QString *contents, unsigned *revision) const;
- bool checkFile(const QString &absoluteFilePath) const;
- QString resolveFile(const QString &fileName, IncludeType type);
- QString resolveFile_helper(const QString &fileName, IncludeType type);
-
- void mergeEnvironment(CPlusPlus::Document::Ptr doc);
-
- virtual void macroAdded(const CPlusPlus::Macro &macro);
- virtual void passedMacroDefinitionCheck(unsigned offset, unsigned line,
- const CPlusPlus::Macro &macro);
- virtual void failedMacroDefinitionCheck(unsigned offset, const CPlusPlus::ByteArrayRef &name);
- virtual void notifyMacroReference(unsigned offset, unsigned line,
- const CPlusPlus::Macro &macro);
- virtual void startExpandingMacro(unsigned offset,
- unsigned line,
- const CPlusPlus::Macro &macro,
- const QVector<CPlusPlus::MacroArgumentReference> &actuals);
- virtual void stopExpandingMacro(unsigned offset, const CPlusPlus::Macro &macro);
- virtual void markAsIncludeGuard(const QByteArray &macroName);
- virtual void startSkippingBlocks(unsigned offset);
- virtual void stopSkippingBlocks(unsigned offset);
- virtual void sourceNeeded(unsigned line, const QString &fileName, IncludeType type);
-
-private:
- CPlusPlus::Snapshot m_snapshot;
- QPointer<CppModelManager> m_modelManager;
- bool m_dumpFileNameWhileParsing;
- CPlusPlus::Environment m_env;
- CPlusPlus::Preprocessor m_preprocess;
- QStringList m_includePaths;
- CppTools::CppModelManagerInterface::WorkingCopy m_workingCopy;
- QStringList m_frameworkPaths;
- QSet<QString> m_included;
- CPlusPlus::Document::Ptr m_currentDoc;
- QSet<QString> m_todo;
- QSet<QString> m_processed;
- unsigned m_revision;
- QHash<QString, QString> m_fileNameCache;
-};
-
} // namespace Internal
} // namespace CppTools
diff --git a/src/plugins/cpptools/cppmodelmanager_test.cpp b/src/plugins/cpptools/cppmodelmanager_test.cpp
index 2a9462674f..3385768c15 100644
--- a/src/plugins/cpptools/cppmodelmanager_test.cpp
+++ b/src/plugins/cpptools/cppmodelmanager_test.cpp
@@ -29,7 +29,7 @@
#include "cpptoolsplugin.h"
-#include "cppmodelmanager.h"
+#include "cpppreprocessor.h"
#include "modelmanagertesthelper.h"
#include <QtTest>
diff --git a/src/plugins/cpptools/cpppreprocessor.cpp b/src/plugins/cpptools/cpppreprocessor.cpp
new file mode 100644
index 0000000000..5ab1c9a04e
--- /dev/null
+++ b/src/plugins/cpptools/cpppreprocessor.cpp
@@ -0,0 +1,425 @@
+#include "cppmodelmanager.h"
+#include "cpppreprocessor.h"
+
+#include <utils/hostosinfo.h>
+
+#include <QCoreApplication>
+
+using namespace CPlusPlus;
+using namespace CppTools;
+using namespace CppTools::Internal;
+
+CppPreprocessor::CppPreprocessor(QPointer<CppModelManager> modelManager, bool dumpFileNameWhileParsing)
+ : m_snapshot(modelManager->snapshot()),
+ m_modelManager(modelManager),
+ m_dumpFileNameWhileParsing(dumpFileNameWhileParsing),
+ m_preprocess(this, &m_env),
+ m_revision(0)
+{
+ m_preprocess.setKeepComments(true);
+}
+
+CppPreprocessor::~CppPreprocessor()
+{ }
+
+void CppPreprocessor::setRevision(unsigned revision)
+{ m_revision = revision; }
+
+void CppPreprocessor::setWorkingCopy(const CppModelManagerInterface::WorkingCopy &workingCopy)
+{ m_workingCopy = workingCopy; }
+
+void CppPreprocessor::setIncludePaths(const QStringList &includePaths)
+{
+ m_includePaths.clear();
+
+ for (int i = 0; i < includePaths.size(); ++i) {
+ const QString &path = includePaths.at(i);
+
+ if (Utils::HostOsInfo::isMacHost()) {
+ if (i + 1 < includePaths.size() && path.endsWith(QLatin1String(".framework/Headers"))) {
+ const QFileInfo pathInfo(path);
+ const QFileInfo frameworkFileInfo(pathInfo.path());
+ const QString frameworkName = frameworkFileInfo.baseName();
+
+ const QFileInfo nextIncludePath = includePaths.at(i + 1);
+ if (nextIncludePath.fileName() == frameworkName) {
+ // We got a QtXXX.framework/Headers followed by $QTDIR/include/QtXXX.
+ // In this case we prefer to include files from $QTDIR/include/QtXXX.
+ continue;
+ }
+ }
+ }
+ m_includePaths.append(cleanPath(path));
+ }
+}
+
+void CppPreprocessor::setFrameworkPaths(const QStringList &frameworkPaths)
+{
+ m_frameworkPaths.clear();
+
+ foreach (const QString &frameworkPath, frameworkPaths) {
+ addFrameworkPath(frameworkPath);
+ }
+}
+
+// Add the given framework path, and expand private frameworks.
+//
+// Example:
+// <framework-path>/ApplicationServices.framework
+// has private frameworks in:
+// <framework-path>/ApplicationServices.framework/Frameworks
+// if the "Frameworks" folder exists inside the top level framework.
+void CppPreprocessor::addFrameworkPath(const QString &frameworkPath)
+{
+ // The algorithm below is a bit too eager, but that's because we're not getting
+ // in the frameworks we're linking against. If we would have that, then we could
+ // add only those private frameworks.
+ QString cleanFrameworkPath = cleanPath(frameworkPath);
+ if (!m_frameworkPaths.contains(cleanFrameworkPath))
+ m_frameworkPaths.append(cleanFrameworkPath);
+
+ const QDir frameworkDir(cleanFrameworkPath);
+ const QStringList filter = QStringList() << QLatin1String("*.framework");
+ foreach (const QFileInfo &framework, frameworkDir.entryInfoList(filter)) {
+ if (!framework.isDir())
+ continue;
+ const QFileInfo privateFrameworks(framework.absoluteFilePath(), QLatin1String("Frameworks"));
+ if (privateFrameworks.exists() && privateFrameworks.isDir())
+ addFrameworkPath(privateFrameworks.absoluteFilePath());
+ }
+}
+
+void CppPreprocessor::setTodo(const QStringList &files)
+{ m_todo = QSet<QString>::fromList(files); }
+
+namespace {
+class Process: public std::unary_function<Document::Ptr, void>
+{
+ QPointer<CppModelManager> _modelManager;
+ Document::Ptr _doc;
+ Document::CheckMode _mode;
+
+public:
+ Process(QPointer<CppModelManager> modelManager,
+ Document::Ptr doc,
+ const CppModelManager::WorkingCopy &workingCopy)
+ : _modelManager(modelManager),
+ _doc(doc),
+ _mode(Document::FastCheck)
+ {
+
+ if (workingCopy.contains(_doc->fileName()))
+ _mode = Document::FullCheck;
+ }
+
+ void operator()()
+ {
+ _doc->check(_mode);
+
+ if (_modelManager)
+ _modelManager->emitDocumentUpdated(_doc);
+
+ _doc->releaseSourceAndAST();
+ }
+};
+} // end of anonymous namespace
+
+void CppPreprocessor::run(const QString &fileName)
+{
+ sourceNeeded(0, fileName, IncludeGlobal);
+}
+
+void CppPreprocessor::removeFromCache(const QString &fileName)
+{
+ m_snapshot.remove(fileName);
+}
+
+void CppPreprocessor::resetEnvironment()
+{
+ m_env.reset();
+ m_processed.clear();
+}
+
+void CppPreprocessor::getFileContents(const QString &absoluteFilePath,
+ QString *contents,
+ unsigned *revision) const
+{
+ if (absoluteFilePath.isEmpty())
+ return;
+
+ if (m_workingCopy.contains(absoluteFilePath)) {
+ QPair<QString, unsigned> entry = m_workingCopy.get(absoluteFilePath);
+ if (contents)
+ *contents = entry.first;
+ if (revision)
+ *revision = entry.second;
+ return;
+ }
+
+ QFile file(absoluteFilePath);
+ if (file.open(QFile::ReadOnly | QFile::Text)) {
+ QTextCodec *defaultCodec = Core::EditorManager::instance()->defaultTextCodec();
+ QTextStream stream(&file);
+ stream.setCodec(defaultCodec);
+ if (contents)
+ *contents = stream.readAll();
+ if (revision)
+ *revision = 0;
+ file.close();
+ }
+}
+
+bool CppPreprocessor::checkFile(const QString &absoluteFilePath) const
+{
+ if (absoluteFilePath.isEmpty() || m_included.contains(absoluteFilePath))
+ return true;
+
+ QFileInfo fileInfo(absoluteFilePath);
+ return fileInfo.isFile() && fileInfo.isReadable();
+}
+
+/// Resolve the given file name to its absolute path w.r.t. the include type.
+QString CppPreprocessor::resolveFile(const QString &fileName, IncludeType type)
+{
+ if (type == IncludeGlobal) {
+ QHash<QString, QString>::ConstIterator it = m_fileNameCache.find(fileName);
+ if (it != m_fileNameCache.end())
+ return it.value();
+ const QString fn = resolveFile_helper(fileName, type);
+ m_fileNameCache.insert(fileName, fn);
+ return fn;
+ }
+
+ // IncludeLocal, IncludeNext
+ return resolveFile_helper(fileName, type);
+}
+
+QString CppPreprocessor::cleanPath(const QString &path)
+{
+ QString result = QDir::cleanPath(path);
+ const QChar slash(QLatin1Char('/'));
+ if (!result.endsWith(slash))
+ result.append(slash);
+ return result;
+}
+
+QString CppPreprocessor::resolveFile_helper(const QString &fileName, IncludeType type)
+{
+ QFileInfo fileInfo(fileName);
+ if (fileName == Preprocessor::configurationFileName || fileInfo.isAbsolute())
+ return fileName;
+
+ if (type == IncludeLocal && m_currentDoc) {
+ QFileInfo currentFileInfo(m_currentDoc->fileName());
+ QString path = cleanPath(currentFileInfo.absolutePath()) + fileName;
+ if (checkFile(path))
+ return path;
+ }
+
+ foreach (const QString &includePath, m_includePaths) {
+ QString path = includePath + fileName;
+ if (checkFile(path))
+ return path;
+ }
+
+ int index = fileName.indexOf(QLatin1Char('/'));
+ if (index != -1) {
+ QString frameworkName = fileName.left(index);
+ QString name = frameworkName + QLatin1String(".framework/Headers/") + fileName.mid(index + 1);
+
+ foreach (const QString &frameworkPath, m_frameworkPaths) {
+ QString path = frameworkPath + name;
+ if (checkFile(path))
+ return path;
+ }
+ }
+
+ //qDebug() << "**** file" << fileName << "not found!";
+ return QString();
+}
+
+void CppPreprocessor::macroAdded(const Macro &macro)
+{
+ if (! m_currentDoc)
+ return;
+
+ m_currentDoc->appendMacro(macro);
+}
+
+static inline const Macro revision(const CppModelManagerInterface::WorkingCopy &s, const Macro &macro)
+{
+ Macro newMacro(macro);
+ newMacro.setFileRevision(s.get(macro.fileName()).second);
+ return newMacro;
+}
+
+void CppPreprocessor::passedMacroDefinitionCheck(unsigned offset, unsigned line, const Macro &macro)
+{
+ if (! m_currentDoc)
+ return;
+
+ m_currentDoc->addMacroUse(revision(m_workingCopy, macro), offset, macro.name().length(), line,
+ QVector<MacroArgumentReference>());
+}
+
+void CppPreprocessor::failedMacroDefinitionCheck(unsigned offset, const ByteArrayRef &name)
+{
+ if (! m_currentDoc)
+ return;
+
+ m_currentDoc->addUndefinedMacroUse(QByteArray(name.start(), name.size()), offset);
+}
+
+void CppPreprocessor::notifyMacroReference(unsigned offset, unsigned line, const Macro &macro)
+{
+ if (! m_currentDoc)
+ return;
+
+ m_currentDoc->addMacroUse(revision(m_workingCopy, macro), offset, macro.name().length(), line,
+ QVector<MacroArgumentReference>());
+}
+
+void CppPreprocessor::startExpandingMacro(unsigned offset, unsigned line,
+ const Macro &macro,
+ const QVector<MacroArgumentReference> &actuals)
+{
+ if (! m_currentDoc)
+ return;
+
+ m_currentDoc->addMacroUse(revision(m_workingCopy, macro), offset, macro.name().length(), line, actuals);
+}
+
+void CppPreprocessor::stopExpandingMacro(unsigned, const Macro &)
+{
+ if (! m_currentDoc)
+ return;
+
+ //qDebug() << "stop expanding:" << macro.name;
+}
+
+void CppPreprocessor::markAsIncludeGuard(const QByteArray &macroName)
+{
+ if (!m_currentDoc)
+ return;
+
+ m_currentDoc->setIncludeGuardMacroName(macroName);
+}
+
+void CppPreprocessor::mergeEnvironment(Document::Ptr doc)
+{
+ if (! doc)
+ return;
+
+ const QString fn = doc->fileName();
+
+ if (m_processed.contains(fn))
+ return;
+
+ m_processed.insert(fn);
+
+ foreach (const Document::Include &incl, doc->includes()) {
+ QString includedFile = incl.fileName();
+
+ if (Document::Ptr includedDoc = m_snapshot.document(includedFile))
+ mergeEnvironment(includedDoc);
+ else
+ run(includedFile);
+ }
+
+ m_env.addMacros(doc->definedMacros());
+}
+
+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(unsigned line, const QString &fileName, IncludeType type)
+{
+ if (fileName.isEmpty())
+ return;
+
+ QString absoluteFileName = resolveFile(fileName, type);
+ absoluteFileName = QDir::cleanPath(absoluteFileName);
+ if (m_currentDoc && !absoluteFileName.isEmpty())
+ m_currentDoc->addIncludeFile(absoluteFileName, line);
+ if (m_included.contains(absoluteFileName))
+ return; // we've already seen this file.
+ if (absoluteFileName != modelManager()->configurationFileName())
+ m_included.insert(absoluteFileName);
+
+ unsigned editorRevision = 0;
+ QString contents;
+ getFileContents(absoluteFileName, &contents, &editorRevision);
+ if (m_currentDoc) {
+ if (contents.isEmpty() && ! QFileInfo(absoluteFileName).isAbsolute()) {
+ QString msg = QCoreApplication::translate(
+ "CppPreprocessor", "%1: No such file or directory").arg(fileName);
+
+ Document::DiagnosticMessage d(Document::DiagnosticMessage::Warning,
+ m_currentDoc->fileName(),
+ line, /*column = */ 0,
+ msg);
+
+ m_currentDoc->addDiagnosticMessage(d);
+
+ //qWarning() << "file not found:" << fileName << m_currentDoc->fileName() << env.current_line;
+
+ return;
+ }
+ }
+
+ if (m_dumpFileNameWhileParsing) {
+ qDebug() << "Parsing file:" << absoluteFileName
+// << "contents:" << contents.size()
+ ;
+ }
+
+ Document::Ptr doc = m_snapshot.document(absoluteFileName);
+ if (doc) {
+ mergeEnvironment(doc);
+ return;
+ }
+
+ doc = Document::create(absoluteFileName);
+ doc->setRevision(m_revision);
+ doc->setEditorRevision(editorRevision);
+
+ QFileInfo info(absoluteFileName);
+ if (info.exists())
+ doc->setLastModified(info.lastModified());
+
+ Document::Ptr previousDoc = switchDocument(doc);
+
+ const QByteArray preprocessedCode = m_preprocess.run(absoluteFileName, contents);
+
+// { QByteArray b(preprocessedCode); b.replace("\n", "<<<\n"); qDebug("Preprocessed code for \"%s\": [[%s]]", fileName.toUtf8().constData(), b.constData()); }
+
+ doc->setUtf8Source(preprocessedCode);
+ doc->keepSourceAndAST();
+ doc->tokenize();
+
+ m_snapshot.insert(doc);
+ m_todo.remove(absoluteFileName);
+
+ Process process(m_modelManager, doc, m_workingCopy);
+ process();
+
+ (void) switchDocument(previousDoc);
+}
+
+Document::Ptr CppPreprocessor::switchDocument(Document::Ptr doc)
+{
+ Document::Ptr previousDoc = m_currentDoc;
+ m_currentDoc = doc;
+ return previousDoc;
+}
diff --git a/src/plugins/cpptools/cpppreprocessor.h b/src/plugins/cpptools/cpppreprocessor.h
new file mode 100644
index 0000000000..d931a880c4
--- /dev/null
+++ b/src/plugins/cpptools/cpppreprocessor.h
@@ -0,0 +1,91 @@
+#ifndef CPPPREPROCESSOR_H
+#define CPPPREPROCESSOR_H
+
+#include "cppmodelmanagerinterface.h"
+
+#include <cplusplus/PreprocessorEnvironment.h>
+#include <cplusplus/pp-engine.h>
+
+#include <QHash>
+#include <QPointer>
+
+namespace CppTools {
+namespace Internal {
+
+class CppModelManager;
+
+class CPPTOOLS_EXPORT CppPreprocessor: public CPlusPlus::Client
+{
+ Q_DISABLE_COPY(CppPreprocessor)
+
+public:
+ CppPreprocessor(QPointer<CppModelManager> modelManager, bool dumpFileNameWhileParsing = false);
+ virtual ~CppPreprocessor();
+
+ void setRevision(unsigned revision);
+ void setWorkingCopy(const CppTools::CppModelManagerInterface::WorkingCopy &workingCopy);
+ void setIncludePaths(const QStringList &includePaths);
+ void setFrameworkPaths(const QStringList &frameworkPaths);
+ void addFrameworkPath(const QString &frameworkPath);
+ void setProjectFiles(const QStringList &files);
+ void setTodo(const QStringList &files);
+
+ void run(const QString &fileName);
+ void removeFromCache(const QString &fileName);
+
+ void resetEnvironment();
+ static QString cleanPath(const QString &path);
+
+ const QSet<QString> &todo() const
+ { return m_todo; }
+
+ CppModelManager *modelManager() const
+ { return m_modelManager.data(); }
+
+protected:
+ CPlusPlus::Document::Ptr switchDocument(CPlusPlus::Document::Ptr doc);
+
+ void getFileContents(const QString &absoluteFilePath, QString *contents, unsigned *revision) const;
+ bool checkFile(const QString &absoluteFilePath) const;
+ QString resolveFile(const QString &fileName, IncludeType type);
+ QString resolveFile_helper(const QString &fileName, IncludeType type);
+
+ void mergeEnvironment(CPlusPlus::Document::Ptr doc);
+
+ virtual void macroAdded(const CPlusPlus::Macro &macro);
+ virtual void passedMacroDefinitionCheck(unsigned offset, unsigned line,
+ const CPlusPlus::Macro &macro);
+ virtual void failedMacroDefinitionCheck(unsigned offset, const CPlusPlus::ByteArrayRef &name);
+ virtual void notifyMacroReference(unsigned offset, unsigned line,
+ const CPlusPlus::Macro &macro);
+ virtual void startExpandingMacro(unsigned offset,
+ unsigned line,
+ const CPlusPlus::Macro &macro,
+ const QVector<CPlusPlus::MacroArgumentReference> &actuals);
+ virtual void stopExpandingMacro(unsigned offset, const CPlusPlus::Macro &macro);
+ virtual void markAsIncludeGuard(const QByteArray &macroName);
+ virtual void startSkippingBlocks(unsigned offset);
+ virtual void stopSkippingBlocks(unsigned offset);
+ virtual void sourceNeeded(unsigned line, const QString &fileName, IncludeType type);
+
+private:
+ CPlusPlus::Snapshot m_snapshot;
+ QPointer<CppModelManager> m_modelManager;
+ bool m_dumpFileNameWhileParsing;
+ CPlusPlus::Environment m_env;
+ CPlusPlus::Preprocessor m_preprocess;
+ QStringList m_includePaths;
+ CppTools::CppModelManagerInterface::WorkingCopy m_workingCopy;
+ QStringList m_frameworkPaths;
+ QSet<QString> m_included;
+ CPlusPlus::Document::Ptr m_currentDoc;
+ QSet<QString> m_todo;
+ QSet<QString> m_processed;
+ unsigned m_revision;
+ QHash<QString, QString> m_fileNameCache;
+};
+
+} // namespace Internal
+} // namespace CppTools
+
+#endif // CPPPREPROCESSOR_H
diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro
index f77e869d68..efeff55f25 100644
--- a/src/plugins/cpptools/cpptools.pro
+++ b/src/plugins/cpptools/cpptools.pro
@@ -44,7 +44,8 @@ HEADERS += completionsettingspage.h \
cppindexingsupport.h \
builtinindexingsupport.h \
cpppointerdeclarationformatter.h \
- cppprojectfile.h
+ cppprojectfile.h \
+ cpppreprocessor.h
SOURCES += completionsettingspage.cpp \
cppclassesfilter.cpp \
@@ -87,7 +88,8 @@ SOURCES += completionsettingspage.cpp \
cppindexingsupport.cpp \
builtinindexingsupport.cpp \
cpppointerdeclarationformatter.cpp \
- cppprojectfile.cpp
+ cppprojectfile.cpp \
+ cpppreprocessor.cpp
FORMS += completionsettingspage.ui \
cppfilesettingspage.ui \
diff --git a/src/plugins/cpptools/cpptools.qbs b/src/plugins/cpptools/cpptools.qbs
index a6a98539b8..059a3dfc7e 100644
--- a/src/plugins/cpptools/cpptools.qbs
+++ b/src/plugins/cpptools/cpptools.qbs
@@ -105,7 +105,9 @@ QtcPlugin {
"uicodecompletionsupport.cpp",
"uicodecompletionsupport.h",
"builtinindexingsupport.cpp",
- "builtinindexingsupport.h"
+ "builtinindexingsupport.h",
+ "cpppreprocessor.cpp",
+ "cpppreprocessor.h"
]
Group {
diff --git a/src/plugins/cpptools/cpptoolsplugin.cpp b/src/plugins/cpptools/cpptoolsplugin.cpp
index e8f1a46c84..7f70a37640 100644
--- a/src/plugins/cpptools/cpptoolsplugin.cpp
+++ b/src/plugins/cpptools/cpptoolsplugin.cpp
@@ -27,8 +27,8 @@
**
****************************************************************************/
+#include "cpptoolsconstants.h"
#include "cpptoolsplugin.h"
-
#include "cppfilesettingspage.h"
#include "cppcodestylesettingspage.h"
#include "cppclassesfilter.h"
diff --git a/src/plugins/cpptools/symbolsfindfilter.cpp b/src/plugins/cpptools/symbolsfindfilter.cpp
index fe4fc332c9..78c636674d 100644
--- a/src/plugins/cpptools/symbolsfindfilter.cpp
+++ b/src/plugins/cpptools/symbolsfindfilter.cpp
@@ -28,8 +28,8 @@
****************************************************************************/
#include "symbolsfindfilter.h"
-
#include "cppmodelmanager.h"
+#include "cpptoolsconstants.h"
#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/futureprogress.h>