Browse Source

fixing some bugs and playing around with cancellation

pull/23/head
Siegfried Pammer 14 years ago
parent
commit
1570138319
  1. 6
      src/AddIns/Misc/SearchAndReplace/Project/Engine/Enums.cs
  2. 56
      src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchManager.cs
  3. 16
      src/AddIns/Misc/SearchAndReplace/Project/Gui/DefaultSearchResult.cs
  4. 95
      src/AddIns/Misc/SearchAndReplace/Project/Gui/SearchAndReplacePanel.cs
  5. 5
      src/AddIns/Misc/SearchAndReplace/Project/SearchAndReplace.csproj
  6. 3
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/RegexSearchStrategy.cs
  7. 1
      src/Main/Base/Project/Src/Editor/Search/ISearchResultFactory.cs
  8. 2
      src/Main/Base/Project/Src/Editor/Search/SearchResultsPad.cs
  9. 2
      src/Main/Core/Project/Src/Services/FileUtility/FileUtility.cs

6
src/AddIns/Misc/SearchAndReplace/Project/Engine/Enums.cs

@ -2,15 +2,21 @@ @@ -2,15 +2,21 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.ComponentModel;
namespace SearchAndReplace
{
public enum SearchTarget
{
[Description("${res:Dialog.NewProject.SearchReplace.LookIn.CurrentDocument}")]
CurrentDocument,
[Description("${res:Dialog.NewProject.SearchReplace.LookIn.CurrentSelection}")]
CurrentSelection,
[Description("${res:Dialog.NewProject.SearchReplace.LookIn.AllOpenDocuments}")]
AllOpenFiles,
[Description("${res:Dialog.NewProject.SearchReplace.LookIn.WholeProject}")]
WholeProject,
[Description("${res:Dialog.NewProject.SearchReplace.LookIn.WholeSolution}")]
WholeSolution,
Directory
}

56
src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchManager.cs

@ -7,8 +7,8 @@ using System.IO; @@ -7,8 +7,8 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit.Search;
using ICSharpCode.Core;
@ -74,38 +74,14 @@ namespace SearchAndReplace @@ -74,38 +74,14 @@ namespace SearchAndReplace
SearchResultsPad.Instance.BringToFront();
}
public static IObservable<SearchResultMatch> FindAll(string pattern, bool ignoreCase, bool matchWholeWords, SearchMode mode,
SearchTarget target, string baseDirectory = null, string filter = "*.*", bool searchSubdirs = false, bool useParallel = true, IProgressMonitor progressMonitor = null)
public static IObservable<SearchResultMatch> FindAll(IProgressMonitor progressMonitor, string pattern, bool ignoreCase, bool matchWholeWords, SearchMode mode,
SearchTarget target, string baseDirectory = null, string filter = "*.*", bool searchSubdirs = false, ISegment selection = null, bool useParallel = true)
{
currentSearchRegion = null;
CancellationToken ct = progressMonitor != null ? progressMonitor.CancellationToken : new CancellationTokenSource().Token;
var monitor = progressMonitor ?? WorkbenchSingleton.Workbench.StatusBar.CreateProgressMonitor(ct);
monitor.TaskName = "Find all occurrences of '" + pattern + "' in " + GetTargetDescription(target, baseDirectory);
monitor.Status = OperationStatus.Normal;
var strategy = SearchStrategyFactory.Create(pattern, ignoreCase, matchWholeWords, mode);
ParseableFileContentFinder fileFinder = new ParseableFileContentFinder();
IEnumerable<FileName> fileList = GenerateFileList(target, baseDirectory, filter, searchSubdirs);
return new SearchRun(strategy, fileFinder, fileList, monitor);
}
static string GetTargetDescription(SearchTarget target, string baseDirectory = null)
{
switch (target) {
case SearchTarget.CurrentDocument:
return "the current document";
case SearchTarget.CurrentSelection:
return "the current selection";
case SearchTarget.AllOpenFiles:
return "all open files";
case SearchTarget.WholeProject:
return "the whole project";
case SearchTarget.WholeSolution:
return "the whole solution";
case SearchTarget.Directory:
return "the directory '" + baseDirectory + "'";
default:
throw new Exception("Invalid value for SearchTarget");
}
return new SearchRun(strategy, fileFinder, fileList, progressMonitor) { UseParallel = useParallel, Target = target, Selection = selection };
}
class SearchRun : IObservable<SearchResultMatch>, IDisposable
@ -116,15 +92,21 @@ namespace SearchAndReplace @@ -116,15 +92,21 @@ namespace SearchAndReplace
IEnumerable<FileName> fileList;
IProgressMonitor monitor;
int count;
CancellationTokenSource cts;
public bool UseParallel { get; set; }
public SearchTarget Target { get; set; }
public ISegment Selection { get; set; }
public SearchRun(ISearchStrategy strategy, ParseableFileContentFinder fileFinder, IEnumerable<FileName> fileList, IProgressMonitor monitor)
{
this.strategy = strategy;
this.fileFinder = fileFinder;
this.fileList = fileList;
this.monitor = monitor;
this.cts = new CancellationTokenSource();
}
public IDisposable Subscribe(IObserver<SearchResultMatch> observer)
@ -135,12 +117,18 @@ namespace SearchAndReplace @@ -135,12 +117,18 @@ namespace SearchAndReplace
delegate {
var list = fileList.ToList();
this.count = list.Count;
monitor.CancellationToken.ThrowIfCancellationRequested();
cts.Token.ThrowIfCancellationRequested();
Parallel.ForEach(list, new ParallelOptions { CancellationToken = monitor.CancellationToken, MaxDegreeOfParallelism = Environment.ProcessorCount }, fileName => SearchFile(fileName, strategy, monitor.CancellationToken));
});
task.ContinueWith(t => { if (t.Exception != null) observer.OnError(t.Exception); else observer.OnCompleted(); this.Dispose(); });
task.Start();
} else {
foreach (var file in fileList) {
var list = fileList.ToList();
this.count = list.Count;
monitor.CancellationToken.ThrowIfCancellationRequested();
cts.Token.ThrowIfCancellationRequested();
foreach (var file in list) {
SearchFile(file, strategy, monitor.CancellationToken);
}
}
@ -149,6 +137,7 @@ namespace SearchAndReplace @@ -149,6 +137,7 @@ namespace SearchAndReplace
public void Dispose()
{
cts.Cancel();
monitor.Dispose();
}
@ -163,8 +152,15 @@ namespace SearchAndReplace @@ -163,8 +152,15 @@ namespace SearchAndReplace
var source = DocumentUtilitites.GetTextSource(buffer);
TextDocument document = null;
DocumentHighlighter highlighter = null;
foreach(var result in strategy.FindAll(source, 0, source.TextLength)) {
int offset = 0;
int length = source.TextLength;
if (Target == SearchTarget.CurrentSelection && Selection != null) {
offset = Selection.Offset;
length = Selection.Length;
}
foreach(var result in strategy.FindAll(source, offset, length)) {
ct.ThrowIfCancellationRequested();
cts.Token.ThrowIfCancellationRequested();
if (document == null) {
document = new TextDocument(source);
var highlighting = HighlightingManager.Instance.GetDefinitionByExtension(Path.GetExtension(fileName));

16
src/AddIns/Misc/SearchAndReplace/Project/Gui/DefaultSearchResult.cs

@ -5,6 +5,7 @@ using System; @@ -5,6 +5,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
@ -13,6 +14,7 @@ using ICSharpCode.Core.Presentation; @@ -13,6 +14,7 @@ using ICSharpCode.Core.Presentation;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor.Search;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Widgets.Resources;
namespace SearchAndReplace
{
@ -192,15 +194,19 @@ namespace SearchAndReplace @@ -192,15 +194,19 @@ namespace SearchAndReplace
collapseAll.Click += delegate { ExpandCollapseAll(false); };
toolbarItems.Add(collapseAll);
stopButton = new Button { Content = "Stop" };
stopButton.Click += delegate {
stopButton.Visibility = Visibility.Collapsed;
if (Registration != null) Registration.Dispose();
};
stopButton = new Button { Content = new Image { Height = 16, Source = PresentationResourceService.GetBitmapSource("Icons.16x16.Debug.StopProcess") } };
stopButton.Click += StopButtonClick;
toolbarItems.Add(stopButton);
}
stopButton.Visibility = Visibility.Visible;
return toolbarItems;
}
void StopButtonClick(object sender, RoutedEventArgs e)
{
stopButton.Visibility = Visibility.Hidden;
if (Registration != null) Registration.Dispose();
}
static void ExpandCollapseAll(bool newIsExpanded)
{

95
src/AddIns/Misc/SearchAndReplace/Project/Gui/SearchAndReplacePanel.cs

@ -1,6 +1,11 @@ @@ -1,6 +1,11 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System.ComponentModel;
using System.Linq;
using System.Threading;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.AvalonEdit.Search;
using ICSharpCode.SharpDevelop.Editor;
using System;
@ -14,32 +19,11 @@ using ICSharpCode.SharpDevelop.Gui.XmlForms; @@ -14,32 +19,11 @@ using ICSharpCode.SharpDevelop.Gui.XmlForms;
namespace SearchAndReplace
{
class StoredSelection
{
public readonly int Offset, Length;
public int EndOffset {
get { return Offset + Length; }
}
public bool IsTextSelected {
get { return Length > 0; }
}
public StoredSelection(int offset, int length)
{
this.Offset = offset;
this.Length = length;
}
}
public class SearchAndReplacePanel : BaseSharpDevelopUserControl
{
SearchAndReplaceMode searchAndReplaceMode;
StoredSelection selection;
SearchAndReplaceMode searchAndReplaceMode;
ITextEditor textEditor;
bool ignoreSelectionChanges;
bool findFirst;
ISegment selection;
public SearchAndReplaceMode SearchAndReplaceMode {
get {
@ -119,24 +103,30 @@ namespace SearchAndReplace @@ -119,24 +103,30 @@ namespace SearchAndReplace
void FindAllButtonClicked(object sender, EventArgs e)
{
WritebackOptions();
var results = SearchManager.FindAll(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchStrategyType, SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories);
var monitor = WorkbenchSingleton.StatusBar.CreateProgressMonitor();
monitor.TaskName = "Searching ...";
var results = SearchManager.FindAll(monitor, SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchStrategyType, SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories, selection);
SearchManager.ShowSearchResults(SearchOptions.FindPattern, results);
}
void BookmarkAllButtonClicked(object sender, EventArgs e)
{
WritebackOptions();
var results = SearchManager.FindAll(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchStrategyType, SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories);
var monitor = WorkbenchSingleton.StatusBar.CreateProgressMonitor();
monitor.TaskName = "Searching ...";
var results = SearchManager.FindAll(monitor, SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchStrategyType, SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories);
SearchManager.MarkAll(results);
}
void ReplaceAllButtonClicked(object sender, EventArgs e)
{
WritebackOptions();
using (AsynchronousWaitDialog monitor = AsynchronousWaitDialog.ShowWaitDialog("Search", true)) {
var results = SearchManager.FindAll(SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchStrategyType, SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories, false, monitor);
SearchManager.ReplaceAll(results, SearchOptions.ReplacePattern, monitor.CancellationToken);
}
AsynchronousWaitDialog.RunInCancellableWaitDialog(
"Searching ...", "replaceall",
monitor => {
var results = SearchManager.FindAll(monitor, SearchOptions.FindPattern, !SearchOptions.MatchCase, SearchOptions.MatchWholeWord, SearchOptions.SearchStrategyType, SearchOptions.SearchTarget, SearchOptions.LookIn, SearchOptions.LookInFiletypes, SearchOptions.IncludeSubdirectories, selection, false);
SearchManager.ReplaceAll(results, SearchOptions.ReplacePattern, monitor.CancellationToken);
});
}
void ReplaceButtonClicked(object sender, EventArgs e)
@ -195,15 +185,7 @@ namespace SearchAndReplace @@ -195,15 +185,7 @@ namespace SearchAndReplace
}
Get<ComboBox>("lookIn").Text = SearchOptions.LookIn;
string[] lookInTexts = {
// must be in the same order as the DocumentIteratorType enum
"${res:Dialog.NewProject.SearchReplace.LookIn.CurrentDocument}",
"${res:Dialog.NewProject.SearchReplace.LookIn.CurrentSelection}",
"${res:Dialog.NewProject.SearchReplace.LookIn.AllOpenDocuments}",
"${res:Dialog.NewProject.SearchReplace.LookIn.WholeProject}",
"${res:Dialog.NewProject.SearchReplace.LookIn.WholeSolution}"
};
foreach (string lookInText in lookInTexts) {
foreach (string lookInText in typeof(SearchTarget).GetFields().SelectMany(f => f.GetCustomAttributes(false).OfType<DescriptionAttribute>()).Select(da => da.Description)) {
Get<ComboBox>("lookIn").Items.Add(StringParser.Parse(lookInText));
}
Get<ComboBox>("lookIn").Items.Add(SearchOptions.LookIn);
@ -280,11 +262,11 @@ namespace SearchAndReplace @@ -280,11 +262,11 @@ namespace SearchAndReplace
/// <summary>
/// Returns the first ISelection object from the currently active text editor
/// </summary>
static StoredSelection GetCurrentTextSelection()
static ISegment GetCurrentTextSelection()
{
ITextEditor textArea = SearchManager.GetActiveTextEditor();
if (textArea != null) {
return new StoredSelection(textArea.SelectionStart, textArea.SelectionLength);
return new TextSegment { StartOffset = textArea.SelectionStart, Length = textArea.SelectionLength };
}
return null;
}
@ -329,16 +311,12 @@ namespace SearchAndReplace @@ -329,16 +311,12 @@ namespace SearchAndReplace
/// changed.</remarks>
void TextSelectionChanged(object source, EventArgs e)
{
if (!ignoreSelectionChanges) {
LoggingService.Debug("TextSelectionChanged.");
selection = GetCurrentTextSelection();
findFirst = true;
}
LoggingService.Debug("TextSelectionChanged.");
selection = GetCurrentTextSelection();
}
void InitSelectionSearch()
{
findFirst = true;
selection = GetCurrentTextSelection();
AddSelectionChangedHandler(SearchManager.GetActiveTextEditor());
WorkbenchSingleton.Workbench.ActiveViewContentChanged += WorkbenchActiveViewContentChanged;
@ -350,31 +328,6 @@ namespace SearchAndReplace @@ -350,31 +328,6 @@ namespace SearchAndReplace
RemoveActiveWindowChangedHandler();
}
void ReplaceInSelection()
{
int startOffset = Math.Min(selection.Offset, selection.EndOffset);
int endOffset = Math.Max(selection.Offset, selection.EndOffset);
if (findFirst) {
textEditor.Caret.Offset = startOffset;
}
try {
ignoreSelectionChanges = true;
if (findFirst) {
findFirst = false;
// SearchReplaceManager.ReplaceFirstInSelection(startOffset, endOffset - startOffset, null);
} else {
// findFirst = !SearchReplaceManager.ReplaceNextInSelection(null);
if (findFirst) {
textEditor.Select(startOffset, endOffset - startOffset);
}
}
} finally {
ignoreSelectionChanges = false;
}
}
/// <summary>
/// Enables the various find, bookmark and replace buttons
/// depending on whether any find string has been entered. The buttons

5
src/AddIns/Misc/SearchAndReplace/Project/SearchAndReplace.csproj

@ -126,5 +126,10 @@ @@ -126,5 +126,10 @@
</ProjectReference>
<Page Include="Gui\ResultsTreeView.xaml">
</Page>
<ProjectReference Include="..\..\..\..\Main\ICSharpCode.SharpDevelop.Widgets\Project\ICSharpCode.SharpDevelop.Widgets.csproj">
<Project>{8035765F-D51F-4A0C-A746-2FD100E19419}</Project>
<Name>ICSharpCode.SharpDevelop.Widgets</Name>
<Private>False</Private>
</ProjectReference>
</ItemGroup>
</Project>

3
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Search/RegexSearchStrategy.cs

@ -22,8 +22,9 @@ namespace ICSharpCode.AvalonEdit.Search @@ -22,8 +22,9 @@ namespace ICSharpCode.AvalonEdit.Search
public IEnumerable<ISearchResult> FindAll(ITextSource document, int offset, int length)
{
int endOffset = offset + length;
foreach (Match result in searchPattern.Matches(document.Text)) {
if (offset <= result.Index && (offset + length) >= (result.Index + result.Length))
if (offset <= result.Index && endOffset >= (result.Length + result.Index))
yield return new SearchResult { StartOffset = result.Index, Length = result.Length, Data = result };
}
}

1
src/Main/Base/Project/Src/Editor/Search/ISearchResultFactory.cs

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Threading;
namespace ICSharpCode.SharpDevelop.Editor.Search
{

2
src/Main/Base/Project/Src/Editor/Search/SearchResultsPad.cs

@ -4,9 +4,11 @@ @@ -4,9 +4,11 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.Core;

2
src/Main/Core/Project/Src/Services/FileUtility/FileUtility.cs

@ -361,7 +361,7 @@ namespace ICSharpCode.Core @@ -361,7 +361,7 @@ namespace ICSharpCode.Core
dir = dir.Flatten(
d => {
try {
if (ignoreHidden && (File.GetAttributes(d) & FileAttributes.Hidden) == FileAttributes.Hidden)
if (Directory.GetDirectoryRoot(d) != d && ignoreHidden && (File.GetAttributes(d) & FileAttributes.Hidden) == FileAttributes.Hidden)
return empty;
return Directory.EnumerateDirectories(d);
} catch (UnauthorizedAccessException) {

Loading…
Cancel
Save