2014-08-19 15:59:29 +02:00
|
|
|
/****************************************************************************
|
|
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2014-08-19 15:59:29 +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:40 +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.
|
2014-08-19 15:59:29 +02:00
|
|
|
**
|
2016-01-15 14:57:40 +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.
|
2014-08-19 15:59:29 +02:00
|
|
|
**
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "clangeditordocumentprocessor.h"
|
|
|
|
|
|
2015-12-15 12:16:25 +01:00
|
|
|
#include "clangbackendipcintegration.h"
|
2016-01-29 17:17:18 +01:00
|
|
|
#include "clangdiagnostictooltipwidget.h"
|
2015-08-24 18:26:09 +02:00
|
|
|
#include "clangfixitoperation.h"
|
|
|
|
|
#include "clangfixitoperationsextractor.h"
|
2015-11-30 09:43:50 +01:00
|
|
|
#include "clanghighlightingmarksreporter.h"
|
2016-02-26 17:50:38 +01:00
|
|
|
#include "clangprojectsettings.h"
|
2015-05-08 15:48:17 +02:00
|
|
|
#include "clangutils.h"
|
2014-08-19 15:59:29 +02:00
|
|
|
|
2015-08-31 16:28:26 +02:00
|
|
|
#include <diagnosticcontainer.h>
|
|
|
|
|
#include <sourcelocationcontainer.h>
|
|
|
|
|
|
2016-02-26 17:50:38 +01:00
|
|
|
#include <cpptools/clangdiagnosticconfigsmodel.h>
|
|
|
|
|
#include <cpptools/clangdiagnosticconfigsmodel.h>
|
2016-01-12 12:51:33 +01:00
|
|
|
#include <cpptools/compileroptionsbuilder.h>
|
2015-11-10 16:54:53 +01:00
|
|
|
#include <cpptools/cppcodemodelsettings.h>
|
2015-12-15 11:59:48 +01:00
|
|
|
#include <cpptools/cppmodelmanager.h>
|
2016-01-11 20:50:14 +01:00
|
|
|
#include <cpptools/cpptoolsbridge.h>
|
2015-11-10 16:54:53 +01:00
|
|
|
#include <cpptools/cpptoolsreuse.h>
|
2014-08-19 15:59:29 +02:00
|
|
|
#include <cpptools/cppworkingcopy.h>
|
2016-11-22 15:17:42 +01:00
|
|
|
#include <cpptools/editordocumenthandle.h>
|
2014-08-19 15:59:29 +02:00
|
|
|
|
2015-08-24 18:26:09 +02:00
|
|
|
#include <texteditor/convenience.h>
|
2015-09-10 14:18:09 +02:00
|
|
|
#include <texteditor/fontsettings.h>
|
2015-08-31 16:28:26 +02:00
|
|
|
#include <texteditor/texteditor.h>
|
2015-09-10 14:18:09 +02:00
|
|
|
#include <texteditor/texteditorconstants.h>
|
|
|
|
|
#include <texteditor/texteditorsettings.h>
|
2015-08-31 16:28:26 +02:00
|
|
|
|
2014-08-19 15:59:29 +02:00
|
|
|
#include <cplusplus/CppDocument.h>
|
|
|
|
|
|
|
|
|
|
#include <utils/qtcassert.h>
|
2016-02-12 09:46:22 +01:00
|
|
|
#include <utils/runextensions.h>
|
2014-08-19 15:59:29 +02:00
|
|
|
|
2015-08-31 16:28:26 +02:00
|
|
|
#include <QTextBlock>
|
2016-10-04 16:23:42 +02:00
|
|
|
#include <QVBoxLayout>
|
|
|
|
|
#include <QWidget>
|
2015-08-31 16:28:26 +02:00
|
|
|
|
2014-08-19 15:59:29 +02:00
|
|
|
namespace ClangCodeModel {
|
2015-05-08 15:48:17 +02:00
|
|
|
namespace Internal {
|
2014-08-19 15:59:29 +02:00
|
|
|
|
2015-05-08 15:48:17 +02:00
|
|
|
ClangEditorDocumentProcessor::ClangEditorDocumentProcessor(
|
2015-12-15 12:16:25 +01:00
|
|
|
IpcCommunicator &ipcCommunicator,
|
2015-05-08 15:48:17 +02:00
|
|
|
TextEditor::TextDocument *document)
|
2016-01-11 20:40:05 +01:00
|
|
|
: BaseEditorDocumentProcessor(document->document(), document->filePath().toString())
|
2017-06-09 12:19:09 +02:00
|
|
|
, m_document(*document)
|
2015-09-04 12:15:17 +02:00
|
|
|
, m_diagnosticManager(document)
|
2015-12-15 12:16:25 +01:00
|
|
|
, m_ipcCommunicator(ipcCommunicator)
|
2015-09-01 17:34:07 +02:00
|
|
|
, m_parser(new ClangEditorDocumentParser(document->filePath().toString()))
|
2014-08-19 15:59:29 +02:00
|
|
|
, m_parserRevision(0)
|
|
|
|
|
, m_semanticHighlighter(document)
|
|
|
|
|
, m_builtinProcessor(document, /*enableSemanticHighlighter=*/ false)
|
|
|
|
|
{
|
2016-09-14 16:16:10 +02:00
|
|
|
m_updateTranslationUnitTimer.setSingleShot(true);
|
|
|
|
|
m_updateTranslationUnitTimer.setInterval(350);
|
|
|
|
|
connect(&m_updateTranslationUnitTimer, &QTimer::timeout,
|
|
|
|
|
this, &ClangEditorDocumentProcessor::updateTranslationUnitIfProjectPartExists);
|
|
|
|
|
|
2017-01-17 15:27:31 +01:00
|
|
|
connect(m_parser.data(), &ClangEditorDocumentParser::projectPartInfoUpdated,
|
|
|
|
|
this, &BaseEditorDocumentProcessor::projectPartInfoUpdated);
|
|
|
|
|
|
2014-08-19 15:59:29 +02:00
|
|
|
// Forwarding the semantic info from the builtin processor enables us to provide all
|
|
|
|
|
// editor (widget) related features that are not yet implemented by the clang plugin.
|
|
|
|
|
connect(&m_builtinProcessor, &CppTools::BuiltinEditorDocumentProcessor::cppDocumentUpdated,
|
|
|
|
|
this, &ClangEditorDocumentProcessor::cppDocumentUpdated);
|
|
|
|
|
connect(&m_builtinProcessor, &CppTools::BuiltinEditorDocumentProcessor::semanticInfoUpdated,
|
|
|
|
|
this, &ClangEditorDocumentProcessor::semanticInfoUpdated);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ClangEditorDocumentProcessor::~ClangEditorDocumentProcessor()
|
|
|
|
|
{
|
2016-09-14 16:16:10 +02:00
|
|
|
m_updateTranslationUnitTimer.stop();
|
|
|
|
|
|
2014-08-19 15:59:29 +02:00
|
|
|
m_parserWatcher.cancel();
|
|
|
|
|
m_parserWatcher.waitForFinished();
|
2015-05-08 15:48:17 +02:00
|
|
|
|
2015-07-14 19:01:32 +02:00
|
|
|
if (m_projectPart) {
|
2015-12-15 12:16:25 +01:00
|
|
|
m_ipcCommunicator.unregisterTranslationUnitsForEditor(
|
2015-07-14 19:01:32 +02:00
|
|
|
{ClangBackEnd::FileContainer(filePath(), m_projectPart->id())});
|
|
|
|
|
}
|
2014-08-19 15:59:29 +02:00
|
|
|
}
|
|
|
|
|
|
2016-12-14 18:58:23 +01:00
|
|
|
void ClangEditorDocumentProcessor::runImpl(
|
|
|
|
|
const CppTools::BaseEditorDocumentParser::UpdateParams &updateParams)
|
2014-08-19 15:59:29 +02:00
|
|
|
{
|
2016-09-14 16:16:10 +02:00
|
|
|
m_updateTranslationUnitTimer.start();
|
2015-08-31 16:28:26 +02:00
|
|
|
|
2014-08-19 15:59:29 +02:00
|
|
|
// Run clang parser
|
|
|
|
|
disconnect(&m_parserWatcher, &QFutureWatcher<void>::finished,
|
|
|
|
|
this, &ClangEditorDocumentProcessor::onParserFinished);
|
|
|
|
|
m_parserWatcher.cancel();
|
|
|
|
|
m_parserWatcher.setFuture(QFuture<void>());
|
|
|
|
|
|
|
|
|
|
m_parserRevision = revision();
|
|
|
|
|
connect(&m_parserWatcher, &QFutureWatcher<void>::finished,
|
|
|
|
|
this, &ClangEditorDocumentProcessor::onParserFinished);
|
2016-12-14 18:58:23 +01:00
|
|
|
const QFuture<void> future = ::Utils::runAsync(&runParser, parser(), updateParams);
|
2014-08-19 15:59:29 +02:00
|
|
|
m_parserWatcher.setFuture(future);
|
|
|
|
|
|
|
|
|
|
// Run builtin processor
|
2016-12-15 11:21:44 +01:00
|
|
|
m_builtinProcessor.runImpl(updateParams);
|
2014-08-19 15:59:29 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-19 14:37:26 +02:00
|
|
|
void ClangEditorDocumentProcessor::recalculateSemanticInfoDetached(bool force)
|
2014-08-19 15:59:29 +02:00
|
|
|
{
|
2015-06-19 14:37:26 +02:00
|
|
|
m_builtinProcessor.recalculateSemanticInfoDetached(force);
|
2014-08-19 15:59:29 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-19 14:43:41 +02:00
|
|
|
void ClangEditorDocumentProcessor::semanticRehighlight()
|
|
|
|
|
{
|
|
|
|
|
m_semanticHighlighter.updateFormatMapFromFontSettings();
|
2015-11-30 10:55:25 +01:00
|
|
|
|
|
|
|
|
if (m_projectPart)
|
|
|
|
|
requestDocumentAnnotations(m_projectPart->id());
|
2015-06-19 14:43:41 +02:00
|
|
|
}
|
|
|
|
|
|
2014-08-19 15:59:29 +02:00
|
|
|
CppTools::SemanticInfo ClangEditorDocumentProcessor::recalculateSemanticInfo()
|
|
|
|
|
{
|
|
|
|
|
return m_builtinProcessor.recalculateSemanticInfo();
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-01 17:34:07 +02:00
|
|
|
CppTools::BaseEditorDocumentParser::Ptr ClangEditorDocumentProcessor::parser()
|
2014-08-19 15:59:29 +02:00
|
|
|
{
|
2015-09-01 17:34:07 +02:00
|
|
|
return m_parser;
|
2014-08-19 15:59:29 +02:00
|
|
|
}
|
|
|
|
|
|
2014-11-28 12:03:58 +01:00
|
|
|
CPlusPlus::Snapshot ClangEditorDocumentProcessor::snapshot()
|
|
|
|
|
{
|
|
|
|
|
return m_builtinProcessor.snapshot();
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-19 15:59:29 +02:00
|
|
|
bool ClangEditorDocumentProcessor::isParserRunning() const
|
|
|
|
|
{
|
|
|
|
|
return m_parserWatcher.isRunning();
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-28 15:15:25 +02:00
|
|
|
bool ClangEditorDocumentProcessor::hasProjectPart() const
|
|
|
|
|
{
|
|
|
|
|
return m_projectPart;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-14 19:01:32 +02:00
|
|
|
CppTools::ProjectPart::Ptr ClangEditorDocumentProcessor::projectPart() const
|
|
|
|
|
{
|
|
|
|
|
return m_projectPart;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-18 12:19:46 +02:00
|
|
|
void ClangEditorDocumentProcessor::clearProjectPart()
|
|
|
|
|
{
|
|
|
|
|
m_projectPart.clear();
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-04 16:23:42 +02:00
|
|
|
void ClangEditorDocumentProcessor::updateCodeWarnings(
|
|
|
|
|
const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
|
|
|
|
|
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic,
|
|
|
|
|
uint documentRevision)
|
2015-08-31 16:28:26 +02:00
|
|
|
{
|
|
|
|
|
if (documentRevision == revision()) {
|
2017-07-10 09:53:34 +02:00
|
|
|
m_diagnosticManager.processNewDiagnostics(diagnostics, m_isProjectFile);
|
2015-09-04 12:15:17 +02:00
|
|
|
const auto codeWarnings = m_diagnosticManager.takeExtraSelections();
|
2016-02-05 15:16:02 +01:00
|
|
|
const auto fixitAvailableMarkers = m_diagnosticManager.takeFixItAvailableMarkers();
|
2016-10-04 16:23:42 +02:00
|
|
|
const auto creator = creatorForHeaderErrorDiagnosticWidget(firstHeaderErrorDiagnostic);
|
|
|
|
|
|
|
|
|
|
emit codeWarningsUpdated(revision(),
|
|
|
|
|
codeWarnings,
|
|
|
|
|
creator,
|
|
|
|
|
fixitAvailableMarkers);
|
2015-08-31 16:28:26 +02:00
|
|
|
}
|
|
|
|
|
}
|
2015-12-02 20:07:29 +01:00
|
|
|
namespace {
|
2015-08-31 16:28:26 +02:00
|
|
|
|
2015-12-02 20:07:29 +01:00
|
|
|
int positionInText(QTextDocument *textDocument,
|
|
|
|
|
const ClangBackEnd::SourceLocationContainer &sourceLocationContainer)
|
|
|
|
|
{
|
|
|
|
|
auto textBlock = textDocument->findBlockByNumber(int(sourceLocationContainer.line()) - 1);
|
|
|
|
|
|
|
|
|
|
return textBlock.position() + int(sourceLocationContainer.column()) - 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TextEditor::BlockRange
|
|
|
|
|
toTextEditorBlock(QTextDocument *textDocument,
|
|
|
|
|
const ClangBackEnd::SourceRangeContainer &sourceRangeContainer)
|
|
|
|
|
{
|
|
|
|
|
return TextEditor::BlockRange(positionInText(textDocument, sourceRangeContainer.start()),
|
|
|
|
|
positionInText(textDocument, sourceRangeContainer.end()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QList<TextEditor::BlockRange>
|
|
|
|
|
toTextEditorBlocks(QTextDocument *textDocument,
|
|
|
|
|
const QVector<ClangBackEnd::SourceRangeContainer> &ifdefedOutRanges)
|
2015-11-18 17:07:44 +01:00
|
|
|
{
|
|
|
|
|
QList<TextEditor::BlockRange> blockRanges;
|
|
|
|
|
blockRanges.reserve(ifdefedOutRanges.size());
|
|
|
|
|
|
|
|
|
|
for (const auto &range : ifdefedOutRanges)
|
2015-12-02 20:07:29 +01:00
|
|
|
blockRanges.append(toTextEditorBlock(textDocument, range));
|
2015-11-18 17:07:44 +01:00
|
|
|
|
|
|
|
|
return blockRanges;
|
|
|
|
|
}
|
2015-12-02 20:07:29 +01:00
|
|
|
}
|
2015-11-18 17:07:44 +01:00
|
|
|
|
|
|
|
|
void ClangEditorDocumentProcessor::updateHighlighting(
|
|
|
|
|
const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks,
|
|
|
|
|
const QVector<ClangBackEnd::SourceRangeContainer> &skippedPreprocessorRanges,
|
|
|
|
|
uint documentRevision)
|
|
|
|
|
{
|
|
|
|
|
if (documentRevision == revision()) {
|
2015-12-02 20:07:29 +01:00
|
|
|
const auto skippedPreprocessorBlocks = toTextEditorBlocks(textDocument(), skippedPreprocessorRanges);
|
2015-11-18 17:07:44 +01:00
|
|
|
emit ifdefedOutBlocksUpdated(documentRevision, skippedPreprocessorBlocks);
|
|
|
|
|
|
|
|
|
|
m_semanticHighlighter.setHighlightingRunner(
|
|
|
|
|
[highlightingMarks]() {
|
|
|
|
|
auto *reporter = new HighlightingMarksReporter(highlightingMarks);
|
|
|
|
|
return reporter->start();
|
|
|
|
|
});
|
|
|
|
|
m_semanticHighlighter.run();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-24 18:26:09 +02:00
|
|
|
static int currentLine(const TextEditor::AssistInterface &assistInterface)
|
|
|
|
|
{
|
|
|
|
|
int line, column;
|
|
|
|
|
TextEditor::Convenience::convertPosition(assistInterface.textDocument(),
|
|
|
|
|
assistInterface.position(),
|
|
|
|
|
&line,
|
|
|
|
|
&column);
|
|
|
|
|
return line;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TextEditor::QuickFixOperations ClangEditorDocumentProcessor::extraRefactoringOperations(
|
|
|
|
|
const TextEditor::AssistInterface &assistInterface)
|
|
|
|
|
{
|
|
|
|
|
ClangFixItOperationsExtractor extractor(m_diagnosticManager.diagnosticsWithFixIts());
|
|
|
|
|
|
|
|
|
|
return extractor.extract(assistInterface.fileName(), currentLine(assistInterface));
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-27 13:37:19 +01:00
|
|
|
bool ClangEditorDocumentProcessor::hasDiagnosticsAt(uint line, uint column) const
|
|
|
|
|
{
|
|
|
|
|
return m_diagnosticManager.hasDiagnosticsAt(line, column);
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-22 08:57:32 +02:00
|
|
|
void ClangEditorDocumentProcessor::addDiagnosticToolTipToLayout(uint line,
|
|
|
|
|
uint column,
|
|
|
|
|
QLayout *target) const
|
2016-01-27 13:37:19 +01:00
|
|
|
{
|
2016-10-18 18:01:57 +02:00
|
|
|
using Internal::ClangDiagnosticWidget;
|
|
|
|
|
|
|
|
|
|
const QVector<ClangBackEnd::DiagnosticContainer> diagnostics
|
|
|
|
|
= m_diagnosticManager.diagnosticsAt(line, column);
|
|
|
|
|
|
|
|
|
|
target->addWidget(ClangDiagnosticWidget::create(diagnostics, ClangDiagnosticWidget::ToolTip));
|
2016-01-27 13:37:19 +01:00
|
|
|
}
|
|
|
|
|
|
2016-09-14 16:16:10 +02:00
|
|
|
void ClangEditorDocumentProcessor::editorDocumentTimerRestarted()
|
|
|
|
|
{
|
|
|
|
|
m_updateTranslationUnitTimer.stop(); // Wait for the next call to run().
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-03 13:29:30 +02:00
|
|
|
void ClangEditorDocumentProcessor::invalidateDiagnostics()
|
|
|
|
|
{
|
|
|
|
|
m_diagnosticManager.invalidateDiagnostics();
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-18 15:05:46 +01:00
|
|
|
void ClangEditorDocumentProcessor::setParserConfig(
|
|
|
|
|
const CppTools::BaseEditorDocumentParser::Configuration config)
|
|
|
|
|
{
|
|
|
|
|
m_parser->setConfiguration(config);
|
|
|
|
|
m_builtinProcessor.parser()->setConfiguration(config);
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-09 12:19:09 +02:00
|
|
|
static bool isCursorOnIdentifier(const QTextCursor &textCursor)
|
|
|
|
|
{
|
|
|
|
|
QTextDocument *document = textCursor.document();
|
|
|
|
|
return CppTools::isValidIdentifierChar(document->characterAt(textCursor.position()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static QFuture<CppTools::CursorInfo> defaultCursorInfoFuture()
|
|
|
|
|
{
|
|
|
|
|
QFutureInterface<CppTools::CursorInfo> futureInterface;
|
|
|
|
|
futureInterface.reportResult(CppTools::CursorInfo());
|
|
|
|
|
futureInterface.reportFinished();
|
|
|
|
|
|
|
|
|
|
return futureInterface.future();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool convertPosition(const QTextCursor &textCursor, int *line, int *column)
|
|
|
|
|
{
|
|
|
|
|
const bool converted = TextEditor::Convenience::convertPosition(textCursor.document(),
|
|
|
|
|
textCursor.position(),
|
|
|
|
|
line,
|
|
|
|
|
column);
|
|
|
|
|
QTC_CHECK(converted);
|
|
|
|
|
return converted;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-24 13:23:01 +02:00
|
|
|
QFuture<CppTools::CursorInfo>
|
|
|
|
|
ClangEditorDocumentProcessor::cursorInfo(const CppTools::CursorInfoParams ¶ms)
|
|
|
|
|
{
|
2017-06-09 12:19:09 +02:00
|
|
|
int line, column;
|
|
|
|
|
convertPosition(params.textCursor, &line, &column);
|
|
|
|
|
++column; // for 1-based columns
|
|
|
|
|
|
|
|
|
|
if (!isCursorOnIdentifier(params.textCursor))
|
|
|
|
|
return defaultCursorInfoFuture();
|
|
|
|
|
|
|
|
|
|
const QTextBlock block = params.textCursor.document()->findBlockByNumber(line - 1);
|
|
|
|
|
column += ClangCodeModel::Utils::extraUtf8CharsShift(block.text(), column);
|
|
|
|
|
|
|
|
|
|
return m_ipcCommunicator.requestReferences(simpleFileContainer(),
|
|
|
|
|
static_cast<quint32>(line),
|
|
|
|
|
static_cast<quint32>(column),
|
|
|
|
|
textDocument());
|
2017-05-24 13:23:01 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-30 10:55:25 +01:00
|
|
|
ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainerWithArguments() const
|
2015-10-05 11:17:03 +02:00
|
|
|
{
|
2015-11-30 10:55:25 +01:00
|
|
|
return fileContainerWithArguments(m_projectPart.data());
|
2015-10-05 11:17:03 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-25 15:11:23 +01:00
|
|
|
void ClangEditorDocumentProcessor::clearDiagnosticsWithFixIts()
|
|
|
|
|
{
|
|
|
|
|
m_diagnosticManager.clearDiagnosticsWithFixIts();
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-14 19:01:32 +02:00
|
|
|
ClangEditorDocumentProcessor *ClangEditorDocumentProcessor::get(const QString &filePath)
|
|
|
|
|
{
|
2016-01-11 20:50:14 +01:00
|
|
|
auto *processor = CppTools::CppToolsBridge::baseEditorDocumentProcessor(filePath);
|
|
|
|
|
|
|
|
|
|
return qobject_cast<ClangEditorDocumentProcessor*>(processor);
|
2015-07-14 19:01:32 +02:00
|
|
|
}
|
|
|
|
|
|
2015-09-24 12:17:43 +02:00
|
|
|
static bool isProjectPartLoadedOrIsFallback(CppTools::ProjectPart::Ptr projectPart)
|
|
|
|
|
{
|
|
|
|
|
return projectPart
|
2015-09-24 14:25:53 +02:00
|
|
|
&& (projectPart->id().isEmpty() || ClangCodeModel::Utils::isProjectPartLoaded(projectPart));
|
2015-09-24 12:17:43 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-18 17:07:44 +01:00
|
|
|
void ClangEditorDocumentProcessor::updateProjectPartAndTranslationUnitForEditor()
|
2015-07-14 19:01:32 +02:00
|
|
|
{
|
2017-01-17 15:27:31 +01:00
|
|
|
const CppTools::ProjectPart::Ptr projectPart = m_parser->projectPartInfo().projectPart;
|
2015-07-14 19:01:32 +02:00
|
|
|
|
2015-09-24 12:17:43 +02:00
|
|
|
if (isProjectPartLoadedOrIsFallback(projectPart)) {
|
2015-11-30 10:55:25 +01:00
|
|
|
registerTranslationUnitForEditor(projectPart.data());
|
2015-08-31 16:28:26 +02:00
|
|
|
|
2015-09-24 12:17:43 +02:00
|
|
|
m_projectPart = projectPart;
|
2017-07-10 09:53:34 +02:00
|
|
|
m_isProjectFile = m_parser->projectPartInfo().hints
|
|
|
|
|
& CppTools::ProjectPartInfo::IsFromProjectMatch;
|
2015-09-24 12:17:43 +02:00
|
|
|
}
|
2015-07-14 19:01:32 +02:00
|
|
|
}
|
|
|
|
|
|
2014-08-19 15:59:29 +02:00
|
|
|
void ClangEditorDocumentProcessor::onParserFinished()
|
|
|
|
|
{
|
|
|
|
|
if (revision() != m_parserRevision)
|
|
|
|
|
return;
|
|
|
|
|
|
2015-11-18 17:07:44 +01:00
|
|
|
updateProjectPartAndTranslationUnitForEditor();
|
2015-07-14 19:01:32 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-30 10:55:25 +01:00
|
|
|
void ClangEditorDocumentProcessor::registerTranslationUnitForEditor(CppTools::ProjectPart *projectPart)
|
2015-07-14 19:01:32 +02:00
|
|
|
{
|
2017-02-27 13:10:19 +01:00
|
|
|
// On registration we send the document content immediately as an unsaved
|
|
|
|
|
// file, because
|
|
|
|
|
// (1) a refactoring action might have opened and already modified
|
|
|
|
|
// this document.
|
|
|
|
|
// (2) it prevents an extra preamble generation on first user
|
|
|
|
|
// modification of the document in case the line endings on disk
|
|
|
|
|
// differ from the ones returned by textDocument()->toPlainText(),
|
|
|
|
|
// like on Windows.
|
|
|
|
|
|
2015-07-14 19:01:32 +02:00
|
|
|
if (m_projectPart) {
|
2017-02-27 13:10:19 +01:00
|
|
|
if (projectPart->id() == m_projectPart->id())
|
|
|
|
|
return;
|
|
|
|
|
m_ipcCommunicator.unregisterTranslationUnitsForEditor({fileContainerWithArguments()});
|
2015-08-31 16:28:26 +02:00
|
|
|
}
|
2017-02-27 13:10:19 +01:00
|
|
|
|
|
|
|
|
m_ipcCommunicator.registerTranslationUnitsForEditor(
|
|
|
|
|
{fileContainerWithArgumentsAndDocumentContent(projectPart)});
|
|
|
|
|
ClangCodeModel::Utils::setLastSentDocumentRevision(filePath(), revision());
|
2015-08-31 16:28:26 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-30 10:55:25 +01:00
|
|
|
void ClangEditorDocumentProcessor::updateTranslationUnitIfProjectPartExists()
|
2015-08-31 16:28:26 +02:00
|
|
|
{
|
2015-11-30 10:55:25 +01:00
|
|
|
if (m_projectPart) {
|
|
|
|
|
const ClangBackEnd::FileContainer fileContainer = fileContainerWithDocumentContent(m_projectPart->id());
|
2015-08-31 16:28:26 +02:00
|
|
|
|
2015-12-15 12:16:25 +01:00
|
|
|
m_ipcCommunicator.updateTranslationUnitWithRevisionCheck(fileContainer);
|
2015-08-31 16:28:26 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-30 10:55:25 +01:00
|
|
|
void ClangEditorDocumentProcessor::requestDocumentAnnotations(const QString &projectpartId)
|
2015-11-18 17:07:44 +01:00
|
|
|
{
|
2015-11-30 10:55:25 +01:00
|
|
|
const auto fileContainer = fileContainerWithDocumentContent(projectpartId);
|
2015-11-18 17:07:44 +01:00
|
|
|
|
2016-06-09 12:55:42 +02:00
|
|
|
m_ipcCommunicator.requestDocumentAnnotations(fileContainer);
|
2014-08-19 15:59:29 +02:00
|
|
|
}
|
|
|
|
|
|
2016-10-04 16:23:42 +02:00
|
|
|
CppTools::BaseEditorDocumentProcessor::HeaderErrorDiagnosticWidgetCreator
|
|
|
|
|
ClangEditorDocumentProcessor::creatorForHeaderErrorDiagnosticWidget(
|
|
|
|
|
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic)
|
|
|
|
|
{
|
|
|
|
|
if (firstHeaderErrorDiagnostic.text().isEmpty())
|
|
|
|
|
return CppTools::BaseEditorDocumentProcessor::HeaderErrorDiagnosticWidgetCreator();
|
|
|
|
|
|
|
|
|
|
return [firstHeaderErrorDiagnostic]() {
|
|
|
|
|
auto vbox = new QVBoxLayout;
|
|
|
|
|
vbox->setMargin(0);
|
|
|
|
|
vbox->setContentsMargins(10, 0, 0, 2);
|
|
|
|
|
vbox->setSpacing(2);
|
|
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
vbox->addWidget(ClangDiagnosticWidget::create({firstHeaderErrorDiagnostic},
|
|
|
|
|
ClangDiagnosticWidget::InfoBar));
|
2016-10-04 16:23:42 +02:00
|
|
|
|
|
|
|
|
auto widget = new QWidget;
|
|
|
|
|
widget->setLayout(vbox);
|
|
|
|
|
|
|
|
|
|
return widget;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-09 12:19:09 +02:00
|
|
|
ClangBackEnd::FileContainer ClangEditorDocumentProcessor::simpleFileContainer() const
|
|
|
|
|
{
|
|
|
|
|
Utf8String projectPartId;
|
|
|
|
|
if (m_projectPart)
|
|
|
|
|
projectPartId = m_projectPart->id();
|
|
|
|
|
|
|
|
|
|
return ClangBackEnd::FileContainer(filePath(), projectPartId, Utf8String(), false, revision());
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-05 13:57:57 +01:00
|
|
|
static CppTools::ProjectPart projectPartForLanguageOption(CppTools::ProjectPart *projectPart)
|
|
|
|
|
{
|
|
|
|
|
if (projectPart)
|
|
|
|
|
return *projectPart;
|
|
|
|
|
return *CppTools::CppModelManager::instance()->fallbackProjectPart().data();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static QStringList languageOptions(const QString &filePath, CppTools::ProjectPart *projectPart)
|
|
|
|
|
{
|
2015-11-05 11:47:01 +01:00
|
|
|
const auto theProjectPart = projectPartForLanguageOption(projectPart);
|
2017-01-12 18:01:12 +01:00
|
|
|
|
|
|
|
|
// Determine file kind with respect to ambiguous headers.
|
|
|
|
|
CppTools::ProjectFile::Kind fileKind = CppTools::ProjectFile::classify(filePath);
|
|
|
|
|
if (fileKind == CppTools::ProjectFile::AmbiguousHeader) {
|
|
|
|
|
fileKind = theProjectPart.languageVersion <= CppTools::ProjectPart::LatestCVersion
|
|
|
|
|
? CppTools::ProjectFile::CHeader
|
|
|
|
|
: CppTools::ProjectFile::CXXHeader;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-05 13:57:57 +01:00
|
|
|
CppTools::CompilerOptionsBuilder builder(theProjectPart);
|
2017-01-12 18:01:12 +01:00
|
|
|
builder.addLanguageOption(fileKind);
|
2015-11-05 13:57:57 +01:00
|
|
|
|
|
|
|
|
return builder.options();
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-26 17:50:38 +01:00
|
|
|
static QStringList warningOptions(CppTools::ProjectPart *projectPart)
|
|
|
|
|
{
|
|
|
|
|
if (projectPart && projectPart->project) {
|
|
|
|
|
ClangProjectSettings projectSettings(projectPart->project);
|
2017-05-23 09:49:22 +02:00
|
|
|
if (!projectSettings.useGlobalConfig()) {
|
2016-02-26 17:50:38 +01:00
|
|
|
const Core::Id warningConfigId = projectSettings.warningConfigId();
|
|
|
|
|
const CppTools::ClangDiagnosticConfigsModel configsModel(
|
|
|
|
|
CppTools::codeModelSettings()->clangCustomDiagnosticConfigs());
|
|
|
|
|
if (configsModel.hasConfigWithId(warningConfigId))
|
2017-05-23 09:49:22 +02:00
|
|
|
return configsModel.configWithId(warningConfigId).commandLineWarnings();
|
2016-02-26 17:50:38 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-23 09:49:22 +02:00
|
|
|
return CppTools::codeModelSettings()->clangDiagnosticConfig().commandLineWarnings();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static QStringList commandLineOptions(CppTools::ProjectPart *projectPart)
|
|
|
|
|
{
|
|
|
|
|
if (!projectPart || !projectPart->project)
|
|
|
|
|
return ClangProjectSettings::globalCommandLineOptions();
|
|
|
|
|
|
|
|
|
|
return ClangProjectSettings{projectPart->project}.commandLineOptions();
|
2016-02-26 17:50:38 +01:00
|
|
|
}
|
|
|
|
|
|
2016-11-02 12:21:54 +03:00
|
|
|
static QStringList precompiledHeaderOptions(
|
|
|
|
|
const QString& filePath,
|
|
|
|
|
CppTools::ProjectPart *projectPart)
|
|
|
|
|
{
|
|
|
|
|
using namespace CppTools;
|
|
|
|
|
|
|
|
|
|
if (CppTools::getPchUsage() == CompilerOptionsBuilder::PchUsage::None)
|
|
|
|
|
return QStringList();
|
|
|
|
|
|
|
|
|
|
if (projectPart->precompiledHeaders.contains(filePath))
|
|
|
|
|
return QStringList();
|
|
|
|
|
|
|
|
|
|
const CppTools::ProjectPart theProjectPart = projectPartForLanguageOption(projectPart);
|
|
|
|
|
CppTools::CompilerOptionsBuilder builder(theProjectPart);
|
|
|
|
|
builder.addPrecompiledHeaderOptions(CompilerOptionsBuilder::PchUsage::Use);
|
|
|
|
|
|
|
|
|
|
return builder.options();
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-10 16:54:53 +01:00
|
|
|
static QStringList fileArguments(const QString &filePath, CppTools::ProjectPart *projectPart)
|
|
|
|
|
{
|
2016-11-02 12:21:54 +03:00
|
|
|
return languageOptions(filePath, projectPart)
|
|
|
|
|
+ warningOptions(projectPart)
|
2017-05-23 09:49:22 +02:00
|
|
|
+ commandLineOptions(projectPart)
|
2016-11-02 12:21:54 +03:00
|
|
|
+ precompiledHeaderOptions(filePath, projectPart);
|
2015-11-10 16:54:53 +01:00
|
|
|
}
|
|
|
|
|
|
2015-10-05 11:17:03 +02:00
|
|
|
ClangBackEnd::FileContainer
|
2015-11-30 10:55:25 +01:00
|
|
|
ClangEditorDocumentProcessor::fileContainerWithArguments(CppTools::ProjectPart *projectPart) const
|
2015-10-05 11:17:03 +02:00
|
|
|
{
|
2015-11-05 13:57:57 +01:00
|
|
|
const auto projectPartId = projectPart
|
|
|
|
|
? Utf8String::fromString(projectPart->id())
|
|
|
|
|
: Utf8String();
|
2015-11-10 16:54:53 +01:00
|
|
|
const QStringList theFileArguments = fileArguments(filePath(), projectPart);
|
2015-10-05 11:17:03 +02:00
|
|
|
|
2015-11-10 16:54:53 +01:00
|
|
|
return {filePath(), projectPartId, Utf8StringVector(theFileArguments), revision()};
|
2015-10-05 11:17:03 +02:00
|
|
|
}
|
|
|
|
|
|
2016-11-22 15:17:42 +01:00
|
|
|
ClangBackEnd::FileContainer
|
|
|
|
|
ClangEditorDocumentProcessor::fileContainerWithArgumentsAndDocumentContent(
|
|
|
|
|
CppTools::ProjectPart *projectPart) const
|
|
|
|
|
{
|
|
|
|
|
const QStringList theFileArguments = fileArguments(filePath(), projectPart);
|
|
|
|
|
|
|
|
|
|
return ClangBackEnd::FileContainer(filePath(),
|
|
|
|
|
projectPart->id(),
|
|
|
|
|
Utf8StringVector(theFileArguments),
|
|
|
|
|
textDocument()->toPlainText(),
|
|
|
|
|
true,
|
|
|
|
|
revision());
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-30 10:55:25 +01:00
|
|
|
ClangBackEnd::FileContainer
|
|
|
|
|
ClangEditorDocumentProcessor::fileContainerWithDocumentContent(const QString &projectpartId) const
|
|
|
|
|
{
|
|
|
|
|
return ClangBackEnd::FileContainer(filePath(),
|
|
|
|
|
projectpartId,
|
2016-01-11 20:40:05 +01:00
|
|
|
textDocument()->toPlainText(),
|
2015-11-30 10:55:25 +01:00
|
|
|
true,
|
|
|
|
|
revision());
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-08 15:48:17 +02:00
|
|
|
} // namespace Internal
|
2014-08-19 15:59:29 +02:00
|
|
|
} // namespace ClangCodeModel
|