Browse Source

rewrote Find Next algorithm

pull/23/head
Siegfried Pammer 14 years ago
parent
commit
0f29a06847
  1. 2
      SharpDevelop.sln
  2. 161
      src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchManager.cs

2
SharpDevelop.sln

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
# SharpDevelop 4.2.0.7998-alpha
# SharpDevelop 4.1.0.8000
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Main", "Main", "{256F5C28-532C-44C0-8AB8-D8EC5E492E01}"
ProjectSection(SolutionItems) = postProject
EndProjectSection

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

@ -125,13 +125,17 @@ namespace SearchAndReplace @@ -125,13 +125,17 @@ namespace SearchAndReplace
this.fileList = fileList;
this.monitor = monitor;
this.cts = cts;
this.count = fileList.Count();
}
public IDisposable Subscribe(IObserver<SearchResultMatch> observer)
{
this.observer = observer;
var task = new System.Threading.Tasks.Task(delegate { Parallel.ForEach(fileList, new ParallelOptions { CancellationToken = monitor.CancellationToken, MaxDegreeOfParallelism = Environment.ProcessorCount }, fileName => SearchFile(fileName, strategy, monitor.CancellationToken)); });
var task = new System.Threading.Tasks.Task(
delegate {
var list = fileList.ToList();
this.count = list.Count;
Parallel.ForEach(fileList, 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();
return this;
@ -139,8 +143,7 @@ namespace SearchAndReplace @@ -139,8 +143,7 @@ namespace SearchAndReplace
public void Dispose()
{
if (!cts.IsCancellationRequested)
cts.Cancel();
cts.Cancel();
monitor.Dispose();
}
@ -150,7 +153,7 @@ namespace SearchAndReplace @@ -150,7 +153,7 @@ namespace SearchAndReplace
if (buffer == null)
return;
if (!MimeTypeDetection.FindMimeType(buffer).StartsWith("text/"))
if (!MimeTypeDetection.FindMimeType(buffer).StartsWith("text/", StringComparison.Ordinal))
return;
var source = DocumentUtilitites.GetTextSource(buffer);
TextDocument document = null;
@ -191,6 +194,8 @@ namespace SearchAndReplace @@ -191,6 +194,8 @@ namespace SearchAndReplace
if (string.IsNullOrEmpty(pattern))
return null;
var files = GenerateFileList(target, baseDirectory, filter, searchSubdirs).ToArray();
if (files.Length == 0)
return null;
if (currentSearchRegion == null || !currentSearchRegion.IsSameState(files, pattern, ignoreCase, matchWholeWords, mode,
target, baseDirectory, filter, searchSubdirs))
currentSearchRegion = SearchRegion.CreateSearchRegion(files, pattern, ignoreCase, matchWholeWords, mode,
@ -209,81 +214,97 @@ namespace SearchAndReplace @@ -209,81 +214,97 @@ namespace SearchAndReplace
AnchorSegment selection;
PermanentAnchor searchStart;
ISearchStrategy strategy;
IEnumerator<SearchResultMatch> enumerator;
ParseableFileContentFinder finder = new ParseableFileContentFinder();
bool reachedEnd;
public SearchResultMatch FindNext()
{
if (enumerator == null)
enumerator = RunSearch();
if (enumerator.MoveNext())
return enumerator.Current;
// Setup search inside current or first file.
ParseableFileContentFinder finder = new ParseableFileContentFinder();
int index = GetCurrentFileIndex();
int startIndex = index;
int i = 0;
int searchOffset = 0;
return null;
}
IEnumerator<SearchResultMatch> RunSearch()
{
int startIndex = files.FindIndex(file => file.Equals(searchStart.FileName));
int endIndex = files.Length - 1;
int index = startIndex;
bool processSecondPart = false;
FileName file = files[index];
ITextBuffer buffer = finder.Create(file);
SearchResultMatch result = null;
TextDocument document = null;
while (index <= endIndex) {
FileName file = files[index];
ITextBuffer buffer = finder.Create(file);
if (buffer == null) {
processSecondPart = false;
index++;
continue;
// always use the caret position except if there is no editor open,
// or we are in the first file and have passed the end of the file (reachedEnd == true).
var editor = GetActiveTextEditor();
if (editor != null)
searchOffset = editor.Caret.Offset;
// if the file could be opened, search in it.
if (buffer != null) {
document = new TextDocument(DocumentUtilitites.GetTextSource(buffer));
int length;
// if (target == SearchTarget.CurrentSelection) selection will be not null
// hence use the selection as search region.
if (selection != null) {
searchOffset = Math.Max(selection.Offset, searchOffset);
length = selection.EndOffset - searchOffset;
} else {
length = buffer.TextLength - searchOffset;
}
var document = new TextDocument(DocumentUtilitites.GetTextSource(buffer));
ICSharpCode.AvalonEdit.Search.ISearchResult result;
var editor = GetActiveTextEditor();
int searchOffset = 0;
// try to find a result
if (length > 0 && (searchOffset + length) <= buffer.TextLength)
result = Find(buffer, file, document, searchOffset, length);
if (!processSecondPart && file.Equals(searchStart.FileName))
searchOffset = searchStart.Offset;
if (editor != null && files.Equals(editor.FileName))
searchOffset = editor.Caret.Offset;
// we already passed the end of the file before and have found the first match again, so just stop.
if (reachedEnd) {
if (file.Equals(searchStart.FileName) && result != null && document.GetOffset(result.StartLocation.ToTextLocation()) >= searchStart.Offset)
return null;
} else
reachedEnd = file.Equals(searchStart.FileName) && result == null;
}
// try the other files until we find something, or have processed all of them
while ((buffer == null || result == null) && i < files.Length) {
index = (index + 1) % files.Length;
do {
int length;
if (selection != null && file.Equals(searchStart.FileName)) {
searchOffset = Math.Max(selection.Offset, searchOffset);
length = selection.EndOffset - searchOffset;
} else {
length = buffer.TextLength - searchOffset;
}
if (length > 0 && (searchOffset + length) <= buffer.TextLength)
result = strategy.FindNext(DocumentUtilitites.GetTextSource(buffer), searchOffset, length);
else
result = null;
if (result != null)
searchOffset = result.EndOffset;
if (processSecondPart && file.Equals(searchStart.FileName) && searchOffset >= searchStart.Offset) {
yield break;
}
if (result != null) {
var start = document.GetLocation(result.Offset).ToLocation();
var end = document.GetLocation(result.EndOffset).ToLocation();
yield return new SearchResultMatch(file, start, end, null);
}
} while (result != null);
file = files[index];
buffer = finder.Create(file);
index++;
if (!processSecondPart && index > endIndex) {
processSecondPart = true;
index = 0;
endIndex = startIndex;
}
if (buffer == null)
continue;
document = new TextDocument(DocumentUtilitites.GetTextSource(buffer));
searchOffset = 0;
int length = buffer.TextLength - searchOffset;
// try to find a result
result = Find(buffer, file, document, searchOffset, length);
// if we have not found anything and are at the start of the file, we started with, just stop
if (result != null && reachedEnd && file.Equals(searchStart.FileName)
&& document.GetOffset(result.StartLocation.ToTextLocation()) >= searchStart.Offset)
return null;
i++;
}
return result;
}
SearchResultMatch Find(ITextBuffer buffer, FileName file, TextDocument document, int searchOffset, int length)
{
var result = strategy.FindNext(DocumentUtilitites.GetTextSource(buffer), searchOffset, length);
if (result != null) {
var start = document.GetLocation(result.Offset).ToLocation();
var end = document.GetLocation(result.EndOffset).ToLocation();
return new SearchResultMatch(file, start, end, null);
}
return null;
}
int GetCurrentFileIndex()
{
var editor = GetActiveTextEditor();
if (editor == null)
return 0;
return files.FindIndex(file => editor.FileName.Equals(file));
}
public static SearchRegion CreateSearchRegion(FileName[] files, string pattern, bool ignoreCase, bool matchWholeWords, SearchMode mode, SearchTarget target, string baseDirectory, string filter, bool searchSubdirs)
@ -404,7 +425,7 @@ namespace SearchAndReplace @@ -404,7 +425,7 @@ namespace SearchAndReplace
void IObserver<SearchResultMatch>.OnNext(SearchResultMatch value)
{
Interlocked.Increment(ref count);
WorkbenchSingleton.SafeThreadCall((Action)delegate { MarkResult(value, false); });
WorkbenchSingleton.SafeThreadAsyncCall((Action)delegate { MarkResult(value, false); });
}
void IObserver<SearchResultMatch>.OnError(Exception error)

Loading…
Cancel
Save