ClangCodeModel: Remove libclang-based diagnostics and highlighting

Change-Id: Ib7c423884b76c27a6350ddea611919d3352fb80e
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Kandeler
2022-04-28 12:10:53 +02:00
parent 15f3b46133
commit b52fac7148
27 changed files with 80 additions and 2171 deletions

View File

@@ -25,8 +25,6 @@ add_qtc_plugin(ClangCodeModel
clangcompletioncontextanalyzer.cpp clangcompletioncontextanalyzer.h
clangconstants.h
clangdclient.cpp clangdclient.h
clangdiagnosticfilter.cpp clangdiagnosticfilter.h
clangdiagnosticmanager.cpp clangdiagnosticmanager.h
clangdiagnostictooltipwidget.cpp clangdiagnostictooltipwidget.h
clangdquickfixfactory.cpp clangdquickfixfactory.h
clangdqpropertyhighlighter.cpp clangdqpropertyhighlighter.h
@@ -36,8 +34,6 @@ add_qtc_plugin(ClangCodeModel
clangfixitoperationsextractor.cpp clangfixitoperationsextractor.h
clangfunctionhintmodel.cpp clangfunctionhintmodel.h
clangdlocatorfilters.cpp clangdlocatorfilters.h
clanghighlightingresultreporter.cpp clanghighlightingresultreporter.h
clangisdiagnosticrelatedtolocation.h
clangmodelmanagersupport.cpp clangmodelmanagersupport.h
clangpreprocessorassistproposalitem.cpp clangpreprocessorassistproposalitem.h
clangprojectsettings.cpp clangprojectsettings.h

View File

@@ -301,12 +301,6 @@ void BackendCommunicator::documentsChangedWithRevisionCheck(const FileContainer
}
}
void BackendCommunicator::requestAnnotations(const FileContainer &fileContainer)
{
const RequestAnnotationsMessage message(fileContainer);
m_sender->requestAnnotations(message);
}
QFuture<CppEditor::CursorInfo> BackendCommunicator::requestReferences(
const FileContainer &fileContainer,
quint32 line,

View File

@@ -91,7 +91,6 @@ public:
qint32 funcNameStartLine = -1,
qint32 funcNameStartColumn = -1);
void cancelCompletions(TextEditor::IAssistProcessor *processor);
void requestAnnotations(const ClangBackEnd::FileContainer &fileContainer);
QFuture<CppEditor::CursorInfo> requestReferences(
const FileContainer &fileContainer,
quint32 line,

View File

@@ -207,22 +207,6 @@ void BackendReceiver::annotations(const ClangBackEnd::AnnotationsMessage &messag
<< message.diagnostics.size() << "diagnostics" << message.tokenInfos.size()
<< "token infos" << message.skippedPreprocessorRanges.size()
<< "skipped preprocessor ranges";
auto processor = ClangEditorDocumentProcessor::get(message.fileContainer.filePath);
if (!processor)
return;
const quint32 documentRevision = message.fileContainer.documentRevision;
if (message.onlyTokenInfos) {
processor->updateTokenInfos(message.tokenInfos, documentRevision);
return;
}
processor->updateCodeWarnings(message.diagnostics,
message.firstHeaderErrorDiagnostic,
documentRevision);
processor->updateHighlighting(message.tokenInfos,
message.skippedPreprocessorRanges,
documentRevision);
}
static

View File

@@ -56,10 +56,6 @@ QtcPlugin {
"clangconstants.h",
"clangdclient.cpp",
"clangdclient.h",
"clangdiagnosticfilter.cpp",
"clangdiagnosticfilter.h",
"clangdiagnosticmanager.cpp",
"clangdiagnosticmanager.h",
"clangdiagnostictooltipwidget.cpp",
"clangdiagnostictooltipwidget.h",
"clangdlocatorfilters.cpp",
@@ -78,9 +74,6 @@ QtcPlugin {
"clangfixitoperationsextractor.h",
"clangfunctionhintmodel.cpp",
"clangfunctionhintmodel.h",
"clanghighlightingresultreporter.cpp",
"clanghighlightingresultreporter.h",
"clangisdiagnosticrelatedtolocation.h",
"clangmodelmanagersupport.cpp",
"clangmodelmanagersupport.h",
"clangpreprocessorassistproposalitem.cpp",

View File

@@ -27,7 +27,7 @@
#include "clangcompletionassistprocessor.h"
#include "clangcompletioncontextanalyzer.h"
#include "clangdiagnosticmanager.h"
#include "clangconstants.h"
#include "clangdqpropertyhighlighter.h"
#include "clangmodelmanagersupport.h"
#include "clangpreprocessorassistproposalitem.h"
@@ -62,6 +62,7 @@
#include <projectexplorer/project.h>
#include <projectexplorer/projecttree.h>
#include <projectexplorer/session.h>
#include <projectexplorer/taskhub.h>
#include <texteditor/basefilefind.h>
#include <texteditor/codeassist/assistinterface.h>
#include <texteditor/codeassist/iassistprocessor.h>
@@ -1613,7 +1614,7 @@ public:
void hideDiagnostics(const Utils::FilePath &filePath) override
{
DiagnosticManager::hideDiagnostics(filePath);
ClangDiagnosticManager::clearTaskHubIssues();
TaskHub::clearTasks(Constants::TASK_CATEGORY_DIAGNOSTICS);
}
QList<Diagnostic> filteredDiagnostics(const QList<Diagnostic> &diagnostics) const override

View File

@@ -1,188 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** 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 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.
**
** 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.
**
****************************************************************************/
#include "clangdiagnosticfilter.h"
#include <cppeditor/cppprojectfile.h>
#include <utf8stringvector.h>
namespace {
bool isWarningOrNote(ClangBackEnd::DiagnosticSeverity severity)
{
using ClangBackEnd::DiagnosticSeverity;
switch (severity) {
case DiagnosticSeverity::Ignored:
case DiagnosticSeverity::Note:
case DiagnosticSeverity::Warning: return true;
case DiagnosticSeverity::Error:
case DiagnosticSeverity::Fatal: return false;
}
Q_UNREACHABLE();
}
bool isBlackListedHeaderDiagnostic(const ClangBackEnd::DiagnosticContainer &diagnostic,
bool isHeaderFile)
{
static const Utf8StringVector blackList{
Utf8StringLiteral("warning: #pragma once in main file"),
Utf8StringLiteral("warning: #include_next in primary source file")
};
return isHeaderFile && blackList.contains(diagnostic.text);
}
bool isBlackListedQtDiagnostic(const ClangBackEnd::DiagnosticContainer &diagnostic)
{
static const Utf8StringVector blackList{
// From Q_OBJECT:
Utf8StringLiteral("warning: "
"'metaObject' overrides a member function but is not marked 'override'"),
Utf8StringLiteral("warning: "
"'qt_metacast' overrides a member function but is not marked 'override'"),
Utf8StringLiteral("warning: "
"'qt_metacall' overrides a member function but is not marked 'override'"),
};
return blackList.contains(diagnostic.text);
}
template <class Condition>
QVector<ClangBackEnd::DiagnosticContainer>
filterDiagnostics(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
const Condition &condition)
{
QVector<ClangBackEnd::DiagnosticContainer> filteredDiagnostics;
std::copy_if(diagnostics.cbegin(),
diagnostics.cend(),
std::back_inserter(filteredDiagnostics),
condition);
return filteredDiagnostics;
}
template <class Condition>
void
filterDiagnostics(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
const Condition &condition,
QVector<ClangBackEnd::DiagnosticContainer> &filteredDiagnostic)
{
std::copy_if(diagnostics.cbegin(),
diagnostics.cend(),
std::back_inserter(filteredDiagnostic),
condition);
}
} // anonymous namespace
namespace ClangCodeModel {
namespace Internal {
void ClangDiagnosticFilter::filterDocumentRelatedWarnings(
const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics)
{
using namespace CppEditor;
const bool isHeaderFile = ProjectFile::isHeader(ProjectFile::classify(m_filePath));
const auto isLocalWarning = [this, isHeaderFile]
(const ClangBackEnd::DiagnosticContainer &diagnostic) {
return isWarningOrNote(diagnostic.severity)
&& !isBlackListedHeaderDiagnostic(diagnostic, isHeaderFile)
&& !isBlackListedQtDiagnostic(diagnostic)
&& diagnostic.location.filePath == m_filePath;
};
m_warningDiagnostics = filterDiagnostics(diagnostics, isLocalWarning);
}
void ClangDiagnosticFilter::filterDocumentRelatedErrors(
const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics)
{
const auto isLocalWarning = [this] (const ClangBackEnd::DiagnosticContainer &diagnostic) {
return !isWarningOrNote(diagnostic.severity)
&& diagnostic.location.filePath == m_filePath;
};
m_errorDiagnostics = filterDiagnostics(diagnostics, isLocalWarning);
}
void ClangDiagnosticFilter::filterFixits()
{
const auto hasFixIts = [] (const ClangBackEnd::DiagnosticContainer &diagnostic) {
return diagnostic.fixIts.size() > 0;
};
m_fixItdiagnostics.clear();
filterDiagnostics(m_warningDiagnostics, hasFixIts, m_fixItdiagnostics);
filterDiagnostics(m_errorDiagnostics, hasFixIts, m_fixItdiagnostics);
for (const auto &warningDiagnostic : m_warningDiagnostics)
filterDiagnostics(warningDiagnostic.children, hasFixIts, m_fixItdiagnostics);
for (const auto &warningDiagnostic : m_errorDiagnostics)
filterDiagnostics(warningDiagnostic.children, hasFixIts, m_fixItdiagnostics);
}
ClangDiagnosticFilter::ClangDiagnosticFilter(const QString &filePath)
: m_filePath(filePath)
{
}
void ClangDiagnosticFilter::filter(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics)
{
filterDocumentRelatedWarnings(diagnostics);
filterDocumentRelatedErrors(diagnostics);
filterFixits();
}
QVector<ClangBackEnd::DiagnosticContainer> ClangDiagnosticFilter::takeWarnings()
{
auto diagnostics = m_warningDiagnostics;
m_warningDiagnostics.clear();
return diagnostics;
}
QVector<ClangBackEnd::DiagnosticContainer> ClangDiagnosticFilter::takeErrors()
{
auto diagnostics = m_errorDiagnostics;
m_errorDiagnostics.clear();
return diagnostics;
}
QVector<ClangBackEnd::DiagnosticContainer> ClangDiagnosticFilter::takeFixIts()
{
auto diagnostics = m_fixItdiagnostics;
m_fixItdiagnostics.clear();
return diagnostics;
}
} // namespace Internal
} // namespace ClangCodeModel

View File

@@ -1,60 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** 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 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.
**
** 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.
**
****************************************************************************/
#pragma once
#include <clangsupport/diagnosticcontainer.h>
#include <QVector>
namespace ClangCodeModel {
namespace Internal {
class ClangDiagnosticFilter
{
public:
ClangDiagnosticFilter(const QString &filePath);
void filter(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics);
QVector<ClangBackEnd::DiagnosticContainer> takeWarnings();
QVector<ClangBackEnd::DiagnosticContainer> takeErrors();
QVector<ClangBackEnd::DiagnosticContainer> takeFixIts();
private:
void filterDocumentRelatedWarnings(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics);
void filterDocumentRelatedErrors(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics);
void filterFixits();
private:
const QString m_filePath;
QVector<ClangBackEnd::DiagnosticContainer> m_warningDiagnostics;
QVector<ClangBackEnd::DiagnosticContainer> m_errorDiagnostics;
QVector<ClangBackEnd::DiagnosticContainer> m_fixItdiagnostics;
};
} // namespace Internal
} // namespace ClangCodeModel

View File

@@ -1,504 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** 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 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.
**
** 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.
**
****************************************************************************/
#include "clangconstants.h"
#include "clangdiagnosticfilter.h"
#include "clangdiagnosticmanager.h"
#include "clangisdiagnosticrelatedtolocation.h"
#include "clangutils.h"
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <cppeditor/cppeditorconstants.h>
#include <projectexplorer/taskhub.h>
#include <texteditor/fontsettings.h>
#include <texteditor/textdocument.h>
#include <texteditor/texteditor.h>
#include <texteditor/texteditorsettings.h>
#include <utils/textutils.h>
#include <utils/fileutils.h>
#include <utils/proxyaction.h>
#include <utils/qtcassert.h>
#include <utils/theme/theme.h>
#include <utils/utilsicons.h>
#include <QFileInfo>
#include <QTextBlock>
namespace {
QTextEdit::ExtraSelection createExtraSelections(const QTextCharFormat &mainformat,
const QTextCursor &cursor)
{
QTextEdit::ExtraSelection extraSelection;
extraSelection.format = mainformat;
extraSelection.cursor = cursor;
return extraSelection;
}
void addRangeSelections(const ClangBackEnd::DiagnosticContainer &diagnostic,
QTextDocument *textDocument,
const QTextCharFormat &contextFormat,
QList<QTextEdit::ExtraSelection> &extraSelections)
{
for (auto &&range : diagnostic.ranges) {
QTextCursor cursor(textDocument);
cursor.setPosition(::Utils::Text::positionInText(textDocument,
range.start.line,
range.start.column));
cursor.setPosition(::Utils::Text::positionInText(textDocument,
range.end.line,
range.end.column),
QTextCursor::KeepAnchor);
auto extraSelection = createExtraSelections(contextFormat, cursor);
extraSelections.push_back(std::move(extraSelection));
}
}
QChar selectionEndChar(const QChar startSymbol)
{
if (startSymbol == '"')
return QLatin1Char('"');
if (startSymbol == '<')
return QLatin1Char('>');
return {};
}
void selectToLocationEnd(QTextCursor &cursor)
{
const QTextBlock textBlock = cursor.document()->findBlock(cursor.position());
const QString simplifiedStr = textBlock.text().simplified();
if (!simplifiedStr.startsWith("#include") && !simplifiedStr.startsWith("# include")) {
// General case, not the line with #include
cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
return;
}
const QChar endChar = selectionEndChar(cursor.document()->characterAt(cursor.position()));
if (endChar.isNull()) {
cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
} else {
const int endPosition = textBlock.text().indexOf(endChar, cursor.position()
- textBlock.position() + 1);
if (endPosition >= 0)
cursor.setPosition(textBlock.position() + endPosition + 1, QTextCursor::KeepAnchor);
else
cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
}
}
QTextCursor createSelectionCursor(QTextDocument *textDocument,
const ClangBackEnd::SourceLocationContainer &sourceLocationContainer)
{
QTextCursor cursor(textDocument);
cursor.setPosition(::Utils::Text::positionInText(textDocument,
sourceLocationContainer.line,
sourceLocationContainer.column));
selectToLocationEnd(cursor);
if (!cursor.hasSelection()) {
cursor.setPosition(::Utils::Text::positionInText(textDocument,
sourceLocationContainer.line,
sourceLocationContainer.column) - 1);
cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 2);
}
return cursor;
}
void addSelections(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
QTextDocument *textDocument,
const QTextCharFormat &mainFormat,
const QTextCharFormat &contextFormat,
QList<QTextEdit::ExtraSelection> &extraSelections)
{
for (auto &&diagnostic : diagnostics) {
auto cursor = createSelectionCursor(textDocument, diagnostic.location);
auto extraSelection = createExtraSelections(mainFormat, cursor);
addRangeSelections(diagnostic, textDocument, contextFormat, extraSelections);
extraSelections.push_back(std::move(extraSelection));
}
}
void addWarningSelections(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
QTextDocument *textDocument,
QList<QTextEdit::ExtraSelection> &extraSelections)
{
const auto fontSettings = TextEditor::TextEditorSettings::fontSettings();
QTextCharFormat warningFormat = fontSettings.toTextCharFormat(TextEditor::C_WARNING);
QTextCharFormat warningContextFormat = fontSettings.toTextCharFormat(TextEditor::C_WARNING_CONTEXT);
addSelections(diagnostics, textDocument, warningFormat, warningContextFormat, extraSelections);
}
void addErrorSelections(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
QTextDocument *textDocument,
QList<QTextEdit::ExtraSelection> &extraSelections)
{
const auto fontSettings = TextEditor::TextEditorSettings::fontSettings();
QTextCharFormat errorFormat = fontSettings.toTextCharFormat(TextEditor::C_ERROR);
QTextCharFormat errorContextFormat = fontSettings.toTextCharFormat(TextEditor::C_ERROR_CONTEXT);
addSelections(diagnostics, textDocument, errorFormat, errorContextFormat, extraSelections);
}
ClangBackEnd::SourceLocationContainer toSourceLocation(QTextDocument *textDocument, int position)
{
int line, column;
if (Utils::Text::convertPosition(textDocument, position, &line, &column))
return ClangBackEnd::SourceLocationContainer(Utf8String(), line, column);
return ClangBackEnd::SourceLocationContainer();
}
ClangBackEnd::SourceRangeContainer toSourceRange(const QTextCursor &cursor)
{
using namespace ClangBackEnd;
QTextDocument *textDocument = cursor.document();
return SourceRangeContainer(toSourceLocation(textDocument, cursor.anchor()),
toSourceLocation(textDocument, cursor.position()));
}
bool isDiagnosticAtLocation(const ClangBackEnd::DiagnosticContainer &diagnostic,
uint line,
uint column,
QTextDocument *textDocument)
{
using namespace ClangCodeModel::Internal;
const ClangBackEnd::SourceLocationContainer &location = diagnostic.location;
const QTextCursor cursor = createSelectionCursor(textDocument, location);
const ClangBackEnd::SourceRangeContainer cursorRange = toSourceRange(cursor);
return isDiagnosticRelatedToLocation(diagnostic, {cursorRange}, line, column);
}
QTextCursor cursorAtLastPositionOfLine(QTextDocument *textDocument, int lineNumber)
{
const QTextBlock textBlock = textDocument->findBlockByNumber(lineNumber - 1);
QTC_ASSERT(textBlock.isValid(), return QTextCursor());
const int lastPositionOfLine = textBlock.position() + textBlock.length() - 1;
QTextCursor textCursor(textDocument);
textCursor.setPosition(lastPositionOfLine);
return textCursor;
}
QString tooltipForFixItAvailableMarker()
{
QString text = QCoreApplication::translate("ClangCodeModel::Internal::ClangDiagnosticManager", "Inspect available fixits");
Core::Command *command = Core::ActionManager::command(TextEditor::Constants::QUICKFIX_THIS);
if (command)
text = Utils::ProxyAction::stringWithAppendedShortcut(text, command->keySequence());
return text;
}
TextEditor::RefactorMarker createFixItAvailableMarker(QTextDocument *textDocument, int lineNumber)
{
TextEditor::RefactorMarker marker;
marker.tooltip = tooltipForFixItAvailableMarker();
marker.cursor = cursorAtLastPositionOfLine(textDocument, lineNumber);
marker.callback = [marker](TextEditor::TextEditorWidget *editor) {
int line, column;
if (Utils::Text::convertPosition(marker.cursor.document(),
marker.cursor.position(), &line, &column)) {
editor->setTextCursor(marker.cursor);
editor->invokeAssist(TextEditor::QuickFix);
}
};
marker.type = CppEditor::Constants::CPP_CLANG_FIXIT_AVAILABLE_MARKER_ID;
return marker;
}
} // anonymous
namespace ClangCodeModel {
namespace Internal {
ClangDiagnosticManager::ClangDiagnosticManager(TextEditor::TextDocument *textDocument)
: m_textDocument(textDocument)
{
m_textMarkDelay.setInterval(1500);
m_textMarkDelay.setSingleShot(true);
}
ClangDiagnosticManager::~ClangDiagnosticManager()
{
cleanMarks();
}
void ClangDiagnosticManager::cleanMarks()
{
for (ClangTextMark *textMark : m_clangTextMarks) {
m_textDocument->removeMark(textMark);
delete textMark;
}
m_clangTextMarks.clear();
}
void ClangDiagnosticManager::generateTextMarks()
{
QObject::disconnect(&m_textMarkDelay, &QTimer::timeout, nullptr, nullptr);
cleanMarks();
m_clangTextMarks.reserve(m_warningDiagnostics.size() + m_errorDiagnostics.size());
addClangTextMarks(m_warningDiagnostics);
addClangTextMarks(m_errorDiagnostics);
}
void ClangDiagnosticManager::generateFixItAvailableMarkers()
{
m_fixItAvailableMarkers.clear();
if (!m_fullVisualization)
return;
QSet<int> lineNumbersWithFixItMarker;
addFixItAvailableMarker(m_warningDiagnostics, lineNumbersWithFixItMarker);
addFixItAvailableMarker(m_errorDiagnostics, lineNumbersWithFixItMarker);
}
void ClangDiagnosticManager::addTask(const ClangBackEnd::DiagnosticContainer &diagnostic,
bool isChild)
{
using namespace ProjectExplorer;
using ::Utils::FilePath;
Task::TaskType taskType = ProjectExplorer::Task::TaskType::Unknown;
FilePath iconPath;
QIcon icon;
if (!isChild) {
switch (diagnostic.severity) {
case ClangBackEnd::DiagnosticSeverity::Fatal:
case ClangBackEnd::DiagnosticSeverity::Error:
taskType = Task::TaskType::Error;
icon = ::Utils::Icons::CODEMODEL_ERROR.icon();
break;
case ClangBackEnd::DiagnosticSeverity::Warning:
taskType = Task::TaskType::Warning;
icon = ::Utils::Icons::CODEMODEL_WARNING.icon();
break;
default:
break;
}
}
TaskHub::addTask(Task(taskType,
diagnosticCategoryPrefixRemoved(diagnostic.text.toString()),
FilePath::fromString(diagnostic.location.filePath.toString()),
diagnostic.location.line,
Constants::TASK_CATEGORY_DIAGNOSTICS,
icon,
Task::NoOptions));
}
void ClangDiagnosticManager::clearTaskHubIssues()
{
ProjectExplorer::TaskHub::clearTasks(Constants::TASK_CATEGORY_DIAGNOSTICS);
}
void ClangDiagnosticManager::generateTaskHubIssues()
{
if (!m_fullVisualization)
return;
const QVector<ClangBackEnd::DiagnosticContainer> diagnostics = m_errorDiagnostics
+ m_warningDiagnostics;
for (const ClangBackEnd::DiagnosticContainer &diagnostic : diagnostics) {
addTask(diagnostic);
for (const ClangBackEnd::DiagnosticContainer &child : diagnostic.children)
addTask(child, /*isChild = */ true);
}
}
QList<QTextEdit::ExtraSelection> ClangDiagnosticManager::takeExtraSelections()
{
auto extraSelections = m_extraSelections;
m_extraSelections.clear();
return extraSelections;
}
TextEditor::RefactorMarkers ClangDiagnosticManager::takeFixItAvailableMarkers()
{
TextEditor::RefactorMarkers fixItAvailableMarkers = m_fixItAvailableMarkers;
m_fixItAvailableMarkers.clear();
return fixItAvailableMarkers;
}
TextEditor::TextMarks ClangDiagnosticManager::diagnosticTextMarksAt(uint line, uint column) const
{
QList<TextEditor::TextMark *> textMarks;
for (ClangTextMark *textMark : m_clangTextMarks) {
if (isDiagnosticAtLocation(textMark->diagnostic(), line, column, m_textDocument->document()))
textMarks << textMark;
}
return textMarks;
}
void ClangDiagnosticManager::invalidateDiagnostics()
{
m_textMarkDelay.start();
if (m_diagnosticsInvalidated)
return;
m_diagnosticsInvalidated = true;
for (ClangTextMark *textMark : m_clangTextMarks) {
textMark->setColor(::Utils::Theme::Color::IconsDisabledColor);
textMark->updateIcon(/*valid=*/ false);
}
}
void ClangDiagnosticManager::clearDiagnosticsWithFixIts()
{
m_fixItdiagnostics.clear();
}
void ClangDiagnosticManager::generateEditorSelections()
{
m_extraSelections.clear();
m_extraSelections.reserve(int(m_warningDiagnostics.size() + m_errorDiagnostics.size()));
if (!m_fullVisualization)
return;
addWarningSelections(m_warningDiagnostics, m_textDocument->document(), m_extraSelections);
addErrorSelections(m_errorDiagnostics, m_textDocument->document(), m_extraSelections);
}
void ClangDiagnosticManager::processNewDiagnostics(
const QVector<ClangBackEnd::DiagnosticContainer> &allDiagnostics,
bool fullVisualization)
{
m_diagnosticsInvalidated = false;
m_fullVisualization = fullVisualization;
filterDiagnostics(allDiagnostics);
generateEditorSelections();
generateFixItAvailableMarkers();
if (m_firstDiagnostics) {
m_firstDiagnostics = false;
generateTextMarks();
} else if (!m_textMarkDelay.isActive()) {
generateTextMarks();
} else {
QObject::connect(&m_textMarkDelay, &QTimer::timeout, [this]() {
generateTextMarks();
});
}
clearTaskHubIssues();
generateTaskHubIssues();
}
const QVector<ClangBackEnd::DiagnosticContainer> &
ClangDiagnosticManager::diagnosticsWithFixIts() const
{
return m_fixItdiagnostics;
}
void ClangDiagnosticManager::addClangTextMarks(
const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics)
{
for (const ClangBackEnd::DiagnosticContainer &diagnostic : diagnostics) {
const auto onMarkRemoved = [this](const ClangTextMark *mark) {
const auto it = std::remove(m_clangTextMarks.begin(), m_clangTextMarks.end(), mark);
m_clangTextMarks.erase(it, m_clangTextMarks.end());
delete mark;
};
auto textMark = new ClangTextMark(::Utils::FilePath::fromString(filePath()),
diagnostic,
onMarkRemoved,
m_fullVisualization,
this);
m_clangTextMarks.push_back(textMark);
m_textDocument->addMark(textMark);
}
}
void ClangDiagnosticManager::addFixItAvailableMarker(
const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
QSet<int> &lineNumbersWithFixItMarker)
{
for (auto &&diagnostic : diagnostics) {
for (auto &&fixit : diagnostic.fixIts) {
const ClangBackEnd::SourceLocationContainer &location = fixit.range.start;
const int line = int(location.line);
if (location.filePath == filePath() && !lineNumbersWithFixItMarker.contains(line)) {
const TextEditor::RefactorMarker marker
= createFixItAvailableMarker(m_textDocument->document(), line);
lineNumbersWithFixItMarker.insert(line);
m_fixItAvailableMarkers.append(marker);
}
}
addFixItAvailableMarker(diagnostic.children, lineNumbersWithFixItMarker);
}
}
QString ClangDiagnosticManager::filePath() const
{
return m_textDocument->filePath().toString();
}
void ClangDiagnosticManager::filterDiagnostics(
const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics)
{
ClangDiagnosticFilter filter(filePath());
filter.filter(diagnostics);
m_warningDiagnostics = filter.takeWarnings();
m_errorDiagnostics = filter.takeErrors();
m_fixItdiagnostics = filter.takeFixIts();
}
} // namespace Internal
} // namespace ClangCodeModel

View File

@@ -1,98 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** 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 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.
**
** 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.
**
****************************************************************************/
#pragma once
#include "clangtextmark.h"
#include <texteditor/refactoroverlay.h>
#include <clangsupport/diagnosticcontainer.h>
#include <QList>
#include <QSet>
#include <QTextEdit>
#include <QTimer>
#include <QVector>
#include <vector>
namespace TextEditor { class TextDocument; }
namespace ClangCodeModel {
namespace Internal {
class ClangDiagnosticManager
{
public:
ClangDiagnosticManager(TextEditor::TextDocument *textDocument);
~ClangDiagnosticManager();
void processNewDiagnostics(const QVector<ClangBackEnd::DiagnosticContainer> &allDiagnostics,
bool fullVisualization);
const QVector<ClangBackEnd::DiagnosticContainer> &diagnosticsWithFixIts() const;
QList<QTextEdit::ExtraSelection> takeExtraSelections();
TextEditor::RefactorMarkers takeFixItAvailableMarkers();
QList<TextEditor::TextMark *> diagnosticTextMarksAt(uint line, uint column) const;
bool diagnosticsInvalidated() const { return m_diagnosticsInvalidated; }
void invalidateDiagnostics();
void clearDiagnosticsWithFixIts();
static void clearTaskHubIssues();
void generateTaskHubIssues();
void cleanMarks();
static void addTask(const ClangBackEnd::DiagnosticContainer &diagnostic, bool isChild = false);
private:
QString filePath() const;
void filterDiagnostics(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics);
void generateEditorSelections();
void generateTextMarks();
void generateFixItAvailableMarkers();
void addClangTextMarks(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics);
void addFixItAvailableMarker(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
QSet<int> &lineNumbersWithFixItMarker);
private:
TextEditor::TextDocument *m_textDocument;
QVector<ClangBackEnd::DiagnosticContainer> m_warningDiagnostics;
QVector<ClangBackEnd::DiagnosticContainer> m_errorDiagnostics;
QVector<ClangBackEnd::DiagnosticContainer> m_fixItdiagnostics;
QList<QTextEdit::ExtraSelection> m_extraSelections;
TextEditor::RefactorMarkers m_fixItAvailableMarkers;
std::vector<ClangTextMark *> m_clangTextMarks;
bool m_firstDiagnostics = true;
bool m_diagnosticsInvalidated = false;
bool m_fullVisualization = false;
QTimer m_textMarkDelay;
};
} // namespace Internal
} // namespace ClangCodeModel

View File

@@ -25,7 +25,6 @@
#include "clangdiagnostictooltipwidget.h"
#include "clangdiagnosticmanager.h"
#include "clangfixitoperation.h"
#include "clangutils.h"

View File

@@ -36,7 +36,6 @@ QT_END_NAMESPACE
namespace ClangCodeModel {
namespace Internal {
class ClangDiagnosticManager;
class ClangDiagnosticWidget {
public:

View File

@@ -31,7 +31,6 @@
#include "clangfixitoperation.h"
#include "clangfixitoperationsextractor.h"
#include "clangmodelmanagersupport.h"
#include "clanghighlightingresultreporter.h"
#include "clangutils.h"
#include <diagnosticcontainer.h>
@@ -72,12 +71,10 @@ ClangEditorDocumentProcessor::ClangEditorDocumentProcessor(
TextEditor::TextDocument *document)
: BaseEditorDocumentProcessor(document->document(), document->filePath().toString())
, m_document(*document)
, m_diagnosticManager(document)
, m_communicator(communicator)
, m_parser(new ClangEditorDocumentParser(document->filePath().toString()))
, m_parserRevision(0)
, m_semanticHighlighter(document)
, m_builtinProcessor(document, /*enableSemanticHighlighter=*/ false)
, m_builtinProcessor(document)
{
m_updateBackendDocumentTimer.setSingleShot(true);
m_updateBackendDocumentTimer.setInterval(350);
@@ -93,6 +90,11 @@ ClangEditorDocumentProcessor::ClangEditorDocumentProcessor(
this, &ClangEditorDocumentProcessor::cppDocumentUpdated);
connect(&m_builtinProcessor, &CppEditor::BuiltinEditorDocumentProcessor::semanticInfoUpdated,
this, &ClangEditorDocumentProcessor::semanticInfoUpdated);
connect(&m_builtinProcessor, &CppEditor::BuiltinEditorDocumentProcessor::codeWarningsUpdated,
this, &ClangEditorDocumentProcessor::codeWarningsUpdated);
m_builtinProcessor.setSemanticHighlightingChecker([this] {
return !ClangModelManagerSupport::instance()->clientForFile(m_document.filePath());
});
m_parserSynchronizer.setCancelOnWait(true);
}
@@ -141,10 +143,7 @@ void ClangEditorDocumentProcessor::semanticRehighlight()
return;
if (ClangModelManagerSupport::instance()->clientForFile(m_document.filePath()))
return;
m_semanticHighlighter.updateFormatMapFromFontSettings();
if (m_projectPart)
requestAnnotationsFromBackend();
m_builtinProcessor.semanticRehighlight();
}
CppEditor::SemanticInfo ClangEditorDocumentProcessor::recalculateSemanticInfo()
@@ -187,142 +186,12 @@ void ClangEditorDocumentProcessor::clearProjectPart()
return m_diagnosticConfigId;
}
void ClangEditorDocumentProcessor::updateCodeWarnings(
const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic,
uint documentRevision)
{
if (ClangModelManagerSupport::instance()->clientForFile(m_document.filePath()))
return;
if (documentRevision == revision()) {
if (m_invalidationState == InvalidationState::Scheduled)
m_invalidationState = InvalidationState::Canceled;
m_diagnosticManager.processNewDiagnostics(diagnostics, m_isProjectFile);
const auto codeWarnings = m_diagnosticManager.takeExtraSelections();
const auto fixitAvailableMarkers = m_diagnosticManager.takeFixItAvailableMarkers();
const auto creator = creatorForHeaderErrorDiagnosticWidget(firstHeaderErrorDiagnostic);
emit codeWarningsUpdated(revision(),
codeWarnings,
creator,
fixitAvailableMarkers);
}
}
namespace {
TextEditor::BlockRange
toTextEditorBlock(QTextDocument *textDocument,
const ClangBackEnd::SourceRangeContainer &sourceRangeContainer)
{
return {::Utils::Text::positionInText(textDocument,
sourceRangeContainer.start.line,
sourceRangeContainer.start.column),
::Utils::Text::positionInText(textDocument,
sourceRangeContainer.end.line,
sourceRangeContainer.end.column)};
}
QList<TextEditor::BlockRange>
toTextEditorBlocks(QTextDocument *textDocument,
const QVector<ClangBackEnd::SourceRangeContainer> &ifdefedOutRanges)
{
QList<TextEditor::BlockRange> blockRanges;
blockRanges.reserve(ifdefedOutRanges.size());
for (const auto &range : ifdefedOutRanges)
blockRanges.append(toTextEditorBlock(textDocument, range));
return blockRanges;
}
}
const QVector<ClangBackEnd::TokenInfoContainer>
&ClangEditorDocumentProcessor::tokenInfos() const
{
return m_tokenInfos;
}
void ClangEditorDocumentProcessor::clearTaskHubIssues()
{
ClangDiagnosticManager::clearTaskHubIssues();
}
void ClangEditorDocumentProcessor::generateTaskHubIssues()
{
m_diagnosticManager.generateTaskHubIssues();
}
void ClangEditorDocumentProcessor::clearTextMarks(const Utils::FilePath &filePath)
{
if (ClangEditorDocumentProcessor * const proc = get(filePath.toString())) {
proc->m_diagnosticManager.cleanMarks();
emit proc->codeWarningsUpdated(proc->revision(), {}, {}, {});
}
}
void ClangEditorDocumentProcessor::updateHighlighting(
const QVector<ClangBackEnd::TokenInfoContainer> &tokenInfos,
const QVector<ClangBackEnd::SourceRangeContainer> &skippedPreprocessorRanges,
uint documentRevision)
{
if (ClangModelManagerSupport::instance()->clientForFile(m_document.filePath()))
return;
if (documentRevision == revision()) {
const auto skippedPreprocessorBlocks = toTextEditorBlocks(textDocument(), skippedPreprocessorRanges);
emit ifdefedOutBlocksUpdated(documentRevision, skippedPreprocessorBlocks);
m_semanticHighlighter.setHighlightingRunner(
[tokenInfos]() { return highlightResults(tokenInfos); });
m_semanticHighlighter.run();
}
}
void ClangEditorDocumentProcessor::updateTokenInfos(
const QVector<ClangBackEnd::TokenInfoContainer> &tokenInfos,
uint documentRevision)
{
if (documentRevision != revision())
return;
m_tokenInfos = tokenInfos;
emit tokenInfosUpdated();
}
static int currentLine(const TextEditor::AssistInterface &assistInterface)
{
int line, column;
::Utils::Text::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.filePath().toString(), currentLine(assistInterface));
}
void ClangEditorDocumentProcessor::editorDocumentTimerRestarted()
{
m_updateBackendDocumentTimer.stop(); // Wait for the next call to run().
m_invalidationState = InvalidationState::Scheduled;
}
void ClangEditorDocumentProcessor::invalidateDiagnostics()
{
if (m_invalidationState != InvalidationState::Canceled)
m_diagnosticManager.invalidateDiagnostics();
m_invalidationState = InvalidationState::Off;
}
TextEditor::TextMarks ClangEditorDocumentProcessor::diagnosticTextMarksAt(uint line,
uint column) const
{
return m_diagnosticManager.diagnosticTextMarksAt(line, column);
}
void ClangEditorDocumentProcessor::setParserConfig(
const CppEditor::BaseEditorDocumentParser::Configuration &config)
{
@@ -413,11 +282,6 @@ QFuture<CppEditor::ToolTipInfo> ClangEditorDocumentProcessor::toolTipInfo(const
static_cast<quint32>(column));
}
void ClangEditorDocumentProcessor::clearDiagnosticsWithFixIts()
{
m_diagnosticManager.clearDiagnosticsWithFixIts();
}
ClangEditorDocumentProcessor *ClangEditorDocumentProcessor::get(const QString &filePath)
{
return qobject_cast<ClangEditorDocumentProcessor*>(
@@ -492,35 +356,6 @@ void ClangEditorDocumentProcessor::updateBackendDocumentIfProjectPartExists()
}
}
void ClangEditorDocumentProcessor::requestAnnotationsFromBackend()
{
const auto fileContainer = fileContainerWithDocumentContent();
m_communicator.requestAnnotations(fileContainer);
}
CppEditor::BaseEditorDocumentProcessor::HeaderErrorDiagnosticWidgetCreator
ClangEditorDocumentProcessor::creatorForHeaderErrorDiagnosticWidget(
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic)
{
if (firstHeaderErrorDiagnostic.text.isEmpty())
return CppEditor::BaseEditorDocumentProcessor::HeaderErrorDiagnosticWidgetCreator();
return [firstHeaderErrorDiagnostic]() {
auto vbox = new QVBoxLayout;
vbox->setContentsMargins(10, 0, 0, 2);
vbox->setSpacing(2);
vbox->addWidget(ClangDiagnosticWidget::createWidget({firstHeaderErrorDiagnostic},
ClangDiagnosticWidget::InfoBar, {},
"libclang"));
auto widget = new QWidget;
widget->setLayout(vbox);
return widget;
};
}
ClangBackEnd::FileContainer ClangEditorDocumentProcessor::simpleFileContainer(
const QByteArray &codecName) const
{

View File

@@ -25,11 +25,11 @@
#pragma once
#include "clangdiagnosticmanager.h"
#include "clangeditordocumentparser.h"
#include <clangsupport/sourcerangecontainer.h>
#include <cppeditor/builtineditordocumentprocessor.h>
#include <cppeditor/semantichighlighter.h>
#include <utils/futuresynchronizer.h>
#include <utils/id.h>
@@ -72,22 +72,6 @@ public:
::Utils::Id diagnosticConfigId() const;
void updateCodeWarnings(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic,
uint documentRevision);
void updateHighlighting(const QVector<ClangBackEnd::TokenInfoContainer> &tokenInfos,
const QVector<ClangBackEnd::SourceRangeContainer> &skippedPreprocessorRanges,
uint documentRevision);
void updateTokenInfos(const QVector<ClangBackEnd::TokenInfoContainer> &tokenInfos,
uint documentRevision);
TextEditor::QuickFixOperations
extraRefactoringOperations(const TextEditor::AssistInterface &assistInterface) override;
void invalidateDiagnostics() override;
TextEditor::TextMarks diagnosticTextMarksAt(uint line, uint column) const;
void editorDocumentTimerRestarted() override;
void setParserConfig(const CppEditor::BaseEditorDocumentParser::Configuration &config) override;
@@ -102,15 +86,6 @@ public:
void closeBackendDocument();
void clearDiagnosticsWithFixIts();
const QVector<ClangBackEnd::TokenInfoContainer> &tokenInfos() const;
static void clearTaskHubIssues();
void generateTaskHubIssues();
static void clearTextMarks(const Utils::FilePath &filePath);
public:
static ClangEditorDocumentProcessor *get(const QString &filePath);
@@ -125,10 +100,7 @@ private:
void updateBackendProjectPartAndDocument();
void updateBackendDocument(const CppEditor::ProjectPart &projectPart);
void updateBackendDocumentIfProjectPartExists();
void requestAnnotationsFromBackend();
HeaderErrorDiagnosticWidgetCreator creatorForHeaderErrorDiagnosticWidget(
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic);
ClangBackEnd::FileContainer simpleFileContainer(const QByteArray &codecName = QByteArray()) const;
ClangBackEnd::FileContainer fileContainerWithOptionsAndDocumentContent(
const QStringList &compilationArguments,
@@ -137,7 +109,6 @@ private:
private:
TextEditor::TextDocument &m_document;
ClangDiagnosticManager m_diagnosticManager;
BackendCommunicator &m_communicator;
QSharedPointer<ClangEditorDocumentParser> m_parser;
CppEditor::ProjectPart::ConstPtr m_projectPart;
@@ -148,8 +119,6 @@ private:
unsigned m_parserRevision;
enum class InvalidationState { Off, Scheduled, Canceled } m_invalidationState;
QVector<ClangBackEnd::TokenInfoContainer> m_tokenInfos;
CppEditor::SemanticHighlighter m_semanticHighlighter;
CppEditor::BuiltinEditorDocumentProcessor m_builtinProcessor;
Utils::FutureSynchronizer m_parserSynchronizer;
};

View File

@@ -1,224 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** 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 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.
**
** 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.
**
****************************************************************************/
#include "clanghighlightingresultreporter.h"
#include <clangsupport/tokeninfocontainer.h>
#include <cppeditor/semantichighlighter.h>
#include <texteditor/semantichighlighter.h>
#include <texteditor/textstyles.h>
#include <utils/runextensions.h>
#include <utils/qtcassert.h>
namespace {
TextEditor::TextStyle toTextStyle(ClangBackEnd::HighlightingType type)
{
using ClangBackEnd::HighlightingType;
switch (type) {
case HighlightingType::Keyword:
return TextEditor::C_KEYWORD;
case HighlightingType::Function:
return TextEditor::C_FUNCTION;
case HighlightingType::VirtualFunction:
return TextEditor::C_VIRTUAL_METHOD;
case HighlightingType::Type:
return TextEditor::C_TYPE;
case HighlightingType::PrimitiveType:
return TextEditor::C_PRIMITIVE_TYPE;
case HighlightingType::LocalVariable:
return TextEditor::C_LOCAL;
case HighlightingType::Parameter:
return TextEditor::C_PARAMETER;
case HighlightingType::Field:
case HighlightingType::QtProperty:
return TextEditor::C_FIELD;
case HighlightingType::GlobalVariable:
return TextEditor::C_GLOBAL;
case HighlightingType::Enumeration:
return TextEditor::C_ENUMERATION;
case HighlightingType::Label:
return TextEditor::C_LABEL;
case HighlightingType::Preprocessor:
case HighlightingType::PreprocessorDefinition:
case HighlightingType::PreprocessorExpansion:
return TextEditor::C_PREPROCESSOR;
case HighlightingType::Punctuation:
return TextEditor::C_PUNCTUATION;
case HighlightingType::Declaration:
return TextEditor::C_DECLARATION;
case HighlightingType::FunctionDefinition:
return TextEditor::C_FUNCTION_DEFINITION;
case HighlightingType::OutputArgument:
return TextEditor::C_OUTPUT_ARGUMENT;
case HighlightingType::Operator:
return TextEditor::C_OPERATOR;
case HighlightingType::OverloadedOperator:
return TextEditor::C_OVERLOADED_OPERATOR;
case HighlightingType::Comment:
return TextEditor::C_COMMENT;
case HighlightingType::StringLiteral:
return TextEditor::C_STRING;
case HighlightingType::NumberLiteral:
return TextEditor::C_NUMBER;
case HighlightingType::Invalid:
QTC_CHECK(false); // never called
return TextEditor::C_TEXT;
default:
break;
}
Q_UNREACHABLE();
}
bool ignore(ClangBackEnd::HighlightingType type)
{
using ClangBackEnd::HighlightingType;
switch (type) {
default:
break;
case HighlightingType::Namespace:
case HighlightingType::Class:
case HighlightingType::Struct:
case HighlightingType::Enum:
case HighlightingType::Union:
case HighlightingType::TypeAlias:
case HighlightingType::Typedef:
case HighlightingType::ObjectiveCClass:
case HighlightingType::ObjectiveCCategory:
case HighlightingType::ObjectiveCProtocol:
case HighlightingType::ObjectiveCInterface:
case HighlightingType::ObjectiveCImplementation:
case HighlightingType::ObjectiveCProperty:
case HighlightingType::ObjectiveCMethod:
case HighlightingType::TemplateTypeParameter:
case HighlightingType::TemplateTemplateParameter:
case HighlightingType::AngleBracketOpen:
case HighlightingType::AngleBracketClose:
case HighlightingType::DoubleAngleBracketClose:
case HighlightingType::TernaryIf:
case HighlightingType::TernaryElse:
return true;
}
return false;
}
TextEditor::TextStyles toTextStyles(ClangBackEnd::HighlightingTypes types)
{
TextEditor::TextStyles textStyles;
textStyles.mixinStyles.initializeElements();
textStyles.mainStyle = toTextStyle(types.mainHighlightingType);
for (ClangBackEnd::HighlightingType type : types.mixinHighlightingTypes) {
if (!ignore(type))
textStyles.mixinStyles.push_back(toTextStyle(type));
}
return textStyles;
}
TextEditor::HighlightingResult toHighlightingResult(
const ClangBackEnd::TokenInfoContainer &tokenInfo)
{
using ClangBackEnd::HighlightingType;
const auto textStyles = toTextStyles(tokenInfo.types);
TextEditor::HighlightingResult result(tokenInfo.line, tokenInfo.column, tokenInfo.length,
textStyles);
if (tokenInfo.types.mixinHighlightingTypes.contains(HighlightingType::AngleBracketOpen))
result.kind = CppEditor::SemanticHighlighter::AngleBracketOpen;
else if (tokenInfo.types.mixinHighlightingTypes.contains(HighlightingType::AngleBracketClose))
result.kind = CppEditor::SemanticHighlighter::AngleBracketClose;
else if (tokenInfo.types.mixinHighlightingTypes.contains(HighlightingType::DoubleAngleBracketClose))
result.kind = CppEditor::SemanticHighlighter::DoubleAngleBracketClose;
else if (tokenInfo.types.mixinHighlightingTypes.contains(HighlightingType::TernaryIf))
result.kind = CppEditor::SemanticHighlighter::TernaryIf;
else if (tokenInfo.types.mixinHighlightingTypes.contains(HighlightingType::TernaryElse))
result.kind = CppEditor::SemanticHighlighter::TernaryElse;
return result;
}
void highlightResultsImpl(QFutureInterface<TextEditor::HighlightingResult> &fi,
const QVector<ClangBackEnd::TokenInfoContainer> &tokenInfos,
int chunkSize)
{
if (fi.isCanceled())
return;
QVector<TextEditor::HighlightingResult> chunksToReport;
chunksToReport.reserve(chunkSize + 1);
using ClangBackEnd::HighlightingType;
bool flushRequested = false;
int flushLine = 0;
auto reportAndClearCurrentChunks = [&] {
flushRequested = false;
flushLine = 0;
if (!chunksToReport.isEmpty()) {
fi.reportResults(chunksToReport);
chunksToReport.erase(chunksToReport.begin(), chunksToReport.end());
}
};
auto reportChunkWise = [&](const TextEditor::HighlightingResult &highlightingResult) {
if (chunksToReport.size() >= chunkSize) {
if (flushRequested && highlightingResult.line != flushLine) {
reportAndClearCurrentChunks();
} else if (!flushRequested) {
flushRequested = true;
flushLine = highlightingResult.line;
}
}
chunksToReport.append(highlightingResult);
};
for (const auto &tokenInfo : tokenInfos)
reportChunkWise(toHighlightingResult(tokenInfo));
if (fi.isCanceled())
return;
reportAndClearCurrentChunks();
}
} // anonymous
namespace ClangCodeModel {
namespace Internal {
QFuture<TextEditor::HighlightingResult> highlightResults(
const QVector<ClangBackEnd::TokenInfoContainer> &tokenInfos,
int chunkSize)
{
return Utils::runAsync(highlightResultsImpl, tokenInfos, chunkSize);
}
} // namespace Internal
} // namespace ClangCodeModel

View File

@@ -1,42 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** 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 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.
**
** 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.
**
****************************************************************************/
#pragma once
#include <QFuture>
#include <QVector>
namespace TextEditor { class HighlightingResult; }
namespace ClangBackEnd { class TokenInfoContainer; }
namespace ClangCodeModel {
namespace Internal {
QFuture<TextEditor::HighlightingResult> highlightResults(
const QVector<ClangBackEnd::TokenInfoContainer> &tokenInfos,
int chunkSize = 100);
} // namespace Internal
} // namespace ClangCodeModel

View File

@@ -1,78 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** 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 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.
**
** 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.
**
****************************************************************************/
#pragma once
#include <clangsupport/diagnosticcontainer.h>
namespace ClangCodeModel {
namespace Internal {
static bool isWithinRange(const ClangBackEnd::SourceRangeContainer &range,
int line,
int column)
{
const ClangBackEnd::SourceLocationContainer &startLocation = range.start;
const ClangBackEnd::SourceLocationContainer &endLocation = range.end;
return startLocation.line <= line
&& startLocation.column <= column
&& line <= endLocation.line
&& column <= endLocation.column;
}
static bool isWithinOneRange(const QVector<ClangBackEnd::SourceRangeContainer> &ranges,
int line,
int column)
{
for (const ClangBackEnd::SourceRangeContainer &range : ranges) {
if (isWithinRange(range, line, column))
return true;
}
return false;
}
bool isDiagnosticRelatedToLocation(const ClangBackEnd::DiagnosticContainer &diagnostic,
const QVector<ClangBackEnd::SourceRangeContainer> &additionalRanges,
int line,
int column)
{
const ClangBackEnd::SourceLocationContainer &location = diagnostic.location;
if (location.line == line && location.column == column)
return true;
if (isWithinOneRange(additionalRanges, line, column))
return true;
if (isWithinOneRange(diagnostic.ranges, line, column))
return true;
return false;
}
} // namespace Internal
} // namespace ClangCodeModel

View File

@@ -62,6 +62,7 @@
#include <projectexplorer/projecttree.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
#include <projectexplorer/taskhub.h>
#include <clangsupport/filecontainer.h>
#include <utils/algorithm.h>
@@ -260,14 +261,13 @@ void ClangModelManagerSupport::onCurrentEditorChanged(Core::IEditor *editor)
m_communicator.documentVisibilityChanged();
// Update task hub issues for current CppEditorDocument
ClangEditorDocumentProcessor::clearTaskHubIssues();
ProjectExplorer::TaskHub::clearTasks(Constants::TASK_CATEGORY_DIAGNOSTICS);
if (!editor || !editor->document() || !cppModelManager()->isCppEditor(editor))
return;
const ::Utils::FilePath filePath = editor->document()->filePath();
if (auto processor = ClangEditorDocumentProcessor::get(filePath.toString())) {
processor->semanticRehighlight();
processor->generateTaskHubIssues();
if (const auto client = clientForFile(filePath))
client->updateParserConfig(filePath, processor->parserConfig());
}
@@ -404,7 +404,6 @@ void ClangModelManagerSupport::updateLanguageClient(
|| currentClient->state() != Client::Initialized
|| project->isKnownFile(doc->filePath())) {
LanguageClientManager::openDocumentWithClient(doc, client);
ClangEditorDocumentProcessor::clearTextMarks(doc->filePath());
hasDocuments = true;
}
}
@@ -496,7 +495,6 @@ void ClangModelManagerSupport::claimNonProjectSources(ClangdClient *client)
&& (currentClient == client || currentClient->project())) {
continue;
}
ClangEditorDocumentProcessor::clearTextMarks(doc->filePath());
if (!ClangdSettings::instance().sizeIsOkay(doc->filePath()))
continue;
client->openDocument(doc);
@@ -632,15 +630,6 @@ void ClangModelManagerSupport::onCppDocumentReloadFinishedOnTranslationUnit(bool
}
}
namespace {
void clearDiagnosticFixIts(const QString &filePath)
{
auto processor = ClangEditorDocumentProcessor::get(filePath);
if (processor)
processor->clearDiagnosticsWithFixIts();
}
}
void ClangModelManagerSupport::onCppDocumentContentsChangedOnTranslationUnit(int position,
int /*charsRemoved*/,
int /*charsAdded*/)
@@ -650,8 +639,6 @@ void ClangModelManagerSupport::onCppDocumentContentsChangedOnTranslationUnit(int
m_communicator.updateChangeContentStartPosition(document->filePath().toString(),
position);
m_communicator.documentsChangedIfNotCurrentDocument(document);
clearDiagnosticFixIts(document->filePath().toString());
}
void ClangModelManagerSupport::onCppDocumentAboutToReloadOnUnsavedFile()

View File

@@ -39,6 +39,8 @@
#include <cppeditor/cpptoolsreuse.h>
#include <cppeditor/cppcodemodelsettings.h>
#include <projectexplorer/taskhub.h>
#include <utils/fadingindicator.h>
#include <utils/qtcassert.h>
#include <utils/theme/theme.h>
@@ -53,9 +55,9 @@
#include <QString>
using namespace CppEditor;
using namespace ClangCodeModel::Internal;
using namespace LanguageClient;
using namespace LanguageServerProtocol;
using namespace ProjectExplorer;
using namespace Utils;
namespace ClangCodeModel {
@@ -63,26 +65,7 @@ namespace Internal {
namespace {
bool isWarningOrNote(ClangBackEnd::DiagnosticSeverity severity)
{
using ClangBackEnd::DiagnosticSeverity;
switch (severity) {
case DiagnosticSeverity::Ignored:
case DiagnosticSeverity::Note:
case DiagnosticSeverity::Warning: return true;
case DiagnosticSeverity::Error:
case DiagnosticSeverity::Fatal: return false;
}
Q_UNREACHABLE();
}
static Id categoryForSeverity(ClangBackEnd::DiagnosticSeverity severity)
{
return isWarningOrNote(severity) ? Constants::CLANG_WARNING : Constants::CLANG_ERROR;
}
ProjectExplorer::Project *projectForCurrentEditor()
Project *projectForCurrentEditor()
{
const QString filePath = currentCppEditorDocumentFilePath();
if (filePath.isEmpty())
@@ -134,7 +117,7 @@ void disableDiagnosticInConfig(ClangDiagnosticConfig &config,
ClangDiagnosticConfig diagnosticConfig(const ClangProjectSettings &projectSettings,
const CppCodeModelSettings &globalSettings)
{
ProjectExplorer::Project *project = projectForCurrentEditor();
Project *project = projectForCurrentEditor();
QTC_ASSERT(project, return {});
// Get config id
@@ -148,7 +131,7 @@ ClangDiagnosticConfig diagnosticConfig(const ClangProjectSettings &projectSettin
return configsModel.configWithId(currentConfigId);
}
bool isDiagnosticConfigChangable(ProjectExplorer::Project *project,
bool isDiagnosticConfigChangable(Project *project,
const ClangBackEnd::DiagnosticContainer &diagnostic)
{
if (!project)
@@ -168,7 +151,7 @@ bool isDiagnosticConfigChangable(ProjectExplorer::Project *project,
void disableDiagnosticInCurrentProjectConfig(const ClangBackEnd::DiagnosticContainer &diagnostic)
{
ProjectExplorer::Project *project = projectForCurrentEditor();
Project *project = projectForCurrentEditor();
QTC_ASSERT(project, return );
// Get settings
@@ -211,90 +194,6 @@ void disableDiagnosticInCurrentProjectConfig(const ClangBackEnd::DiagnosticConta
FadingIndicator::SmallText);
}
} // anonymous namespace
ClangTextMark::ClangTextMark(const FilePath &fileName,
const ClangBackEnd::DiagnosticContainer &diagnostic,
const RemovedFromEditorHandler &removedHandler,
bool fullVisualization, const ClangDiagnosticManager *diagMgr)
: TextEditor::TextMark(fileName,
int(diagnostic.location.line),
categoryForSeverity(diagnostic.severity))
, m_diagnostic(diagnostic)
, m_removedFromEditorHandler(removedHandler)
, m_diagMgr(diagMgr)
{
setSettingsPage(CppEditor::Constants::CPP_CODE_MODEL_SETTINGS_ID);
const bool warning = isWarningOrNote(diagnostic.severity);
setDefaultToolTip(warning ? QApplication::translate("Clang Code Model Marks", "Code Model Warning")
: QApplication::translate("Clang Code Model Marks", "Code Model Error"));
setPriority(warning ? TextEditor::TextMark::NormalPriority
: TextEditor::TextMark::HighPriority);
updateIcon();
if (fullVisualization) {
setLineAnnotation(diagnosticCategoryPrefixRemoved(diagnostic.text.toString()));
setColor(warning ? Theme::CodeModel_Warning_TextMarkColor
: Theme::CodeModel_Error_TextMarkColor);
}
// Copy to clipboard action
QVector<QAction *> actions;
QAction *action = new QAction();
action->setIcon(QIcon::fromTheme("edit-copy", Icons::COPY.icon()));
action->setToolTip(QApplication::translate("Clang Code Model Marks", "Copy to Clipboard"));
QObject::connect(action, &QAction::triggered, [diagnostic]() {
const QString text = ClangDiagnosticWidget::createText({diagnostic},
ClangDiagnosticWidget::InfoBar);
QApplication::clipboard()->setText(text, QClipboard::Clipboard);
});
actions << action;
// Remove diagnostic warning action
ProjectExplorer::Project *project = projectForCurrentEditor();
if (project && isDiagnosticConfigChangable(project, diagnostic)) {
action = new QAction();
action->setIcon(Icons::BROKEN.icon());
action->setToolTip(QApplication::translate("Clang Code Model Marks",
"Disable Diagnostic in Current Project"));
QObject::connect(action, &QAction::triggered, [diagnostic]() {
disableDiagnosticInCurrentProjectConfig(diagnostic);
});
actions << action;
}
setActions(actions);
}
void ClangTextMark::updateIcon(bool valid)
{
using namespace Icons;
if (isWarningOrNote(m_diagnostic.severity))
setIcon(valid ? CODEMODEL_WARNING.icon() : CODEMODEL_DISABLED_WARNING.icon());
else
setIcon(valid ? CODEMODEL_ERROR.icon() : CODEMODEL_DISABLED_ERROR.icon());
}
bool ClangTextMark::addToolTipContent(QLayout *target) const
{
const auto canApplyFixIt = [diag = m_diagnostic, diagMgr = m_diagMgr, c = color()] {
return c != Utils::Theme::Color::IconsDisabledColor
&& !diagMgr->diagnosticsInvalidated()
&& diagMgr->diagnosticsWithFixIts().contains(diag);
};
QWidget *widget = ClangDiagnosticWidget::createWidget(
{m_diagnostic}, ClangDiagnosticWidget::ToolTip, canApplyFixIt, "libclang");
target->addWidget(widget);
return true;
}
void ClangTextMark::removedFromEditor()
{
QTC_ASSERT(m_removedFromEditorHandler, return);
m_removedFromEditorHandler(this);
}
ClangBackEnd::DiagnosticSeverity convertSeverity(DiagnosticSeverity src)
{
if (src == DiagnosticSeverity::Error)
@@ -383,6 +282,36 @@ ClangBackEnd::DiagnosticContainer convertDiagnostic(const ClangdDiagnostic &src,
return target;
}
void addTask(const ClangBackEnd::DiagnosticContainer &diagnostic)
{
Task::TaskType taskType = Task::TaskType::Unknown;
QIcon icon;
switch (diagnostic.severity) {
case ClangBackEnd::DiagnosticSeverity::Fatal:
case ClangBackEnd::DiagnosticSeverity::Error:
taskType = Task::TaskType::Error;
icon = ::Utils::Icons::CODEMODEL_ERROR.icon();
break;
case ClangBackEnd::DiagnosticSeverity::Warning:
taskType = Task::TaskType::Warning;
icon = ::Utils::Icons::CODEMODEL_WARNING.icon();
break;
default:
break;
}
TaskHub::addTask(Task(taskType,
diagnosticCategoryPrefixRemoved(diagnostic.text.toString()),
FilePath::fromString(diagnostic.location.filePath.toString()),
diagnostic.location.line,
Constants::TASK_CATEGORY_DIAGNOSTICS,
icon,
Task::NoOptions));
}
} // anonymous namespace
ClangdTextMark::ClangdTextMark(const FilePath &filePath,
const Diagnostic &diagnostic,
bool isProjectFile,
@@ -404,7 +333,7 @@ ClangdTextMark::ClangdTextMark(const FilePath &filePath,
setLineAnnotation(diagnostic.message());
setColor(isError ? Theme::CodeModel_Error_TextMarkColor
: Theme::CodeModel_Warning_TextMarkColor);
ClangDiagnosticManager::addTask(m_diagnostic);
addTask(m_diagnostic);
}
// Copy to clipboard action
@@ -420,7 +349,7 @@ ClangdTextMark::ClangdTextMark(const FilePath &filePath,
actions << action;
// Remove diagnostic warning action
ProjectExplorer::Project *project = projectForCurrentEditor();
Project *project = projectForCurrentEditor();
if (project && isDiagnosticConfigChangable(project, m_diagnostic)) {
action = new QAction();
action->setIcon(Icons::BROKEN.icon());

View File

@@ -40,31 +40,6 @@ namespace LanguageClient { class Client; }
namespace ClangCodeModel {
namespace Internal {
class ClangDiagnosticManager;
class ClangTextMark : public TextEditor::TextMark
{
public:
using RemovedFromEditorHandler = std::function<void(ClangTextMark *)>;
ClangTextMark(const ::Utils::FilePath &fileName,
const ClangBackEnd::DiagnosticContainer &diagnostic,
const RemovedFromEditorHandler &removedHandler,
bool fullVisualization,
const ClangDiagnosticManager *diagMgr);
ClangBackEnd::DiagnosticContainer diagnostic() const { return m_diagnostic; }
void updateIcon(bool valid = true);
private:
bool addToolTipContent(QLayout *target) const override;
void removedFromEditor() override;
private:
ClangBackEnd::DiagnosticContainer m_diagnostic;
RemovedFromEditorHandler m_removedFromEditorHandler;
const ClangDiagnosticManager * const m_diagMgr;
};
class ClangdTextMark : public TextEditor::TextMark
{

View File

@@ -157,16 +157,12 @@ QList<TextEditor::BlockRange> toTextEditorBlocks(
} // anonymous namespace
BuiltinEditorDocumentProcessor::BuiltinEditorDocumentProcessor(
TextEditor::TextDocument *document,
bool enableSemanticHighlighter)
BuiltinEditorDocumentProcessor::BuiltinEditorDocumentProcessor(TextEditor::TextDocument *document)
: BaseEditorDocumentProcessor(document->document(), document->filePath().toString())
, m_parser(new BuiltinEditorDocumentParser(document->filePath().toString(),
indexerFileSizeLimitInMb()))
, m_codeWarningsUpdated(false)
, m_semanticHighlighter(enableSemanticHighlighter
? new SemanticHighlighter(document)
: nullptr)
, m_semanticHighlighter(new SemanticHighlighter(document))
{
using namespace Internal;
@@ -176,18 +172,16 @@ BuiltinEditorDocumentProcessor::BuiltinEditorDocumentProcessor(
config.usePrecompiledHeaders = cms->pchUsage() != CppCodeModelSettings::PchUse_None;
m_parser->setConfiguration(config);
if (m_semanticHighlighter) {
m_semanticHighlighter->setHighlightingRunner(
[this]() -> QFuture<TextEditor::HighlightingResult> {
const SemanticInfo semanticInfo = m_semanticInfoUpdater.semanticInfo();
CheckSymbols *checkSymbols = createHighlighter(semanticInfo.doc, semanticInfo.snapshot,
textDocument());
QTC_ASSERT(checkSymbols, return QFuture<TextEditor::HighlightingResult>());
connect(checkSymbols, &CheckSymbols::codeWarningsUpdated,
this, &BuiltinEditorDocumentProcessor::onCodeWarningsUpdated);
return checkSymbols->start();
});
}
m_semanticHighlighter->setHighlightingRunner(
[this]() -> QFuture<TextEditor::HighlightingResult> {
const SemanticInfo semanticInfo = m_semanticInfoUpdater.semanticInfo();
CheckSymbols *checkSymbols = createHighlighter(semanticInfo.doc, semanticInfo.snapshot,
textDocument());
QTC_ASSERT(checkSymbols, return QFuture<TextEditor::HighlightingResult>());
connect(checkSymbols, &CheckSymbols::codeWarningsUpdated,
this, &BuiltinEditorDocumentProcessor::onCodeWarningsUpdated);
return checkSymbols->start();
});
connect(m_parser.data(), &BuiltinEditorDocumentParser::projectPartInfoUpdated,
this, &BaseEditorDocumentProcessor::projectPartInfoUpdated);
@@ -229,7 +223,7 @@ void BuiltinEditorDocumentProcessor::recalculateSemanticInfoDetached(bool force)
void BuiltinEditorDocumentProcessor::semanticRehighlight()
{
if (m_semanticHighlighter && m_semanticInfoUpdater.semanticInfo().doc) {
if (m_semanticInfoUpdater.semanticInfo().doc) {
if (const CPlusPlus::Document::Ptr document = m_documentSnapshot.document(filePath())) {
m_codeWarnings = toTextEditorSelections(document->diagnosticMessages(), textDocument());
m_codeWarningsUpdated = false;
@@ -275,6 +269,12 @@ QFuture<SymbolInfo> BuiltinEditorDocumentProcessor::requestFollowSymbol(int, int
return futureInterface.future();
}
void BuiltinEditorDocumentProcessor::setSemanticHighlightingChecker(
const SemanticHighlightingChecker &checker)
{
m_semanticHighlightingChecker = checker;
}
void BuiltinEditorDocumentProcessor::onParserFinished(CPlusPlus::Document::Ptr document,
CPlusPlus::Snapshot snapshot)
{
@@ -312,7 +312,7 @@ void BuiltinEditorDocumentProcessor::onSemanticInfoUpdated(const SemanticInfo se
emit semanticInfoUpdated(semanticInfo);
if (m_semanticHighlighter)
if (!m_semanticHighlightingChecker || m_semanticHighlightingChecker())
m_semanticHighlighter->run();
}

View File

@@ -31,6 +31,8 @@
#include "cppsemanticinfoupdater.h"
#include "semantichighlighter.h"
#include <functional>
namespace CppEditor {
class CPPEDITOR_EXPORT BuiltinEditorDocumentProcessor : public BaseEditorDocumentProcessor
@@ -38,8 +40,7 @@ class CPPEDITOR_EXPORT BuiltinEditorDocumentProcessor : public BaseEditorDocumen
Q_OBJECT
public:
BuiltinEditorDocumentProcessor(TextEditor::TextDocument *document,
bool enableSemanticHighlighter = true);
BuiltinEditorDocumentProcessor(TextEditor::TextDocument *document);
~BuiltinEditorDocumentProcessor() override;
// BaseEditorDocumentProcessor interface
@@ -55,6 +56,9 @@ public:
QFuture<CursorInfo> requestLocalReferences(const QTextCursor &) override;
QFuture<SymbolInfo> requestFollowSymbol(int, int) override;
using SemanticHighlightingChecker = std::function<bool()>;
void setSemanticHighlightingChecker(const SemanticHighlightingChecker &checker);
private:
void onParserFinished(CPlusPlus::Document::Ptr document, CPlusPlus::Snapshot snapshot);
void onSemanticInfoUpdated(const SemanticInfo semanticInfo);
@@ -73,6 +77,7 @@ private:
SemanticInfoUpdater m_semanticInfoUpdater;
QScopedPointer<SemanticHighlighter> m_semanticHighlighter;
SemanticHighlightingChecker m_semanticHighlightingChecker;
};
} // namespace CppEditor

View File

@@ -182,7 +182,6 @@ extend_qtc_test(unittest
clangcodemodelserver-test.cpp
clangcompletecodejob-test.cpp
clangcompletioncontextanalyzer-test.cpp
clangdiagnosticfilter-test.cpp
clangdocumentprocessors-test.cpp
clangdocumentprocessor-test.cpp
clangdocuments-test.cpp
@@ -190,7 +189,6 @@ extend_qtc_test(unittest
clangdocument-test.cpp
clangfixitoperation-test.cpp
clangfollowsymbol-test.cpp
clangisdiagnosticrelatedtolocation-test.cpp
clangjobqueue-test.cpp
clangjobs-test.cpp
clangparsesupportivetranslationunitjob-test.cpp
@@ -213,7 +211,6 @@ extend_qtc_test(unittest
diagnostic-test.cpp
fixit-test.cpp
gtest-clang-printing.cpp gtest-clang-printing.h
highlightingresultreporter-test.cpp
readexporteddiagnostics-test.cpp
skippedsourceranges-test.cpp
sourcelocation-test.cpp
@@ -422,11 +419,8 @@ extend_qtc_test(unittest
clangactivationsequenceprocessor.cpp clangactivationsequenceprocessor.h
clangcompletionchunkstotextconverter.cpp clangcompletionchunkstotextconverter.h
clangcompletioncontextanalyzer.cpp clangcompletioncontextanalyzer.h
clangdiagnosticfilter.cpp clangdiagnosticfilter.h
clangfixitoperation.cpp clangfixitoperation.h
clanghighlightingresultreporter.cpp clanghighlightingresultreporter.h
clanguiheaderondiskmanager.cpp clanguiheaderondiskmanager.h
clangisdiagnosticrelatedtolocation.h
)
find_package(yaml-cpp QUIET MODULE)

View File

@@ -1,238 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** 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 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.
**
** 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.
**
****************************************************************************/
#include "googletest.h"
#include <clangdiagnosticfilter.h>
#include <diagnosticcontainer.h>
#include <fixitcontainer.h>
namespace {
using ::testing::Contains;
using ::testing::Not;
using ClangBackEnd::DiagnosticContainer;
using ClangBackEnd::FixItContainer;
using ClangBackEnd::SourceLocationContainer;
using ClangBackEnd::SourceRangeContainer;
DiagnosticContainer createDiagnostic(const QString &text,
ClangBackEnd::DiagnosticSeverity severity,
const QString &filePath,
QVector<DiagnosticContainer> children = QVector<DiagnosticContainer>(),
bool addFixItContainer = false)
{
QVector<FixItContainer> fixIts;
if (addFixItContainer)
fixIts.append(FixItContainer(Utf8StringLiteral("("), {{filePath, 1, 1}, {filePath, 1, 2}}));
return DiagnosticContainer(
text,
Utf8StringLiteral(""),
{},
severity,
{filePath, 0u, 0u},
{},
fixIts,
children
);
}
const QString mainFileHeaderPath = QString::fromUtf8(TESTDATA_DIR "/someHeader.h");
const QString mainFilePath = QString::fromUtf8(TESTDATA_DIR "/diagnostic_erroneous_source.cpp");
const QString headerFilePath = QString::fromUtf8(TESTDATA_DIR "/diagnostic_erroneous_header.cpp");
DiagnosticContainer warningFromHeader()
{
return createDiagnostic(
QStringLiteral("warning: control reaches end of non-void function"),
ClangBackEnd::DiagnosticSeverity::Warning,
headerFilePath);
}
DiagnosticContainer errorFromHeader()
{
return createDiagnostic(
QStringLiteral("C++ requires a type specifier for all declarations"),
ClangBackEnd::DiagnosticSeverity::Error,
headerFilePath);
}
DiagnosticContainer warningFromMainFile()
{
return createDiagnostic(
QStringLiteral("warning: enumeration value 'Three' not handled in switch"),
ClangBackEnd::DiagnosticSeverity::Warning,
mainFilePath);
}
DiagnosticContainer pragmaOnceWarningInHeader()
{
return createDiagnostic(
QStringLiteral("warning: #pragma once in main file"),
ClangBackEnd::DiagnosticSeverity::Warning,
mainFileHeaderPath);
}
DiagnosticContainer includeNextInPrimarySourceFileWarningInHeader()
{
return createDiagnostic(
QStringLiteral("warning: #include_next in primary source file"),
ClangBackEnd::DiagnosticSeverity::Warning,
mainFileHeaderPath);
}
DiagnosticContainer errorFromMainFile()
{
return createDiagnostic(
QStringLiteral("error: void function 'g' should not return a value"),
ClangBackEnd::DiagnosticSeverity::Error,
mainFilePath);
}
DiagnosticContainer fixIt1(const QString &filePath)
{
return createDiagnostic(
QStringLiteral("note: place parentheses around the assignment to silence this warning"),
ClangBackEnd::DiagnosticSeverity::Note,
filePath);
}
DiagnosticContainer fixIt2(const QString &filePath)
{
return createDiagnostic(
QStringLiteral("note: use '==' to turn this assignment into an equality comparison"),
ClangBackEnd::DiagnosticSeverity::Note,
filePath);
}
DiagnosticContainer createDiagnosticWithFixIt(const QString &filePath)
{
return createDiagnostic(
QStringLiteral("warning: using the result of an assignment as a condition without parentheses"),
ClangBackEnd::DiagnosticSeverity::Warning,
filePath,
{fixIt1(filePath), fixIt2(filePath)},
true);
}
DiagnosticContainer warningFromMainFileWithFixits()
{
return createDiagnosticWithFixIt(mainFilePath);
}
DiagnosticContainer warningFromHeaderFileWithFixits()
{
return createDiagnosticWithFixIt(headerFilePath);
}
class ClangDiagnosticFilter : public ::testing::Test
{
protected:
ClangCodeModel::Internal::ClangDiagnosticFilter clangDiagnosticFilter{mainFilePath};
};
TEST_F(ClangDiagnosticFilter, WarningsFromMainFileAreLetThrough)
{
clangDiagnosticFilter.filter({warningFromMainFile()});
ASSERT_THAT(clangDiagnosticFilter.takeWarnings(),Contains(warningFromMainFile()));
}
TEST_F(ClangDiagnosticFilter, WarningsFromHeaderAreIgnored)
{
clangDiagnosticFilter.filter({warningFromHeader()});
ASSERT_THAT(clangDiagnosticFilter.takeWarnings(), Not(Contains(warningFromHeader())));
}
TEST_F(ClangDiagnosticFilter, ErrorsFromMainFileAreLetThrough)
{
clangDiagnosticFilter.filter({errorFromMainFile()});
ASSERT_THAT(clangDiagnosticFilter.takeErrors(), Contains(errorFromMainFile()));
}
TEST_F(ClangDiagnosticFilter, ErrorsFromHeaderAreIgnored)
{
clangDiagnosticFilter.filter({errorFromHeader()});
ASSERT_THAT(clangDiagnosticFilter.takeErrors(), Not(Contains(errorFromHeader())));
}
TEST_F(ClangDiagnosticFilter, FixItsFromMainFileAreLetThrough)
{
clangDiagnosticFilter.filter({warningFromMainFileWithFixits()});
ASSERT_THAT(clangDiagnosticFilter.takeFixIts(), Contains(warningFromMainFileWithFixits()));
}
TEST_F(ClangDiagnosticFilter, FixItsFromHeaderAreIgnored)
{
clangDiagnosticFilter.filter({warningFromHeaderFileWithFixits()});
ASSERT_THAT(clangDiagnosticFilter.takeFixIts(),
Not(Contains(warningFromHeaderFileWithFixits())));
}
TEST_F(ClangDiagnosticFilter, WarningsAreEmptyAfterTaking)
{
clangDiagnosticFilter.filter({warningFromMainFile()});
clangDiagnosticFilter.takeWarnings();
ASSERT_TRUE(clangDiagnosticFilter.takeWarnings().isEmpty());
}
TEST_F(ClangDiagnosticFilter, IgnoreCertainWarningsInHeaderFiles)
{
ClangCodeModel::Internal::ClangDiagnosticFilter myClangDiagnosticFilter{mainFileHeaderPath};
myClangDiagnosticFilter.filter({pragmaOnceWarningInHeader(),
includeNextInPrimarySourceFileWarningInHeader()});
ASSERT_TRUE(myClangDiagnosticFilter.takeWarnings().isEmpty());
}
TEST_F(ClangDiagnosticFilter, ErrorsAreEmptyAfterTaking)
{
clangDiagnosticFilter.filter({errorFromMainFile()});
clangDiagnosticFilter.takeErrors();
ASSERT_TRUE(clangDiagnosticFilter.takeErrors().isEmpty());
}
TEST_F(ClangDiagnosticFilter, FixItssAreEmptyAfterTaking)
{
clangDiagnosticFilter.filter({warningFromMainFileWithFixits()});
clangDiagnosticFilter.takeFixIts();
ASSERT_TRUE(clangDiagnosticFilter.takeFixIts().isEmpty());
}
} // anonymous namespace

View File

@@ -1,146 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** 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 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.
**
** 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.
**
****************************************************************************/
#include "googletest.h"
#include <clangisdiagnosticrelatedtolocation.h>
#include <diagnosticcontainer.h>
using ClangBackEnd::DiagnosticContainer;
using ClangBackEnd::SourceLocationContainer;
using ClangBackEnd::SourceRangeContainer;
using ClangCodeModel::Internal::isDiagnosticRelatedToLocation;
namespace {
SourceRangeContainer createRange(uint startLine,
uint startColumn,
uint endLine,
uint endColumn)
{
const SourceLocationContainer startLocation(Utf8String(), startLine, startColumn);
const SourceLocationContainer endLocation(Utf8String(), endLine, endColumn);
return SourceRangeContainer(startLocation, endLocation);
}
DiagnosticContainer createDiagnosticWithLocation(uint line, uint column)
{
const SourceLocationContainer location(Utf8String(), line, column);
return DiagnosticContainer(Utf8String(),
Utf8String(),
std::pair<Utf8String, Utf8String>(),
ClangBackEnd::DiagnosticSeverity::Error,
location,
QVector<SourceRangeContainer>(),
QVector<ClangBackEnd::FixItContainer>(),
QVector<DiagnosticContainer>());
}
DiagnosticContainer createDiagnosticWithRange(uint startLine,
uint startColumn,
uint endLine,
uint endColumn)
{
const SourceRangeContainer range = createRange(startLine, startColumn, endLine, endColumn);
return DiagnosticContainer(Utf8String(),
Utf8String(),
std::pair<Utf8String, Utf8String>(),
ClangBackEnd::DiagnosticSeverity::Error,
SourceLocationContainer(),
{range},
QVector<ClangBackEnd::FixItContainer>(),
QVector<DiagnosticContainer>());
}
class ClangIsDiagnosticRelatedToLocation : public ::testing::Test
{
public:
ClangIsDiagnosticRelatedToLocation() {}
protected:
const QVector<SourceRangeContainer> emptyRanges;
};
TEST_F(ClangIsDiagnosticRelatedToLocation, MatchLocation)
{
const DiagnosticContainer diagnostic = createDiagnosticWithLocation(5, 5);
ASSERT_TRUE(isDiagnosticRelatedToLocation(diagnostic, emptyRanges, 5, 5));
}
TEST_F(ClangIsDiagnosticRelatedToLocation, DoNotMatchLocation)
{
const DiagnosticContainer diagnostic = createDiagnosticWithLocation(5, 5);
ASSERT_FALSE(isDiagnosticRelatedToLocation(diagnostic, emptyRanges, 5, 4));
}
TEST_F(ClangIsDiagnosticRelatedToLocation, MatchStartRange)
{
const DiagnosticContainer diagnostic = createDiagnosticWithRange(5, 5, 5, 10);
ASSERT_TRUE(isDiagnosticRelatedToLocation(diagnostic, emptyRanges, 5, 5));
}
TEST_F(ClangIsDiagnosticRelatedToLocation, MatchWithinRange)
{
const DiagnosticContainer diagnostic = createDiagnosticWithRange(5, 5, 5, 10);
ASSERT_TRUE(isDiagnosticRelatedToLocation(diagnostic, emptyRanges, 5, 7));
}
TEST_F(ClangIsDiagnosticRelatedToLocation, MatchEndRange)
{
const DiagnosticContainer diagnostic = createDiagnosticWithRange(5, 5, 5, 10);
ASSERT_TRUE(isDiagnosticRelatedToLocation(diagnostic, emptyRanges, 5, 10));
}
TEST_F(ClangIsDiagnosticRelatedToLocation, DoNoMatchBeforeRangeStart)
{
const DiagnosticContainer diagnostic = createDiagnosticWithRange(5, 5, 5, 10);
ASSERT_FALSE(isDiagnosticRelatedToLocation(diagnostic, emptyRanges, 5, 4));
}
TEST_F(ClangIsDiagnosticRelatedToLocation, DoNoMatchAfterRangeEnd)
{
const DiagnosticContainer diagnostic = createDiagnosticWithRange(5, 5, 5, 10);
ASSERT_FALSE(isDiagnosticRelatedToLocation(diagnostic, emptyRanges, 5, 11));
}
TEST_F(ClangIsDiagnosticRelatedToLocation, MatchInAdditionalRange)
{
const QVector<SourceRangeContainer> additionalRanges{createRange(5, 5, 5, 10)};
const DiagnosticContainer diagnostic = createDiagnosticWithLocation(1, 1);
ASSERT_TRUE(isDiagnosticRelatedToLocation(diagnostic, additionalRanges, 5, 7));
}
} // anonymous

View File

@@ -1,164 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** 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 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.
**
** 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.
**
****************************************************************************/
#include "googletest.h"
#include "unittest-utility-functions.h"
#include <chunksreportedmonitor.h>
#include <clangdocument.h>
#include <clangdocuments.h>
#include <cursor.h>
#include <tokeninfocontainer.h>
#include <tokenprocessor.h>
#include <clanghighlightingresultreporter.h>
#include <unsavedfiles.h>
using ClangBackEnd::Cursor;
using ClangBackEnd::TokenProcessor;
using ClangBackEnd::TokenInfoContainer;
using ClangBackEnd::HighlightingType;
using ClangBackEnd::Document;
using ClangBackEnd::Documents;
using ClangBackEnd::UnsavedFiles;
using ClangBackEnd::ChunksReportedMonitor;
namespace {
struct Data {
UnsavedFiles unsavedFiles;
Documents documents{unsavedFiles};
Document document{Utf8StringLiteral(TESTDATA_DIR "/highlightingmarks.cpp"),
UnitTest::addPlatformArguments({Utf8StringLiteral("-std=c++14")}),
Utf8StringVector(),
documents};
};
class HighlightingResultReporter : public ::testing::Test
{
public:
static void SetUpTestCase();
static void TearDownTestCase();
protected:
static Data *d;
};
QVector<TokenInfoContainer> noTokenInfos()
{
return QVector<TokenInfoContainer>();
}
QVector<TokenInfoContainer> generateTokenInfos(uint count)
{
auto container = QVector<TokenInfoContainer>();
for (uint i = 0; i < count; ++i) {
const uint line = i + 1;
ClangBackEnd::HighlightingTypes types;
types.mainHighlightingType = ClangBackEnd::HighlightingType::Type;
container.append(TokenInfoContainer(line, 1, 1, types));
}
return container;
}
TEST_F(HighlightingResultReporter, StartAndFinish)
{
auto future = ClangCodeModel::Internal::highlightResults(noTokenInfos());
future.waitForFinished();
ASSERT_THAT(future.isFinished(), true);
}
TEST_F(HighlightingResultReporter, ReportNothingIfNothingToReport)
{
auto future = ClangCodeModel::Internal::highlightResults(generateTokenInfos(0));
ChunksReportedMonitor monitor(future);
ASSERT_THAT(monitor.resultsReadyCounter(), 0L);
}
TEST_F(HighlightingResultReporter, ReportSingleResultAsOneChunk)
{
auto future = ClangCodeModel::Internal::highlightResults(generateTokenInfos(1), 1);
ChunksReportedMonitor monitor(future);
ASSERT_THAT(monitor.resultsReadyCounter(), 1L);
}
TEST_F(HighlightingResultReporter, ReportRestIfChunkSizeNotReached)
{
auto future = ClangCodeModel::Internal::highlightResults(generateTokenInfos(1), 100);
ChunksReportedMonitor monitor(future);
ASSERT_THAT(monitor.resultsReadyCounter(), 1L);
}
TEST_F(HighlightingResultReporter, ReportChunksWithoutRest)
{
auto future = ClangCodeModel::Internal::highlightResults(generateTokenInfos(4), 1);
ChunksReportedMonitor monitor(future);
ASSERT_THAT(monitor.resultsReadyCounter(), 2L);
}
TEST_F(HighlightingResultReporter, ReportSingleChunkAndRest)
{
auto future = ClangCodeModel::Internal::highlightResults(generateTokenInfos(5), 2);
ChunksReportedMonitor monitor(future);
ASSERT_THAT(monitor.resultsReadyCounter(), 2L);
}
TEST_F(HighlightingResultReporter, ReportCompleteLines)
{
ClangBackEnd::HighlightingTypes types;
types.mainHighlightingType = ClangBackEnd::HighlightingType::Type;
QVector<TokenInfoContainer> tokenInfos {
TokenInfoContainer(1, 1, 1, types),
TokenInfoContainer(1, 2, 1, types),
TokenInfoContainer(2, 1, 1, types),
};
auto future = ClangCodeModel::Internal::highlightResults(tokenInfos, 1);
ChunksReportedMonitor monitor(future);
ASSERT_THAT(monitor.resultsReadyCounter(), 2L);
}
Data *HighlightingResultReporter::d;
void HighlightingResultReporter::SetUpTestCase()
{
d = new Data;
}
void HighlightingResultReporter::TearDownTestCase()
{
delete d;
d = nullptr;
}
} // anonymous

View File

@@ -204,14 +204,12 @@ Project {
"clangcompareoperators.h",
"clangcompletecodejob-test.cpp",
"clangcompletioncontextanalyzer-test.cpp",
"clangdiagnosticfilter-test.cpp",
"clangdocument-test.cpp",
"clangdocumentprocessor-test.cpp",
"clangdocumentprocessors-test.cpp",
"clangdocuments-test.cpp",
"clangfixitoperation-test.cpp",
"clangfollowsymbol-test.cpp",
"clangisdiagnosticrelatedtolocation-test.cpp",
"clangjobqueue-test.cpp",
"clangjobs-test.cpp",
"clangparsesupportivetranslationunitjob-test.cpp",
@@ -235,7 +233,6 @@ Project {
"fixit-test.cpp",
"gtest-clang-printing.cpp",
"gtest-clang-printing.h",
"highlightingresultreporter-test.cpp",
"readexporteddiagnostics-test.cpp",
"skippedsourceranges-test.cpp",
"sourcelocation-test.cpp",
@@ -403,13 +400,8 @@ Project {
"clangcompletionchunkstotextconverter.h",
"clangcompletioncontextanalyzer.cpp",
"clangcompletioncontextanalyzer.h",
"clangdiagnosticfilter.cpp",
"clangdiagnosticfilter.h",
"clangfixitoperation.cpp",
"clangfixitoperation.h",
"clanghighlightingresultreporter.cpp",
"clanghighlightingresultreporter.h",
"clangisdiagnosticrelatedtolocation.h",
"clanguiheaderondiskmanager.cpp",
"clanguiheaderondiskmanager.h",
]