summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Bubke <marco.bubke@qt.io>2017-07-19 10:43:47 +0200
committerTim Jenssen <tim.jenssen@qt.io>2017-07-24 13:37:18 +0000
commit9428624fc1d24492ef71b3f738edb4598b53df53 (patch)
treede7627c4ed7763bbc603c873dffac34505a8b1d6
parent9b5d6546b8282f237214115285fc864b87f2d857 (diff)
downloadqt-creator-9428624fc1d24492ef71b3f738edb4598b53df53.tar.gz
Clang: Tool tips for clang query diagnostics
If you hover a diagnostics in for a clang query you get now a simple tool tip. Change-Id: I6352dd3d4b9a33c183e69037eac903469b90eea4 Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
-rw-r--r--src/libs/clangbackendipc/dynamicastmatcherdiagnosticcontextcontainer.h2
-rw-r--r--src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.cpp2
-rw-r--r--src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.h2
-rw-r--r--src/plugins/clangrefactoring/clangqueryhighlighter.cpp12
-rw-r--r--src/plugins/clangrefactoring/clangqueryhighlighter.h6
-rw-r--r--src/plugins/clangrefactoring/clangqueryhighlightmarker.h79
-rw-r--r--src/plugins/clangrefactoring/clangqueryhoverhandler.cpp60
-rw-r--r--src/plugins/clangrefactoring/clangqueryhoverhandler.h46
-rw-r--r--src/plugins/clangrefactoring/clangquerytexteditorwidget.cpp11
-rw-r--r--src/plugins/clangrefactoring/clangquerytexteditorwidget.h5
-rw-r--r--src/plugins/clangrefactoring/clangrefactoring.pro6
-rw-r--r--src/plugins/texteditor/texteditor.cpp5
-rw-r--r--src/plugins/texteditor/texteditor.h2
-rw-r--r--src/tools/clangrefactoringbackend/source/clangquery.cpp2
-rw-r--r--src/tools/clangrefactoringbackend/source/clangquery.h2
-rw-r--r--tests/unit/unittest/clangqueryhighlightmarker-test.cpp261
16 files changed, 492 insertions, 11 deletions
diff --git a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticcontextcontainer.h b/src/libs/clangbackendipc/dynamicastmatcherdiagnosticcontextcontainer.h
index 61d7e2fff5..c220aa2377 100644
--- a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticcontextcontainer.h
+++ b/src/libs/clangbackendipc/dynamicastmatcherdiagnosticcontextcontainer.h
@@ -55,7 +55,7 @@ public:
return m_contextType;
}
- Utils::SmallString contextTypeText() const;
+ CMBIPC_EXPORT Utils::SmallString contextTypeText() const;
const Utils::SmallStringVector &arguments() const
{
diff --git a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.cpp b/src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.cpp
index af4de3e058..e17ecd4da9 100644
--- a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.cpp
+++ b/src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.cpp
@@ -33,8 +33,8 @@ namespace ClangBackEnd {
QDebug operator<<(QDebug debug, const DynamicASTMatcherDiagnosticMessageContainer &container)
{
debug.nospace() << "DynamicASTMatcherDiagnosticMessageContainer("
- << container.sourceRange() << ", "
<< container.errorTypeText() << ", "
+ << container.sourceRange() << ", "
<< container.arguments()
<< ")";
diff --git a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.h b/src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.h
index 8f9581872d..07a21af605 100644
--- a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.h
+++ b/src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.h
@@ -55,7 +55,7 @@ public:
return m_errorType;
}
- Utils::SmallString errorTypeText() const;
+ CMBIPC_EXPORT Utils::SmallString errorTypeText() const;
const Utils::SmallStringVector &arguments() const
{
diff --git a/src/plugins/clangrefactoring/clangqueryhighlighter.cpp b/src/plugins/clangrefactoring/clangqueryhighlighter.cpp
index 5f9e72d4be..d00bf82d29 100644
--- a/src/plugins/clangrefactoring/clangqueryhighlighter.cpp
+++ b/src/plugins/clangrefactoring/clangqueryhighlighter.cpp
@@ -72,6 +72,18 @@ bool ClangQueryHighlighter::hasDiagnostics() const
return m_marker.hasMessagesOrContexts();
}
+ClangBackEnd::DynamicASTMatcherDiagnosticMessageContainers
+ClangQueryHighlighter::messagesForLineAndColumn(uint line, uint column) const
+{
+ return m_marker.messagesForLineAndColumn(line, column);
+}
+
+ClangBackEnd::DynamicASTMatcherDiagnosticContextContainers
+ClangQueryHighlighter::contextsForLineAndColumn(uint line, uint column) const
+{
+ return m_marker.contextsForLineAndColumn(line, column);
+}
+
void ClangQueryHighlighter::highlightBlock(const QString &text)
{
int currentLineNumber = currentBlock().blockNumber() + 1;
diff --git a/src/plugins/clangrefactoring/clangqueryhighlighter.h b/src/plugins/clangrefactoring/clangqueryhighlighter.h
index 977f91fd11..7e96a1a5f9 100644
--- a/src/plugins/clangrefactoring/clangqueryhighlighter.h
+++ b/src/plugins/clangrefactoring/clangqueryhighlighter.h
@@ -44,6 +44,12 @@ public:
bool hasDiagnostics() const;
+ ClangBackEnd::DynamicASTMatcherDiagnosticMessageContainers
+ messagesForLineAndColumn(uint line, uint column) const;
+
+ ClangBackEnd::DynamicASTMatcherDiagnosticContextContainers
+ contextsForLineAndColumn(uint line, uint column) const;
+
protected:
void highlightBlock(const QString &text) override;
diff --git a/src/plugins/clangrefactoring/clangqueryhighlightmarker.h b/src/plugins/clangrefactoring/clangqueryhighlightmarker.h
index 8f53d59538..6ef61627b7 100644
--- a/src/plugins/clangrefactoring/clangqueryhighlightmarker.h
+++ b/src/plugins/clangrefactoring/clangqueryhighlightmarker.h
@@ -250,6 +250,85 @@ public:
return !m_messages.empty() || !m_contexts.empty();
}
+ static
+ bool isAfterStartColumn(const SourceRange &sourceRange, uint line, uint column)
+ {
+ return sourceRange.start().line() == line && sourceRange.start().column() <= column;
+ }
+
+ static
+ bool isBeforeEndColumn(const SourceRange &sourceRange, uint line, uint column)
+ {
+ return sourceRange.end().line() == line && sourceRange.end().column() >= column;
+ }
+
+ static
+ bool isInBetweenLine(const SourceRange &sourceRange, uint line)
+ {
+ return sourceRange.start().line() < line && sourceRange.end().line() > line;
+ }
+
+ static
+ bool isSingleLine(const SourceRange &sourceRange)
+ {
+ return sourceRange.start().line() == sourceRange.end().line();
+ }
+
+ static
+ bool isInsideMultiLine(const SourceRange &sourceRange, uint line, uint column)
+ {
+ return !isSingleLine(sourceRange)
+ && (isAfterStartColumn(sourceRange, line, column)
+ || isInBetweenLine(sourceRange, line)
+ || isBeforeEndColumn(sourceRange, line, column));
+ }
+
+ static
+ bool isInsideSingleLine(const SourceRange &sourceRange, uint line, uint column)
+ {
+ return isSingleLine(sourceRange)
+ && isAfterStartColumn(sourceRange, line, column)
+ && isBeforeEndColumn(sourceRange, line, column);
+ }
+
+ static
+ bool isInsideRange(const SourceRange &sourceRange, uint line, uint column)
+ {
+ return isInsideSingleLine(sourceRange, line, column)
+ || isInsideMultiLine(sourceRange, line, column);
+ }
+
+ Messages messagesForLineAndColumn(uint line, uint column) const
+ {
+ Messages messages;
+
+ auto underPosition = [=] (const Message &message) {
+ return ClangQueryHighlightMarker::isInsideRange(message.sourceRange(), line, column);
+ };
+
+ std::copy_if(m_messages.begin(),
+ m_messages.end(),
+ std::back_inserter(messages),
+ underPosition);
+
+ return messages;
+ }
+
+ Contexts contextsForLineAndColumn(uint line, uint column) const
+ {
+ Contexts contexts;
+
+ auto underPosition = [=] (const Context &context) {
+ return ClangQueryHighlightMarker::isInsideRange(context.sourceRange(), line, column);
+ };
+
+ std::copy_if(m_contexts.begin(),
+ m_contexts.end(),
+ std::back_inserter(contexts),
+ underPosition);
+
+ return contexts;
+ }
private:
Contexts m_contexts;
diff --git a/src/plugins/clangrefactoring/clangqueryhoverhandler.cpp b/src/plugins/clangrefactoring/clangqueryhoverhandler.cpp
new file mode 100644
index 0000000000..47ca0dbe79
--- /dev/null
+++ b/src/plugins/clangrefactoring/clangqueryhoverhandler.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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 "clangqueryhoverhandler.h"
+
+#include "clangqueryhighlighter.h"
+
+#include <dynamicastmatcherdiagnosticmessagecontainer.h>
+
+#include <texteditor/texteditor.h>
+
+namespace ClangRefactoring {
+
+ClangQueryHoverHandler::ClangQueryHoverHandler(ClangQueryHighlighter *highligher)
+ : m_highligher(highligher)
+{
+}
+
+void ClangQueryHoverHandler::identifyMatch(TextEditor::TextEditorWidget *editorWidget, int position)
+{
+ using Messages = ClangBackEnd::DynamicASTMatcherDiagnosticMessageContainers;
+ using Contexts = ClangBackEnd::DynamicASTMatcherDiagnosticContextContainers;
+
+ QTextCursor textCursor = editorWidget->textCursor();
+ textCursor.setPosition(position);
+ int line = textCursor.blockNumber() + 1;
+ int column = textCursor.columnNumber() + 1;
+
+ Messages messages = m_highligher->messagesForLineAndColumn(uint(line), uint(column));
+ Contexts contexts = m_highligher->contextsForLineAndColumn(uint(line), uint(column));
+
+ if (!messages.empty())
+ setToolTip(QString("%1: %2").arg(messages[0].errorTypeText()).arg(messages[0].arguments().join(", ")));
+ else if (!contexts.empty())
+ setToolTip(QString("%1: %2").arg(contexts[0].contextTypeText()).arg(contexts[0].arguments().join(", ")));
+}
+
+} // namespace ClangRefactoring
diff --git a/src/plugins/clangrefactoring/clangqueryhoverhandler.h b/src/plugins/clangrefactoring/clangqueryhoverhandler.h
new file mode 100644
index 0000000000..7a93bcbf5d
--- /dev/null
+++ b/src/plugins/clangrefactoring/clangqueryhoverhandler.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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 <texteditor/basehoverhandler.h>
+
+namespace ClangRefactoring {
+
+class ClangQueryHighlighter;
+
+class ClangQueryHoverHandler : public TextEditor::BaseHoverHandler
+{
+public:
+ ClangQueryHoverHandler(ClangQueryHighlighter *highligher);
+
+protected:
+ void identifyMatch(TextEditor::TextEditorWidget *editorWidget, int position) override;
+
+private:
+ ClangQueryHighlighter *m_highligher;
+};
+
+} // namespace ClangRefactoring
diff --git a/src/plugins/clangrefactoring/clangquerytexteditorwidget.cpp b/src/plugins/clangrefactoring/clangquerytexteditorwidget.cpp
index 7ca9d90254..2d0552680c 100644
--- a/src/plugins/clangrefactoring/clangquerytexteditorwidget.cpp
+++ b/src/plugins/clangrefactoring/clangquerytexteditorwidget.cpp
@@ -26,19 +26,24 @@
#include "clangquerytexteditorwidget.h"
#include "clangqueryhighlighter.h"
+#include "clangqueryhoverhandler.h"
#include <texteditor/textdocument.h>
namespace ClangRefactoring {
ClangQueryTextEditorWidget::ClangQueryTextEditorWidget(QWidget *parent)
- : BaseClangQueryTextEditorWidget(parent)
+ : BaseClangQueryTextEditorWidget(parent),
+ m_syntaxHighlighter(new ClangQueryHighlighter),
+ m_hoverHandler(std::make_unique<ClangQueryHoverHandler>(m_syntaxHighlighter))
{
- m_syntaxHighlighter = new ClangQueryHighlighter;
-
textDocument()->setSyntaxHighlighter(m_syntaxHighlighter);
+
+ addHoverHandler(m_hoverHandler.get());
}
+ClangQueryTextEditorWidget::~ClangQueryTextEditorWidget() = default;
+
ClangQueryHighlighter *ClangQueryTextEditorWidget::syntaxHighlighter() const
{
return m_syntaxHighlighter;
diff --git a/src/plugins/clangrefactoring/clangquerytexteditorwidget.h b/src/plugins/clangrefactoring/clangquerytexteditorwidget.h
index 85dace1432..a221eb03fe 100644
--- a/src/plugins/clangrefactoring/clangquerytexteditorwidget.h
+++ b/src/plugins/clangrefactoring/clangquerytexteditorwidget.h
@@ -27,9 +27,12 @@
#include "baseclangquerytexteditorwidget.h"
+#include <memory>
+
namespace ClangRefactoring {
class ClangQueryHighlighter;
+class ClangQueryHoverHandler;
class ClangQueryTextEditorWidget : public BaseClangQueryTextEditorWidget
{
@@ -37,11 +40,13 @@ class ClangQueryTextEditorWidget : public BaseClangQueryTextEditorWidget
public:
ClangQueryTextEditorWidget(QWidget *parent);
+ ~ClangQueryTextEditorWidget();
ClangQueryHighlighter *syntaxHighlighter() const;
private:
ClangQueryHighlighter *m_syntaxHighlighter;
+ std::unique_ptr<ClangQueryHoverHandler> m_hoverHandler;
};
} // namespace ClangRefactoring
diff --git a/src/plugins/clangrefactoring/clangrefactoring.pro b/src/plugins/clangrefactoring/clangrefactoring.pro
index 1a8d16e3e3..918398bef0 100644
--- a/src/plugins/clangrefactoring/clangrefactoring.pro
+++ b/src/plugins/clangrefactoring/clangrefactoring.pro
@@ -14,7 +14,8 @@ HEADERS += \
clangqueryprojectsfindfilterwidget.h \
clangqueryexampletexteditorwidget.h \
clangquerytexteditorwidget.h \
- baseclangquerytexteditorwidget.h
+ baseclangquerytexteditorwidget.h \
+ clangqueryhoverhandler.h
SOURCES += \
clangrefactoringplugin.cpp \
@@ -24,7 +25,8 @@ SOURCES += \
clangqueryprojectsfindfilterwidget.cpp \
clangqueryexampletexteditorwidget.cpp \
clangquerytexteditorwidget.cpp \
- baseclangquerytexteditorwidget.cpp
+ baseclangquerytexteditorwidget.cpp \
+ clangqueryhoverhandler.cpp
FORMS += \
clangqueryprojectsfindfilter.ui
diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp
index 692faa1c50..120e43f46c 100644
--- a/src/plugins/texteditor/texteditor.cpp
+++ b/src/plugins/texteditor/texteditor.cpp
@@ -5339,6 +5339,11 @@ void TextEditorWidget::showDefaultContextMenu(QContextMenuEvent *e, Id menuConte
menu.exec(e->globalPos());
}
+void TextEditorWidget::addHoverHandler(BaseHoverHandler *handler)
+{
+ d->m_hoverHandlers.append(handler);
+}
+
void TextEditorWidget::extraAreaLeaveEvent(QEvent *)
{
d->extraAreaPreviousMarkTooltipRequestedLine = -1;
diff --git a/src/plugins/texteditor/texteditor.h b/src/plugins/texteditor/texteditor.h
index 0c2e83e1e8..f6fb864404 100644
--- a/src/plugins/texteditor/texteditor.h
+++ b/src/plugins/texteditor/texteditor.h
@@ -512,6 +512,8 @@ protected:
virtual void finalizeInitializationAfterDuplication(TextEditorWidget *) {}
static QTextCursor flippedCursor(const QTextCursor &cursor);
+ void addHoverHandler(BaseHoverHandler *handler);
+
public:
struct Link
{
diff --git a/src/tools/clangrefactoringbackend/source/clangquery.cpp b/src/tools/clangrefactoringbackend/source/clangquery.cpp
index be93b61a1a..b625e9e197 100644
--- a/src/tools/clangrefactoringbackend/source/clangquery.cpp
+++ b/src/tools/clangrefactoringbackend/source/clangquery.cpp
@@ -92,7 +92,7 @@ SourceRangesContainer ClangQuery::takeSourceRanges()
return std::move(sourceRangesContainer);
}
-std::vector<DynamicASTMatcherDiagnosticContainer> ClangQuery::takeDiagnosticContainers()
+DynamicASTMatcherDiagnosticContainers ClangQuery::takeDiagnosticContainers()
{
return std::move(diagnosticContainers_);
}
diff --git a/src/tools/clangrefactoringbackend/source/clangquery.h b/src/tools/clangrefactoringbackend/source/clangquery.h
index 20b38a7ab1..faa5821ca3 100644
--- a/src/tools/clangrefactoringbackend/source/clangquery.h
+++ b/src/tools/clangrefactoringbackend/source/clangquery.h
@@ -58,7 +58,7 @@ public:
void findLocations();
SourceRangesContainer takeSourceRanges();
- std::vector<DynamicASTMatcherDiagnosticContainer> takeDiagnosticContainers();
+ DynamicASTMatcherDiagnosticContainers takeDiagnosticContainers();
private:
void parseDiagnostics(const clang::ast_matchers::dynamic::Diagnostics &diagnostics);
diff --git a/tests/unit/unittest/clangqueryhighlightmarker-test.cpp b/tests/unit/unittest/clangqueryhighlightmarker-test.cpp
index 01d9f848f2..05e657b9ea 100644
--- a/tests/unit/unittest/clangqueryhighlightmarker-test.cpp
+++ b/tests/unit/unittest/clangqueryhighlightmarker-test.cpp
@@ -32,12 +32,16 @@
namespace {
using testing::AllOf;
using testing::Contains;
+using testing::ElementsAre;
+using testing::Pointwise;
using testing::IsEmpty;
using testing::Not;
using testing::InSequence;
using testing::_;
using SourceRange = ClangBackEnd::V2::SourceRangeContainer;
+using Message = ClangBackEnd::DynamicASTMatcherDiagnosticMessageContainer;
+using Context = ClangBackEnd::DynamicASTMatcherDiagnosticContextContainer;
using Messages = ClangBackEnd::DynamicASTMatcherDiagnosticMessageContainers;
using Contexts = ClangBackEnd::DynamicASTMatcherDiagnosticContextContainers;
using Marker = ClangRefactoring::ClangQueryHighlightMarker<MockSyntaxHighlighter>;
@@ -54,7 +58,6 @@ protected:
QTextCharFormat contextTextFormat;
MockSyntaxHighlighter highlighter;
Marker marker{highlighter};
-
};
TEST_F(ClangQueryHighlightMarker, NoCallForNoMessagesAndContexts)
@@ -120,6 +123,262 @@ TEST_F(ClangQueryHighlightMarker, CallForMessagesAndContextForAMultiLine)
marker.highlightBlock(3, " ) ");
}
+TEST_F(ClangQueryHighlightMarker, NoMessagesIfEmpty)
+{
+ Messages messages;
+ Contexts contexts;
+ marker.setMessagesAndContexts(std::move(messages), std::move(contexts));
+
+ auto foundMessages = marker.messagesForLineAndColumn(1, 1);
+
+ ASSERT_THAT(foundMessages, IsEmpty());
+}
+
+TEST_F(ClangQueryHighlightMarker, NoMessagesForBeforePosition)
+{
+ Messages messages{{{1, 1, 5, 0, 3, 3, 0},
+ ErrorType::RegistryMatcherNotFound,
+ {"foo"}}};
+ Contexts contexts;
+ marker.setMessagesAndContexts(std::move(messages), std::move(contexts));
+
+ auto foundMessages = marker.messagesForLineAndColumn(1, 4);
+
+ ASSERT_THAT(foundMessages, IsEmpty());
+}
+
+TEST_F(ClangQueryHighlightMarker, NoMessagesForAfterPosition)
+{
+ Messages messages{{{1, 1, 5, 0, 3, 3, 0},
+ ErrorType::RegistryMatcherNotFound,
+ {"foo"}}};
+ Contexts contexts;
+ marker.setMessagesAndContexts(std::move(messages), std::move(contexts));
+
+ auto foundMessages = marker.messagesForLineAndColumn(3, 4);
+
+ ASSERT_THAT(foundMessages, IsEmpty());
+}
+
+TEST_F(ClangQueryHighlightMarker, OneMessagesForInsidePosition)
+{
+ Message message{{1, 1, 5, 0, 3, 3, 0},
+ ErrorType::RegistryMatcherNotFound,
+ {"foo"}};
+ Messages messages{message.clone()};
+ Contexts contexts;
+ marker.setMessagesAndContexts(std::move(messages), std::move(contexts));
+
+ auto foundMessages = marker.messagesForLineAndColumn(2, 3);
+
+ ASSERT_THAT(foundMessages, ElementsAre(message));
+}
+
+TEST_F(ClangQueryHighlightMarker, NoMessagesForOutsidePosition)
+{
+ Message message{{1, 1, 5, 0, 3, 3, 0},
+ ErrorType::RegistryMatcherNotFound,
+ {"foo"}};
+ Messages messages{message.clone()};
+ Contexts contexts;
+ marker.setMessagesAndContexts(std::move(messages), std::move(contexts));
+
+ auto foundMessages = marker.messagesForLineAndColumn(3, 4);
+
+ ASSERT_THAT(foundMessages, IsEmpty());
+}
+
+TEST_F(ClangQueryHighlightMarker, AfterStartColumnBeforeLine)
+{
+ SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0};
+
+ bool isAfterStartColumn = marker.isInsideRange(sourceRange, 1, 6);
+
+ ASSERT_FALSE(isAfterStartColumn);
+}
+
+TEST_F(ClangQueryHighlightMarker, AfterStartColumnBeforeColumn)
+{
+ SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0};
+
+ bool isAfterStartColumn = marker.isInsideRange(sourceRange, 2, 4);
+
+ ASSERT_FALSE(isAfterStartColumn);
+}
+
+TEST_F(ClangQueryHighlightMarker, AfterStartColumnAtColumn)
+{
+ SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0};
+
+ bool isAfterStartColumn = marker.isInsideRange(sourceRange, 2, 5);
+
+ ASSERT_TRUE(isAfterStartColumn);
+}
+
+TEST_F(ClangQueryHighlightMarker, AfterStartColumnAfterColumn)
+{
+ SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0};
+
+ bool isAfterStartColumn = marker.isInsideRange(sourceRange, 2, 6);
+
+ ASSERT_TRUE(isAfterStartColumn);
+}
+
+TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAfterLine)
+{
+ SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0};
+
+ bool isBeforeEndColumn = marker.isInsideRange(sourceRange, 4, 1);
+
+ ASSERT_FALSE(isBeforeEndColumn);
+}
+
+TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAfterColumn)
+{
+ SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0};
+
+ bool isBeforeEndColumn = marker.isInsideRange(sourceRange, 3, 4);
+
+ ASSERT_FALSE(isBeforeEndColumn);
+}
+
+TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAtColumn)
+{
+ SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0};
+
+ bool isBeforeEndColumn = marker.isInsideRange(sourceRange, 3, 3);
+
+ ASSERT_TRUE(isBeforeEndColumn);
+}
+
+TEST_F(ClangQueryHighlightMarker, BeforeEndColumnBeforeColumn)
+{
+ SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0};
+
+ bool isBeforeEndColumn = marker.isInsideRange(sourceRange, 3, 2);
+
+ ASSERT_TRUE(isBeforeEndColumn);
+}
+
+TEST_F(ClangQueryHighlightMarker, InBetweenLineBeforeLine)
+{
+ SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0};
+
+ bool isInBetween = marker.isInsideRange(sourceRange, 1, 6);
+
+ ASSERT_FALSE(isInBetween);
+}
+
+TEST_F(ClangQueryHighlightMarker, InBetweenLineAfterLine)
+{
+ SourceRange sourceRange{1, 2, 5, 0, 4, 3, 0};
+
+ bool isInBetween = marker.isInsideRange(sourceRange, 5, 1);
+
+ ASSERT_FALSE(isInBetween);
+}
+
+TEST_F(ClangQueryHighlightMarker, InBetweenLine)
+{
+ SourceRange sourceRange{1, 2, 5, 0, 4, 3, 0};
+
+ bool isInBetween = marker.isInsideRange(sourceRange, 3, 1);
+
+ ASSERT_TRUE(isInBetween);
+}
+
+TEST_F(ClangQueryHighlightMarker, SingleLineBefore)
+{
+ SourceRange sourceRange{1, 2, 5, 0, 2, 10, 0};
+
+ bool isInRange = marker.isInsideRange(sourceRange, 2, 4);
+
+ ASSERT_FALSE(isInRange);
+}
+
+TEST_F(ClangQueryHighlightMarker, SingleLineAfter)
+{
+ SourceRange sourceRange{1, 2, 5, 0, 2, 10, 0};
+
+ bool isInRange = marker.isInsideRange(sourceRange, 2, 11);
+
+ ASSERT_FALSE(isInRange);
+}
+
+TEST_F(ClangQueryHighlightMarker, SingleLineInRange)
+{
+ SourceRange sourceRange{1, 2, 5, 0, 2, 10, 0};
+
+ bool isInRange = marker.isInsideRange(sourceRange, 2, 6);
+
+ ASSERT_TRUE(isInRange);
+}
+
+TEST_F(ClangQueryHighlightMarker, NoContextsIfEmpty)
+{
+ Messages messages;
+ Contexts contexts;
+ marker.setMessagesAndContexts(std::move(messages), std::move(contexts));
+
+ auto foundContexts = marker.contextsForLineAndColumn(1, 1);
+
+ ASSERT_THAT(foundContexts, IsEmpty());
+}
+
+TEST_F(ClangQueryHighlightMarker, NoContextsForBeforePosition)
+{
+ Messages messages;
+ Contexts contexts{{{1, 1, 5, 0, 3, 3, 0},
+ ContextType::MatcherArg,
+ {"foo"}}};
+ marker.setMessagesAndContexts(std::move(messages), std::move(contexts));
+
+ auto foundContexts = marker.contextsForLineAndColumn(1, 4);
+
+ ASSERT_THAT(foundContexts, IsEmpty());
+}
+
+TEST_F(ClangQueryHighlightMarker, NoContextsForAfterPosition)
+{
+ Messages messages;
+ Contexts contexts{{{1, 1, 5, 0, 3, 3, 0},
+ ContextType::MatcherArg,
+ {"foo"}}};
+ marker.setMessagesAndContexts(std::move(messages), std::move(contexts));
+
+ auto foundContexts = marker.contextsForLineAndColumn(3, 4);
+
+ ASSERT_THAT(foundContexts, IsEmpty());
+}
+
+TEST_F(ClangQueryHighlightMarker, OneContextsForInsidePosition)
+{
+ Context context{{1, 1, 5, 0, 3, 3, 0},
+ ContextType::MatcherArg,
+ {"foo"}};
+ Messages messages;
+ Contexts contexts{context.clone()};
+ marker.setMessagesAndContexts(std::move(messages), std::move(contexts));
+
+ auto foundContexts = marker.contextsForLineAndColumn(2, 3);
+
+ ASSERT_THAT(foundContexts, ElementsAre(context));
+}
+
+TEST_F(ClangQueryHighlightMarker, NoContextsForOutsidePosition)
+{
+ Context context{{1, 1, 5, 0, 3, 3, 0},
+ ContextType::MatcherArg,
+ {"foo"}};
+ Messages messages;
+ Contexts contexts{context.clone()};
+ marker.setMessagesAndContexts(std::move(messages), std::move(contexts));
+
+ auto foundContexts = marker.contextsForLineAndColumn(3, 4);
+
+ ASSERT_THAT(foundContexts, IsEmpty());
+}
+
void ClangQueryHighlightMarker::SetUp()
{
messageTextFormat.setFontItalic(true);