builtineditordocumentparser.cpp 8.18 KB
Newer Older
1 2
/****************************************************************************
**
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
** 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://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/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 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: 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.
**
****************************************************************************/

30
#include "builtineditordocumentparser.h"
31
#include "cppsourceprocessor.h"
32 33 34 35 36 37 38

#include <utils/qtcassert.h>

using namespace CPlusPlus;
using namespace CppTools;
using namespace CppTools::Internal;

39
BuiltinEditorDocumentParser::BuiltinEditorDocumentParser(const QString &filePath)
40
    : BaseEditorDocumentParser(filePath)
Erik Verbruggen's avatar
Erik Verbruggen committed
41
    , m_forceSnapshotInvalidation(false)
42
    , m_releaseSourceAndAST(true)
43 44 45
{
}

46
void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy)
47 48 49
{
    QMutexLocker locker(&m_mutex);

50
    if (filePath().isEmpty())
51 52
        return;

53
    bool invalidateSnapshot = false, invalidateConfig = false, editorDefinesChanged_ = false;
54 55 56 57

    CppModelManager *modelManager
        = dynamic_cast<CppModelManager *>(CppModelManagerInterface::instance());
    QByteArray configFile = modelManager->codeModelConfiguration();
58
    ProjectPart::HeaderPaths headerPaths;
59
    QStringList precompiledHeaders;
60
    QString projectConfigFile;
61 62 63

    updateProjectPart();

Erik Verbruggen's avatar
Erik Verbruggen committed
64 65 66 67 68
    if (m_forceSnapshotInvalidation) {
        invalidateSnapshot = true;
        m_forceSnapshotInvalidation = false;
    }

69 70 71 72 73 74 75
    if (const ProjectPart::Ptr part = projectPart()) {
        configFile += part->toolchainDefines;
        configFile += part->projectDefines;
        headerPaths = part->headerPaths;
        projectConfigFile = part->projectConfigFile;
        if (usePrecompiledHeaders())
            precompiledHeaders = part->precompiledHeaders;
76 77 78 79 80 81 82 83
    }

    if (configFile != m_configFile) {
        m_configFile = configFile;
        invalidateSnapshot = true;
        invalidateConfig = true;
    }

84
    if (editorDefinesChanged()) {
85
        invalidateSnapshot = true;
86 87
        editorDefinesChanged_ = true;
        resetEditorDefinesChanged();
88 89
    }

90 91
    if (headerPaths != m_headerPaths) {
        m_headerPaths = headerPaths;
92 93 94
        invalidateSnapshot = true;
    }

95 96 97 98 99
    if (projectConfigFile != m_projectConfigFile) {
        m_projectConfigFile = projectConfigFile;
        invalidateSnapshot = true;
    }

100 101 102 103 104
    if (precompiledHeaders != m_precompiledHeaders) {
        m_precompiledHeaders = precompiledHeaders;
        invalidateSnapshot = true;
    }

105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
    unsigned rev = 0;
    if (Document::Ptr doc = document())
        rev = doc->revision();
    else
        invalidateSnapshot = true;

    Snapshot globalSnapshot = modelManager->snapshot();

    if (invalidateSnapshot) {
        m_snapshot = Snapshot();
    } else {
        // Remove changed files from the snapshot
        QSet<QString> toRemove;
        foreach (const Document::Ptr &doc, m_snapshot) {
            QString fileName = doc->fileName();
            if (workingCopy.contains(fileName)) {
                if (workingCopy.get(fileName).second != doc->editorRevision())
                    addFileAndDependencies(&toRemove, fileName);
                continue;
            }
            Document::Ptr otherDoc = globalSnapshot.document(fileName);
            if (!otherDoc.isNull() && otherDoc->revision() != doc->revision())
                addFileAndDependencies(&toRemove, fileName);
        }

        if (!toRemove.isEmpty()) {
            invalidateSnapshot = true;
            foreach (const QString &fileName, toRemove)
                m_snapshot.remove(fileName);
        }
    }

    // Update the snapshot
    if (invalidateSnapshot) {
        const QString configurationFileName = modelManager->configurationFileName();
        if (invalidateConfig)
            m_snapshot.remove(configurationFileName);
        if (!m_snapshot.contains(configurationFileName))
            workingCopy.insert(configurationFileName, m_configFile);
144
        m_snapshot.remove(filePath());
145

146 147
        static const QString editorDefinesFileName
            = CppModelManagerInterface::editorConfigurationFileName();
148
        if (editorDefinesChanged_) {
149
            m_snapshot.remove(editorDefinesFileName);
150
            workingCopy.insert(editorDefinesFileName, editorDefines());
151 152
        }

153 154
        CppSourceProcessor sourceProcessor(m_snapshot, [&](const Document::Ptr &doc) {
            const QString fileName = doc->fileName();
155
            const bool isInEditor = fileName == filePath();
156 157 158 159 160 161
            Document::Ptr otherDoc = modelManager->document(fileName);
            unsigned newRev = otherDoc.isNull() ? 1U : otherDoc->revision() + 1;
            if (isInEditor)
                newRev = qMax(rev + 1, newRev);
            doc->setRevision(newRev);
            modelManager->emitDocumentUpdated(doc);
162 163
            if (m_releaseSourceAndAST)
                doc->releaseSourceAndAST();
164
        });
165
        Snapshot globalSnapshot = modelManager->snapshot();
166
        globalSnapshot.remove(filePath());
167 168
        sourceProcessor.setGlobalSnapshot(globalSnapshot);
        sourceProcessor.setWorkingCopy(workingCopy);
169
        sourceProcessor.setHeaderPaths(m_headerPaths);
170
        sourceProcessor.run(configurationFileName);
171
        if (!m_projectConfigFile.isEmpty())
172
            sourceProcessor.run(m_projectConfigFile);
173
        if (usePrecompiledHeaders()) {
174
            foreach (const QString &precompiledHeader, m_precompiledHeaders)
175
                sourceProcessor.run(precompiledHeader);
176
        }
177
        if (!editorDefines().isEmpty())
178
            sourceProcessor.run(editorDefinesFileName);
179
        sourceProcessor.run(filePath(), usePrecompiledHeaders() ? m_precompiledHeaders
180
                                                                    : QStringList());
181
        m_snapshot = sourceProcessor.snapshot();
182 183 184 185 186 187
        Snapshot newSnapshot = m_snapshot.simplified(document());
        for (Snapshot::const_iterator i = m_snapshot.begin(), ei = m_snapshot.end(); i != ei; ++i) {
            if (Client::isInjectedFile(i.key()))
                newSnapshot.insert(i.value());
        }
        m_snapshot = newSnapshot;
188 189 190 191
        m_deps.build(m_snapshot);
    }
}

