summaryrefslogtreecommitdiff
path: root/src/plugins/cpptools/cpppreprocessor.cpp
diff options
context:
space:
mode:
authorNikolai Kosjar <nikolai.kosjar@digia.com>2014-05-16 15:51:04 -0400
committerNikolai Kosjar <nikolai.kosjar@digia.com>2014-06-04 16:28:35 +0200
commitec97d967e63e4c66e0147625b09a658a3f99896c (patch)
tree77c44744474915153d08b550dcf2b4bedd3f3516 /src/plugins/cpptools/cpppreprocessor.cpp
parent43895b038f1712d4c98b8f81d7248b44f42f27cd (diff)
downloadqt-creator-ec97d967e63e4c66e0147625b09a658a3f99896c.tar.gz
CppTools: Rename CppPreprocessor to CppSourceProcessor
...since it does quite a bit more than only preprocessing, as the name suggests. We use that class to process source files in general. The output is not a preprocessed source, but a set of CPlusPlus::Documents with symbols. Change-Id: I787d0f22f9f042ddf0c99e8c2f0bdb9aa7001735 Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
Diffstat (limited to 'src/plugins/cpptools/cpppreprocessor.cpp')
-rw-r--r--src/plugins/cpptools/cpppreprocessor.cpp501
1 files changed, 0 insertions, 501 deletions
diff --git a/src/plugins/cpptools/cpppreprocessor.cpp b/src/plugins/cpptools/cpppreprocessor.cpp
deleted file mode 100644
index 4e809989ad..0000000000
--- a/src/plugins/cpptools/cpppreprocessor.cpp
+++ /dev/null
@@ -1,501 +0,0 @@
-#include "cpppreprocessor.h"
-
-#include "cppmodelmanager.h"
-
-#include <coreplugin/editormanager/editormanager.h>
-
-#include <utils/fileutils.h>
-#include <utils/hostosinfo.h>
-#include <utils/textfileformat.h>
-
-#include <QCoreApplication>
-#include <QCryptographicHash>
-#include <QTextCodec>
-
-/*!
- * \class CppTools::Internal::CppPreprocessor
- * \brief The CppPreprocessor class updates set of indexed C++ files.
- *
- * Indexed file is truncated version of fully parsed document: copy of source
- * code and full AST will be dropped when indexing is done. Working copy ensures
- * that documents with most recent copy placed in memory will be parsed correctly.
- *
- * \sa CPlusPlus::Document
- * \sa CppTools::CppModelManagerInterface::WorkingCopy
- */
-
-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_defaultCodec(Core::EditorManager::defaultTextCodec())
-{
- m_preprocess.setKeepComments(true);
-}
-
-CppPreprocessor::CppPreprocessor(QPointer<CppModelManager> modelManager, const Snapshot &snapshot,
- bool dumpFileNameWhileParsing)
- : m_snapshot(snapshot),
- m_modelManager(modelManager),
- m_dumpFileNameWhileParsing(dumpFileNameWhileParsing),
- m_preprocess(this, &m_env),
- m_revision(0),
- m_defaultCodec(Core::EditorManager::defaultTextCodec())
-{
- 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.
- const 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();
- m_included.clear();
-}
-
-bool CppPreprocessor::getFileContents(const QString &absoluteFilePath,
- QByteArray *contents,
- unsigned *revision) const
-{
- if (absoluteFilePath.isEmpty() || !contents || !revision)
- return false;
-
- // Get from working copy
- if (m_workingCopy.contains(absoluteFilePath)) {
- const QPair<QByteArray, unsigned> entry = m_workingCopy.get(absoluteFilePath);
- *contents = entry.first;
- *revision = entry.second;
- return true;
- }
-
- // Get from file
- *revision = 0;
- QString error;
- if (Utils::TextFileFormat::readFileUTF8(absoluteFilePath, m_defaultCodec, contents, &error)
- != Utils::TextFileFormat::ReadSuccess) {
- qWarning("Error reading file \"%s\": \"%s\".", qPrintable(absoluteFilePath),
- qPrintable(error));
- return false;
- }
- return true;
-}
-
-bool CppPreprocessor::checkFile(const QString &absoluteFilePath) const
-{
- if (absoluteFilePath.isEmpty()
- || m_included.contains(absoluteFilePath)
- || m_workingCopy.contains(absoluteFilePath)) {
- return true;
- }
-
- const 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)
-{
- if (isInjectedFile(fileName))
- return fileName;
-
- if (QFileInfo(fileName).isAbsolute())
- return checkFile(fileName) ? fileName : QString();
-
- if (type == IncludeLocal && m_currentDoc) {
- const QFileInfo currentFileInfo(m_currentDoc->fileName());
- const QString path = cleanPath(currentFileInfo.absolutePath()) + fileName;
- if (checkFile(path))
- return path;
- // Fall through! "16.2 Source file inclusion" from the standard states to continue
- // searching as if this would be a global include.
- }
-
- foreach (const QString &includePath, m_includePaths) {
- const QString path = includePath + fileName;
- if (m_workingCopy.contains(path) || checkFile(path))
- return path;
- }
-
- const int index = fileName.indexOf(QLatin1Char('/'));
- if (index != -1) {
- const QString frameworkName = fileName.left(index);
- const QString name = frameworkName + QLatin1String(".framework/Headers/")
- + fileName.mid(index + 1);
-
- foreach (const QString &frameworkPath, m_frameworkPaths) {
- const QString path = frameworkPath + name;
- if (checkFile(path))
- return path;
- }
- }
-
- 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 bytesOffset, unsigned utf16charsOffset,
- unsigned line, const Macro &macro)
-{
- if (!m_currentDoc)
- return;
-
- m_currentDoc->addMacroUse(revision(m_workingCopy, macro),
- bytesOffset, macro.name().length(),
- utf16charsOffset, macro.nameToQString().size(),
- line, QVector<MacroArgumentReference>());
-}
-
-void CppPreprocessor::failedMacroDefinitionCheck(unsigned bytesOffset, unsigned utf16charOffset,
- const ByteArrayRef &name)
-{
- if (!m_currentDoc)
- return;
-
- m_currentDoc->addUndefinedMacroUse(QByteArray(name.start(), name.size()),
- bytesOffset, utf16charOffset);
-}
-
-void CppPreprocessor::notifyMacroReference(unsigned bytesOffset, unsigned utf16charOffset,
- unsigned line, const Macro &macro)
-{
- if (!m_currentDoc)
- return;
-
- m_currentDoc->addMacroUse(revision(m_workingCopy, macro),
- bytesOffset, macro.name().length(),
- utf16charOffset, macro.nameToQString().size(),
- line, QVector<MacroArgumentReference>());
-}
-
-void CppPreprocessor::startExpandingMacro(unsigned bytesOffset, unsigned utf16charOffset,
- unsigned line, const Macro &macro,
- const QVector<MacroArgumentReference> &actuals)
-{
- if (!m_currentDoc)
- return;
-
- m_currentDoc->addMacroUse(revision(m_workingCopy, macro),
- bytesOffset, macro.name().length(),
- utf16charOffset, macro.nameToQString().size(),
- line, actuals);
-}
-
-void CppPreprocessor::stopExpandingMacro(unsigned, const Macro &)
-{
- if (!m_currentDoc)
- return;
-}
-
-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->resolvedIncludes()) {
- const QString includedFile = incl.resolvedFileName();
-
- if (Document::Ptr includedDoc = m_snapshot.document(includedFile))
- mergeEnvironment(includedDoc);
- else if (!m_included.contains(includedFile))
- run(includedFile);
- }
-
- m_env.addMacros(doc->definedMacros());
-}
-
-void CppPreprocessor::startSkippingBlocks(unsigned utf16charsOffset)
-{
- if (m_currentDoc)
- m_currentDoc->startSkippingBlocks(utf16charsOffset);
-}
-
-void CppPreprocessor::stopSkippingBlocks(unsigned utf16charsOffset)
-{
- if (m_currentDoc)
- m_currentDoc->stopSkippingBlocks(utf16charsOffset);
-}
-
-void CppPreprocessor::sourceNeeded(unsigned line, const QString &fileName, IncludeType type)
-{
- typedef Document::DiagnosticMessage Message;
- if (fileName.isEmpty())
- return;
-
- QString absoluteFileName = resolveFile(fileName, type);
- absoluteFileName = QDir::cleanPath(absoluteFileName);
- if (m_currentDoc) {
- m_currentDoc->addIncludeFile(Document::Include(fileName, absoluteFileName, line, type));
- if (absoluteFileName.isEmpty()) {
- const QString text = QCoreApplication::translate(
- "CppPreprocessor", "%1: No such file or directory").arg(fileName);
- Message message(Message::Warning, m_currentDoc->fileName(), line, /*column =*/ 0, text);
- m_currentDoc->addDiagnosticMessage(message);
- return;
- }
- }
- if (m_included.contains(absoluteFileName))
- return; // we've already seen this file.
- if (absoluteFileName != modelManager()->configurationFileName())
- m_included.insert(absoluteFileName);
-
- // Already in snapshot? Use it!
- Document::Ptr doc = m_snapshot.document(absoluteFileName);
- if (doc) {
- mergeEnvironment(doc);
- return;
- }
-
- // Otherwise get file contents
- unsigned editorRevision = 0;
- QByteArray contents;
- const bool gotFileContents = getFileContents(absoluteFileName, &contents, &editorRevision);
- if (m_currentDoc && !gotFileContents) {
- const QString text = QCoreApplication::translate(
- "CppPreprocessor", "%1: Could not get file contents").arg(fileName);
- Message message(Message::Warning, m_currentDoc->fileName(), line, /*column =*/ 0, text);
- m_currentDoc->addDiagnosticMessage(message);
- return;
- }
-
- if (m_dumpFileNameWhileParsing) {
- qDebug() << "Parsing file:" << absoluteFileName
- << "contents:" << contents.size() << "bytes";
- }
-
- doc = Document::create(absoluteFileName);
- doc->setRevision(m_revision);
- doc->setEditorRevision(editorRevision);
-
- const QFileInfo info(absoluteFileName);
- if (info.exists())
- doc->setLastModified(info.lastModified());
-
- const 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());
-// }
-
- QCryptographicHash hash(QCryptographicHash::Sha1);
- hash.addData(preprocessedCode);
- foreach (const Macro &macro, doc->definedMacros()) {
- if (macro.isHidden()) {
- static const QByteArray undef("#undef ");
- hash.addData(undef);
- hash.addData(macro.name());
- } else {
- static const QByteArray def("#define ");
- hash.addData(macro.name());
- hash.addData(" ", 1);
- hash.addData(def);
- hash.addData(macro.definitionText());
- }
- hash.addData("\n", 1);
- }
- doc->setFingerprint(hash.result());
-
- Document::Ptr anotherDoc = m_globalSnapshot.document(absoluteFileName);
- if (anotherDoc && anotherDoc->fingerprint() == doc->fingerprint()) {
- switchDocument(previousDoc);
- mergeEnvironment(anotherDoc);
- m_snapshot.insert(anotherDoc);
- m_todo.remove(absoluteFileName);
- return;
- }
-
- 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)
-{
- const Document::Ptr previousDoc = m_currentDoc;
- m_currentDoc = doc;
- return previousDoc;
-}