Skip to content

Commit

Permalink
fix: [search] Fixed an issue where advanced search could not find res…
Browse files Browse the repository at this point in the history
…ults

as title

Log: fix issue
  • Loading branch information
Kakueeen authored and deepin-mozart committed Jul 24, 2024
1 parent 83e702c commit 37f2a06
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 65 deletions.
8 changes: 4 additions & 4 deletions src/plugins/find/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ enum ResultRole {
LineRole = Qt::UserRole + 1,
ColumnRole,
KeywordRole,
MatchedTextRole,
MatchedLengthRole,
FilePathRole,
ReplaceTextRole
};
Expand All @@ -25,8 +25,8 @@ enum SearchScope {

enum SearchFlag {
SearchNoFlag = 0,
SearchCaseSensitive = 1,
SearchWholeWord = 1 << 1,
SearchCaseSensitively = 1,
SearchWholeWords = 1 << 1,
SearchRegularExpression = 1 << 2
};
Q_DECLARE_FLAGS(SearchFlags, SearchFlag)
Expand All @@ -42,7 +42,7 @@ struct FindItem
int line = -1;
int column = -1;
QString keyword;
QString matchedText;
int matchedLength;
QStringList capturedTexts;
QString context;

Expand Down
8 changes: 4 additions & 4 deletions src/plugins/find/gui/advancedsearchwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,8 +295,8 @@ SearchParams AdvancedSearchWidgetPrivate::searchParams()
}

