builtinindexingsupport.cpp 7.48 KB
Newer Older
1
#include "builtinindexingsupport.h"
2

3
#include "cppmodelmanager.h"
4
#include "cppsourceprocessor.h"
5
#include "searchsymbols.h"
6
#include "cpptoolsconstants.h"
7
#include "cpptoolsplugin.h"
8
#include "cppprojectfile.h"
9 10 11

#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
12

13 14 15 16 17 18 19
#include <utils/runextensions.h>

#include <QCoreApplication>

using namespace CppTools;
using namespace CppTools::Internal;

20 21
static const bool DumpFileNameWhileParsing = qgetenv("QTC_DUMP_FILENAME_WHILE_PARSING") == "1";

22 23 24
namespace {

static void parse(QFutureInterface<void> &future,
25
                  CppSourceProcessor *sourceProcessor,
26
                  QStringList files)
27 28 29 30 31 32 33 34
{
    if (files.isEmpty())
        return;

    QStringList sources;
    QStringList headers;

    foreach (const QString &file, files) {
35
        sourceProcessor->removeFromCache(file);
36
        if (ProjectFile::isSource(ProjectFile::classify(file)))
37 38 39 40 41 42 43 44 45
            sources.append(file);
        else
            headers.append(file);
    }

    const int sourceCount = sources.size();
    files = sources;
    files += headers;

46
    sourceProcessor->setTodo(files);
47 48 49

    future.setProgressRange(0, files.size());

50
    const QString conf = CppModelManagerInterface::configurationFileName();
51 52
    bool processingHeaders = false;

53 54
    CppModelManager *cmm = CppModelManager::instance();
    const QStringList fallbackIncludePaths = cmm->includePaths();
55 56 57 58 59 60 61 62 63 64
    for (int i = 0; i < files.size(); ++i) {
        if (future.isPaused())
            future.waitForResume();

        if (future.isCanceled())
            break;

        const QString fileName = files.at(i);

        const bool isSourceFile = i < sourceCount;
65
        if (isSourceFile) {
66
            (void) sourceProcessor->run(conf);
67
        } else if (!processingHeaders) {
68
            (void) sourceProcessor->run(conf);
69 70 71 72

            processingHeaders = true;
        }

73 74 75 76
        QList<ProjectPart::Ptr> parts = cmm->projectPart(fileName);
        QStringList includePaths = parts.isEmpty()
                ? fallbackIncludePaths
                : parts.first()->includePaths;
77 78
        sourceProcessor->setIncludePaths(includePaths);
        sourceProcessor->run(fileName);
79

80
        future.setProgressValue(files.size() - sourceProcessor->todo().size());
81 82

        if (isSourceFile)
83
            sourceProcessor->resetEnvironment();
84 85 86
    }

    future.setProgressValue(files.size());
87
    sourceProcessor->modelManager()->finishedRefreshingSourceFiles(files);
88

89
    delete sourceProcessor;
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
}

class BuiltinSymbolSearcher: public SymbolSearcher
{
public:
    BuiltinSymbolSearcher(const CPlusPlus::Snapshot &snapshot,
                          Parameters parameters, QSet<QString> fileNames)
        : m_snapshot(snapshot)
        , m_parameters(parameters)
        , m_fileNames(fileNames)
    {}

