Commit ddfd2985 authored by Marco Bubke's avatar Marco Bubke

Utils: First step to extend search results for clang query support

We need multi line support, multi text range support. This is only adding
enablers and adds later the multi line and multi text support because this
triggers larger changes because you have to know the text document.

Change-Id: I44e46d9d80d7d73b2650c69cc83657c20c85bfae
Reviewed-by: Tim Jenssen's avatarTim Jenssen <tim.jenssen@qt.io>
parent 8a7f2119
......@@ -39,6 +39,7 @@
#include <coreplugin/documentmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/find/findplugin.h>
#include <coreplugin/find/searchresultwindow.h>
#include <coreplugin/locator/locator.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/fileutils.h>
......@@ -70,6 +71,7 @@ CorePlugin::CorePlugin()
, m_locator(0)
{
qRegisterMetaType<Id>();
qRegisterMetaType<Core::Search::TextPosition>();
}
CorePlugin::~CorePlugin()
......
......@@ -16,7 +16,8 @@ HEADERS += \
$$PWD/searchresultwidget.h \
$$PWD/searchresultwindow.h \
$$PWD/textfindconstants.h \
$$PWD/highlightscrollbar.h
$$PWD/highlightscrollbar.h \
$$PWD/searchresultitem.h
SOURCES += \
$$PWD/basetextfind.cpp \
......
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <QIcon>
#include <QStringList>
#include <QVariant>
namespace Core {
namespace Search {
class TextPosition
{
public:
TextPosition() = default;
TextPosition(int line, int column) : line(line), column(column) {}
int line = -1; // (0 or -1 for no line number)
int column = -1; // 0-based starting position for a mark (-1 for no mark)
};
class TextRange
{
public:
TextRange() = default;
TextRange(TextPosition begin, TextPosition end) : begin(begin), end(end) {}
QString mid(const QString &text) const
{
if (begin.line == end.line)
return text.mid(begin.column, end.column - begin.column);
return QString();
}
int length() const
{
if (begin.line == end.line)
return end.column - begin.column;
return 0;
}
TextPosition begin;
TextPosition end;
};
} // namespace Search
class SearchResultItem
{
public:
QStringList path; // hierarchy to the parent item of this item
QString text; // text to show for the item itself
QIcon icon; // icon to show in front of the item (by be null icon to hide)
QVariant userData; // user data for identification of the item
Search::TextRange mainRange;
bool useTextEditorFont = false;
};
} // namespace Core
Q_DECLARE_METATYPE(Core::SearchResultItem)
Q_DECLARE_METATYPE(Core::Search::TextPosition)
......@@ -107,7 +107,7 @@ int SearchResultTreeItemDelegate::drawLineNumber(QPainter *painter, const QStyle
const QModelIndex &index) const
{
static const int lineNumberAreaHorizontalPadding = 4;
int lineNumber = index.model()->data(index, ItemDataRoles::ResultLineNumberRole).toInt();
int lineNumber = index.model()->data(index, ItemDataRoles::ResultBeginLineNumberRole).toInt();
if (lineNumber < 1)
return 0;
const bool isSelected = option.state & QStyle::State_Selected;
......@@ -154,7 +154,7 @@ void SearchResultTreeItemDelegate::drawText(QPainter *painter,
+ QLatin1Char(')');
}
const int searchTermStart = index.model()->data(index, ItemDataRoles::SearchTermStartRole).toInt();
const int searchTermStart = index.model()->data(index, ItemDataRoles::ResultBeginColumnNumberRole).toInt();
int searchTermLength = index.model()->data(index, ItemDataRoles::SearchTermLengthRole).toInt();
if (searchTermStart < 0 || searchTermStart >= text.length() || searchTermLength < 1) {
QItemDelegate::drawDisplay(painter, option, rect, text.replace(QLatin1Char('\t'), m_tabString));
......
......@@ -35,11 +35,11 @@ enum Roles
{
ResultItemRole = Qt::UserRole,
ResultLineRole,
ResultLineNumberRole,
ResultBeginLineNumberRole,
ResultIconRole,
ResultHighlightBackgroundColor,
ResultHighlightForegroundColor,
SearchTermStartRole,
ResultBeginColumnNumberRole,
SearchTermLengthRole,
IsGeneratedRole
};
......
......@@ -261,8 +261,8 @@ QVariant SearchResultTreeModel::data(const SearchResultTreeItem *row, int role)
case ItemDataRoles::ResultItemRole:
result = qVariantFromValue(row->item);
break;
case ItemDataRoles::ResultLineNumberRole:
result = row->item.lineNumber;
case ItemDataRoles::ResultBeginLineNumberRole:
result = row->item.mainRange.begin.line;
break;
case ItemDataRoles::ResultIconRole:
result = row->item.icon;
......@@ -273,11 +273,11 @@ QVariant SearchResultTreeModel::data(const SearchResultTreeItem *row, int role)
case ItemDataRoles::ResultHighlightForegroundColor:
result = m_color.highlightForeground;
break;
case ItemDataRoles::SearchTermStartRole:
result = row->item.textMarkPos;
case ItemDataRoles::ResultBeginColumnNumberRole:
result = row->item.mainRange.begin.column;
break;
case ItemDataRoles::SearchTermLengthRole:
result = row->item.textMarkLength;
result = row->item.mainRange.length();
break;
case ItemDataRoles::IsGeneratedRole:
result = row->isGenerated();
......
......@@ -227,15 +227,15 @@ void SearchResultWidget::setInfo(const QString &label, const QString &toolTip, c
m_searchTerm->setVisible(!term.isEmpty());
}
void SearchResultWidget::addResult(const QString &fileName, int lineNumber, const QString &rowText,
int searchTermStart, int searchTermLength, const QVariant &userData)
void SearchResultWidget::addResult(const QString &fileName,
const QString &rowText,
Search::TextRange mainRange,
const QVariant &userData)
{
SearchResultItem item;
item.path = QStringList() << QDir::toNativeSeparators(fileName);
item.lineNumber = lineNumber;
item.path = QStringList({QDir::toNativeSeparators(fileName)});
item.mainRange = mainRange;
item.text = rowText;
item.textMarkPos = searchTermStart;
item.textMarkLength = searchTermLength;
item.useTextEditorFont = true;
item.userData = userData;
addResults(QList<SearchResultItem>() << item, SearchResult::AddOrdered);
......
......@@ -54,8 +54,10 @@ public:
void setInfo(const QString &label, const QString &toolTip, const QString &term);
void addResult(const QString &fileName, int lineNumber, const QString &lineText,
int searchTermStart, int searchTermLength, const QVariant &userData = QVariant());
void addResult(const QString &fileName,
const QString &lineText,
Search::TextRange mainRange,
const QVariant &userData = QVariant());
void addResults(const QList<SearchResultItem> &items, SearchResult::AddMode mode);
int count() const;
......
......@@ -658,8 +658,21 @@ void SearchResult::setSearchAgainSupported(bool supported)
void SearchResult::addResult(const QString &fileName, int lineNumber, const QString &lineText,
int searchTermStart, int searchTermLength, const QVariant &userData)
{
m_widget->addResult(fileName, lineNumber, lineText,
searchTermStart, searchTermLength, userData);
Search::TextRange mainRange;
mainRange.begin.line = lineNumber;
mainRange.begin.column = searchTermStart;
mainRange.end.line = mainRange.begin.line;
mainRange.end.column = mainRange.begin.column + searchTermLength;
m_widget->addResult(fileName, lineText, mainRange, userData);
}
void SearchResult::addResult(const QString &fileName,
const QString &lineText,
Search::TextRange mainRange,
const QVariant &userData)
{
m_widget->addResult(fileName, lineText, mainRange, userData);
emit countChanged(m_widget->count());
}
......
......@@ -25,6 +25,8 @@
#pragma once
#include "searchresultitem.h"
#include <coreplugin/ioutputpane.h>
#include <QVariant>
......@@ -44,39 +46,6 @@ namespace Internal {
class Find;
class SearchResultWindow;
class CORE_EXPORT SearchResultItem
{
public:
SearchResultItem()
: textMarkPos(-1),
textMarkLength(0),
lineNumber(-1),
useTextEditorFont(false)
{
}
SearchResultItem(const SearchResultItem &other)
: path(other.path),
text(other.text),
textMarkPos(other.textMarkPos),
textMarkLength(other.textMarkLength),
icon(other.icon),
lineNumber(other.lineNumber),
useTextEditorFont(other.useTextEditorFont),
userData(other.userData)
{
}
QStringList path; // hierarchy to the parent item of this item
QString text; // text to show for the item itself
int textMarkPos; // 0-based starting position for a mark (-1 for no mark)
int textMarkLength; // length of the mark (0 for no mark)
QIcon icon; // icon to show in front of the item (by be null icon to hide)
int lineNumber; // (0 or -1 for no line number)
bool useTextEditorFont;
QVariant userData; // user data for identification of the item
};
class CORE_EXPORT SearchResult : public QObject
{
Q_OBJECT
......@@ -94,8 +63,16 @@ public:
void setSearchAgainSupported(bool supported);
public slots:
void addResult(const QString &fileName, int lineNumber, const QString &lineText,
int searchTermStart, int searchTermLength, const QVariant &userData = QVariant());
void addResult(const QString &fileName,
int lineNumber,
const QString &lineText,
int searchTermStart,
int searchTermLength,
const QVariant &userData = QVariant());
void addResult(const QString &fileName,
const QString &lineText,
Search::TextRange mainRange,
const QVariant &userData = QVariant());
void addResults(const QList<SearchResultItem> &items, AddMode mode);
void finishSearch(bool canceled);
void setTextToReplace(const QString &textToReplace);
......@@ -191,5 +168,3 @@ private:
};
} // namespace Core
Q_DECLARE_METATYPE(Core::SearchResultItem)
......@@ -308,10 +308,7 @@ public:
Core::SearchResultItem item;
item.path = scope.split(QLatin1String("::"), QString::SkipEmptyParts);
item.text = text;
item.textMarkPos = -1;
item.textMarkLength = 0;
item.icon = info->icon();
item.lineNumber = -1;
item.userData = qVariantFromValue(info);
resultItems << item;
}
......
......@@ -481,7 +481,8 @@ void CppFindReferences::openEditor(const SearchResultItem &item)
{
if (item.path.size() > 0) {
EditorManager::openEditorAt(QDir::fromNativeSeparators(item.path.first()),
item.lineNumber, item.textMarkPos);
item.mainRange.begin.line,
item.mainRange.begin.column);
} else {
EditorManager::openEditor(QDir::fromNativeSeparators(item.text));
}
......
......@@ -301,7 +301,7 @@ IEditor *GitGrep::openEditor(const SearchResultItem &item,
QString title = tr("Git Show %1:%2").arg(params.ref).arg(relativePath);
IEditor *editor = EditorManager::openEditorWithContents(Id(), &title, content, title,
EditorManager::DoNotSwitchToDesignMode);
editor->gotoLine(item.lineNumber, item.textMarkPos);
editor->gotoLine(item.mainRange.begin.line, item.mainRange.begin.column);
editor->document()->setTemporary(true);
return editor;
}
......
......@@ -1009,7 +1009,8 @@ void FindReferences::openEditor(const SearchResultItem &item)
{
if (item.path.size() > 0) {
EditorManager::openEditorAt(QDir::fromNativeSeparators(item.path.first()),
item.lineNumber, item.textMarkPos);
item.mainRange.begin.line,
item.mainRange.begin.column);
} else {
EditorManager::openEditor(QDir::fromNativeSeparators(item.text));
}
......
......@@ -289,10 +289,11 @@ void BaseFileFind::displayResult(int index) {
foreach (const FileSearchResult &result, results) {
SearchResultItem item;
item.path = QStringList() << QDir::toNativeSeparators(result.fileName);
item.lineNumber = result.lineNumber;
item.mainRange.begin.line = result.lineNumber;
item.mainRange.begin.column = result.matchStart;
item.mainRange.end = item.mainRange.begin;
item.mainRange.end.column += result.matchLength;
item.text = result.matchingLine;
item.textMarkLength = result.matchLength;
item.textMarkPos = result.matchStart;
item.useTextEditorFont = true;
item.userData = result.regexpCapturedTexts;
items << item;
......@@ -389,8 +390,8 @@ void BaseFileFind::openEditor(const SearchResultItem &item)
if (!openedEditor) {
if (item.path.size() > 0) {
openedEditor = EditorManager::openEditorAt(QDir::fromNativeSeparators(item.path.first()),
item.lineNumber,
item.textMarkPos, Id(),
item.mainRange.begin.line,
item.mainRange.begin.column, Id(),
EditorManager::DoNotSwitchToDesignMode);
} else {
openedEditor = EditorManager::openEditor(QDir::fromNativeSeparators(item.text));
......@@ -470,7 +471,8 @@ QStringList BaseFileFind::replaceAll(const QString &text,
RefactoringFilePtr file = refactoring.file(fileName);
QSet<QPair<int, int> > processed;
foreach (const SearchResultItem &item, changeItems) {
const QPair<int, int> &p = qMakePair(item.lineNumber, item.textMarkPos);
const QPair<int, int> &p = qMakePair(item.mainRange.begin.line,
item.mainRange.begin.column);
if (processed.contains(p))
continue;
processed.insert(p);
......@@ -479,16 +481,17 @@ QStringList BaseFileFind::replaceAll(const QString &text,
if (item.userData.canConvert<QStringList>() && !item.userData.toStringList().isEmpty()) {
replacement = Utils::expandRegExpReplacement(text, item.userData.toStringList());
} else if (preserveCase) {
const QString originalText = (item.textMarkLength == 0) ? item.text
: item.text.mid(item.textMarkPos, item.textMarkLength);
const QString originalText = (item.mainRange.length() == 0) ? item.text
: item.mainRange.mid(text);
replacement = Utils::matchCaseReplacement(originalText, text);
} else {
replacement = text;
}
const int start = file->position(item.lineNumber, item.textMarkPos + 1);
const int end = file->position(item.lineNumber,
item.textMarkPos + item.textMarkLength + 1);
const int start = file->position(item.mainRange.begin.line,
item.mainRange.begin.column + 1);
const int end = file->position(item.mainRange.end.line,
item.mainRange.end.column + 1);
changeSet.replace(start, end, replacement);
}
file->setChangeSet(changeSet);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment