From 19d5e4234c5ed6e420df671147e0508fd84c1ca2 Mon Sep 17 00:00:00 2001 From: Eran Ifrah Date: Mon, 17 Feb 2025 19:32:08 +0200 Subject: [PATCH] Fixed: find in files does not respect file (type) pattern (#3057) Signed-off-by: Eran Ifrah --- CodeLite/search_thread.cpp | 146 ++++++++++++++++++---------------- LiteEditor/findinfilesdlg.cpp | 7 +- 2 files changed, 83 insertions(+), 70 deletions(-) diff --git a/CodeLite/search_thread.cpp b/CodeLite/search_thread.cpp index b8d258c3cb..46c7f240c7 100644 --- a/CodeLite/search_thread.cpp +++ b/CodeLite/search_thread.cpp @@ -53,9 +53,9 @@ wxDEFINE_EVENT(wxEVT_SEARCH_THREAD_SEARCHCANCELED, wxCommandEvent); wxDEFINE_EVENT(wxEVT_SEARCH_THREAD_SEARCHSTARTED, wxCommandEvent); #define SEND_ST_EVENT() \ - if(owner) { \ + if (owner) { \ wxPostEvent(owner, event); \ - } else if(m_notifiedWindow) { \ + } else if (m_notifiedWindow) { \ wxPostEvent(m_notifiedWindow, event); \ } @@ -76,7 +76,7 @@ const wxString& SearchData::GetExtensions() const { return m_validExt; } SearchData& SearchData::operator=(const SearchData& rhs) { return Copy(rhs); } SearchData& SearchData::Copy(const SearchData& other) { - if(this == &other) { + if (this == &other) { return *this; } m_findString = other.m_findString.c_str(); @@ -92,7 +92,7 @@ SearchData& SearchData::Copy(const SearchData& other) m_files.clear(); m_files.reserve(other.m_files.size()); m_file_scanner_flags = other.m_file_scanner_flags; - for(size_t i = 0; i < other.m_files.size(); ++i) { + for (size_t i = 0; i < other.m_files.size(); ++i) { m_files.Add(other.m_files.Item(i).c_str()); } return *this; @@ -113,7 +113,7 @@ SearchThread::~SearchThread() {} wxRegEx& SearchThread::GetRegex(const wxString& expr, bool matchCase) { - if(m_reExpr == expr && matchCase == m_matchCase) { + if (m_reExpr == expr && matchCase == m_matchCase) { return m_regex; } else { m_reExpr = expr; @@ -124,7 +124,7 @@ wxRegEx& SearchThread::GetRegex(const wxString& expr, bool matchCase) int flags = wxRE_DEFAULT; #endif - if(!matchCase) + if (!matchCase) flags |= wxRE_ICASE; m_regex.Compile(m_reExpr, flags); } @@ -153,28 +153,35 @@ void SearchThread::GetFiles(const SearchData* data, wxArrayString& files) { wxStopWatch sw; clDEBUG() << "Building list of files ..." << endl; - wxStringSet_t scannedFiles; + wxStringSet_t unique_files; const wxArrayString& rootDirs = data->GetRootDirs(); - files = data->GetFiles(); + const auto& non_filtered_files = data->GetFiles(); - // Populate "scannedFiles" with list of files to scan - scannedFiles.insert(files.begin(), files.end()); files.reserve(5000); + + // Populate "unique_files" with list of files to scan + // Filter files that do no match the pattern + clFileExtensionMatcher ext_matcher{ data->GetExtensions() }; + for (const auto& file : non_filtered_files) { + if (unique_files.insert(file).second && ext_matcher.matches(file)) { + files.Add(file); + } + } + clDEBUG() << "Scanning directories..." << endl; sw.Start(); - clFileExtensionMatcher ext_matcher{ data->GetExtensions() }; clPathExcluder path_excluder{ data->GetExcludePatterns() }; wxStringSet_t visited_dirs; - for(size_t i = 0; i < rootDirs.size(); ++i) { + for (size_t i = 0; i < rootDirs.size(); ++i) { clDEBUG() << " scanning root directory:" << rootDirs.Item(i) << endl; // collect only unique files that are matching the pattern auto on_files = [&](const wxArrayString& paths) { files.reserve(files.size() + paths.size()); - for(const wxString& fullpath : paths) { - if(scannedFiles.insert(fullpath).second && ext_matcher.matches(fullpath)) { + for (const wxString& fullpath : paths) { + if (unique_files.insert(fullpath).second && ext_matcher.matches(fullpath)) { files.Add(fullpath); } } @@ -212,7 +219,7 @@ void SearchThread::DoSearchFiles(ThreadRequest* req) SearchData* data = static_cast(req); // Get all files - if(data->GetFindString().IsEmpty()) { + if (data->GetFindString().IsEmpty()) { SendEvent(wxEVT_SEARCH_THREAD_SEARCHSTARTED, data->GetOwner()); return; } @@ -224,10 +231,10 @@ void SearchThread::DoSearchFiles(ThreadRequest* req) wxStopWatch sw; // Send startup message to main thread - if(m_notifiedWindow || data->GetOwner()) { + if (m_notifiedWindow || data->GetOwner()) { wxCommandEvent event(wxEVT_SEARCH_THREAD_SEARCHSTARTED, GetId()); event.SetClientData(new SearchData(*data)); - if(data->GetOwner()) { + if (data->GetOwner()) { ::wxPostEvent(data->GetOwner(), event); } else { // since we are in if ( m_notifiedWindow || data->GetOwner() ) block... @@ -235,11 +242,11 @@ void SearchThread::DoSearchFiles(ThreadRequest* req) } } - for(size_t i = 0; i < fileList.Count(); i++) { + for (size_t i = 0; i < fileList.Count(); i++) { m_summary.SetNumFileScanned((int)i + 1); // give user chance to cancel the search ... - if(TestStopSearch()) { + if (TestStopSearch()) { // Send cancel event SendEvent(wxEVT_SEARCH_THREAD_SEARCHCANCELED, data->GetOwner()); StopSearch(false); @@ -269,17 +276,17 @@ void SearchThread::DoSearchFile(const wxString& fileName, const SearchData* data { // Process single lines int lineNumber = 1; - if(!wxFileName::FileExists(fileName)) { + if (!wxFileName::FileExists(fileName)) { return; } // ignore binary executables - if(FileUtils::IsBinaryExecutable(fileName)) { + if (FileUtils::IsBinaryExecutable(fileName)) { return; } size_t size = FileUtils::GetFileSize(fileName); - if(size == 0) { + if (size == 0) { return; } wxString fileData; @@ -289,12 +296,12 @@ void SearchThread::DoSearchFile(const wxString& fileName, const SearchData* data // support for other encoding wxFontEncoding enc = wxFontMapper::GetEncodingFromName(data->GetEncoding().c_str()); wxCSConv fontEncConv(enc); - if(!FileUtils::ReadFileContent(fileName, fileData, fontEncConv)) { + if (!FileUtils::ReadFileContent(fileName, fileData, fontEncConv)) { m_summary.GetFailedFiles().Add(fileName); return; } #else - if(!FileUtils::ReadFileContent(fileName, fileData, wxConvLibc)) { + if (!FileUtils::ReadFileContent(fileName, fileData, wxConvLibc)) { m_summary.GetFailedFiles().Add(fileName); return; } @@ -302,9 +309,9 @@ void SearchThread::DoSearchFile(const wxString& fileName, const SearchData* data wxArrayString lines = ::wxStringTokenize(fileData, wxT("\n"), wxTOKEN_RET_EMPTY_ALL); int lineOffset = 0; - if(data->IsRegularExpression()) { + if (data->IsRegularExpression()) { // regular expression search - for(const wxString& line : lines) { + for (const wxString& line : lines) { // Read the next line DoSearchLineRE(line, lineNumber, lineOffset, fileName, data); lineOffset += line.Length() + 1; @@ -315,14 +322,14 @@ void SearchThread::DoSearchFile(const wxString& fileName, const SearchData* data wxString findString; wxArrayString filters; findString = data->GetFindString(); - if(data->IsEnablePipeSupport()) { - if(data->GetFindString().Find('|') != wxNOT_FOUND) { + if (data->IsEnablePipeSupport()) { + if (data->GetFindString().Find('|') != wxNOT_FOUND) { findString = data->GetFindString().BeforeFirst('|'); wxString filtersString = data->GetFindString().AfterFirst('|'); filters = ::wxStringTokenize(filtersString, "|", wxTOKEN_STRTOK); - if(!data->IsMatchCase()) { - for(size_t i = 0; i < filters.size(); ++i) { + if (!data->IsMatchCase()) { + for (size_t i = 0; i < filters.size(); ++i) { filters.Item(i).MakeLower(); } } @@ -330,35 +337,35 @@ void SearchThread::DoSearchFile(const wxString& fileName, const SearchData* data } // Dont search for empty strings - if(findString.empty()) { + if (findString.empty()) { return; } - if(!data->IsMatchCase()) { + if (!data->IsMatchCase()) { findString.MakeLower(); } - for(const wxString& line : lines) { + for (const wxString& line : lines) { DoSearchLine(line, lineNumber, lineOffset, fileName, data, findString, filters); lineOffset += line.Length() + 1; lineNumber++; } } - if(m_results.empty() == false) { + if (m_results.empty() == false) { SendEvent(wxEVT_SEARCH_THREAD_MATCHFOUND, data->GetOwner()); } } -void SearchThread::DoSearchLineRE(const wxString& line, const int lineNum, const int lineOffset, - const wxString& fileName, const SearchData* data) +void SearchThread::DoSearchLineRE( + const wxString& line, const int lineNum, const int lineOffset, const wxString& fileName, const SearchData* data) { wxRegEx& re = GetRegex(data->GetFindString(), data->IsMatchCase()); size_t col = 0; int iCorrectedCol = 0; int iCorrectedLen = 0; wxString modLine = line; - if(re.IsValid()) { - while(re.Matches(modLine)) { + if (re.IsValid()) { + while (re.Matches(modLine)) { size_t start, len; re.GetMatch(&start, &len); col += start; @@ -379,7 +386,7 @@ void SearchThread::DoSearchLineRE(const wxString& line, const int lineNum, const result.SetFlags(data->m_flags); result.SetFindWhat(data->GetFindString()); wxArrayString regexCaptures; - for(size_t i = 0; i < re.GetMatchCount(); ++i) { + for (size_t i = 0; i < re.GetMatchCount(); ++i) { regexCaptures.Add(re.GetMatch(modLine, i)); } result.SetRegexCaptures(regexCaptures); @@ -391,19 +398,24 @@ void SearchThread::DoSearchLineRE(const wxString& line, const int lineNum, const col += len; // adjust the line - if(line.Length() - col <= 0) + if (line.Length() - col <= 0) break; modLine = modLine.Right(line.Length() - col); } } } -void SearchThread::DoSearchLine(const wxString& line, const int lineNum, const int lineOffset, const wxString& fileName, - const SearchData* data, const wxString& findWhat, const wxArrayString& filters) +void SearchThread::DoSearchLine(const wxString& line, + const int lineNum, + const int lineOffset, + const wxString& fileName, + const SearchData* data, + const wxString& findWhat, + const wxArrayString& filters) { wxString modLine = line; - if(!data->IsMatchCase()) { + if (!data->IsMatchCase()) { modLine.MakeLower(); } @@ -411,30 +423,30 @@ void SearchThread::DoSearchLine(const wxString& line, const int lineNum, const i int col = 0; int iCorrectedCol = 0; int iCorrectedLen = 0; - while(pos != wxNOT_FOUND) { + while (pos != wxNOT_FOUND) { pos = modLine.Find(findWhat); - if(pos != wxNOT_FOUND) { + if (pos != wxNOT_FOUND) { col += pos; // Pipe support bool allFiltersOK = true; - if(!filters.IsEmpty()) { + if (!filters.IsEmpty()) { // Apply the filters - for(size_t i = 0; i < filters.size() && allFiltersOK; ++i) { + for (size_t i = 0; i < filters.size() && allFiltersOK; ++i) { allFiltersOK = (modLine.Find(filters.Item(i)) != wxNOT_FOUND); } } // Pipe filtes OK? - if(!allFiltersOK) + if (!allFiltersOK) return; // we have a match - if(data->IsMatchWholeWord()) { + if (data->IsMatchWholeWord()) { // make sure that the word before is not in the wordChars map - if(pos > 0 && is_word_char(modLine.GetChar(pos - 1))) { - if(!AdjustLine(modLine, pos, findWhat)) { + if (pos > 0 && is_word_char(modLine.GetChar(pos - 1))) { + if (!AdjustLine(modLine, pos, findWhat)) { break; } else { col += (int)findWhat.Length(); @@ -443,10 +455,10 @@ void SearchThread::DoSearchLine(const wxString& line, const int lineNum, const i } // if we have more characters to the right, make sure that the first char does not match any // in the wordCharsMap - if(pos + findWhat.Length() <= modLine.Length()) { + if (pos + findWhat.Length() <= modLine.Length()) { wxChar nextCh = modLine.GetChar(pos + findWhat.Length()); - if(is_word_char(nextCh)) { - if(!AdjustLine(modLine, pos, findWhat)) { + if (is_word_char(nextCh)) { + if (!AdjustLine(modLine, pos, findWhat)) { break; } else { col += (int)findWhat.Length(); @@ -476,7 +488,7 @@ void SearchThread::DoSearchLine(const wxString& line, const int lineNum, const i m_results.push_back(result); m_summary.SetNumMatchesFound(m_summary.GetNumMatchesFound() + 1); - if(!AdjustLine(modLine, pos, findWhat)) { + if (!AdjustLine(modLine, pos, findWhat)) { break; } col += (int)findWhat.Length(); @@ -487,7 +499,7 @@ void SearchThread::DoSearchLine(const wxString& line, const int lineNum, const i bool SearchThread::AdjustLine(wxString& line, int& pos, const wxString& findString) { // adjust the current line - if(line.Length() - (pos + findString.Length()) >= findString.Length()) { + if (line.Length() - (pos + findString.Length()) >= findString.Length()) { line = line.Right(line.Length() - (pos + findString.Length())); pos += (int)findString.Length(); return true; @@ -498,25 +510,25 @@ bool SearchThread::AdjustLine(wxString& line, int& pos, const wxString& findStri void SearchThread::SendEvent(wxEventType type, wxEvtHandler* owner) { - if(!m_notifiedWindow && !owner) + if (!m_notifiedWindow && !owner) return; wxCommandEvent event(type, GetId()); - if(type == wxEVT_SEARCH_THREAD_MATCHFOUND) { + if (type == wxEVT_SEARCH_THREAD_MATCHFOUND) { // match found and we scanned 10 files event.SetClientData(new SearchResultList(m_results)); m_results.clear(); SEND_ST_EVENT(); - } else if((type == wxEVT_SEARCH_THREAD_SEARCHEND) || (type == wxEVT_SEARCH_THREAD_SEARCHCANCELED)) { + } else if ((type == wxEVT_SEARCH_THREAD_SEARCHEND) || (type == wxEVT_SEARCH_THREAD_SEARCHCANCELED)) { // search eneded, if we got any matches "buffered" send them before the // the summary event - if(m_results.empty() == false) { + if (m_results.empty() == false) { wxCommandEvent evt(wxEVT_SEARCH_THREAD_MATCHFOUND, GetId()); evt.SetClientData(new SearchResultList(m_results)); - if(owner) { + if (owner) { wxPostEvent(owner, evt); - } else if(m_notifiedWindow) { + } else if (m_notifiedWindow) { wxPostEvent(m_notifiedWindow, evt); } } @@ -528,7 +540,7 @@ void SearchThread::SendEvent(wxEventType type, wxEvtHandler* owner) // to avoid flooding the UI with search events, sleep for 1ms after each // send_event call ++send_count; - if(send_count >= 10) { + if (send_count >= 10) { wxThread::Sleep(1); send_count = 0; } @@ -541,10 +553,10 @@ void SearchThread::FilterFiles(wxArrayString& files, const SearchData* data) const wxArrayString& excludePatterns = data->GetExcludePatterns(); const wxString& mask = data->GetExtensions(); std::for_each(files.begin(), files.end(), [&](const wxString& filename) { - if(uniqueFiles.count(filename)) + if (uniqueFiles.count(filename)) return; uniqueFiles.insert(filename); - if(FileUtils::WildMatch(mask, filename) && !FileUtils::WildMatch(excludePatterns, filename)) { + if (FileUtils::WildMatch(mask, filename) && !FileUtils::WildMatch(excludePatterns, filename)) { tmpFiles.Add(filename); } }); @@ -555,7 +567,7 @@ void SearchThread::FilterFiles(wxArrayString& files, const SearchData* data) static SearchThread* gs_SearchThread = NULL; void SearchThreadST::Free() { - if(gs_SearchThread) { + if (gs_SearchThread) { delete gs_SearchThread; } gs_SearchThread = NULL; @@ -563,7 +575,7 @@ void SearchThreadST::Free() SearchThread* SearchThreadST::Get() { - if(gs_SearchThread == NULL) + if (gs_SearchThread == NULL) gs_SearchThread = new SearchThread; return gs_SearchThread; } diff --git a/LiteEditor/findinfilesdlg.cpp b/LiteEditor/findinfilesdlg.cpp index 990f2abd56..f2868104f1 100644 --- a/LiteEditor/findinfilesdlg.cpp +++ b/LiteEditor/findinfilesdlg.cpp @@ -239,7 +239,7 @@ SearchData FindInFilesDialog::DoGetSearchData() } data.SetFileScannerFlags(search_flags); - // for persisntency + // for persistence m_data.files_scanner_flags = search_flags; wxArrayString searchWhere = GetPathsAsArray(); @@ -538,8 +538,9 @@ void FindInFilesDialog::DoAddProjectFiles(const wxString& projectName, wxArraySt if (!filesMap.empty()) { wxArrayString tmpArr; tmpArr.Alloc(filesMap.size()); - std::for_each(filesMap.begin(), filesMap.end(), - [&](const Project::FilesMap_t::value_type& vt) { tmpArr.Add(vt.second->GetFilename()); }); + std::for_each(filesMap.begin(), filesMap.end(), [&](const Project::FilesMap_t::value_type& vt) { + tmpArr.Add(vt.second->GetFilename()); + }); files.insert(files.end(), tmpArr.begin(), tmpArr.end()); } }