diff options
author | Marco Bubke <marco.bubke@qt.io> | 2017-07-03 12:35:58 +0200 |
---|---|---|
committer | Tim Jenssen <tim.jenssen@qt.io> | 2017-07-20 13:32:39 +0000 |
commit | a31eae4d0ad1ffd5a06cd5beff9e16473f929615 (patch) | |
tree | fa0ed3976b9c6822fe24a05346f980a5bd8f3026 /src/plugins/clangrefactoring | |
parent | 8c4127ebacd0508f12db79689ef976a814729d91 (diff) | |
download | qt-creator-a31eae4d0ad1ffd5a06cd5beff9e16473f929615.tar.gz |
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>
Diffstat (limited to 'src/plugins/clangrefactoring')
23 files changed, 1444 insertions, 71 deletions
diff --git a/src/plugins/clangrefactoring/baseclangquerytexteditorwidget.cpp b/src/plugins/clangrefactoring/baseclangquerytexteditorwidget.cpp new file mode 100644 index 0000000000..05cb74f599 --- /dev/null +++ b/src/plugins/clangrefactoring/baseclangquerytexteditorwidget.cpp @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** 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 "baseclangquerytexteditorwidget.h" + +#include <texteditor/texteditorconstants.h> + +namespace ClangRefactoring { + +BaseClangQueryTextEditorWidget::BaseClangQueryTextEditorWidget(QWidget *parent) + : TextEditor::TextEditorWidget(parent) +{ + setupFallBackEditor(Core::Id()); + setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); + setHighlightCurrentLine(false); + setLineNumbersVisible(false); + setParenthesesMatchingEnabled(true); +} + +} // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/baseclangquerytexteditorwidget.h b/src/plugins/clangrefactoring/baseclangquerytexteditorwidget.h new file mode 100644 index 0000000000..b7f54a5325 --- /dev/null +++ b/src/plugins/clangrefactoring/baseclangquerytexteditorwidget.h @@ -0,0 +1,40 @@ +/**************************************************************************** +** +** 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/texteditor.h> + +namespace ClangRefactoring { + +class BaseClangQueryTextEditorWidget : public TextEditor::TextEditorWidget +{ + Q_OBJECT + +public: + BaseClangQueryTextEditorWidget(QWidget *parent); +}; + +} // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/clangqueryexamplehighlighter.cpp b/src/plugins/clangrefactoring/clangqueryexamplehighlighter.cpp new file mode 100644 index 0000000000..d1ff575c02 --- /dev/null +++ b/src/plugins/clangrefactoring/clangqueryexamplehighlighter.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** 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 "clangqueryexamplehighlighter.h" + +#include <sourcerangescontainer.h> + +#include <QTextBlock> + + +namespace ClangRefactoring { + +ClangQueryExampleHighlighter::ClangQueryExampleHighlighter() + : m_marker(*this) +{ + std::array<QTextCharFormat, 5> textFormats; + textFormats[0].setBackground(QColor("#c9ffc3")); + textFormats[1].setBackground(QColor("#c3d9ff")); + textFormats[2].setBackground(QColor("#e5c3ff")); + textFormats[3].setBackground(QColor("#ffc3cb")); + textFormats[4].setBackground(QColor("#ffe8c3")); + + m_marker.setTextFormats(std::move(textFormats)); + + setNoAutomaticHighlighting(true); +} + +void ClangQueryExampleHighlighter::setSourceRanges(ClangBackEnd::SourceRangesContainer &&container) +{ + m_marker.setSourceRanges(container.takeSourceRangeWithTextContainers()); + rehighlight(); +} + +void ClangQueryExampleHighlighter::highlightBlock(const QString &text) +{ + int currentLineNumber = currentBlock().blockNumber() + 1; + m_marker.highlightBlock(uint(currentLineNumber), text); +} + +} // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/clangqueryexamplehighlighter.h b/src/plugins/clangrefactoring/clangqueryexamplehighlighter.h new file mode 100644 index 0000000000..6c943644dc --- /dev/null +++ b/src/plugins/clangrefactoring/clangqueryexamplehighlighter.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** 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 "clangqueryexamplehighlightmarker.h" + +#include <texteditor/syntaxhighlighter.h> + +#include <sourcerangewithtextcontainer.h> + +namespace ClangBackEnd { +class SourceRangesContainer; +} + +namespace ClangRefactoring { + +class ClangQueryExampleHighlighter : public TextEditor::SyntaxHighlighter +{ + friend ClangQueryExampleHighlightMarker<ClangQueryExampleHighlighter>; + +public: + ClangQueryExampleHighlighter(); + + void setSourceRanges(ClangBackEnd::SourceRangesContainer &&container); + +protected: + void highlightBlock(const QString &text) override; + +private: + ClangQueryExampleHighlightMarker<ClangQueryExampleHighlighter> m_marker; +}; + +} // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/clangqueryexamplehighlightmarker.h b/src/plugins/clangrefactoring/clangqueryexamplehighlightmarker.h new file mode 100644 index 0000000000..07b7205a53 --- /dev/null +++ b/src/plugins/clangrefactoring/clangqueryexamplehighlightmarker.h @@ -0,0 +1,220 @@ +/**************************************************************************** +** +** 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 <sourcerangewithtextcontainer.h> + +#include <QString> +#include <QTextCharFormat> + +namespace ClangRefactoring { + +template<typename SyntaxHighlighter> +class ClangQueryExampleHighlightMarker +{ + using SourceRange = ClangBackEnd::V2::SourceRangeContainer; + using SourceRanges = ClangBackEnd::V2::SourceRangeContainers; + using SourceRangeWithTexts = ClangBackEnd::SourceRangeWithTextContainers; +public: + ClangQueryExampleHighlightMarker(SourceRangeWithTexts &&sourceRanges, + SyntaxHighlighter &highlighter, + const std::array<QTextCharFormat, 5> &textFormats) + : m_sourceRanges(std::move(sourceRanges)), + m_currentSourceRangeIterator(m_sourceRanges.begin()), + m_highlighter(highlighter), + m_textFormats(textFormats) + { + } + + ClangQueryExampleHighlightMarker(SyntaxHighlighter &highlighter) + : m_currentSourceRangeIterator(m_sourceRanges.begin()), + m_highlighter(highlighter) + { + } + + void setTextFormats(std::array<QTextCharFormat, 5> &&textFormats) + { + m_textFormats = std::move(textFormats); + } + + void setSourceRanges(SourceRangeWithTexts &&sourceRanges) + { + m_currentlyUsedSourceRanges.clear(); + m_sourceRanges = std::move(sourceRanges); + m_currentSourceRangeIterator = m_sourceRanges.begin(); + } + + void highlightSourceRanges(uint currentLineNumber, const QString ¤tText) + { + while (hasSourceRangesForCurrentLine(currentLineNumber)) { + SourceRange &sourceRange = *m_currentSourceRangeIterator; + + popSourceRangeIfMultiLineEndsHere(currentLineNumber, sourceRange.start().column()); + + formatSourceRange(sourceRange, + currentLineNumber, + currentText.size(), + int(m_currentlyUsedSourceRanges.size())); + + pushSourceRangeIfMultiLine(sourceRange); + ++m_currentSourceRangeIterator; + } + } + + void highlightCurrentlyUsedSourceRanges(uint currentLineNumber, const QString ¤tText) + { + formatCurrentlyUsedSourceRanges(currentLineNumber, currentText.size()); + popSourceRangeIfMultiLineEndsHereAndAllSourceRangesAreConsumed(currentLineNumber); + } + + void highlightBlock(uint currentLineNumber, const QString ¤tText) + { + popSourceRangeIfMultiLineEndedBefore(currentLineNumber); + highlightCurrentlyUsedSourceRanges(currentLineNumber, currentText); + highlightSourceRanges(currentLineNumber, currentText); + } + + bool hasSourceRangesForCurrentLine(uint currentLineNumber) const + { + return m_currentSourceRangeIterator != m_sourceRanges.end() + && m_currentSourceRangeIterator->start().line() == currentLineNumber; + } + + bool hasOnlySCurrentlyUsedSourceRanges() const + { + return m_currentSourceRangeIterator == m_sourceRanges.end() + && !m_currentlyUsedSourceRanges.empty(); + } + + void formatSingleSourceRange(const SourceRange &sourceRange, + int textFormatIndex) + { + int size = int(sourceRange.end().column() - sourceRange.start().column()); + m_highlighter.setFormat(int(sourceRange.start().column()) - 1, + size, + m_textFormats[textFormatIndex]); + } + + void formatStartMultipleSourceRange(const SourceRange &sourceRange, + int textSize, + int textFormatIndex) + { + int size = textSize - int(sourceRange.start().column()) + 1; + m_highlighter.setFormat(int(sourceRange.start().column()) - 1, + size, + m_textFormats[textFormatIndex]); + } + + void formatEndMultipleSourceRange(const SourceRange &sourceRange, + int textFormatIndex) + { + int size = int(sourceRange.end().column()) - 1; + m_highlighter.setFormat(0, size, m_textFormats[textFormatIndex]); + } + + void formatMiddleMultipleSourceRange(int textSize, + int textFormatIndex) + { + m_highlighter.setFormat(0, textSize, m_textFormats[textFormatIndex]); + } + + void formatSourceRange(const SourceRange &sourceRange, + uint currentLineNumber, + int textSize, + int textFormatIndex) + { + if (sourceRange.start().line() == sourceRange.end().line()) + formatSingleSourceRange(sourceRange, textFormatIndex); + else if (sourceRange.start().line() == currentLineNumber) + formatStartMultipleSourceRange(sourceRange, textSize, textFormatIndex); + else if (sourceRange.end().line() == currentLineNumber) + formatEndMultipleSourceRange(sourceRange, textFormatIndex); + else + formatMiddleMultipleSourceRange(textSize, textFormatIndex); + } + + void formatCurrentlyUsedSourceRanges(uint currentLineNumber, int textSize) + { + int textFormatIndex = 0; + + for (const SourceRange &sourceRange : m_currentlyUsedSourceRanges) { + formatSourceRange(sourceRange, currentLineNumber, textSize, textFormatIndex); + ++textFormatIndex; + } + } + + bool currentlyUsedHasEndLineAndColumnNumber(uint currentLineNumber, uint currentColumnNumber) + { + return !m_currentlyUsedSourceRanges.empty() + && m_currentlyUsedSourceRanges.back().end().line() <= currentLineNumber + && m_currentlyUsedSourceRanges.back().end().column() <= currentColumnNumber; + } + + void popSourceRangeIfMultiLineEndsHere(uint currentLineNumber, uint currentColumnNumber) + { + while (currentlyUsedHasEndLineAndColumnNumber(currentLineNumber, currentColumnNumber)) + m_currentlyUsedSourceRanges.pop_back(); + } + + bool currentlyUsedHasEndLineNumberAndSourceRangesAreConsumed(uint currentLineNumber) + { + return !m_currentlyUsedSourceRanges.empty() + && m_currentSourceRangeIterator == m_sourceRanges.end() + && m_currentlyUsedSourceRanges.back().end().line() == currentLineNumber; + } + + void popSourceRangeIfMultiLineEndsHereAndAllSourceRangesAreConsumed(uint currentLineNumber) + { + while (currentlyUsedHasEndLineNumberAndSourceRangesAreConsumed(currentLineNumber)) + m_currentlyUsedSourceRanges.pop_back(); + } + + bool currentlyUsedHasEndedBeforeLineNumber(uint currentLineNumber) + { + return !m_currentlyUsedSourceRanges.empty() + && m_currentlyUsedSourceRanges.back().end().line() < currentLineNumber; + } + + void popSourceRangeIfMultiLineEndedBefore(uint currentLineNumber) + { + while (currentlyUsedHasEndedBeforeLineNumber(currentLineNumber)) + m_currentlyUsedSourceRanges.pop_back(); + } + + void pushSourceRangeIfMultiLine(SourceRange &sourceRange) + { + m_currentlyUsedSourceRanges.push_back(sourceRange); + } + +private: + SourceRangeWithTexts m_sourceRanges; + SourceRangeWithTexts::iterator m_currentSourceRangeIterator; + SourceRanges m_currentlyUsedSourceRanges; + SyntaxHighlighter &m_highlighter; + std::array<QTextCharFormat, 5> m_textFormats; +}; + +} // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/clangqueryexampletexteditorwidget.cpp b/src/plugins/clangrefactoring/clangqueryexampletexteditorwidget.cpp new file mode 100644 index 0000000000..19273d5ede --- /dev/null +++ b/src/plugins/clangrefactoring/clangqueryexampletexteditorwidget.cpp @@ -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. +** +****************************************************************************/ + +#include "clangqueryexampletexteditorwidget.h" + +#include "clangqueryexamplehighlighter.h" + +#include <texteditor/textdocument.h> + +namespace ClangRefactoring { + +ClangQueryExampleTextEditorWidget::ClangQueryExampleTextEditorWidget(QWidget *parent) + : BaseClangQueryTextEditorWidget(parent) +{ + m_syntaxHighlighter = new ClangQueryExampleHighlighter; + textDocument()->setSyntaxHighlighter(m_syntaxHighlighter); +} + +ClangQueryExampleHighlighter *ClangQueryExampleTextEditorWidget::syntaxHighlighter() const +{ + return m_syntaxHighlighter; +} + +} // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/clangqueryexampletexteditorwidget.h b/src/plugins/clangrefactoring/clangqueryexampletexteditorwidget.h new file mode 100644 index 0000000000..0a86f50220 --- /dev/null +++ b/src/plugins/clangrefactoring/clangqueryexampletexteditorwidget.h @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** 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 "baseclangquerytexteditorwidget.h" + +namespace ClangRefactoring { + +class ClangQueryExampleHighlighter; + +class ClangQueryExampleTextEditorWidget : public BaseClangQueryTextEditorWidget +{ + Q_OBJECT + +public: + ClangQueryExampleTextEditorWidget(QWidget *parent); + + ClangQueryExampleHighlighter *syntaxHighlighter() const; + +private: + ClangQueryExampleHighlighter *m_syntaxHighlighter; +}; + +} // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/clangqueryhighlighter.cpp b/src/plugins/clangrefactoring/clangqueryhighlighter.cpp new file mode 100644 index 0000000000..5f9e72d4be --- /dev/null +++ b/src/plugins/clangrefactoring/clangqueryhighlighter.cpp @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** 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 "clangqueryhighlighter.h" + +#include <texteditor/fontsettings.h> +#include <texteditor/texteditorconstants.h> +#include <texteditor/texteditorsettings.h> + +#include <QTextBlock> + +namespace ClangRefactoring { + +ClangQueryHighlighter::ClangQueryHighlighter() + : m_marker(*this) +{ +#ifndef UNIT_TESTS + TextEditor::FontSettings fontSettings = TextEditor::TextEditorSettings::fontSettings(); + + m_marker.setTextFormats(fontSettings.toTextCharFormat(TextEditor::C_ERROR), + fontSettings.toTextCharFormat(TextEditor::C_ERROR_CONTEXT)); +#endif + + setNoAutomaticHighlighting(true); +} + +void ClangQueryHighlighter::setDiagnostics( + const ClangBackEnd::DynamicASTMatcherDiagnosticContainers &diagnostics) +{ + using Messages = ClangBackEnd::DynamicASTMatcherDiagnosticMessageContainers; + using Contexts = ClangBackEnd::DynamicASTMatcherDiagnosticContextContainers; + + Messages messages; + Contexts contexts; + + for (const ClangBackEnd::DynamicASTMatcherDiagnosticContainer &diagnostic : diagnostics) { + Messages newMessages = diagnostic.messages(); + Contexts newContexts = diagnostic.contexts(); + std::copy(newMessages.begin(), newMessages.end(), std::back_inserter(messages)); + std::copy(newContexts.begin(), newContexts.end(), std::back_inserter(contexts)); + } + + m_marker.setMessagesAndContexts(std::move(messages), std::move(contexts)); + + rehighlight(); +} + +bool ClangQueryHighlighter::hasDiagnostics() const +{ + return m_marker.hasMessagesOrContexts(); +} + +void ClangQueryHighlighter::highlightBlock(const QString &text) +{ + int currentLineNumber = currentBlock().blockNumber() + 1; + m_marker.highlightBlock(uint(currentLineNumber), text); +} + +} // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/clangqueryhighlighter.h b/src/plugins/clangrefactoring/clangqueryhighlighter.h new file mode 100644 index 0000000000..977f91fd11 --- /dev/null +++ b/src/plugins/clangrefactoring/clangqueryhighlighter.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** 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 "clangqueryhighlightmarker.h" + +#include <texteditor/syntaxhighlighter.h> + +#include <dynamicastmatcherdiagnosticcontainer.h> + +namespace ClangRefactoring { + +class ClangQueryHighlighter : public TextEditor::SyntaxHighlighter +{ + friend class ClangQueryHighlightMarker<ClangQueryHighlighter>; + +public: + ClangQueryHighlighter(); + + void setDiagnostics(const ClangBackEnd::DynamicASTMatcherDiagnosticContainers &diagnostics); + + bool hasDiagnostics() const; + +protected: + void highlightBlock(const QString &text) override; + +private: + ClangQueryHighlightMarker<ClangQueryHighlighter> m_marker; +}; + +} // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/clangqueryhighlightmarker.h b/src/plugins/clangrefactoring/clangqueryhighlightmarker.h new file mode 100644 index 0000000000..8f53d59538 --- /dev/null +++ b/src/plugins/clangrefactoring/clangqueryhighlightmarker.h @@ -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 diff --git a/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.cpp b/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.cpp index e22bc7e2ad..2289746db3 100644 --- a/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.cpp +++ b/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.cpp @@ -30,20 +30,23 @@ #include "searchinterface.h" #include <refactoringserverinterface.h> -#include <requestsourcerangesanddiagnosticsforquerymessage.h> +#include <clangrefactoringservermessages.h> #include <cpptools/clangcompileroptionsbuilder.h> +#include <QPointer> + namespace ClangRefactoring { ClangQueryProjectsFindFilter::ClangQueryProjectsFindFilter( ClangBackEnd::RefactoringServerInterface &server, SearchInterface &searchInterface, RefactoringClient &refactoringClient) - : server(server), - searchInterface(searchInterface), - refactoringClient(refactoringClient) + : m_server(server), + m_searchInterface(searchInterface), + m_refactoringClient(refactoringClient) { + temporaryFile.open(); } QString ClangQueryProjectsFindFilter::id() const @@ -61,19 +64,57 @@ bool ClangQueryProjectsFindFilter::isEnabled() const return true; } -void ClangQueryProjectsFindFilter::findAll(const QString &queryText, Core::FindFlags) +namespace { +Utils::SmallString toNative(const QString &path) { - searchHandle = searchInterface.startNewSearch(tr("Clang Query"), queryText); + Utils::SmallString nativePath = path; + +#ifdef Q_OS_WIN + nativePath.replace('/', '\\'); +#endif + + return nativePath; +} +} - searchHandle->setRefactoringServer(&server); +void ClangQueryProjectsFindFilter::requestSourceRangesAndDiagnostics(const QString &queryText, + const QString &exampleContent) +{ + const QString filePath = temporaryFile.fileName(); - refactoringClient.setSearchHandle(searchHandle.get()); + ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage message(queryText, + {ClangBackEnd::FilePath(filePath), + exampleContent, + {"cc", toNative(filePath)}}); + + m_server.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(message)); +} + +SearchHandle *ClangQueryProjectsFindFilter::find(const QString &queryText) +{ + m_searchHandle = m_searchInterface.startNewSearch(tr("Clang Query"), queryText); + + m_searchHandle->setRefactoringServer(&m_server); + + m_refactoringClient.setSearchHandle(m_searchHandle.get()); auto message = createMessage(queryText); - refactoringClient.setExpectedResultCount(uint(message.sources().size())); + m_refactoringClient.setExpectedResultCount(uint(message.sources().size())); + + m_server.requestSourceRangesForQueryMessage(std::move(message)); - server.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(message)); + return m_searchHandle.get(); +} + +void ClangQueryProjectsFindFilter::findAll(const QString &, Core::FindFlags) +{ + find(queryText()); +} + +bool ClangQueryProjectsFindFilter::showSearchTermInput() const +{ + return false; } Core::FindFlags ClangQueryProjectsFindFilter::supportedFindFlags() const @@ -83,28 +124,28 @@ Core::FindFlags ClangQueryProjectsFindFilter::supportedFindFlags() const void ClangQueryProjectsFindFilter::setProjectParts(const std::vector<CppTools::ProjectPart::Ptr> &projectParts) { - this->projectParts = projectParts; + this->m_projectParts = projectParts; } bool ClangQueryProjectsFindFilter::isUsable() const { - return server.isUsable(); + return m_server.isUsable(); } void ClangQueryProjectsFindFilter::setUsable(bool isUsable) { - server.setUsable(isUsable); + m_server.setUsable(isUsable); } SearchHandle *ClangQueryProjectsFindFilter::searchHandleForTestOnly() const { - return searchHandle.get(); + return m_searchHandle.get(); } void ClangQueryProjectsFindFilter::setUnsavedContent( std::vector<ClangBackEnd::V2::FileContainer> &&unsavedContent) { - this->unsavedContent = std::move(unsavedContent); + this->m_unsavedContent = std::move(unsavedContent); } Utils::SmallStringVector ClangQueryProjectsFindFilter::compilerArguments(CppTools::ProjectPart *projectPart, @@ -141,6 +182,11 @@ Utils::SmallStringVector ClangQueryProjectsFindFilter::compilerArguments(CppTool return Utils::SmallStringVector(builder.options()); } +QWidget *ClangQueryProjectsFindFilter::widget() const +{ + return nullptr; +} + namespace { Utils::SmallStringVector createCommandLine(CppTools::ProjectPart *projectPart, @@ -205,12 +251,22 @@ createSources(const std::vector<CppTools::ProjectPart::Ptr> &projectParts, } -ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage ClangQueryProjectsFindFilter::createMessage(const QString &queryText) const +ClangBackEnd::RequestSourceRangesForQueryMessage ClangQueryProjectsFindFilter::createMessage(const QString &queryText) const { - return ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage( + return ClangBackEnd::RequestSourceRangesForQueryMessage( Utils::SmallString(queryText), - createSources(projectParts, unsavedContent), - Utils::clone(unsavedContent)); + createSources(m_projectParts, m_unsavedContent), + Utils::clone(m_unsavedContent)); +} + +QString ClangQueryProjectsFindFilter::queryText() const +{ + return QString(); +} + +RefactoringClient &ClangQueryProjectsFindFilter::refactoringClient() +{ + return m_refactoringClient; } diff --git a/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.h b/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.h index d206b0531a..73608557ec 100644 --- a/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.h +++ b/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.h @@ -34,6 +34,7 @@ #include <filecontainerv2.h> #include <utils/smallstringvector.h> +#include <utils/temporaryfile.h> #include <memory> @@ -54,35 +55,44 @@ public: SearchInterface &searchInterface, RefactoringClient &refactoringClient); - QString id() const; - QString displayName() const; - bool isEnabled() const; - void findAll(const QString &queryText, Core::FindFlags findFlags = 0); - Core::FindFlags supportedFindFlags() const; + QString id() const override; + QString displayName() const override; + bool isEnabled() const override; + void requestSourceRangesAndDiagnostics(const QString &queryText, const QString &exampleContent); + SearchHandle *find(const QString &queryText); + void findAll(const QString &queryText, Core::FindFlags findFlags = 0) override; + bool showSearchTermInput() const override; + Core::FindFlags supportedFindFlags() const override; - void setProjectParts(const std::vector<CppTools::ProjectPart::Ptr> &projectParts); + void setProjectParts(const std::vector<CppTools::ProjectPart::Ptr> &m_projectParts); bool isUsable() const; void setUsable(bool isUsable); SearchHandle* searchHandleForTestOnly() const; - void setUnsavedContent(std::vector<ClangBackEnd::V2::FileContainer> &&unsavedContent); + void setUnsavedContent(std::vector<ClangBackEnd::V2::FileContainer> &&m_unsavedContent); static Utils::SmallStringVector compilerArguments(CppTools::ProjectPart *projectPart, CppTools::ProjectFile::Kind fileKind); +protected: + virtual QWidget *widget() const; + virtual QString queryText() const; + RefactoringClient &refactoringClient(); + private: - ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage createMessage( + ClangBackEnd::RequestSourceRangesForQueryMessage createMessage( const QString &queryText) const; private: - std::vector<ClangBackEnd::V2::FileContainer> unsavedContent; - std::unique_ptr<SearchHandle> searchHandle; - std::vector<CppTools::ProjectPart::Ptr> projectParts; - ClangBackEnd::RefactoringServerInterface &server; - SearchInterface &searchInterface; - RefactoringClient &refactoringClient; + std::vector<ClangBackEnd::V2::FileContainer> m_unsavedContent; + std::unique_ptr<SearchHandle> m_searchHandle; + std::vector<CppTools::ProjectPart::Ptr> m_projectParts; + Utils::TemporaryFile temporaryFile{"clangQuery-XXXXXX.cpp"}; + ClangBackEnd::RefactoringServerInterface &m_server; + SearchInterface &m_searchInterface; + RefactoringClient &m_refactoringClient; }; } // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.ui b/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.ui new file mode 100644 index 0000000000..9fbad01f0b --- /dev/null +++ b/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.ui @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Form</class> + <widget class="QWidget" name="Form"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1241</width> + <height>471</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="ClangRefactoring::ClangQueryExampleTextEditorWidget" name="exampleSourceTextEdit"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>3</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item> + <widget class="ClangRefactoring::ClangQueryTextEditorWidget" name="queryTextEdit"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>1</verstretch> + </sizepolicy> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>ClangRefactoring::ClangQueryExampleTextEditorWidget</class> + <extends>QPlainTextEdit</extends> + <header>clangqueryexampletexteditorwidget.h</header> + </customwidget> + <customwidget> + <class>ClangRefactoring::ClangQueryTextEditorWidget</class> + <extends>QPlainTextEdit</extends> + <header>clangquerytexteditorwidget.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/src/plugins/clangrefactoring/clangqueryprojectsfindfilterwidget.cpp b/src/plugins/clangrefactoring/clangqueryprojectsfindfilterwidget.cpp new file mode 100644 index 0000000000..2351ecbcda --- /dev/null +++ b/src/plugins/clangrefactoring/clangqueryprojectsfindfilterwidget.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** 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 "clangqueryprojectsfindfilterwidget.h" + +#include "clangqueryhighlighter.h" + +#include <texteditor/textdocument.h> + +#include <QTextDocument> + +namespace ClangRefactoring { + +ClangQueryProjectsFindFilterWidget::ClangQueryProjectsFindFilterWidget() +{ + m_form.setupUi(this); +} + +QPlainTextEdit *ClangQueryProjectsFindFilterWidget::queryTextEdit() const +{ + return m_form.queryTextEdit; +} + +QPlainTextEdit *ClangQueryProjectsFindFilterWidget::queryExampleTextEdit() const +{ + return m_form.exampleSourceTextEdit; +} + +ClangQueryExampleHighlighter *ClangQueryProjectsFindFilterWidget::clangQueryExampleHighlighter() const +{ + return m_form.exampleSourceTextEdit->syntaxHighlighter(); +} + +ClangQueryHighlighter *ClangQueryProjectsFindFilterWidget::clangQueryHighlighter() const +{ + return m_form.queryTextEdit->syntaxHighlighter(); +} + +bool ClangQueryProjectsFindFilterWidget::isValid() const +{ + return !m_form.queryTextEdit->textDocument()->document()->isEmpty() + && !clangQueryHighlighter()->hasDiagnostics(); + +} + +} // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/clangqueryprojectsfindfilterwidget.h b/src/plugins/clangrefactoring/clangqueryprojectsfindfilterwidget.h new file mode 100644 index 0000000000..2d9fdd785a --- /dev/null +++ b/src/plugins/clangrefactoring/clangqueryprojectsfindfilterwidget.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** 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 "ui_clangqueryprojectsfindfilter.h" + +namespace ClangRefactoring { + +class ClangQueryExampleHighlighter; +class ClangQueryHighlighter; + +class ClangQueryProjectsFindFilterWidget : public QWidget +{ + Q_OBJECT +public: + ClangQueryProjectsFindFilterWidget(); + + QPlainTextEdit *queryTextEdit() const; + QPlainTextEdit *queryExampleTextEdit() const; + ClangQueryExampleHighlighter *clangQueryExampleHighlighter() const; + ClangQueryHighlighter *clangQueryHighlighter() const; + + bool isValid() const; + +private: + Ui::Form m_form; +}; + +} // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/clangquerytexteditorwidget.cpp b/src/plugins/clangrefactoring/clangquerytexteditorwidget.cpp new file mode 100644 index 0000000000..7ca9d90254 --- /dev/null +++ b/src/plugins/clangrefactoring/clangquerytexteditorwidget.cpp @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** 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 "clangquerytexteditorwidget.h" + +#include "clangqueryhighlighter.h" + +#include <texteditor/textdocument.h> + +namespace ClangRefactoring { + +ClangQueryTextEditorWidget::ClangQueryTextEditorWidget(QWidget *parent) + : BaseClangQueryTextEditorWidget(parent) +{ + m_syntaxHighlighter = new ClangQueryHighlighter; + + textDocument()->setSyntaxHighlighter(m_syntaxHighlighter); +} + +ClangQueryHighlighter *ClangQueryTextEditorWidget::syntaxHighlighter() const +{ + return m_syntaxHighlighter; +} + +} // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/clangquerytexteditorwidget.h b/src/plugins/clangrefactoring/clangquerytexteditorwidget.h new file mode 100644 index 0000000000..85dace1432 --- /dev/null +++ b/src/plugins/clangrefactoring/clangquerytexteditorwidget.h @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** 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 "baseclangquerytexteditorwidget.h" + +namespace ClangRefactoring { + +class ClangQueryHighlighter; + +class ClangQueryTextEditorWidget : public BaseClangQueryTextEditorWidget +{ + Q_OBJECT + +public: + ClangQueryTextEditorWidget(QWidget *parent); + + ClangQueryHighlighter *syntaxHighlighter() const; + +private: + ClangQueryHighlighter *m_syntaxHighlighter; +}; + +} // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/clangrefactoring-source.pri b/src/plugins/clangrefactoring/clangrefactoring-source.pri index 24c3c4f597..24102dfd99 100644 --- a/src/plugins/clangrefactoring/clangrefactoring-source.pri +++ b/src/plugins/clangrefactoring/clangrefactoring-source.pri @@ -7,7 +7,11 @@ HEADERS += \ $$PWD/searchinterface.h \ $$PWD/searchhandle.h \ $$PWD/projectpartutilities.h \ - $$PWD/clangqueryprojectsfindfilter.h + $$PWD/clangqueryprojectsfindfilter.h \ + $$PWD/clangqueryexamplehighlightmarker.h \ + $$PWD/clangqueryhighlightmarker.h \ + $$PWD/clangqueryexamplehighlighter.h \ + $$PWD/clangqueryhighlighter.h SOURCES += \ $$PWD/refactoringengine.cpp \ @@ -16,4 +20,6 @@ SOURCES += \ $$PWD/searchinterface.cpp \ $$PWD/searchhandle.cpp \ $$PWD/projectpartutilities.cpp \ - $$PWD/clangqueryprojectsfindfilter.cpp + $$PWD/clangqueryprojectsfindfilter.cpp \ + $$PWD/clangqueryexamplehighlighter.cpp \ + $$PWD/clangqueryhighlighter.cpp diff --git a/src/plugins/clangrefactoring/clangrefactoring.pro b/src/plugins/clangrefactoring/clangrefactoring.pro index 42efebd56a..1a8d16e3e3 100644 --- a/src/plugins/clangrefactoring/clangrefactoring.pro +++ b/src/plugins/clangrefactoring/clangrefactoring.pro @@ -7,13 +7,24 @@ include(../../shared/clang/clang_defines.pri) requires(!isEmpty(LIBTOOLING_LIBS)) HEADERS += \ - $$PWD/clangrefactoringplugin.h \ + clangrefactoringplugin.h \ qtcreatorsearch.h \ qtcreatorsearchhandle.h \ - qtcreatorclangqueryfindfilter.h + qtcreatorclangqueryfindfilter.h \ + clangqueryprojectsfindfilterwidget.h \ + clangqueryexampletexteditorwidget.h \ + clangquerytexteditorwidget.h \ + baseclangquerytexteditorwidget.h SOURCES += \ - $$PWD/clangrefactoringplugin.cpp \ + clangrefactoringplugin.cpp \ qtcreatorsearch.cpp \ qtcreatorsearchhandle.cpp \ - qtcreatorclangqueryfindfilter.cpp + qtcreatorclangqueryfindfilter.cpp \ + clangqueryprojectsfindfilterwidget.cpp \ + clangqueryexampletexteditorwidget.cpp \ + clangquerytexteditorwidget.cpp \ + baseclangquerytexteditorwidget.cpp + +FORMS += \ + clangqueryprojectsfindfilter.ui diff --git a/src/plugins/clangrefactoring/qtcreatorclangqueryfindfilter.cpp b/src/plugins/clangrefactoring/qtcreatorclangqueryfindfilter.cpp index 7fa9daab37..b4ab35e851 100644 --- a/src/plugins/clangrefactoring/qtcreatorclangqueryfindfilter.cpp +++ b/src/plugins/clangrefactoring/qtcreatorclangqueryfindfilter.cpp @@ -25,6 +25,9 @@ #include "qtcreatorclangqueryfindfilter.h" +#include "clangqueryprojectsfindfilterwidget.h" +#include "refactoringclient.h" + #include <cpptools/abstracteditorsupport.h> #include <cpptools/cppmodelmanager.h> #include <cpptools/projectinfo.h> @@ -49,13 +52,61 @@ void QtCreatorClangQueryFindFilter::findAll(const QString &queryText, Core::Find ClangQueryProjectsFindFilter::findAll(queryText, findFlags); } +void QtCreatorClangQueryFindFilter::handleQueryOrExampleTextChanged() +{ + const QString queryText = this->queryText(); + const QString queryExampleText = this->queryExampleText(); + if (!queryText.isEmpty() && !queryExampleText.isEmpty()) + requestSourceRangesAndDiagnostics(queryText, queryExampleText); +} + +QWidget *QtCreatorClangQueryFindFilter::createConfigWidget() +{ + m_widget = new ClangQueryProjectsFindFilterWidget; + + refactoringClient().setClangQueryExampleHighlighter(m_widget->clangQueryExampleHighlighter()); + refactoringClient().setClangQueryHighlighter(m_widget->clangQueryHighlighter()); + + QObject::connect(m_widget->queryExampleTextEdit(), + &QPlainTextEdit::textChanged, + this, + &QtCreatorClangQueryFindFilter::handleQueryOrExampleTextChanged); + + QObject::connect(m_widget->queryTextEdit(), + &QPlainTextEdit::textChanged, + this, + &QtCreatorClangQueryFindFilter::handleQueryOrExampleTextChanged); + + return m_widget; +} + +bool ClangRefactoring::QtCreatorClangQueryFindFilter::isValid() const +{ + return true; +} + +QWidget *QtCreatorClangQueryFindFilter::widget() const +{ + return m_widget; +} + +QString QtCreatorClangQueryFindFilter::queryText() const +{ + return m_widget->queryTextEdit()->toPlainText(); +} + +QString QtCreatorClangQueryFindFilter::queryExampleText() const +{ + return m_widget->queryExampleTextEdit()->toPlainText(); +} + namespace { std::vector<ClangBackEnd::V2::FileContainer> createUnsavedContents() { auto abstractEditors = CppTools::CppModelManager::instance()->abstractEditorSupports(); std::vector<ClangBackEnd::V2::FileContainer> unsavedContents; - unsavedContents.reserve(abstractEditors.size()); + unsavedContents.reserve(std::size_t(abstractEditors.size())); auto toFileContainer = [] (const CppTools::AbstractEditorSupport *abstractEditor) { return ClangBackEnd::V2::FileContainer(ClangBackEnd::FilePath(abstractEditor->fileName()), diff --git a/src/plugins/clangrefactoring/qtcreatorclangqueryfindfilter.h b/src/plugins/clangrefactoring/qtcreatorclangqueryfindfilter.h index 8157779bc9..aa53cd6fd7 100644 --- a/src/plugins/clangrefactoring/qtcreatorclangqueryfindfilter.h +++ b/src/plugins/clangrefactoring/qtcreatorclangqueryfindfilter.h @@ -27,19 +27,38 @@ #include "clangqueryprojectsfindfilter.h" +#include <QPointer> + namespace ClangRefactoring { +class ClangQueryProjectsFindFilterWidget; + class QtCreatorClangQueryFindFilter final : public ClangQueryProjectsFindFilter { public: - QtCreatorClangQueryFindFilter(ClangBackEnd::RefactoringServerInterface &server, - SearchInterface &searchInterface, - RefactoringClient &refactoringClient); + QtCreatorClangQueryFindFilter(ClangBackEnd::RefactoringServerInterface &m_server, + SearchInterface &m_searchInterface, + RefactoringClient &m_refactoringClient); void findAll(const QString &queryText, Core::FindFlags findFlags = 0) override; + void handleQueryOrExampleTextChanged(); + + QWidget *createConfigWidget() override; + + bool isValid() const override; + + +protected: + QWidget *widget() const override; + QString queryText() const override; + QString queryExampleText() const; + private: void prepareFind(); + +private: + QPointer<ClangQueryProjectsFindFilterWidget> m_widget; }; } // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/refactoringclient.cpp b/src/plugins/clangrefactoring/refactoringclient.cpp index 4cb954e231..e4904b53cc 100644 --- a/src/plugins/clangrefactoring/refactoringclient.cpp +++ b/src/plugins/clangrefactoring/refactoringclient.cpp @@ -25,32 +25,40 @@ #include "refactoringclient.h" +#include "clangqueryhighlighter.h" +#include "clangqueryexamplehighlighter.h" + #include <refactoringconnectionclient.h> -#include <sourcelocationsforrenamingmessage.h> -#include <sourcerangesanddiagnosticsforquerymessage.h> +#include <clangrefactoringmessages.h> namespace ClangRefactoring { void RefactoringClient::alive() { - if (connectionClient) - connectionClient->resetProcessAliveTimer(); + if (m_connectionClient) + m_connectionClient->resetProcessAliveTimer(); } void RefactoringClient::sourceLocationsForRenamingMessage( ClangBackEnd::SourceLocationsForRenamingMessage &&message) { - localRenamingCallback(message.symbolName().toQString(), + m_localRenamingCallback(message.symbolName().toQString(), message.sourceLocations(), message.textDocumentRevision()); - refactoringEngine->setUsable(true); + m_refactoringEngine->setUsable(true); } void RefactoringClient::sourceRangesAndDiagnosticsForQueryMessage( ClangBackEnd::SourceRangesAndDiagnosticsForQueryMessage &&message) { - ++resultCounter_; + m_clangQueryExampleHighlighter->setSourceRanges(message.takeSourceRanges()); + m_clangQueryHighlighter->setDiagnostics(message.diagnostics()); +} + +void RefactoringClient::sourceRangesForQueryMessage(ClangBackEnd::SourceRangesForQueryMessage &&message) +{ + ++m_resultCounter; addSearchResults(message.sourceRanges()); setResultCounterAndSendSearchIsFinishedIfFinished(); } @@ -58,50 +66,60 @@ void RefactoringClient::sourceRangesAndDiagnosticsForQueryMessage( void RefactoringClient::setLocalRenamingCallback( CppTools::RefactoringEngineInterface::RenameCallback &&localRenamingCallback) { - this->localRenamingCallback = std::move(localRenamingCallback); + m_localRenamingCallback = std::move(localRenamingCallback); } void RefactoringClient::setRefactoringEngine(RefactoringEngine *refactoringEngine) { - this->refactoringEngine = refactoringEngine; + m_refactoringEngine = refactoringEngine; } void RefactoringClient::setSearchHandle(SearchHandle *searchHandle) { - this->searchHandle_ = searchHandle; + m_searchHandle = searchHandle; } SearchHandle *RefactoringClient::searchHandle() const { - return searchHandle_; + return m_searchHandle; +} + +void RefactoringClient::setClangQueryExampleHighlighter(ClangQueryExampleHighlighter *highlighter) +{ + m_clangQueryExampleHighlighter = highlighter; +} + +void RefactoringClient::setClangQueryHighlighter(ClangQueryHighlighter *highlighter) +{ + m_clangQueryHighlighter = highlighter; } bool RefactoringClient::hasValidLocalRenamingCallback() const { - return bool(localRenamingCallback); + return bool(m_localRenamingCallback); } void RefactoringClient::setExpectedResultCount(uint count) { - expectedResultCount_ = count; - resultCounter_ = 0; - searchHandle_->setExpectedResultCount(count); + m_expectedResultCount = count; + m_resultCounter = 0; + m_searchHandle->setExpectedResultCount(count); } uint RefactoringClient::expectedResultCount() const { - return expectedResultCount_; + return m_expectedResultCount; } uint RefactoringClient::resultCounter() const { - return resultCounter_; + return m_resultCounter; } void RefactoringClient::setRefactoringConnectionClient( ClangBackEnd::RefactoringConnectionClient *connectionClient) { - this->connectionClient = connectionClient; + m_connectionClient = connectionClient; } std::unordered_map<uint, QString> RefactoringClient::convertFilePaths( @@ -135,7 +153,7 @@ void RefactoringClient::addSearchResults(const ClangBackEnd::SourceRangesContain void RefactoringClient::addSearchResult(const ClangBackEnd::SourceRangeWithTextContainer &sourceRangeWithText, std::unordered_map<uint, QString> &filePaths) { - searchHandle_->addResult(filePaths[sourceRangeWithText.fileHash()], + m_searchHandle->addResult(filePaths[sourceRangeWithText.fileHash()], sourceRangeWithText.text(), {{int(sourceRangeWithText.start().line()), int(sourceRangeWithText.start().column() - 1), @@ -147,9 +165,9 @@ void RefactoringClient::addSearchResult(const ClangBackEnd::SourceRangeWithTextC void RefactoringClient::setResultCounterAndSendSearchIsFinishedIfFinished() { - searchHandle_->setResultCounter(resultCounter_); - if (resultCounter_ == expectedResultCount_) - searchHandle_->finishSearch(); + m_searchHandle->setResultCounter(m_resultCounter); + if (m_resultCounter == m_expectedResultCount) + m_searchHandle->finishSearch(); } } // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/refactoringclient.h b/src/plugins/clangrefactoring/refactoringclient.h index ea1abac026..09524f314f 100644 --- a/src/plugins/clangrefactoring/refactoringclient.h +++ b/src/plugins/clangrefactoring/refactoringclient.h @@ -42,6 +42,9 @@ class SourceRangeWithTextContainer; namespace ClangRefactoring { +class ClangQueryExampleHighlighter; +class ClangQueryHighlighter; + class RefactoringClient final : public ClangBackEnd::RefactoringClientInterface { public: @@ -50,12 +53,16 @@ public: ClangBackEnd::SourceLocationsForRenamingMessage &&message) override; void sourceRangesAndDiagnosticsForQueryMessage( ClangBackEnd::SourceRangesAndDiagnosticsForQueryMessage &&message) override; + void sourceRangesForQueryMessage( + ClangBackEnd::SourceRangesForQueryMessage &&message) override; void setLocalRenamingCallback( CppTools::RefactoringEngineInterface::RenameCallback &&localRenamingCallback) override; void setRefactoringEngine(ClangRefactoring::RefactoringEngine *refactoringEngine); void setSearchHandle(ClangRefactoring::SearchHandle *searchHandleInterface); ClangRefactoring::SearchHandle *searchHandle() const; + void setClangQueryExampleHighlighter(ClangQueryExampleHighlighter *highlighter); + void setClangQueryHighlighter(ClangQueryHighlighter *highlighter); bool hasValidLocalRenamingCallback() const; @@ -79,12 +86,14 @@ private: void sendSearchIsFinished(); private: - CppTools::RefactoringEngineInterface::RenameCallback localRenamingCallback; - ClangBackEnd::RefactoringConnectionClient *connectionClient = nullptr; - ClangRefactoring::SearchHandle *searchHandle_ = nullptr; - ClangRefactoring::RefactoringEngine *refactoringEngine = nullptr; - uint expectedResultCount_ = 0; - uint resultCounter_ = 0; + CppTools::RefactoringEngineInterface::RenameCallback m_localRenamingCallback; + ClangBackEnd::RefactoringConnectionClient *m_connectionClient = nullptr; + SearchHandle *m_searchHandle = nullptr; + RefactoringEngine *m_refactoringEngine = nullptr; + ClangQueryExampleHighlighter *m_clangQueryExampleHighlighter = nullptr; + ClangQueryHighlighter *m_clangQueryHighlighter = nullptr; + uint m_expectedResultCount = 0; + uint m_resultCounter = 0; }; } // namespace ClangRefactoring |