    ~BuiltinSymbolSearcher()
    {}

105
    void runSearch(QFutureInterface<Core::SearchResultItem> &future)
106 107 108 109 110
    {
        future.setProgressRange(0, m_snapshot.size());
        future.setProgressValue(0);
        int progress = 0;

111
        SearchSymbols search(CppToolsPlugin::stringTable());
112 113 114
        search.setSymbolsToSearchFor(m_parameters.types);
        CPlusPlus::Snapshot::const_iterator it = m_snapshot.begin();

115
        QString findString = (m_parameters.flags & Core::FindRegularExpression
116
                              ? m_parameters.text : QRegExp::escape(m_parameters.text));
117
        if (m_parameters.flags & Core::FindWholeWords)
118
            findString = QString::fromLatin1("\\b%1\\b").arg(findString);
119
        QRegExp matcher(findString, (m_parameters.flags & Core::FindCaseSensitively
120 121 122 123 124 125 126
                                     ? Qt::CaseSensitive : Qt::CaseInsensitive));
        while (it != m_snapshot.end()) {
            if (future.isPaused())
                future.waitForResume();
            if (future.isCanceled())
                break;
            if (m_fileNames.isEmpty() || m_fileNames.contains(it.value()->fileName())) {
127
                QVector<Core::SearchResultItem> resultItems;
128 129
                search(it.value())->visitAllChildren([&](const ModelItemInfo::Ptr &info) {
                    if (matcher.indexIn(info->symbolName()) != -1) {
130 131 132
                        QString text = info->symbolName();
                        QString scope = info->symbolScope();
                        if (info->type() == ModelItemInfo::Function) {
133
                            QString name;
134 135 136 137 138
                            info->unqualifiedNameAndScope(info->symbolName(), &name, &scope);
                            text = name + info->symbolType();
                        } else if (info->type() == ModelItemInfo::Declaration){
                            text = ModelItemInfo::representDeclaration(info->symbolName(),
                                                                       info->symbolType());
139
                        }
140

141
                        Core::SearchResultItem item;
142
                        item.path = scope.split(QLatin1String("::"), QString::SkipEmptyParts);
143
                        item.text = text;
144 145
                        item.textMarkPos = -1;
                        item.textMarkLength = 0;
146
                        item.icon = info->icon();
147 148 149 150
                        item.lineNumber = -1;
                        item.userData = qVariantFromValue(info);
                        resultItems << item;
                    }
151
                });
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
                if (!resultItems.isEmpty())
                    future.reportResults(resultItems);
            }
            ++it;
            ++progress;
            future.setProgressValue(progress);
        }
        if (future.isPaused())
            future.waitForResume();
    }

private:
    const CPlusPlus::Snapshot m_snapshot;
    const Parameters m_parameters;
    const QSet<QString> m_fileNames;
};

} // anonymous namespace

171 172
BuiltinIndexingSupport::BuiltinIndexingSupport()
    : m_revision(0)
173 174
{
    m_synchronizer.setCancelOnWait(true);
175
    m_dumpFileNameWhileParsing = DumpFileNameWhileParsing;
176 177 178 179 180
}

BuiltinIndexingSupport::~BuiltinIndexingSupport()
{}

181 182
QFuture<void> BuiltinIndexingSupport::refreshSourceFiles(const QStringList &sourceFiles,
    CppModelManagerInterface::ProgressNotificationMode mode)
183 184 185 186
{
    CppModelManager *mgr = CppModelManager::instance();
    const WorkingCopy workingCopy = mgr->workingCopy();

187
    CppSourceProcessor *preproc = new CppSourceProcessor(mgr, m_dumpFileNameWhileParsing);
188 189 190 191 192
    preproc->setRevision(++m_revision);
    preproc->setIncludePaths(mgr->includePaths());
    preproc->setFrameworkPaths(mgr->frameworkPaths());
    preproc->setWorkingCopy(workingCopy);

193
    QFuture<void> result = QtConcurrent::run(&parse, preproc, sourceFiles);
194 195 196 197 198 199 200

    if (m_synchronizer.futures().size() > 10) {
        QList<QFuture<void> > futures = m_synchronizer.futures();

        m_synchronizer.clearFutures();

        foreach (const QFuture<void> &future, futures) {
201
            if (!(future.isFinished() || future.isCanceled()))
202 203 204 205 206 207
                m_synchronizer.addFuture(future);
        }
    }

    m_synchronizer.addFuture(result);

208
    if (mode == CppModelManagerInterface::ForcedProgressNotification || sourceFiles.count() > 1) {
209
        Core::ProgressManager::addTask(result, QCoreApplication::translate("CppTools::Internal::BuiltinIndexingSupport", "Parsing C/C++ Files"),
210
                                                CppTools::Constants::TASK_INDEX);
211 212 213 214 215 216 217 218 219
    }

    return result;
}

SymbolSearcher *BuiltinIndexingSupport::createSymbolSearcher(SymbolSearcher::Parameters parameters, QSet<QString> fileNames)
{
    return new BuiltinSymbolSearcher(CppModelManager::instance()->snapshot(), parameters, fileNames);
}