192
void BuiltinEditorDocumentParser::releaseResources()
Erik Verbruggen's avatar
Erik Verbruggen committed
193 194 195 196 197 198 199
{
    QMutexLocker locker(&m_mutex);
    m_snapshot = Snapshot();
    m_deps = DependencyTable();
    m_forceSnapshotInvalidation = true;
}

200
Document::Ptr BuiltinEditorDocumentParser::document() const
201 202
{
    QMutexLocker locker(&m_mutex);
203
    return m_snapshot.document(filePath());
204 205
}

206
Snapshot BuiltinEditorDocumentParser::snapshot() const
207 208 209 210 211
{
    QMutexLocker locker(&m_mutex);
    return m_snapshot;
}

212
ProjectPart::HeaderPaths BuiltinEditorDocumentParser::headerPaths() const
213 214
{
    QMutexLocker locker(&m_mutex);
215
    return m_headerPaths;
216
}
217

218
void BuiltinEditorDocumentParser::setReleaseSourceAndAST(bool onoff)
219 220 221 222 223
{
    QMutexLocker locker(&m_mutex);
    m_releaseSourceAndAST = onoff;
}

224 225
void BuiltinEditorDocumentParser::addFileAndDependencies(QSet<QString> *toRemove,
                                                            const QString &fileName) const
226 227
{
    toRemove->insert(fileName);
228
    if (fileName != filePath()) {
229 230 231 232 233
        QStringList deps = m_deps.filesDependingOn(fileName);
        toRemove->unite(QSet<QString>::fromList(deps));
    }
}