params.scope = static_cast<SearchScope>(scope);
params.flags |= caseBtn->isChecked() ? SearchCaseSensitive : SearchNoFlag;
params.flags |= wholeWordBtn->isChecked() ? SearchWholeWord : SearchNoFlag;
params.flags |= caseBtn->isChecked() ? SearchCaseSensitively : SearchNoFlag;
params.flags |= wholeWordBtn->isChecked() ? SearchWholeWords : SearchNoFlag;
params.flags |= regexBtn->isChecked() ? SearchRegularExpression : SearchNoFlag;
params.includeList = includeEdit->text().trimmed().split(",", QString::SkipEmptyParts);
params.excludeList = excludeEdit->text().trimmed().split(",", QString::SkipEmptyParts);
Expand All @@ -312,8 +312,8 @@ ReplaceParams AdvancedSearchWidgetPrivate::replaceParams(const QMap<QString, Fin
params.editFileList = editSrv->openedFiles();
params.resultMap = resultMap;
params.replaceText = replaceEdit->text();
params.flags |= caseBtn->isChecked() ? SearchCaseSensitive : SearchNoFlag;
params.flags |= wholeWordBtn->isChecked() ? SearchWholeWord : SearchNoFlag;
params.flags |= caseBtn->isChecked() ? SearchCaseSensitively : SearchNoFlag;
params.flags |= wholeWordBtn->isChecked() ? SearchWholeWords : SearchNoFlag;
params.flags |= regexBtn->isChecked() ? SearchRegularExpression : SearchNoFlag;

return params;
Expand Down
8 changes: 4 additions & 4 deletions src/plugins/find/gui/searchresultitemdelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ void SearchResultItemDelegate::drawContextItem(QPainter *painter, const QStyleOp
optionRect = drawOptionButton(painter, option, index);

const auto &lineNumber = QString::number(index.data(LineRole).toInt());
const auto &matchedText = index.data(MatchedTextRole).toString();
const auto &matchedLength = index.data(MatchedLengthRole).toInt();
const auto &column = index.data(ColumnRole).toInt();
auto context = index.data(Qt::DisplayRole).toString();
const auto &replaceText = index.data(ReplaceTextRole).toString();
Expand All @@ -319,7 +319,7 @@ void SearchResultItemDelegate::drawContextItem(QPainter *painter, const QStyleOp
if (optionRect.isValid())
textRect.setRight(optionRect.left() - Padding);
if (!replaceText.isEmpty()) {
int replaceTextOffset = column + matchedText.length();
int replaceTextOffset = column + matchedLength;
context.insert(replaceTextOffset, replaceText);
QColor matchedBackground;
QColor replaceBackground;
Expand All @@ -334,7 +334,7 @@ void SearchResultItemDelegate::drawContextItem(QPainter *painter, const QStyleOp
replaceBackground.setNamedColor("#57965C");
replaceBackground.setAlpha(180);
}
formats << createFormatRange(opt, column, matchedText.length(), {}, matchedBackground);
formats << createFormatRange(opt, column, matchedLength, {}, matchedBackground);
formats << createFormatRange(opt, replaceTextOffset, replaceText.length(), {}, replaceBackground);
} else {
QColor background;
Expand All @@ -345,7 +345,7 @@ void SearchResultItemDelegate::drawContextItem(QPainter *painter, const QStyleOp
background.setNamedColor("#F2C55C");
background.setAlpha(220);
}
formats << createFormatRange(opt, column, matchedText.length(), {}, background);
formats << createFormatRange(opt, column, matchedLength, {}, background);
}
drawDisplay(painter, option, textRect, context, formats);
}
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/find/gui/searchresultmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,8 @@ QVariant SearchResultModel::data(const FindItem &item, int role) const
return item.column;
case KeywordRole:
return item.keyword;
case MatchedTextRole:
return item.matchedText;
case MatchedLengthRole:
return item.matchedLength;
case ReplaceTextRole:
if (!item.capturedTexts.isEmpty())
return Utils::expandRegExpReplacement(replaceText, item.capturedTexts);
Expand Down
191 changes: 141 additions & 50 deletions src/plugins/find/maincontroller/worker/searchreplaceworker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ void SearchReplaceWorkerPrivate::startNextJob()
std::bind(&SearchReplaceWorker::handleReadSearchResult, q, job.keyword, job.flags));
connect(process.get(), qOverload<int>(&QProcess::finished), q, &SearchReplaceWorker::processDone);

process->start(job.cmd);
process->setProgram(job.program);
process->setArguments(job.arguments);
process->start();
if (!job.channelData.isEmpty()) {
process->write(job.channelData.toUtf8());
process->closeWriteChannel();
Expand All @@ -58,20 +60,17 @@ void SearchReplaceWorkerPrivate::createSearchJob(const SearchParams &params)
for (const auto &file : tmpParams.editFileList) {
const auto &job = buildSearchJob({ file }, tmpParams.includeList, tmpParams.excludeList,
tmpParams.keyword, tmpParams.flags, true);
if (!job.cmd.isEmpty())
jobList << job;
jobList << job;
}

const auto &job = buildSearchJob(tmpParams.projectFileList, tmpParams.includeList, tmpParams.excludeList,
tmpParams.keyword, tmpParams.flags, false);
if (!job.cmd.isEmpty())
jobList << job;
jobList << job;
} break;
case CurrentFile: {
const auto &job = buildSearchJob(params.editFileList, params.includeList, params.excludeList,
params.keyword, params.flags, true);
if (!job.cmd.isEmpty())
jobList << job;
jobList << job;
} break;
default:
break;
Expand All @@ -89,43 +88,157 @@ SearchReplaceWorkerPrivate::buildSearchJob(const QStringList &fileList,
return {};

Job job;
job.program = "grep";
job.keyword = keyword;
job.flags = flags;
QStringList cmd;
cmd << "grep -Hn";
if (!flags.testFlag(SearchCaseSensitive))
cmd << "-i";
job.arguments << "-Hn";
if (!flags.testFlag(SearchCaseSensitively))
job.arguments << "-i";

if (flags.testFlag(SearchWholeWord)) {
cmd << "-w";
if (flags.testFlag(SearchWholeWords)) {
job.arguments << "-w";
}

if (flags.testFlag(SearchRegularExpression)) {
cmd << "-P";
job.arguments << "-P";
} else {
cmd << "-F";
job.arguments << "-F";
}

if (!includeList.isEmpty())
cmd << "--include=" + includeList.join(" --include=");
job.arguments << "--include=" + includeList.join(" --include=");
if (!excludeList.isEmpty())
cmd << "--exclude=" + excludeList.join(" --exclude=");
cmd << "\"" + keyword + "\"";
job.arguments << "--exclude=" + excludeList.join(" --exclude=");
job.arguments << keyword;

if (isOpenedFile) {
if (!editSrv)
editSrv = dpfGetService(EditorService);
job.channelData = editSrv->fileText(fileList.first());
cmd << "--label=" + fileList.first();
job.arguments << "--label=" + fileList.first();
} else {
QString searchPath = fileList.join(' ');
cmd << searchPath;
job.arguments << fileList;
}

job.cmd = cmd.join(' ');
return job;
}

void SearchReplaceWorkerPrivate::parseResultWithRegExp(const QString &fileName, const QString &keyword,
const QString &contents, int line, SearchFlags flags)
{
const QString term = flags & SearchWholeWords
? QString::fromLatin1("\\b%1\\b").arg(keyword)
: keyword;
const auto patternOptions = (flags & SearchCaseSensitively)
? QRegularExpression::NoPatternOption
: QRegularExpression::CaseInsensitiveOption;
const QRegularExpression expression = QRegularExpression(term, patternOptions);
if (!expression.isValid())
return;

QRegularExpressionMatch match;
int lengthOfContents = contents.length();
int pos = 0;
while ((match = expression.match(contents, pos)).hasMatch()) {
pos = match.capturedStart();
FindItem findItem;
findItem.filePathName = fileName;
findItem.line = line;
findItem.keyword = keyword;
findItem.context = contents;
findItem.column = pos;
findItem.matchedLength = match.capturedLength();
findItem.capturedTexts = match.capturedTexts();

{
QMutexLocker lk(&mutex);
searchResults.append(findItem);
}
++resultCount;
if (match.capturedLength() == 0)
break;
pos += match.capturedLength();
if (pos >= lengthOfContents)
break;
}
}

void SearchReplaceWorkerPrivate::parseResultWithoutRegExp(const QString &fileName, const QString &keyword,
const QString &contents, int line, SearchFlags flags)
{
const bool caseSensitive = (flags & SearchCaseSensitively);
const bool wholeWord = (flags & SearchWholeWords);
const QString keywordLower = keyword.toLower();
const QString keywordUpper = keyword.toUpper();
const int keywordMaxIndex = keyword.length() - 1;
const QChar *keywordData = keyword.constData();
const QChar *keywordDataLower = keywordLower.constData();
const QChar *keywordDataUpper = keywordUpper.constData();

const int contentsLength = contents.length();
const QChar *contentsPtr = contents.constData();
const QChar *contentsEnd = contentsPtr + contentsLength - 1;
for (const QChar *regionPtr = contentsPtr; regionPtr + keywordMaxIndex <= contentsEnd; ++regionPtr) {
const QChar *regionEnd = regionPtr + keywordMaxIndex;
if ((caseSensitive && *regionPtr == keywordData[0]
&& *regionEnd == keywordData[keywordMaxIndex])
||
// case insensitive
(!caseSensitive && (*regionPtr == keywordDataLower[0] || *regionPtr == keywordDataUpper[0])
&& (*regionEnd == keywordDataLower[keywordMaxIndex]
|| *regionEnd == keywordDataUpper[keywordMaxIndex]))) {
bool equal = true;

// whole word check
const QChar *beforeRegion = regionPtr - 1;
const QChar *afterRegion = regionEnd + 1;
if (wholeWord
&& (((beforeRegion >= contentsPtr)
&& (beforeRegion->isLetterOrNumber()
|| ((*beforeRegion) == QLatin1Char('_'))))
|| ((afterRegion <= contentsEnd)
&& (afterRegion->isLetterOrNumber()
|| ((*afterRegion) == QLatin1Char('_')))))) {
equal = false;
} else {
// check all chars
int regionIndex = 1;
for (const QChar *regionCursor = regionPtr + 1;
regionCursor < regionEnd;
++regionCursor, ++regionIndex) {
if ( // case sensitive
(caseSensitive
&& *regionCursor != keywordData[regionIndex])
||
// case insensitive
(!caseSensitive
&& *regionCursor != keywordDataLower[regionIndex]
&& *regionCursor != keywordDataUpper[regionIndex])) {
equal = false;
break;
}
}
}

if (equal) {
FindItem result;
result.filePathName = fileName;
result.line = line;
result.column = regionPtr - contentsPtr;
result.context = contents;
result.keyword = keyword;
result.matchedLength = keywordMaxIndex + 1;

++resultCount;
regionPtr += keywordMaxIndex;

QMutexLocker lk(&mutex);
searchResults.append(result);
}
}
}
}

void SearchReplaceWorkerPrivate::processWorkingFiles(QStringList &baseFiles, QStringList &openedFiles)
{
for (int i = 0; i < openedFiles.size();) {
Expand Down Expand Up @@ -170,8 +283,8 @@ void SearchReplaceWorkerPrivate::replaceLocalFile(const QString &fileName, const
offset = 0;

lastReplaceLine = realLine;
offset += newText.length() - item.matchedText.length();
lines[realLine].replace(index, item.matchedText.length(), newText);
offset += newText.length() - item.matchedLength;
lines[realLine].replace(index, item.matchedLength, newText);
}

QTextStream out(&file);
Expand Down Expand Up @@ -201,8 +314,8 @@ void SearchReplaceWorkerPrivate::replaceOpenedFile(const QString &fileName, cons
offset = 0;

lastReplaceLine = realLine;
offset += newText.length() - item.matchedText.length();
editSrv->replaceRange(fileName, realLine, index, item.matchedText.length(), newText);
offset += newText.length() - item.matchedLength;
editSrv->replaceRange(fileName, realLine, index, item.matchedLength, newText);
}
}

Expand Down Expand Up @@ -282,30 +395,8 @@ void SearchReplaceWorker::handleReadSearchResult(const QString &keyword, SearchF
auto line = regMatch.captured(2).toInt();
auto context = regMatch.captured(3);

QString pattern = flags.testFlag(SearchWholeWord)
? QString::fromLatin1("\\b%1\\b").arg(keyword)
: keyword;

QRegularExpression regex(pattern, flags.testFlag(SearchCaseSensitive) ? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption);
QRegularExpressionMatchIterator it = regex.globalMatch(context);
while (it.hasNext()) {
QRegularExpressionMatch match = it.next();
if (match.hasMatch()) {
FindItem findItem;
findItem.filePathName = name;
findItem.line = line;
findItem.keyword = keyword;
findItem.context = context;
findItem.column = match.capturedStart();
findItem.matchedText = match.captured();
if (flags.testFlag(SearchRegularExpression))
findItem.capturedTexts = match.capturedTexts();

QMutexLocker lk(&d->mutex);
d->searchResults.append(findItem);
++d->resultCount;
}
}
flags.testFlag(SearchRegularExpression) ? d->parseResultWithRegExp(name, keyword, context, line, flags)
: d->parseResultWithoutRegExp(name, keyword, context, line, flags);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ class SearchReplaceWorkerPrivate : public QObject
public:
struct Job
{
QString cmd;
QString program;
QStringList arguments;
QString channelData;
QString keyword;
SearchFlags flags;
Expand All @@ -34,6 +35,9 @@ class SearchReplaceWorkerPrivate : public QObject
SearchFlags flags,
bool isOpenedFile);

void parseResultWithRegExp(const QString &fileName, const QString &keyword, const QString &contents, int line, SearchFlags flags);
void parseResultWithoutRegExp(const QString &fileName, const QString &keyword, const QString &contents, int line, SearchFlags flags);

void processWorkingFiles(QStringList &baseFiles, QStringList &openedFiles);
void replaceLocalFile(const QString &fileName, const QString &replacement, const FindItemList &itemList);
Q_INVOKABLE void replaceOpenedFile(const QString &fileName, const QString &replacement, const FindItemList &itemList);
Expand Down

0 comments on commit 37f2a06

Please sign in to comment.