CppDocument.h 13.8 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
con's avatar
con committed
2
**
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
con's avatar
con committed
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
con's avatar
con committed
7
**
hjk's avatar
hjk committed
8 9 10 11 12
** 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
Eike Ziller's avatar
Eike Ziller committed
13 14
** conditions see http://www.qt.io/licensing.  For further information
** use the contact form at http://www.qt.io/contact-us.
15
**
16
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17
** Alternatively, this file may be used under the terms of the GNU Lesser
Eike Ziller's avatar
Eike Ziller committed
18 19 20 21 22 23
** 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.
24
**
hjk's avatar
hjk committed
25 26
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
con's avatar
con committed
27 28
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
29
****************************************************************************/
hjk's avatar
hjk committed
30

Roberto Raggi's avatar
Roberto Raggi committed
31 32
#ifndef CPLUSPLUS_CPPDOCUMENT_H
#define CPLUSPLUS_CPPDOCUMENT_H
con's avatar
con committed
33

34
#include "Macro.h"
Roberto Raggi's avatar
Roberto Raggi committed
35

36
#include <cplusplus/CPlusPlusForwardDeclarations.h>
37
#include <cplusplus/PreprocessorClient.h>
38
#include <cplusplus/DependencyTable.h>
39

40 41
#include <utils/fileutils.h>

42 43 44 45 46
#include <QSharedPointer>
#include <QDateTime>
#include <QHash>
#include <QFileInfo>
#include <QAtomicInt>
con's avatar
con committed
47

48 49 50 51 52
// in debug mode: make dumpers widely available without an extra include
#ifdef QT_DEBUG
#include "Dumpers.h"
#endif

con's avatar
con committed
53 54
namespace CPlusPlus {

Roberto Raggi's avatar
Roberto Raggi committed
55
class Macro;
56
class MacroArgumentReference;
57
class LookupContext;
Roberto Raggi's avatar
Roberto Raggi committed
58

con's avatar
con committed
59 60 61 62 63 64 65 66 67 68 69 70 71
class CPLUSPLUS_EXPORT Document
{
    Document(const Document &other);
    void operator =(const Document &other);

    Document(const QString &fileName);

public:
    typedef QSharedPointer<Document> Ptr;

public:
    ~Document();

72 73 74
    unsigned revision() const;
    void setRevision(unsigned revision);

75 76 77
    unsigned editorRevision() const;
    void setEditorRevision(unsigned editorRevision);

78 79 80
    QDateTime lastModified() const;
    void setLastModified(const QDateTime &lastModified);

con's avatar
con committed
81 82
    QString fileName() const;

Roberto Raggi's avatar
Roberto Raggi committed
83
    void appendMacro(const Macro &macro);
84 85 86 87 88 89
    void addMacroUse(const Macro &macro,
                     unsigned bytesOffset, unsigned bytesLength,
                     unsigned utf16charsOffset, unsigned utf16charLength,
                     unsigned beginLine, const QVector<MacroArgumentReference> &range);
    void addUndefinedMacroUse(const QByteArray &name,
                              unsigned bytesOffset, unsigned utf16charsOffset);
90

con's avatar
con committed
91 92 93 94 95 96 97 98
    Control *control() const;
    TranslationUnit *translationUnit() const;

    bool skipFunctionBody() const;
    void setSkipFunctionBody(bool skipFunctionBody);

    unsigned globalSymbolCount() const;
    Symbol *globalSymbolAt(unsigned index) const;
99

con's avatar
con committed
100
    Namespace *globalNamespace() const;
101
    void setGlobalNamespace(Namespace *globalNamespace); // ### internal
con's avatar
con committed
102

Roberto Raggi's avatar
Roberto Raggi committed
103 104 105
    QList<Macro> definedMacros() const
    { return _definedMacros; }

106 107
    QString functionAt(int line, int column, int *lineOpeningDeclaratorParenthesis = 0,
                       int *lineClosingBrace = 0) const;
108 109
    Symbol *lastVisibleSymbolAt(unsigned line, unsigned column = 0) const;
    Scope *scopeAt(unsigned line, unsigned column = 0);
con's avatar
con committed
110

111 112
    QByteArray utf8Source() const;
    void setUtf8Source(const QByteArray &utf8Source);
Roberto Raggi's avatar
Roberto Raggi committed
113

114 115 116 117
    QByteArray fingerprint() const { return m_fingerprint; }
    void setFingerprint(const QByteArray &fingerprint)
    { m_fingerprint = fingerprint; }

118 119
    void startSkippingBlocks(unsigned utf16charsOffset);
    void stopSkippingBlocks(unsigned utf16charsOffset);
con's avatar
con committed
120

121 122 123 124
    enum ParseMode { // ### keep in sync with CPlusPlus::TranslationUnit
        ParseTranlationUnit,
        ParseDeclaration,
        ParseExpression,
125
        ParseDeclarator,
126 127 128
        ParseStatement
    };

129 130 131
    bool isTokenized() const;
    void tokenize();

132
    void setRetryHarderToParseDeclarations(bool yesno);
133
    bool isParsed() const;
134
    bool parse(ParseMode mode = ParseTranlationUnit);
135

136
    enum CheckMode {
137
        Unchecked,
138 139 140 141 142
        FullCheck,
        FastCheck
    };

    void check(CheckMode mode = FullCheck);
143

con's avatar
con committed
144 145
    static Ptr create(const QString &fileName);

Leandro Melo's avatar
Leandro Melo committed
146
    class CPLUSPLUS_EXPORT DiagnosticMessage
con's avatar
con committed
147 148 149 150 151 152 153 154 155 156
    {
    public:
        enum Level {
            Warning,
            Error,
            Fatal
        };

    public:
        DiagnosticMessage(int level, const QString &fileName,
157 158 159
                          unsigned line, unsigned column,
                          const QString &text,
                          unsigned length = 0)
con's avatar
con committed
160 161
            : _level(level),
              _line(line),
162
              _fileName(fileName),
con's avatar
con committed
163
              _column(column),
164
              _length(length),
con's avatar
con committed
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
              _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; }

183
        unsigned line() const
con's avatar
con committed
184 185
        { return _line; }

186
        unsigned column() const
con's avatar
con committed
187 188
        { return _column; }

189 190 191
        unsigned length() const
        { return _length; }

con's avatar
con committed
192 193 194
        QString text() const
        { return _text; }

195 196 197
        bool operator==(const DiagnosticMessage &other) const;
        bool operator!=(const DiagnosticMessage &other) const;

con's avatar
con committed
198 199
    private:
        int _level;
200
        unsigned _line;
201
        QString _fileName;
202
        unsigned _column;
203
        unsigned _length;
con's avatar
con committed
204 205 206 207 208 209
        QString _text;
    };

    void addDiagnosticMessage(const DiagnosticMessage &d)
    { _diagnosticMessages.append(d); }

210 211 212
    void clearDiagnosticMessages()
    { _diagnosticMessages.clear(); }

con's avatar
con committed
213 214 215 216 217
    QList<DiagnosticMessage> diagnosticMessages() const
    { return _diagnosticMessages; }

    class Block
    {
218 219 220 221
        unsigned _bytesBegin;
        unsigned _bytesEnd;
        unsigned _utf16charsBegin;
        unsigned _utf16charsEnd;
con's avatar
con committed
222 223

    public:
224 225 226 227 228 229 230 231 232 233 234 235 236
        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; }
con's avatar
con committed
237

238 239
        inline unsigned utf16charsBegin() const
        { return _utf16charsBegin; }
con's avatar
con committed
240

241 242
        inline unsigned utf16charsEnd() const
        { return _utf16charsEnd; }
Roberto Raggi's avatar
Roberto Raggi committed
243

244 245
        bool containsUtf16charOffset(unsigned utf16charOffset) const
        { return utf16charOffset >= _utf16charsBegin && utf16charOffset < _utf16charsEnd; }
Roberto Raggi's avatar
Roberto Raggi committed
246 247
    };

