2015-06-01 18:51:55 +02:00
|
|
|
/****************************************************************************
|
|
|
|
|
**
|
2016-01-15 14:57:14 +01:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2015-06-01 18:51:55 +02:00
|
|
|
**
|
|
|
|
|
** 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
|
2016-01-15 14:57:14 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2015-06-01 18:51:55 +02:00
|
|
|
**
|
2016-01-15 14:57:14 +01:00
|
|
|
** GNU General Public License Usage
|
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
2015-06-01 18:51:55 +02:00
|
|
|
**
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
2016-06-29 16:49:56 +02:00
|
|
|
#include "clangcodemodelserver.h"
|
2015-06-01 18:51:55 +02:00
|
|
|
|
2016-09-07 10:42:12 +02:00
|
|
|
#include "clangdocuments.h"
|
2017-07-28 15:15:46 +02:00
|
|
|
#include "clangdocumentsuspenderresumer.h"
|
2015-08-26 16:26:50 +02:00
|
|
|
#include "clangfilesystemwatcher.h"
|
2015-08-31 16:28:26 +02:00
|
|
|
#include "codecompleter.h"
|
|
|
|
|
#include "diagnosticset.h"
|
2018-02-06 15:48:24 +01:00
|
|
|
#include "tokenprocessor.h"
|
2016-09-09 14:25:59 +02:00
|
|
|
#include "clangexceptions.h"
|
2015-11-18 17:07:44 +01:00
|
|
|
#include "skippedsourceranges.h"
|
2015-08-31 16:28:26 +02:00
|
|
|
|
2017-08-24 12:28:01 +02:00
|
|
|
#include <clangsupport/clangsupportdebugutils.h>
|
|
|
|
|
#include <clangsupport/clangcodemodelservermessages.h>
|
2015-06-01 18:51:55 +02:00
|
|
|
|
2017-05-03 15:48:44 +02:00
|
|
|
#include <utils/algorithm.h>
|
2016-10-14 13:05:44 +02:00
|
|
|
#include <utils/qtcassert.h>
|
|
|
|
|
|
2015-06-16 12:38:04 +02:00
|
|
|
#include <QCoreApplication>
|
2015-06-01 18:51:55 +02:00
|
|
|
#include <QDebug>
|
2018-01-10 11:59:15 +01:00
|
|
|
#include <QLoggingCategory>
|
|
|
|
|
|
|
|
|
|
Q_LOGGING_CATEGORY(serverLog, "qtc.clangbackend.server");
|
2015-06-01 18:51:55 +02:00
|
|
|
|
2016-10-25 11:40:32 +02:00
|
|
|
static bool useSupportiveTranslationUnit()
|
|
|
|
|
{
|
|
|
|
|
static bool use = !qEnvironmentVariableIntValue("QTC_CLANG_NO_SUPPORTIVE_TRANSLATIONUNIT");
|
|
|
|
|
return use;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-16 11:56:00 +02:00
|
|
|
namespace ClangBackEnd {
|
2015-06-01 18:51:55 +02:00
|
|
|
|
2016-06-29 16:49:56 +02:00
|
|
|
ClangCodeModelServer::ClangCodeModelServer()
|
2016-09-07 10:42:12 +02:00
|
|
|
: documents(projects, unsavedFiles)
|
2015-06-01 18:51:55 +02:00
|
|
|
{
|
2018-05-31 15:21:53 +02:00
|
|
|
updateAnnotationsTimer.setSingleShot(true);
|
|
|
|
|
QObject::connect(&updateAnnotationsTimer,
|
2015-08-26 16:33:32 +02:00
|
|
|
&QTimer::timeout,
|
2016-05-31 16:07:09 +02:00
|
|
|
[this]() {
|
|
|
|
|
processJobsForDirtyAndVisibleDocuments();
|
|
|
|
|
});
|
2015-08-26 16:47:38 +02:00
|
|
|
|
2016-10-14 13:05:44 +02:00
|
|
|
updateVisibleButNotCurrentDocumentsTimer.setSingleShot(true);
|
|
|
|
|
QObject::connect(&updateVisibleButNotCurrentDocumentsTimer,
|
|
|
|
|
&QTimer::timeout,
|
|
|
|
|
[this]() {
|
2018-01-03 14:18:08 +01:00
|
|
|
addAndRunUpdateJobs(documents.dirtyAndVisibleButNotCurrentDocuments());
|
2016-10-14 13:05:44 +02:00
|
|
|
});
|
|
|
|
|
|
2016-09-07 10:42:12 +02:00
|
|
|
QObject::connect(documents.clangFileSystemWatcher(),
|
2015-08-26 16:47:38 +02:00
|
|
|
&ClangFileSystemWatcher::fileChanged,
|
2016-05-31 16:07:09 +02:00
|
|
|
[this](const Utf8String &filePath) {
|
2018-01-03 14:18:08 +01:00
|
|
|
if (!documents.hasDocumentWithFilePath(filePath))
|
2018-05-31 15:21:53 +02:00
|
|
|
updateAnnotationsTimer.start(0);
|
2016-05-31 16:07:09 +02:00
|
|
|
});
|
2015-06-01 18:51:55 +02:00
|
|
|
}
|
|
|
|
|
|
2016-06-29 16:49:56 +02:00
|
|
|
void ClangCodeModelServer::end()
|
2015-06-01 18:51:55 +02:00
|
|
|
{
|
|
|
|
|
QCoreApplication::exit();
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-10 14:54:45 +01:00
|
|
|
static std::vector<Document> operator+(const std::vector<Document> &a,
|
|
|
|
|
const std::vector<Document> &b)
|
|
|
|
|
{
|
|
|
|
|
std::vector<Document> result = a;
|
|
|
|
|
result.insert(result.end(), b.begin(), b.end());
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-31 15:21:53 +02:00
|
|
|
void ClangCodeModelServer::documentsOpened(const ClangBackEnd::DocumentsOpenedMessage &message)
|
2015-06-01 18:51:55 +02:00
|
|
|
{
|
2018-05-31 15:21:53 +02:00
|
|
|
qCDebug(serverLog) << "########## documentsOpened";
|
|
|
|
|
TIME_SCOPE_DURATION("ClangCodeModelServer::documentsOpened");
|
2015-07-28 16:04:49 +02:00
|
|
|
|
2015-10-13 15:56:41 +02:00
|
|
|
try {
|
2018-01-10 14:54:45 +01:00
|
|
|
DocumentResetInfos toReset;
|
|
|
|
|
QVector<FileContainer> toCreate;
|
2018-04-04 18:25:23 +02:00
|
|
|
categorizeFileContainers(message.fileContainers, toCreate, toReset);
|
2018-01-10 14:54:45 +01:00
|
|
|
|
|
|
|
|
const std::vector<Document> createdDocuments = documents.create(toCreate);
|
2017-08-22 15:09:12 +02:00
|
|
|
for (const auto &document : createdDocuments)
|
|
|
|
|
documentProcessors().create(document);
|
2018-01-10 14:54:45 +01:00
|
|
|
const std::vector<Document> resetDocuments_ = resetDocuments(toReset);
|
|
|
|
|
|
2018-04-04 18:25:23 +02:00
|
|
|
unsavedFiles.createOrUpdate(message.fileContainers);
|
|
|
|
|
documents.setUsedByCurrentEditor(message.currentEditorFilePath);
|
|
|
|
|
documents.setVisibleInEditors(message.visibleEditorFilePaths);
|
2016-05-31 16:07:09 +02:00
|
|
|
|
2018-01-10 14:54:45 +01:00
|
|
|
processSuspendResumeJobs(documents.documents());
|
|
|
|
|
processInitialJobsForDocuments(createdDocuments + resetDocuments_);
|
2015-10-13 15:56:41 +02:00
|
|
|
} catch (const std::exception &exception) {
|
2018-05-31 15:21:53 +02:00
|
|
|
qWarning() << "Error in ClangCodeModelServer::documentsOpened:" << exception.what();
|
2015-10-13 15:56:41 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-31 15:21:53 +02:00
|
|
|
void ClangCodeModelServer::documentsChanged(const DocumentsChangedMessage &message)
|
2015-10-13 15:56:41 +02:00
|
|
|
{
|
2018-05-31 15:21:53 +02:00
|
|
|
qCDebug(serverLog) << "########## documentsChanged";
|
|
|
|
|
TIME_SCOPE_DURATION("ClangCodeModelServer::documentsChanged");
|
2015-10-13 15:56:41 +02:00
|
|
|
|
2015-06-01 18:51:55 +02:00
|
|
|
try {
|
2018-04-04 18:25:23 +02:00
|
|
|
const auto newerFileContainers = documents.newerFileContainers(message.fileContainers);
|
2015-08-31 12:40:14 +02:00
|
|
|
if (newerFileContainers.size() > 0) {
|
2017-05-04 11:49:31 +02:00
|
|
|
std::vector<Document> updateDocuments = documents.update(newerFileContainers);
|
2015-08-31 12:40:14 +02:00
|
|
|
unsavedFiles.createOrUpdate(newerFileContainers);
|
2016-05-31 16:07:09 +02:00
|
|
|
|
2017-05-04 11:49:31 +02:00
|
|
|
for (Document &document : updateDocuments) {
|
|
|
|
|
if (!document.isResponsivenessIncreased())
|
|
|
|
|
document.setResponsivenessIncreaseNeeded(true);
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-14 16:16:10 +02:00
|
|
|
// Start the jobs on the next event loop iteration since otherwise
|
|
|
|
|
// we might block the translation unit for a completion request
|
|
|
|
|
// that comes right after this message.
|
2018-05-31 15:21:53 +02:00
|
|
|
updateAnnotationsTimer.start(0);
|
2015-08-31 12:40:14 +02:00
|
|
|
}
|
2015-06-01 18:51:55 +02:00
|
|
|
} catch (const std::exception &exception) {
|
2018-05-31 15:21:53 +02:00
|
|
|
qWarning() << "Error in ClangCodeModelServer::documentsChanged:" << exception.what();
|
2015-06-01 18:51:55 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-31 15:21:53 +02:00
|
|
|
void ClangCodeModelServer::documentsClosed(const ClangBackEnd::DocumentsClosedMessage &message)
|
2015-06-01 18:51:55 +02:00
|
|
|
{
|
2018-05-31 15:21:53 +02:00
|
|
|
qCDebug(serverLog) << "########## documentsClosed";
|
|
|
|
|
TIME_SCOPE_DURATION("ClangCodeModelServer::documentsClosed");
|
2015-07-28 16:04:49 +02:00
|
|
|
|
2015-06-01 18:51:55 +02:00
|
|
|
try {
|
2018-04-04 18:25:23 +02:00
|
|
|
for (const auto &fileContainer : message.fileContainers) {
|
2016-09-08 15:49:54 +02:00
|
|
|
const Document &document = documents.document(fileContainer);
|
|
|
|
|
documentProcessors().remove(document);
|
|
|
|
|
}
|
2018-04-04 18:25:23 +02:00
|
|
|
documents.remove(message.fileContainers);
|
|
|
|
|
unsavedFiles.remove(message.fileContainers);
|
2015-06-01 18:51:55 +02:00
|
|
|
} catch (const std::exception &exception) {
|
2018-05-31 15:21:53 +02:00
|
|
|
qWarning() << "Error in ClangCodeModelServer::documentsClosed:" << exception.what();
|
2015-06-01 18:51:55 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-10 14:54:45 +01:00
|
|
|
static DocumentResetInfos toDocumentResetInfos(const std::vector<Document> &documents)
|
|
|
|
|
{
|
|
|
|
|
DocumentResetInfos infos;
|
|
|
|
|
for (const auto &d : documents)
|
|
|
|
|
infos.push_back(DocumentResetInfo{d, d.fileContainer()});
|
|
|
|
|
return infos;
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-31 15:21:53 +02:00
|
|
|
void ClangCodeModelServer::projectPartsUpdated(const ProjectPartsUpdatedMessage &message)
|
2015-06-01 18:51:55 +02:00
|
|
|
{
|
2018-05-31 15:21:53 +02:00
|
|
|
qCDebug(serverLog) << "########## projectPartsUpdated";
|
|
|
|
|
TIME_SCOPE_DURATION("ClangCodeModelServer::projectPartsUpdated");
|
2015-07-28 16:04:49 +02:00
|
|
|
|
2015-06-01 18:51:55 +02:00
|
|
|
try {
|
2018-04-04 18:25:23 +02:00
|
|
|
projects.createOrUpdate(message.projectContainers);
|
2017-05-03 15:48:44 +02:00
|
|
|
std::vector<Document> affectedDocuments = documents.setDocumentsDirtyIfProjectPartChanged();
|
|
|
|
|
|
2018-01-10 14:54:45 +01:00
|
|
|
resetDocuments(toDocumentResetInfos(affectedDocuments));
|
2016-05-31 16:07:09 +02:00
|
|
|
|
|
|
|
|
processJobsForDirtyAndVisibleDocuments();
|
2015-06-01 18:51:55 +02:00
|
|
|
} catch (const std::exception &exception) {
|
2018-05-31 15:21:53 +02:00
|
|
|
qWarning() << "Error in ClangCodeModelServer::projectPartsUpdated:" << exception.what();
|
2015-06-01 18:51:55 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-31 15:21:53 +02:00
|
|
|
void ClangCodeModelServer::projectPartsRemoved(const ProjectPartsRemovedMessage &message)
|
2015-06-01 18:51:55 +02:00
|
|
|
{
|
2018-05-31 15:21:53 +02:00
|
|
|
qCDebug(serverLog) << "########## projectPartsRemoved";
|
|
|
|
|
TIME_SCOPE_DURATION("ClangCodeModelServer::projectPartsRemoved");
|
2015-07-28 16:04:49 +02:00
|
|
|
|
2015-06-01 18:51:55 +02:00
|
|
|
try {
|
2018-04-04 18:25:23 +02:00
|
|
|
projects.remove(message.projectPartIds);
|
2015-06-01 18:51:55 +02:00
|
|
|
} catch (const std::exception &exception) {
|
2018-05-31 15:21:53 +02:00
|
|
|
qWarning() << "Error in ClangCodeModelServer::projectPartsRemoved:" << exception.what();
|
2015-08-31 16:10:36 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-31 15:21:53 +02:00
|
|
|
void ClangCodeModelServer::unsavedFilesUpdated(const UnsavedFilesUpdatedMessage &message)
|
2015-08-31 16:10:36 +02:00
|
|
|
{
|
2018-05-31 15:21:53 +02:00
|
|
|
qCDebug(serverLog) << "########## unsavedFilesUpdated";
|
|
|
|
|
TIME_SCOPE_DURATION("ClangCodeModelServer::unsavedFilesUpdated");
|
2015-08-31 16:10:36 +02:00
|
|
|
|
|
|
|
|
try {
|
2018-04-04 18:25:23 +02:00
|
|
|
unsavedFiles.createOrUpdate(message.fileContainers);
|
|
|
|
|
documents.updateDocumentsWithChangedDependencies(message.fileContainers);
|
2016-05-31 16:07:09 +02:00
|
|
|
|
2018-05-31 15:21:53 +02:00
|
|
|
updateAnnotationsTimer.start(updateAnnotationsTimeOutInMs);
|
2015-08-31 16:10:36 +02:00
|
|
|
} catch (const std::exception &exception) {
|
2018-05-31 15:21:53 +02:00
|
|
|
qWarning() << "Error in ClangCodeModelServer::unsavedFilesUpdated:" << exception.what();
|
2015-08-31 16:10:36 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-31 15:21:53 +02:00
|
|
|
void ClangCodeModelServer::unsavedFilesRemoved(const UnsavedFilesRemovedMessage &message)
|
2015-08-31 16:10:36 +02:00
|
|
|
{
|
2018-05-31 15:21:53 +02:00
|
|
|
qCDebug(serverLog) << "########## unsavedFilesRemoved";
|
|
|
|
|
TIME_SCOPE_DURATION("ClangCodeModelServer::unsavedFilesRemoved");
|
2015-08-31 16:10:36 +02:00
|
|
|
|
|
|
|
|
try {
|
2018-04-04 18:25:23 +02:00
|
|
|
unsavedFiles.remove(message.fileContainers);
|
|
|
|
|
documents.updateDocumentsWithChangedDependencies(message.fileContainers);
|
2015-08-31 16:10:36 +02:00
|
|
|
} catch (const std::exception &exception) {
|
2018-05-31 15:21:53 +02:00
|
|
|
qWarning() << "Error in ClangCodeModelServer::unsavedFilesRemoved:" << exception.what();
|
2015-06-01 18:51:55 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-31 15:21:53 +02:00
|
|
|
void ClangCodeModelServer::requestCompletions(const ClangBackEnd::RequestCompletionsMessage &message)
|
2015-06-01 18:51:55 +02:00
|
|
|
{
|
2018-05-31 15:21:53 +02:00
|
|
|
qCDebug(serverLog) << "########## requestCompletions";
|
|
|
|
|
TIME_SCOPE_DURATION("ClangCodeModelServer::requestCompletions");
|
2015-07-28 16:04:49 +02:00
|
|
|
|
2015-06-01 18:51:55 +02:00
|
|
|
try {
|
2018-04-04 18:25:23 +02:00
|
|
|
Document document = documents.document(message.filePath, message.projectPartId);
|
2017-05-04 12:43:38 +02:00
|
|
|
DocumentProcessor processor = documentProcessors().processor(document);
|
2016-06-05 19:59:23 +02:00
|
|
|
|
2018-05-31 15:21:53 +02:00
|
|
|
JobRequest jobRequest = processor.createJobRequest(JobRequest::Type::RequestCompletions);
|
2018-04-04 18:25:23 +02:00
|
|
|
jobRequest.line = message.line;
|
|
|
|
|
jobRequest.column = message.column;
|
|
|
|
|
jobRequest.funcNameStartLine = message.funcNameStartLine;
|
|
|
|
|
jobRequest.funcNameStartColumn = message.funcNameStartColumn;
|
|
|
|
|
jobRequest.ticketNumber = message.ticketNumber;
|
2015-06-01 18:51:55 +02:00
|
|
|
|
2016-09-08 15:49:54 +02:00
|
|
|
processor.addJob(jobRequest);
|
|
|
|
|
processor.process();
|
2015-06-01 18:51:55 +02:00
|
|
|
} catch (const std::exception &exception) {
|
2018-05-31 15:21:53 +02:00
|
|
|
qWarning() << "Error in ClangCodeModelServer::requestCompletions:" << exception.what();
|
2015-06-01 18:51:55 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-31 15:21:53 +02:00
|
|
|
void ClangCodeModelServer::requestAnnotations(const RequestAnnotationsMessage &message)
|
2015-08-31 16:28:26 +02:00
|
|
|
{
|
2018-05-31 15:21:53 +02:00
|
|
|
qCDebug(serverLog) << "########## requestAnnotations";
|
|
|
|
|
TIME_SCOPE_DURATION("ClangCodeModelServer::requestAnnotations");
|
2015-11-18 17:07:44 +01:00
|
|
|
|
|
|
|
|
try {
|
2018-04-04 18:25:23 +02:00
|
|
|
auto document = documents.document(message.fileContainer.filePath,
|
|
|
|
|
message.fileContainer.projectPartId);
|
2015-11-18 17:07:44 +01:00
|
|
|
|
2016-09-08 15:49:54 +02:00
|
|
|
DocumentProcessor processor = documentProcessors().processor(document);
|
2018-05-31 15:21:53 +02:00
|
|
|
processor.addJob(JobRequest::Type::RequestAnnotations);
|
|
|
|
|
processor.addJob(JobRequest::Type::UpdateExtraAnnotations);
|
2016-09-08 15:49:54 +02:00
|
|
|
processor.process();
|
2016-06-09 12:55:42 +02:00
|
|
|
} catch (const std::exception &exception) {
|
2018-05-31 15:21:53 +02:00
|
|
|
qWarning() << "Error in ClangCodeModelServer::requestAnnotations:" << exception.what();
|
2015-11-18 17:07:44 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-27 10:58:05 +02:00
|
|
|
template <class MessageType>
|
|
|
|
|
static void fillJobRequest(JobRequest &jobRequest, const MessageType &message)
|
|
|
|
|
{
|
2018-04-04 18:25:23 +02:00
|
|
|
jobRequest.line = message.line;
|
|
|
|
|
jobRequest.column = message.column;
|
|
|
|
|
jobRequest.ticketNumber = message.ticketNumber;
|
|
|
|
|
jobRequest.textCodecName = message.fileContainer.textCodecName;
|
2017-07-27 10:58:05 +02:00
|
|
|
// The unsaved files might get updater later, so take the current
|
|
|
|
|
// revision for the request.
|
2018-04-04 18:25:23 +02:00
|
|
|
jobRequest.documentRevision = message.fileContainer.documentRevision;
|
2017-07-27 10:58:05 +02:00
|
|
|
}
|
|
|
|
|
|
2017-06-09 12:19:09 +02:00
|
|
|
void ClangCodeModelServer::requestReferences(const RequestReferencesMessage &message)
|
|
|
|
|
{
|
2018-01-10 11:59:15 +01:00
|
|
|
qCDebug(serverLog) << "########## requestReferences";
|
2017-06-09 12:19:09 +02:00
|
|
|
TIME_SCOPE_DURATION("ClangCodeModelServer::requestReferences");
|
|
|
|
|
|
|
|
|
|
try {
|
2018-04-04 18:25:23 +02:00
|
|
|
const Document document = documents.document(message.fileContainer.filePath,
|
|
|
|
|
message.fileContainer.projectPartId);
|
2017-06-09 12:19:09 +02:00
|
|
|
DocumentProcessor processor = documentProcessors().processor(document);
|
|
|
|
|
|
|
|
|
|
JobRequest jobRequest = processor.createJobRequest(JobRequest::Type::RequestReferences);
|
2017-07-27 10:58:05 +02:00
|
|
|
fillJobRequest(jobRequest, message);
|
2018-04-04 18:25:23 +02:00
|
|
|
jobRequest.localReferences = message.local;
|
2017-06-09 12:19:09 +02:00
|
|
|
processor.addJob(jobRequest);
|
|
|
|
|
processor.process();
|
|
|
|
|
} catch (const std::exception &exception) {
|
|
|
|
|
qWarning() << "Error in ClangCodeModelServer::requestReferences:" << exception.what();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-27 10:58:05 +02:00
|
|
|
void ClangCodeModelServer::requestFollowSymbol(const RequestFollowSymbolMessage &message)
|
|
|
|
|
{
|
2018-01-10 11:59:15 +01:00
|
|
|
qCDebug(serverLog) << "########## requestFollowSymbol";
|
2017-07-27 11:42:37 +02:00
|
|
|
TIME_SCOPE_DURATION("ClangCodeModelServer::requestFollowSymbol");
|
2017-07-27 10:58:05 +02:00
|
|
|
|
|
|
|
|
try {
|
2018-04-04 18:25:23 +02:00
|
|
|
const Utf8String &projectPartId = message.fileContainer.projectPartId;
|
|
|
|
|
Document document = documents.document(message.fileContainer.filePath, projectPartId);
|
2017-07-27 10:58:05 +02:00
|
|
|
DocumentProcessor processor = documentProcessors().processor(document);
|
|
|
|
|
|
2018-05-31 15:21:53 +02:00
|
|
|
JobRequest jobRequest = processor.createJobRequest(JobRequest::Type::RequestFollowSymbol);
|
2017-07-27 10:58:05 +02:00
|
|
|
fillJobRequest(jobRequest, message);
|
|
|
|
|
processor.addJob(jobRequest);
|
|
|
|
|
processor.process();
|
|
|
|
|
} catch (const std::exception &exception) {
|
2017-07-27 11:42:37 +02:00
|
|
|
qWarning() << "Error in ClangCodeModelServer::requestFollowSymbol:" << exception.what();
|
2017-07-27 10:58:05 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-12 12:29:43 +01:00
|
|
|
void ClangCodeModelServer::requestToolTip(const RequestToolTipMessage &message)
|
|
|
|
|
{
|
|
|
|
|
TIME_SCOPE_DURATION("ClangCodeModelServer::requestToolTip");
|
|
|
|
|
|
|
|
|
|
try {
|
2018-04-04 18:25:23 +02:00
|
|
|
const Document document = documents.document(message.fileContainer.filePath,
|
|
|
|
|
message.fileContainer.projectPartId);
|
2018-01-12 12:29:43 +01:00
|
|
|
DocumentProcessor processor = documentProcessors().processor(document);
|
|
|
|
|
|
|
|
|
|
JobRequest jobRequest = processor.createJobRequest(JobRequest::Type::RequestToolTip);
|
|
|
|
|
fillJobRequest(jobRequest, message);
|
|
|
|
|
|
|
|
|
|
processor.addJob(jobRequest);
|
|
|
|
|
processor.process();
|
|
|
|
|
} catch (const std::exception &exception) {
|
|
|
|
|
qWarning() << "Error in ClangCodeModelServer::requestToolTip:" << exception.what();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-31 15:21:53 +02:00
|
|
|
void ClangCodeModelServer::documentVisibilityChanged(const DocumentVisibilityChangedMessage &message)
|
2015-11-25 15:29:28 +01:00
|
|
|
{
|
2018-05-31 15:21:53 +02:00
|
|
|
qCDebug(serverLog) << "########## documentVisibilityChanged";
|
|
|
|
|
TIME_SCOPE_DURATION("ClangCodeModelServer::documentVisibilityChanged");
|
2015-11-25 15:29:28 +01:00
|
|
|
|
|
|
|
|
try {
|
2018-04-04 18:25:23 +02:00
|
|
|
documents.setUsedByCurrentEditor(message.currentEditorFilePath);
|
|
|
|
|
documents.setVisibleInEditors(message.visibleEditorFilePaths);
|
2017-07-28 15:15:46 +02:00
|
|
|
processSuspendResumeJobs(documents.documents());
|
|
|
|
|
|
2018-05-31 15:21:53 +02:00
|
|
|
updateAnnotationsTimer.start(0);
|
2015-11-25 15:29:28 +01:00
|
|
|
} catch (const std::exception &exception) {
|
2018-05-31 15:21:53 +02:00
|
|
|
qWarning() << "Error in ClangCodeModelServer::documentVisibilityChanged:" << exception.what();
|
2015-11-25 15:29:28 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-07 10:42:12 +02:00
|
|
|
const Documents &ClangCodeModelServer::documentsForTestOnly() const
|
2015-10-13 15:56:41 +02:00
|
|
|
{
|
2016-09-07 10:42:12 +02:00
|
|
|
return documents;
|
2015-10-13 15:56:41 +02:00
|
|
|
}
|
|
|
|
|
|
2016-09-08 15:49:54 +02:00
|
|
|
QList<Jobs::RunningJob> ClangCodeModelServer::runningJobsForTestsOnly()
|
2016-05-31 16:07:09 +02:00
|
|
|
{
|
2016-09-08 15:49:54 +02:00
|
|
|
return documentProcessors().runningJobs();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ClangCodeModelServer::queueSizeForTestsOnly()
|
|
|
|
|
{
|
|
|
|
|
return documentProcessors().queueSize();
|
2016-05-31 16:07:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ClangCodeModelServer::isTimerRunningForTestOnly() const
|
|
|
|
|
{
|
2018-05-31 15:21:53 +02:00
|
|
|
return updateAnnotationsTimer.isActive();
|
2015-10-13 12:54:22 +02:00
|
|
|
}
|
|
|
|
|
|
2016-09-08 15:49:54 +02:00
|
|
|
void ClangCodeModelServer::processJobsForDirtyAndVisibleDocuments()
|
2015-12-02 13:31:07 +01:00
|
|
|
{
|
2016-10-14 13:05:44 +02:00
|
|
|
processJobsForDirtyCurrentDocument();
|
|
|
|
|
processTimerForVisibleButNotCurrentDocuments();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ClangCodeModelServer::processJobsForDirtyCurrentDocument()
|
|
|
|
|
{
|
2017-05-04 11:49:31 +02:00
|
|
|
auto currentDirtyDocuments = documents.filtered([](const Document &document) {
|
2017-05-03 10:10:50 +02:00
|
|
|
return document.isDirty() && document.isUsedByCurrentEditor();
|
2016-10-14 13:05:44 +02:00
|
|
|
});
|
|
|
|
|
QTC_CHECK(currentDirtyDocuments.size() <= 1);
|
|
|
|
|
|
|
|
|
|
addAndRunUpdateJobs(currentDirtyDocuments);
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-04 11:49:31 +02:00
|
|
|
void ClangCodeModelServer::addAndRunUpdateJobs(std::vector<Document> documents)
|
2016-10-14 13:05:44 +02:00
|
|
|
{
|
2017-05-04 11:49:31 +02:00
|
|
|
for (auto &document : documents) {
|
2016-10-14 13:05:44 +02:00
|
|
|
DocumentProcessor processor = documentProcessors().processor(document);
|
2017-05-04 11:49:31 +02:00
|
|
|
|
|
|
|
|
// Run the regular edit-reparse-job
|
2018-05-31 15:21:53 +02:00
|
|
|
processor.addJob(JobRequest::Type::UpdateAnnotations,
|
2017-05-04 12:43:38 +02:00
|
|
|
PreferredTranslationUnit::PreviouslyParsed);
|
2018-05-31 15:21:53 +02:00
|
|
|
processor.addJob(JobRequest::Type::UpdateExtraAnnotations,
|
2018-04-12 11:09:41 +02:00
|
|
|
PreferredTranslationUnit::RecentlyParsed);
|
2016-10-14 13:05:44 +02:00
|
|
|
processor.process();
|
2017-05-04 11:49:31 +02:00
|
|
|
|
|
|
|
|
// If requested, run jobs to increase the responsiveness of the document
|
|
|
|
|
if (useSupportiveTranslationUnit() && document.isResponsivenessIncreaseNeeded()) {
|
|
|
|
|
QTC_CHECK(!document.isResponsivenessIncreased());
|
|
|
|
|
QTC_CHECK(!processor.hasSupportiveTranslationUnit());
|
|
|
|
|
document.setResponsivenessIncreaseNeeded(false);
|
|
|
|
|
processor.startInitializingSupportiveTranslationUnit();
|
|
|
|
|
}
|
2016-10-14 13:05:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ClangCodeModelServer::processTimerForVisibleButNotCurrentDocuments()
|
|
|
|
|
{
|
|
|
|
|
if (documents.dirtyAndVisibleButNotCurrentDocuments().empty()) {
|
|
|
|
|
updateVisibleButNotCurrentDocumentsTimer.stop();
|
|
|
|
|
} else {
|
|
|
|
|
updateVisibleButNotCurrentDocumentsTimer.start(
|
|
|
|
|
updateVisibleButNotCurrentDocumentsTimeOutInMs);
|
2016-05-31 16:07:09 +02:00
|
|
|
}
|
2016-10-14 13:05:44 +02:00
|
|
|
}
|
2016-05-31 16:07:09 +02:00
|
|
|
|
2017-07-28 15:15:46 +02:00
|
|
|
void ClangCodeModelServer::processSuspendResumeJobs(const std::vector<Document> &documents)
|
|
|
|
|
{
|
|
|
|
|
const SuspendResumeJobs suspendResumeJobs = createSuspendResumeJobs(documents);
|
|
|
|
|
for (const SuspendResumeJobsEntry &entry : suspendResumeJobs) {
|
|
|
|
|
DocumentProcessor processor = documentProcessors().processor(entry.document);
|
|
|
|
|
processor.addJob(entry.jobRequestType, entry.preferredTranslationUnit);
|
2018-02-06 08:30:49 +01:00
|
|
|
if (entry.jobRequestType == JobRequest::Type::ResumeDocument) {
|
2018-05-31 15:21:53 +02:00
|
|
|
processor.addJob(JobRequest::Type::UpdateExtraAnnotations,
|
2018-04-12 11:09:41 +02:00
|
|
|
PreferredTranslationUnit::RecentlyParsed);
|
2018-02-06 08:30:49 +01:00
|
|
|
}
|
2017-07-28 15:15:46 +02:00
|
|
|
processor.process();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-10 14:54:45 +01:00
|
|
|
void ClangCodeModelServer::categorizeFileContainers(const QVector<FileContainer> &fileContainers,
|
|
|
|
|
QVector<FileContainer> &toCreate,
|
|
|
|
|
DocumentResetInfos &toReset) const
|
|
|
|
|
{
|
|
|
|
|
for (const FileContainer &fileContainer : fileContainers) {
|
|
|
|
|
const std::vector<Document> matching = documents.filtered([&](const Document &document) {
|
2018-04-04 18:25:23 +02:00
|
|
|
return document.filePath() == fileContainer.filePath;
|
2018-01-10 14:54:45 +01:00
|
|
|
});
|
|
|
|
|
if (matching.empty())
|
|
|
|
|
toCreate.push_back(fileContainer);
|
|
|
|
|
else
|
|
|
|
|
toReset.push_back(DocumentResetInfo{*matching.begin(), fileContainer});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<Document> ClangCodeModelServer::resetDocuments(const DocumentResetInfos &infos)
|
|
|
|
|
{
|
|
|
|
|
std::vector<Document> newDocuments;
|
|
|
|
|
|
|
|
|
|
for (const DocumentResetInfo &info : infos) {
|
|
|
|
|
const Document &document = info.documentToRemove;
|
2018-04-04 18:25:23 +02:00
|
|
|
QTC_CHECK(document.filePath() == info.fileContainer.filePath);
|
2018-01-10 14:54:45 +01:00
|
|
|
|
|
|
|
|
documents.remove({document.fileContainer()});
|
|
|
|
|
|
|
|
|
|
Document newDocument = *documents.create({info.fileContainer}).begin();
|
|
|
|
|
newDocument.setDirtyIfDependencyIsMet(document.filePath());
|
|
|
|
|
newDocument.setIsUsedByCurrentEditor(document.isUsedByCurrentEditor());
|
|
|
|
|
newDocument.setIsVisibleInEditor(document.isVisibleInEditor(), document.visibleTimePoint());
|
|
|
|
|
newDocument.setResponsivenessIncreaseNeeded(document.isResponsivenessIncreased());
|
|
|
|
|
|
|
|
|
|
documentProcessors().reset(document, newDocument);
|
|
|
|
|
|
|
|
|
|
newDocuments.push_back(newDocument);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return newDocuments;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-07 10:42:12 +02:00
|
|
|
void ClangCodeModelServer::processInitialJobsForDocuments(const std::vector<Document> &documents)
|
2016-05-31 16:07:09 +02:00
|
|
|
{
|
2016-09-07 10:42:12 +02:00
|
|
|
for (const auto &document : documents) {
|
2017-08-22 15:09:12 +02:00
|
|
|
DocumentProcessor processor = documentProcessors().processor(document);
|
2018-05-31 15:21:53 +02:00
|
|
|
processor.addJob(JobRequest::Type::UpdateAnnotations);
|
|
|
|
|
processor.addJob(JobRequest::Type::UpdateExtraAnnotations);
|
2016-09-08 15:49:54 +02:00
|
|
|
processor.process();
|
2016-05-31 16:07:09 +02:00
|
|
|
}
|
|
|
|
|
}
|
2015-12-02 13:31:07 +01:00
|
|
|
|
2018-05-31 15:21:53 +02:00
|
|
|
void ClangCodeModelServer::setUpdateAnnotationsTimeOutInMsForTestsOnly(int value)
|
2015-12-02 13:31:07 +01:00
|
|
|
{
|
2018-05-31 15:21:53 +02:00
|
|
|
updateAnnotationsTimeOutInMs = value;
|
2015-12-02 13:31:07 +01:00
|
|
|
}
|
|
|
|
|
|
2016-10-14 13:05:44 +02:00
|
|
|
void ClangCodeModelServer::setUpdateVisibleButNotCurrentDocumentsTimeOutInMsForTestsOnly(int value)
|
|
|
|
|
{
|
|
|
|
|
updateVisibleButNotCurrentDocumentsTimeOutInMs = value;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-08 15:49:54 +02:00
|
|
|
DocumentProcessors &ClangCodeModelServer::documentProcessors()
|
2016-05-31 16:07:09 +02:00
|
|
|
{
|
2016-09-08 15:49:54 +02:00
|
|
|
if (!documentProcessors_) {
|
|
|
|
|
// DocumentProcessors needs a reference to the client, but the client
|
|
|
|
|
// is not known at construction time of ClangCodeModelServer, so
|
|
|
|
|
// construct DocumentProcessors in a lazy manner.
|
|
|
|
|
documentProcessors_.reset(new DocumentProcessors(documents, unsavedFiles, projects, *client()));
|
2016-05-31 16:07:09 +02:00
|
|
|
}
|
|
|
|
|
|
2016-09-08 15:49:54 +02:00
|
|
|
return *documentProcessors_.data();
|
2015-06-01 18:51:55 +02:00
|
|
|
}
|
2016-05-31 16:07:09 +02:00
|
|
|
|
|
|
|
|
} // namespace ClangBackEnd
|