/**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://www.qt.io/licensing. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef CPLUSPLUS_CPPDOCUMENT_H #define CPLUSPLUS_CPPDOCUMENT_H #include "Macro.h" #include #include #include #include #include #include #include #include #include // in debug mode: make dumpers widely available without an extra include #ifdef QT_DEBUG #include "Dumpers.h" #endif namespace CPlusPlus { class Macro; class MacroArgumentReference; class LookupContext; class CPLUSPLUS_EXPORT Document { Document(const Document &other); void operator =(const Document &other); Document(const QString &fileName); public: typedef QSharedPointer Ptr; public: ~Document(); unsigned revision() const; void setRevision(unsigned revision); unsigned editorRevision() const; void setEditorRevision(unsigned editorRevision); QDateTime lastModified() const; void setLastModified(const QDateTime &lastModified); QString fileName() const; void appendMacro(const Macro ¯o); void addMacroUse(const Macro ¯o, unsigned bytesOffset, unsigned bytesLength, unsigned utf16charsOffset, unsigned utf16charLength, unsigned beginLine, const QVector &range); void addUndefinedMacroUse(const QByteArray &name, unsigned bytesOffset, unsigned utf16charsOffset); Control *control() const; TranslationUnit *translationUnit() const; bool skipFunctionBody() const; void setSkipFunctionBody(bool skipFunctionBody); unsigned globalSymbolCount() const; Symbol *globalSymbolAt(unsigned index) const; Namespace *globalNamespace() const; void setGlobalNamespace(Namespace *globalNamespace); // ### internal QList definedMacros() const { return _definedMacros; } QString functionAt(int line, int column, int *lineOpeningDeclaratorParenthesis = 0, int *lineClosingBrace = 0) const; Symbol *lastVisibleSymbolAt(unsigned line, unsigned column = 0) const; Scope *scopeAt(unsigned line, unsigned column = 0); QByteArray utf8Source() const; void setUtf8Source(const QByteArray &utf8Source); QByteArray fingerprint() const { return m_fingerprint; } void setFingerprint(const QByteArray &fingerprint) { m_fingerprint = fingerprint; } void startSkippingBlocks(unsigned utf16charsOffset); void stopSkippingBlocks(unsigned utf16charsOffset); enum ParseMode { // ### keep in sync with CPlusPlus::TranslationUnit ParseTranlationUnit, ParseDeclaration, ParseExpression, ParseDeclarator, ParseStatement }; bool isTokenized() const; void tokenize(); void setRetryHarderToParseDeclarations(bool yesno); bool isParsed() const; bool parse(ParseMode mode = ParseTranlationUnit); enum CheckMode { Unchecked, FullCheck, FastCheck }; void check(CheckMode mode = FullCheck); static Ptr create(const QString &fileName); class CPLUSPLUS_EXPORT DiagnosticMessage { public: enum Level { Warning, Error, Fatal }; public: DiagnosticMessage(int level, const QString &fileName, unsigned line, unsigned column, const QString &text, unsigned length = 0) : _level(level), _line(line), _fileName(fileName), _column(column), _length(length), _text(text) { } int level() const { return _level; } bool isWarning() const { return _level == Warning; } bool isError() const { return _level == Error; } bool isFatal() const { return _level == Fatal; } QString fileName() const { return _fileName; } unsigned line() const { return _line; } unsigned column() const { return _column; } unsigned length() const { return _length; } QString text() const { return _text; } bool operator==(const DiagnosticMessage &other) const; bool operator!=(const DiagnosticMessage &other) const; private: int _level; unsigned _line; QString _fileName; unsigned _column; unsigned _length; QString _text; }; void addDiagnosticMessage(const DiagnosticMessage &d) { _diagnosticMessages.append(d); } void clearDiagnosticMessages() { _diagnosticMessages.clear(); } QList diagnosticMessages() const { return _diagnosticMessages; } class Block { unsigned _bytesBegin; unsigned _bytesEnd; unsigned _utf16charsBegin; unsigned _utf16charsEnd; public: inline Block(unsigned bytesBegin = 0, unsigned bytesEnd = 0, unsigned utf16charsBegin = 0, unsigned utf16charsEnd = 0) : _bytesBegin(bytesBegin), _bytesEnd(bytesEnd), _utf16charsBegin(utf16charsBegin), _utf16charsEnd(utf16charsEnd) {} inline unsigned bytesBegin() const { return _bytesBegin; } inline unsigned bytesEnd() const { return _bytesEnd; } inline unsigned utf16charsBegin() const { return _utf16charsBegin; } inline unsigned utf16charsEnd() const { return _utf16charsEnd; } bool containsUtf16charOffset(unsigned utf16charOffset) const { return utf16charOffset >= _utf16charsBegin && utf16charOffset < _utf16charsEnd; } }; class Include { QString _resolvedFileName; QString _unresolvedFileName; unsigned _line; Client::IncludeType _type; public: Include(const QString &unresolvedFileName, const QString &resolvedFileName, unsigned line, Client::IncludeType type) : _resolvedFileName(resolvedFileName) , _unresolvedFileName(unresolvedFileName) , _line(line) , _type(type) { } QString resolvedFileName() const { return _resolvedFileName; } QString unresolvedFileName() const { return _unresolvedFileName; } unsigned line() const { return _line; } Client::IncludeType type() const { return _type; } }; class MacroUse: public Block { Macro _macro; QVector _arguments; unsigned _beginLine; public: inline MacroUse(const Macro ¯o, unsigned bytesBegin, unsigned bytesEnd, unsigned utf16charsBegin, unsigned utf16charsEnd, unsigned beginLine) : Block(bytesBegin, bytesEnd, utf16charsBegin, utf16charsEnd), _macro(macro), _beginLine(beginLine) { } const Macro ¯o() const { return _macro; } bool isFunctionLike() const { return _macro.isFunctionLike(); } QVector arguments() const { return _arguments; } unsigned beginLine() const { return _beginLine; } private: void setArguments(const QVector &arguments) { _arguments = arguments; } void addArgument(const Block &block) { _arguments.append(block); } friend class Document; }; class UndefinedMacroUse: public Block { QByteArray _name; public: inline UndefinedMacroUse( const QByteArray &name, unsigned bytesBegin, unsigned utf16charsBegin) : Block(bytesBegin, bytesBegin + name.length(), utf16charsBegin, utf16charsBegin + QString::fromUtf8(name, name.size()).size()), _name(name) { } QByteArray name() const { return _name; } }; QStringList includedFiles() const; void addIncludeFile(const Include &include); QList resolvedIncludes() const { return _resolvedIncludes; } QList unresolvedIncludes() const { return _unresolvedIncludes; } QList skippedBlocks() const { return _skippedBlocks; } QList macroUses() const { return _macroUses; } QList undefinedMacroUses() const { return _undefinedMacroUses; } void setIncludeGuardMacroName(const QByteArray &includeGuardMacroName) { _includeGuardMacroName = includeGuardMacroName; } QByteArray includeGuardMacroName() const { return _includeGuardMacroName; } const Macro *findMacroDefinitionAt(unsigned line) const; const MacroUse *findMacroUseAt(unsigned utf16charsOffset) const; const UndefinedMacroUse *findUndefinedMacroUseAt(unsigned utf16charsOffset) const; void keepSourceAndAST(); void releaseSourceAndAST(); CheckMode checkMode() const { return static_cast(_checkMode); } private: QString _fileName; Control *_control; TranslationUnit *_translationUnit; Namespace *_globalNamespace; /// All messages generated during lexical/syntactic/semantic analysis. QList _diagnosticMessages; QList _resolvedIncludes; QList _unresolvedIncludes; QList _definedMacros; QList _skippedBlocks; QList _macroUses; QList _undefinedMacroUses; /// the macro name of the include guard, if there is one. QByteArray _includeGuardMacroName; QByteArray m_fingerprint; QByteArray _source; QDateTime _lastModified; QAtomicInt _keepSourceAndASTCount; unsigned _revision; unsigned _editorRevision; quint8 _checkMode; friend class Snapshot; }; class CPLUSPLUS_EXPORT Snapshot { typedef QHash Base; public: Snapshot(); ~Snapshot(); typedef Base::const_iterator iterator; typedef Base::const_iterator const_iterator; typedef QPair IncludeLocation; int size() const; // ### remove bool isEmpty() const; void insert(Document::Ptr doc); // ### remove void remove(const Utils::FileName &fileName); // ### remove void remove(const QString &fileName) { remove(Utils::FileName::fromString(fileName)); } const_iterator begin() const { return _documents.begin(); } const_iterator end() const { return _documents.end(); } bool contains(const Utils::FileName &fileName) const; bool contains(const QString &fileName) const { return contains(Utils::FileName::fromString(fileName)); } Document::Ptr document(const Utils::FileName &fileName) const; Document::Ptr document(const QString &fileName) const { return document(Utils::FileName::fromString(fileName)); } const_iterator find(const Utils::FileName &fileName) const; const_iterator find(const QString &fileName) const { return find(Utils::FileName::fromString(fileName)); } Snapshot simplified(Document::Ptr doc) const; Document::Ptr preprocessedDocument(const QByteArray &source, const Utils::FileName &fileName) const; Document::Ptr preprocessedDocument(const QByteArray &source, const QString &fileName) const { return preprocessedDocument(source, Utils::FileName::fromString(fileName)); } Document::Ptr documentFromSource(const QByteArray &preprocessedDocument, const QString &fileName) const; QSet allIncludesForDocument(const QString &fileName) const; QList includeLocationsOfDocument(const QString &fileName) const; Utils::FileNameList filesDependingOn(const Utils::FileName &fileName) const; Utils::FileNameList filesDependingOn(const QString &fileName) const { return filesDependingOn(Utils::FileName::fromString(fileName)); } void updateDependencyTable() const; bool operator==(const Snapshot &other) const; private: void allIncludesForDocument_helper(const QString &fileName, QSet &result) const; mutable DependencyTable m_deps; Base _documents; }; } // namespace CPlusPlus #endif // CPLUSPLUS_CPPDOCUMENT_H