248
    class Include {
249 250
        QString _resolvedFileName;
        QString _unresolvedFileName;
251
        unsigned _line;
252
        Client::IncludeType _type;
253 254

    public:
255 256 257 258 259 260
        Include(const QString &unresolvedFileName, const QString &resolvedFileName, unsigned line,
                Client::IncludeType type)
            : _resolvedFileName(resolvedFileName)
            , _unresolvedFileName(unresolvedFileName)
            , _line(line)
            , _type(type)
261 262
        { }

263 264 265 266 267
        QString resolvedFileName() const
        { return _resolvedFileName; }

        QString unresolvedFileName() const
        { return _unresolvedFileName; }
268 269 270

        unsigned line() const
        { return _line; }
271

272 273
        Client::IncludeType type() const
        { return _type; }
274 275
    };

Roberto Raggi's avatar
Roberto Raggi committed
276 277
    class MacroUse: public Block {
        Macro _macro;
278
        QVector<Block> _arguments;
279
        unsigned _beginLine;
Roberto Raggi's avatar
Roberto Raggi committed
280 281

    public:
282 283 284 285 286
        inline MacroUse(const Macro &macro,
                        unsigned bytesBegin, unsigned bytesEnd,
                        unsigned utf16charsBegin, unsigned utf16charsEnd,
                        unsigned beginLine)
            : Block(bytesBegin, bytesEnd, utf16charsBegin, utf16charsEnd),
Christian Kamm's avatar
Christian Kamm committed
287
              _macro(macro),
288
              _beginLine(beginLine)
Roberto Raggi's avatar
Roberto Raggi committed
289 290 291 292
        { }

        const Macro &macro() const
        { return _macro; }
293 294 295 296 297 298 299

        bool isFunctionLike() const
        { return _macro.isFunctionLike(); }

        QVector<Block> arguments() const
        { return _arguments; }

300 301 302
        unsigned beginLine() const
        { return _beginLine; }

Christian Kamm's avatar
Christian Kamm committed
303
    private:
304 305 306 307 308
        void setArguments(const QVector<Block> &arguments)
        { _arguments = arguments; }

        void addArgument(const Block &block)
        { _arguments.append(block); }
Christian Kamm's avatar
Christian Kamm committed
309 310 311 312 313 314 315 316 317 318

        friend class Document;
    };

    class UndefinedMacroUse: public Block {
        QByteArray _name;

    public:
        inline UndefinedMacroUse(
                const QByteArray &name,
319 320 321 322 323 324
                unsigned bytesBegin,
                unsigned utf16charsBegin)
            : Block(bytesBegin,
                    bytesBegin + name.length(),
                    utf16charsBegin,
                    utf16charsBegin + QString::fromUtf8(name, name.size()).size()),
Christian Kamm's avatar
Christian Kamm committed
325 326 327 328 329 330 331
              _name(name)
        { }

        QByteArray name() const
        {
            return _name;
        }
con's avatar
con committed
332 333
    };

334 335 336
    QStringList includedFiles() const;
    void addIncludeFile(const Include &include);

337 338 339 340 341
    QList<Include> resolvedIncludes() const
    { return _resolvedIncludes; }

    QList<Include> unresolvedIncludes() const
    { return _unresolvedIncludes; }
342

con's avatar
con committed
343 344 345
    QList<Block> skippedBlocks() const
    { return _skippedBlocks; }

Roberto Raggi's avatar
Roberto Raggi committed
346
    QList<MacroUse> macroUses() const
347 348
    { return _macroUses; }

Christian Kamm's avatar
Christian Kamm committed
349 350 351
    QList<UndefinedMacroUse> undefinedMacroUses() const
    { return _undefinedMacroUses; }

352 353 354 355 356
    void setIncludeGuardMacroName(const QByteArray &includeGuardMacroName)
    { _includeGuardMacroName = includeGuardMacroName; }
    QByteArray includeGuardMacroName() const
    { return _includeGuardMacroName; }

357
    const Macro *findMacroDefinitionAt(unsigned line) const;
358 359
    const MacroUse *findMacroUseAt(unsigned utf16charsOffset) const;
    const UndefinedMacroUse *findUndefinedMacroUseAt(unsigned utf16charsOffset) const;
360

361 362
    void keepSourceAndAST();
    void releaseSourceAndAST();
