forked from qt-creator/qt-creator
Clang: Add clang query pane
We now support highlighting for an example text and for the query. Change-Id: I88c415ff871cf3e4c2d4fc83d60a8555bf0ce08a Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
266
src/plugins/clangrefactoring/clangqueryhighlightmarker.h
Normal file
266
src/plugins/clangrefactoring/clangqueryhighlightmarker.h
Normal file
@@ -0,0 +1,266 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** 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 <dynamicastmatcherdiagnosticcontextcontainer.h>
|
||||
#include <dynamicastmatcherdiagnosticmessagecontainer.h>
|
||||
#include <sourcerangecontainerv2.h>
|
||||
|
||||
#include <QString>
|
||||
#include <QTextCharFormat>
|
||||
|
||||
namespace ClangRefactoring {
|
||||
|
||||
template<typename SyntaxHighlighter>
|
||||
class ClangQueryHighlightMarker
|
||||
{
|
||||
using SourceRange = ClangBackEnd::V2::SourceRangeContainer;
|
||||
using Message = ClangBackEnd::DynamicASTMatcherDiagnosticMessageContainer;
|
||||
using Context = ClangBackEnd::DynamicASTMatcherDiagnosticContextContainer;
|
||||
using Messages = ClangBackEnd::DynamicASTMatcherDiagnosticMessageContainers;
|
||||
using Contexts = ClangBackEnd::DynamicASTMatcherDiagnosticContextContainers;
|
||||
|
||||
public:
|
||||
ClangQueryHighlightMarker(SyntaxHighlighter &highlighter)
|
||||
: m_highlighter(highlighter)
|
||||
{
|
||||
}
|
||||
|
||||
void setTextFormats(const QTextCharFormat &messageTextFormat,
|
||||
const QTextCharFormat &contextTextFormat)
|
||||
{
|
||||
m_contextTextFormat = contextTextFormat;
|
||||
m_messageTextFormat = messageTextFormat;
|
||||
}
|
||||
|
||||
void setMessagesAndContexts(Messages &&messages, Contexts &&contexts)
|
||||
{
|
||||
m_currentlyUsedContexts.clear();
|
||||
m_currentlyUsedMessages.clear();
|
||||
m_contexts = std::move(contexts);
|
||||
m_messages = std::move(messages);
|
||||
m_currentContextsIterator = m_contexts.begin();
|
||||
m_currentMessagesIterator = m_messages.begin();
|
||||
}
|
||||
|
||||
bool hasMessage(uint currentLineNumber) const
|
||||
{
|
||||
return m_currentMessagesIterator != m_messages.end()
|
||||
&& m_currentMessagesIterator->sourceRange().start().line() == currentLineNumber;
|
||||
}
|
||||
|
||||
bool hasContext(uint currentLineNumber) const
|
||||
{
|
||||
return m_currentContextsIterator != m_contexts.end()
|
||||
&& m_currentContextsIterator->sourceRange().start().line() == currentLineNumber;
|
||||
}
|
||||
|
||||
bool isMessageNext() const
|
||||
{
|
||||
return m_currentMessagesIterator->sourceRange().start().column()
|
||||
< m_currentContextsIterator->sourceRange().start().column();
|
||||
}
|
||||
|
||||
void formatSameLineSourceRange(const SourceRange &sourceRange, const QTextCharFormat &textFormat)
|
||||
{
|
||||
uint startColumn = sourceRange.start().column();
|
||||
uint endColumn = sourceRange.end().column();
|
||||
m_highlighter.setFormat(startColumn - 1, endColumn - startColumn, textFormat);
|
||||
}
|
||||
|
||||
void formatStartLineSourceRange(const SourceRange &sourceRange,
|
||||
int textSize,
|
||||
const QTextCharFormat &textFormat)
|
||||
{
|
||||
uint startColumn = sourceRange.start().column();
|
||||
m_highlighter.setFormat(startColumn - 1, textSize - startColumn, textFormat);
|
||||
}
|
||||
|
||||
void formatEndLineSourceRange(const SourceRange &sourceRange, const QTextCharFormat &textFormat)
|
||||
{
|
||||
uint endColumn = sourceRange.end().column();
|
||||
m_highlighter.setFormat(0, endColumn - 1, textFormat);
|
||||
}
|
||||
|
||||
void formatMiddleLineSourceRange(int textSize, const QTextCharFormat &textFormat)
|
||||
{
|
||||
m_highlighter.setFormat(0, textSize, textFormat);
|
||||
}
|
||||
|
||||
static
|
||||
bool isSameLine(const SourceRange &sourceRange)
|
||||
{
|
||||
uint startLine = sourceRange.start().line();
|
||||
uint endLine = sourceRange.end().line();
|
||||
|
||||
return startLine == endLine;
|
||||
}
|
||||
|
||||
static
|
||||
bool isStartLine(const SourceRange &sourceRange, uint currentLineNumber)
|
||||
{
|
||||
uint startLine = sourceRange.start().line();
|
||||
|
||||
return startLine == currentLineNumber;
|
||||
}
|
||||
|
||||
static
|
||||
bool isEndLine(const SourceRange &sourceRange, uint currentLineNumber)
|
||||
{
|
||||
uint endLine = sourceRange.end().line();
|
||||
|
||||
return endLine == currentLineNumber;
|
||||
}
|
||||
|
||||
void formatLine(const SourceRange &sourceRange,
|
||||
uint currentLineNumber,
|
||||
int textSize,
|
||||
const QTextCharFormat &textFormat)
|
||||
{
|
||||
if (isSameLine(sourceRange))
|
||||
formatSameLineSourceRange(sourceRange, textFormat);
|
||||
else if (isStartLine(sourceRange, currentLineNumber))
|
||||
formatStartLineSourceRange(sourceRange, textSize, textFormat);
|
||||
else if (isEndLine(sourceRange, currentLineNumber))
|
||||
formatEndLineSourceRange(sourceRange, textFormat);
|
||||
else
|
||||
formatMiddleLineSourceRange(textSize, textFormat);
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
void format(Container &container,
|
||||
typename Container::iterator &iterator,
|
||||
uint currentLineNumber,
|
||||
int textSize,
|
||||
const QTextCharFormat &textFormat)
|
||||
{
|
||||
const SourceRange &sourceRange = iterator->sourceRange();
|
||||
|
||||
formatLine(sourceRange, currentLineNumber, textSize, textFormat);
|
||||
|
||||
if (isStartLine(sourceRange, currentLineNumber))
|
||||
container.push_back(*iterator);
|
||||
|
||||
if (isSameLine(sourceRange) || isStartLine(sourceRange, currentLineNumber))
|
||||
++iterator;
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
static
|
||||
void removeEndedContainers(uint currentLineNumber, Container &container)
|
||||
{
|
||||
auto newEnd = std::remove_if(container.begin(),
|
||||
container.end(),
|
||||
[&] (const auto &entry) {
|
||||
return ClangQueryHighlightMarker::isEndLine(entry.sourceRange(), currentLineNumber);
|
||||
});
|
||||
|
||||
container.erase(newEnd, container.end());
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
void formatCurrentlyUsed(Container container,
|
||||
uint currentLineNumber,
|
||||
int textSize,
|
||||
const QTextCharFormat &textFormat)
|
||||
{
|
||||
for (const auto &entry : container) {
|
||||
formatLine(entry.sourceRange(), currentLineNumber, textSize, textFormat);;
|
||||
}
|
||||
}
|
||||
|
||||
void formatMessage(uint currentLineNumber, int textSize)
|
||||
{
|
||||
format(m_currentlyUsedMessages,
|
||||
m_currentMessagesIterator,
|
||||
currentLineNumber,
|
||||
textSize,
|
||||
m_messageTextFormat);
|
||||
}
|
||||
|
||||
void formatContext(uint currentLineNumber, int textSize)
|
||||
{
|
||||
format(m_currentlyUsedContexts,
|
||||
m_currentContextsIterator,
|
||||
currentLineNumber,
|
||||
textSize,
|
||||
m_contextTextFormat);
|
||||
}
|
||||
|
||||
void formatCurrentlyUsedMessagesAndContexts(uint currentLineNumber, int textSize)
|
||||
{
|
||||
formatCurrentlyUsed(m_currentlyUsedContexts, currentLineNumber, textSize, m_contextTextFormat);
|
||||
formatCurrentlyUsed(m_currentlyUsedMessages, currentLineNumber, textSize, m_messageTextFormat);
|
||||
|
||||
removeEndedContainers(currentLineNumber, m_currentlyUsedContexts);
|
||||
removeEndedContainers(currentLineNumber, m_currentlyUsedMessages);
|
||||
}
|
||||
|
||||
void formatCurrentMessageOrContext(uint currentLineNumber, int textSize)
|
||||
{
|
||||
bool hasContext = this->hasContext(currentLineNumber);
|
||||
bool hasMessage = this->hasMessage(currentLineNumber);
|
||||
|
||||
while (hasContext || hasMessage) {
|
||||
if (!hasContext)
|
||||
formatMessage(currentLineNumber, textSize);
|
||||
else if (!hasMessage)
|
||||
formatContext(currentLineNumber, textSize);
|
||||
else if (isMessageNext())
|
||||
formatMessage(currentLineNumber, textSize);
|
||||
else
|
||||
formatContext(currentLineNumber, textSize);
|
||||
|
||||
hasContext = this->hasContext(currentLineNumber);
|
||||
hasMessage = this->hasMessage(currentLineNumber);
|
||||
}
|
||||
}
|
||||
|
||||
void highlightBlock(uint currentLineNumber, const QString ¤tText)
|
||||
{
|
||||
formatCurrentlyUsedMessagesAndContexts(currentLineNumber, currentText.size());
|
||||
formatCurrentMessageOrContext(currentLineNumber, currentText.size());
|
||||
}
|
||||
|
||||
bool hasMessagesOrContexts() const
|
||||
{
|
||||
return !m_messages.empty() || !m_contexts.empty();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
Contexts m_contexts;
|
||||
Messages m_messages;
|
||||
Contexts m_currentlyUsedContexts;
|
||||
Messages m_currentlyUsedMessages;
|
||||
Contexts::iterator m_currentContextsIterator{m_contexts.begin()};
|
||||
Messages::iterator m_currentMessagesIterator{m_messages.begin()};
|
||||
QTextCharFormat m_messageTextFormat;
|
||||
QTextCharFormat m_contextTextFormat;
|
||||
SyntaxHighlighter &m_highlighter;
|
||||
};
|
||||
|
||||
} // namespace ClangRefactoring
|
||||
Reference in New Issue
Block a user