forked from qt-creator/qt-creator
		
	CppTools: Clean up CppSourceProcessor
This mostly makes sourceNeeded() a bit more readable. Change-Id: I8da40090fb499837ec56276e7a4273211920c2d2 Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
This commit is contained in:
		| @@ -10,6 +10,7 @@ | ||||
|  | ||||
| #include <QCoreApplication> | ||||
| #include <QCryptographicHash> | ||||
| #include <QDir> | ||||
| #include <QTextCodec> | ||||
|  | ||||
| /*! | ||||
| @@ -28,6 +29,56 @@ using namespace CPlusPlus; | ||||
| using namespace CppTools; | ||||
| using namespace CppTools::Internal; | ||||
|  | ||||
| typedef Document::DiagnosticMessage Message; | ||||
|  | ||||
| namespace { | ||||
|  | ||||
| inline QByteArray generateFingerPrint(const QList<Macro> &definedMacros, const QByteArray &code) | ||||
| { | ||||
|     QCryptographicHash hash(QCryptographicHash::Sha1); | ||||
|     hash.addData(code); | ||||
|     foreach (const Macro ¯o, 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); | ||||
|     } | ||||
|     return hash.result(); | ||||
| } | ||||
|  | ||||
| inline Message messageNoSuchFile(Document::Ptr &document, const QString &fileName, unsigned line) | ||||
| { | ||||
|     const QString text = QCoreApplication::translate( | ||||
|         "CppSourceProcessor", "%1: No such file or directory").arg(fileName); | ||||
|     return Message(Message::Warning, document->fileName(), line, /*column =*/ 0, text); | ||||
| } | ||||
|  | ||||
| inline Message messageNoFileContents(Document::Ptr &document, const QString &fileName, | ||||
|                                      unsigned line) | ||||
| { | ||||
|     const QString text = QCoreApplication::translate( | ||||
|         "CppSourceProcessor", "%1: Could not get file contents").arg(fileName); | ||||
|     return Message(Message::Warning, document->fileName(), line, /*column =*/ 0, text); | ||||
| } | ||||
|  | ||||
| inline const Macro revision(const CppModelManagerInterface::WorkingCopy &workingCopy, | ||||
|                             const Macro ¯o) | ||||
| { | ||||
|     Macro newMacro(macro); | ||||
|     newMacro.setFileRevision(workingCopy.get(macro.fileName()).second); | ||||
|     return newMacro; | ||||
| } | ||||
|  | ||||
| } // anonymous namespace | ||||
|  | ||||
| CppSourceProcessor::CppSourceProcessor(QPointer<CppModelManager> modelManager, | ||||
|                                        bool dumpFileNameWhileParsing) | ||||
|     : m_snapshot(modelManager->snapshot()), | ||||
| @@ -125,37 +176,6 @@ void CppSourceProcessor::addFrameworkPath(const QString &frameworkPath) | ||||
| void CppSourceProcessor::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 CppSourceProcessor::run(const QString &fileName) | ||||
| { | ||||
|     sourceNeeded(0, fileName, IncludeGlobal); | ||||
| @@ -284,14 +304,6 @@ void CppSourceProcessor::macroAdded(const Macro ¯o) | ||||
|     m_currentDoc->appendMacro(macro); | ||||
| } | ||||
|  | ||||
| static inline const Macro revision(const CppModelManagerInterface::WorkingCopy &s, | ||||
|                                    const Macro ¯o) | ||||
| { | ||||
|     Macro newMacro(macro); | ||||
|     newMacro.setFileRevision(s.get(macro.fileName()).second); | ||||
|     return newMacro; | ||||
| } | ||||
|  | ||||
| void CppSourceProcessor::passedMacroDefinitionCheck(unsigned bytesOffset, unsigned utf16charsOffset, | ||||
|                                                     unsigned line, const Macro ¯o) | ||||
| { | ||||
| @@ -391,7 +403,6 @@ void CppSourceProcessor::stopSkippingBlocks(unsigned utf16charsOffset) | ||||
|  | ||||
| void CppSourceProcessor::sourceNeeded(unsigned line, const QString &fileName, IncludeType type) | ||||
| { | ||||
|     typedef Document::DiagnosticMessage Message; | ||||
|     if (fileName.isEmpty()) | ||||
|         return; | ||||
|  | ||||
| @@ -400,22 +411,18 @@ void CppSourceProcessor::sourceNeeded(unsigned line, const QString &fileName, In | ||||
|     if (m_currentDoc) { | ||||
|         m_currentDoc->addIncludeFile(Document::Include(fileName, absoluteFileName, line, type)); | ||||
|         if (absoluteFileName.isEmpty()) { | ||||
|             const QString text = QCoreApplication::translate( | ||||
|                 "CppSourceProcessor", "%1: No such file or directory").arg(fileName); | ||||
|             Message message(Message::Warning, m_currentDoc->fileName(), line, /*column =*/ 0, text); | ||||
|             m_currentDoc->addDiagnosticMessage(message); | ||||
|             m_currentDoc->addDiagnosticMessage(messageNoSuchFile(m_currentDoc, fileName, line)); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|     if (m_included.contains(absoluteFileName)) | ||||
|         return; // we've already seen this file. | ||||
|         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); | ||||
|     if (Document::Ptr document = m_snapshot.document(absoluteFileName)) { | ||||
|         mergeEnvironment(document); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
| @@ -424,77 +431,56 @@ void CppSourceProcessor::sourceNeeded(unsigned line, const QString &fileName, In | ||||
|     QByteArray contents; | ||||
|     const bool gotFileContents = getFileContents(absoluteFileName, &contents, &editorRevision); | ||||
|     if (m_currentDoc && !gotFileContents) { | ||||
|         const QString text = QCoreApplication::translate( | ||||
|             "CppSourceProcessor", "%1: Could not get file contents").arg(fileName); | ||||
|         Message message(Message::Warning, m_currentDoc->fileName(), line, /*column =*/ 0, text); | ||||
|         m_currentDoc->addDiagnosticMessage(message); | ||||
|         m_currentDoc->addDiagnosticMessage(messageNoFileContents(m_currentDoc, fileName, line)); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     if (m_dumpFileNameWhileParsing) { | ||||
|         qDebug() << "Parsing file:" << absoluteFileName | ||||
|                  << "contents:" << contents.size() << "bytes"; | ||||
|     } | ||||
|  | ||||
|     doc = Document::create(absoluteFileName); | ||||
|     doc->setRevision(m_revision); | ||||
|     doc->setEditorRevision(editorRevision); | ||||
|     if (m_dumpFileNameWhileParsing) | ||||
|         qDebug() << "Parsing:" << absoluteFileName << "contents:" << contents.size() << "bytes"; | ||||
|  | ||||
|     Document::Ptr document = Document::create(absoluteFileName); | ||||
|     document->setRevision(m_revision); | ||||
|     document->setEditorRevision(editorRevision); | ||||
|     const QFileInfo info(absoluteFileName); | ||||
|     if (info.exists()) | ||||
|         doc->setLastModified(info.lastModified()); | ||||
|  | ||||
|     const Document::Ptr previousDoc = switchDocument(doc); | ||||
|         document->setLastModified(info.lastModified()); | ||||
|  | ||||
|     const Document::Ptr previousDocument = switchCurrentDocument(document); | ||||
|     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()); | ||||
| //        QByteArray b(preprocessedCode); b.replace("\n", "<<<\n"); | ||||
| //        qDebug("Preprocessed code for \"%s\": [[%s]]", fileName.toUtf8().constData(), b.constData()); | ||||
| //    } | ||||
|     document->setFingerprint(generateFingerPrint(document->definedMacros(), preprocessedCode)); | ||||
|  | ||||
|     QCryptographicHash hash(QCryptographicHash::Sha1); | ||||
|     hash.addData(preprocessedCode); | ||||
|     foreach (const Macro ¯o, 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); | ||||
|     // Re-use document from global snapshot if possible | ||||
|     Document::Ptr globalDocument = m_globalSnapshot.document(absoluteFileName); | ||||
|     if (globalDocument && globalDocument->fingerprint() == document->fingerprint()) { | ||||
|         switchCurrentDocument(previousDocument); | ||||
|         mergeEnvironment(globalDocument); | ||||
|         m_snapshot.insert(globalDocument); | ||||
|         m_todo.remove(absoluteFileName); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     doc->setUtf8Source(preprocessedCode); | ||||
|     doc->keepSourceAndAST(); | ||||
|     doc->tokenize(); | ||||
|     // Otherwise process the document | ||||
|     document->setUtf8Source(preprocessedCode); | ||||
|     document->keepSourceAndAST(); | ||||
|     document->tokenize(); | ||||
|     document->check(m_workingCopy.contains(document->fileName()) ? Document::FullCheck | ||||
|                                                                  : Document::FastCheck); | ||||
|  | ||||
|     m_snapshot.insert(doc); | ||||
|     if (m_modelManager) { | ||||
|         m_modelManager->emitDocumentUpdated(document); | ||||
|         document->releaseSourceAndAST(); | ||||
|     } | ||||
|  | ||||
|     m_snapshot.insert(document); | ||||
|     m_todo.remove(absoluteFileName); | ||||
|  | ||||
|     Process process(m_modelManager, doc, m_workingCopy); | ||||
|     process(); | ||||
|  | ||||
|     (void) switchDocument(previousDoc); | ||||
|     switchCurrentDocument(previousDocument); | ||||
| } | ||||
|  | ||||
| Document::Ptr CppSourceProcessor::switchDocument(Document::Ptr doc) | ||||
| Document::Ptr CppSourceProcessor::switchCurrentDocument(Document::Ptr doc) | ||||
| { | ||||
|     const Document::Ptr previousDoc = m_currentDoc; | ||||
|     m_currentDoc = doc; | ||||
|   | ||||
| @@ -5,9 +5,12 @@ | ||||
|  | ||||
| #include <cplusplus/PreprocessorEnvironment.h> | ||||
| #include <cplusplus/pp-engine.h> | ||||
| #include <utils/qtcoverride.h> | ||||
|  | ||||
| #include <QHash> | ||||
| #include <QPointer> | ||||
| #include <QSet> | ||||
| #include <QStringList> | ||||
|  | ||||
| QT_BEGIN_NAMESPACE | ||||
| class QTextCodec; | ||||
| @@ -29,7 +32,7 @@ public: | ||||
|     CppSourceProcessor(QPointer<CppModelManager> modelManager, bool dumpFileNameWhileParsing = false); | ||||
|     CppSourceProcessor(QPointer<CppModelManager> modelManager, const CPlusPlus::Snapshot &snapshot, | ||||
|                        bool dumpFileNameWhileParsing = false); | ||||
|     virtual ~CppSourceProcessor(); | ||||
|     ~CppSourceProcessor(); | ||||
|  | ||||
|     void setRevision(unsigned revision); | ||||
|     void setWorkingCopy(const CppTools::CppModelManagerInterface::WorkingCopy &workingCopy); | ||||
| @@ -41,19 +44,17 @@ public: | ||||
|     void removeFromCache(const QString &fileName); | ||||
|     void resetEnvironment(); | ||||
|  | ||||
|     CPlusPlus::Snapshot snapshot() const | ||||
|     { return m_snapshot; } | ||||
|  | ||||
|     const QSet<QString> &todo() const | ||||
|     { return m_todo; } | ||||
|  | ||||
|     CppModelManager *modelManager() const | ||||
|     { return m_modelManager.data(); } | ||||
|     CPlusPlus::Snapshot snapshot() const { return m_snapshot; } | ||||
|     const QSet<QString> &todo() const { return m_todo; } | ||||
|     CppModelManager *modelManager() const { return m_modelManager.data(); } | ||||
|  | ||||
|     void setGlobalSnapshot(const CPlusPlus::Snapshot &snapshot) { m_globalSnapshot = snapshot; } | ||||
|  | ||||
| protected: | ||||
|     CPlusPlus::Document::Ptr switchDocument(CPlusPlus::Document::Ptr doc); | ||||
| private: | ||||
|     CppSourceProcessor(); | ||||
|     void addFrameworkPath(const QString &frameworkPath); | ||||
|  | ||||
|     CPlusPlus::Document::Ptr switchCurrentDocument(CPlusPlus::Document::Ptr doc); | ||||
|  | ||||
|     bool getFileContents(const QString &absoluteFilePath, QByteArray *contents, | ||||
|                          unsigned *revision) const; | ||||
| @@ -63,28 +64,24 @@ protected: | ||||
|  | ||||
|     void mergeEnvironment(CPlusPlus::Document::Ptr doc); | ||||
|  | ||||
|     virtual void macroAdded(const CPlusPlus::Macro ¯o); | ||||
|     virtual void passedMacroDefinitionCheck(unsigned bytesOffset, unsigned utf16charsOffset, | ||||
|                                             unsigned line, const CPlusPlus::Macro ¯o); | ||||
|     virtual void failedMacroDefinitionCheck(unsigned bytesOffset, unsigned utf16charOffset, | ||||
|                                             const CPlusPlus::ByteArrayRef &name); | ||||
|     virtual void notifyMacroReference(unsigned bytesOffset, unsigned utf16charOffset, | ||||
|                                       unsigned line, const CPlusPlus::Macro ¯o); | ||||
|     virtual void startExpandingMacro(unsigned bytesOffset, | ||||
|                                      unsigned utf16charOffset, | ||||
|                                      unsigned line, | ||||
|                                      const CPlusPlus::Macro ¯o, | ||||
|                                      const QVector<CPlusPlus::MacroArgumentReference> &actuals); | ||||
|     virtual void stopExpandingMacro(unsigned bytesOffset, const CPlusPlus::Macro ¯o); | ||||
|     virtual void markAsIncludeGuard(const QByteArray ¯oName); | ||||
|     virtual void startSkippingBlocks(unsigned utf16charsOffset); | ||||
|     virtual void stopSkippingBlocks(unsigned utf16charsOffset); | ||||
|     virtual void sourceNeeded(unsigned line, const QString &fileName, IncludeType type); | ||||
|     // Client interface | ||||
|     void macroAdded(const CPlusPlus::Macro ¯o) QTC_OVERRIDE; | ||||
|     void passedMacroDefinitionCheck(unsigned bytesOffset, unsigned utf16charsOffset, | ||||
|                                     unsigned line, const CPlusPlus::Macro ¯o) QTC_OVERRIDE; | ||||
|     void failedMacroDefinitionCheck(unsigned bytesOffset, unsigned utf16charOffset, | ||||
|                                     const CPlusPlus::ByteArrayRef &name) QTC_OVERRIDE; | ||||
|     void notifyMacroReference(unsigned bytesOffset, unsigned utf16charOffset, | ||||
|                               unsigned line, const CPlusPlus::Macro ¯o) QTC_OVERRIDE; | ||||
|     void startExpandingMacro(unsigned bytesOffset, unsigned utf16charOffset, | ||||
|                              unsigned line, const CPlusPlus::Macro ¯o, | ||||
|                              const QVector<CPlusPlus::MacroArgumentReference> &actuals) QTC_OVERRIDE; | ||||
|     void stopExpandingMacro(unsigned bytesOffset, const CPlusPlus::Macro ¯o) QTC_OVERRIDE; | ||||
|     void markAsIncludeGuard(const QByteArray ¯oName) QTC_OVERRIDE; | ||||
|     void startSkippingBlocks(unsigned utf16charsOffset) QTC_OVERRIDE; | ||||
|     void stopSkippingBlocks(unsigned utf16charsOffset) QTC_OVERRIDE; | ||||
|     void sourceNeeded(unsigned line, const QString &fileName, IncludeType type) QTC_OVERRIDE; | ||||
|  | ||||
| private: | ||||
|     CppSourceProcessor(); | ||||
|     void addFrameworkPath(const QString &frameworkPath); | ||||
|  | ||||
|     CPlusPlus::Snapshot m_snapshot; | ||||
|     CPlusPlus::Snapshot m_globalSnapshot; | ||||
|     QPointer<CppModelManager> m_modelManager; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user