363

364 365 366
    CheckMode checkMode() const
    { return static_cast<CheckMode>(_checkMode); }

con's avatar
con committed
367 368 369 370 371
private:
    QString _fileName;
    Control *_control;
    TranslationUnit *_translationUnit;
    Namespace *_globalNamespace;
372 373

    /// All messages generated during lexical/syntactic/semantic analysis.
con's avatar
con committed
374
    QList<DiagnosticMessage> _diagnosticMessages;
375

376 377
    QList<Include> _resolvedIncludes;
    QList<Include> _unresolvedIncludes;
Roberto Raggi's avatar
Roberto Raggi committed
378
    QList<Macro> _definedMacros;
con's avatar
con committed
379
    QList<Block> _skippedBlocks;
Roberto Raggi's avatar
Roberto Raggi committed
380
    QList<MacroUse> _macroUses;
Christian Kamm's avatar
Christian Kamm committed
381
    QList<UndefinedMacroUse> _undefinedMacroUses;
382 383 384 385

     /// the macro name of the include guard, if there is one.
    QByteArray _includeGuardMacroName;

386 387
    QByteArray m_fingerprint;

388
    QByteArray _source;
389
    QDateTime _lastModified;
390
    QAtomicInt _keepSourceAndASTCount;
391
    unsigned _revision;
392
    unsigned _editorRevision;
393
    quint8 _checkMode;
394 395

    friend class Snapshot;
con's avatar
con committed
396 397
};

398
class CPLUSPLUS_EXPORT Snapshot
399
{
400
    typedef QHash<Utils::FileName, Document::Ptr> Base;
401

402
public:
403 404 405
    Snapshot();
    ~Snapshot();

Erik Verbruggen's avatar
Erik Verbruggen committed
406 407
    typedef Base::const_iterator iterator;
    typedef Base::const_iterator const_iterator;
408
    typedef QPair<Document::Ptr, unsigned> IncludeLocation;
409 410 411 412 413

    int size() const; // ### remove
    bool isEmpty() const;

    void insert(Document::Ptr doc); // ### remove
414 415 416
    void remove(const Utils::FileName &fileName); // ### remove
    void remove(const QString &fileName)
    { remove(Utils::FileName::fromString(fileName)); }
417 418 419 420

    const_iterator begin() const { return _documents.begin(); }
    const_iterator end() const { return _documents.end(); }

421 422 423 424 425 426 427
    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)); }
428

429 430 431
    const_iterator find(const Utils::FileName &fileName) const;
    const_iterator find(const QString &fileName) const
    { return find(Utils::FileName::fromString(fileName)); }
432

433 434
    Snapshot simplified(Document::Ptr doc) const;

435
    Document::Ptr preprocessedDocument(const QByteArray &source,
436 437 438 439
                                       const Utils::FileName &fileName) const;
    Document::Ptr preprocessedDocument(const QByteArray &source,
                                       const QString &fileName) const
    { return preprocessedDocument(source, Utils::FileName::fromString(fileName)); }
440

441
    Document::Ptr documentFromSource(const QByteArray &preprocessedDocument,
442 443
                                     const QString &fileName) const;

444
    QSet<QString> allIncludesForDocument(const QString &fileName) const;
445
    QList<IncludeLocation> includeLocationsOfDocument(const QString &fileName) const;
446

447 448 449
    Utils::FileNameList filesDependingOn(const Utils::FileName &fileName) const;
    Utils::FileNameList filesDependingOn(const QString &fileName) const
    { return filesDependingOn(Utils::FileName::fromString(fileName)); }
450 451
    void updateDependencyTable() const;

452 453
    bool operator==(const Snapshot &other) const;

454
private:
455
    void allIncludesForDocument_helper(const QString &fileName, QSet<QString> &result) const;
456

457
    mutable DependencyTable m_deps;
Erik Verbruggen's avatar
Erik Verbruggen committed
458
    Base _documents;
459 460
};

461
} // namespace CPlusPlus
con's avatar
con committed
462

Roberto Raggi's avatar
Roberto Raggi committed
463
#endif // CPLUSPLUS_CPPDOCUMENT_H