Skip to content
This repository has been archived by the owner on Oct 16, 2020. It is now read-only.

Commit

Permalink
implement XamlSymbolSearch
Browse files Browse the repository at this point in the history
  • Loading branch information
siegfriedpammer committed Mar 23, 2012
1 parent a45a631 commit bd32925
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 13 deletions.
Expand Up @@ -186,9 +186,7 @@ public override ItemType GetDefaultItemType(string fileName)

public override ISymbolSearch PrepareSymbolSearch(IEntity entity)
{
// TODO implement CompositeSymbolSearch to allow multiple instances to be returned, e.g., XamlSymbolSearch, etc.
// return CompositeSymbolSearch.Create(new XamlSymbolSearch(...), base.PrepareSymbolSearch(...))
return new CSharpSymbolSearch(Project, entity);
return CompositeSymbolSearch.Create(new CSharpSymbolSearch(Project, entity), base.PrepareSymbolSearch(entity));
}
}
}
Expand Up @@ -32,7 +32,7 @@ public override ItemType GetDefaultItemType(string fileName)

public override ISymbolSearch PrepareSymbolSearch(IEntity entity)
{
return new XamlSymbolSearch(entity);
return CompositeSymbolSearch.Create(new XamlSymbolSearch(Project, entity), base.PrepareSymbolSearch(entity));
}
}

Expand Down
Expand Up @@ -13,9 +13,8 @@
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<SourceAnalysisOverrideSettingsFile>C:\Users\Daniel\AppData\Roaming\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis</SourceAnalysisOverrideSettingsFile>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
Expand Down
Expand Up @@ -2,9 +2,20 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Editor.Search;
using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Refactoring;

namespace ICSharpCode.XamlBinding
Expand All @@ -14,19 +25,88 @@ namespace ICSharpCode.XamlBinding
/// </summary>
public class XamlSymbolSearch : ISymbolSearch
{
public XamlSymbolSearch(IEntity entity)
IProject project;
ICompilation compilation;
IEntity entity;
List<FileName> interestingFileNames;
int workAmount;
double workAmountInverse;

public XamlSymbolSearch(IProject project, IEntity entity)
{
this.entity = entity;
compilation = ParserService.GetCompilation(project);
interestingFileNames = new List<FileName>();
foreach (var item in project.ParentSolution.SolutionFolderContainers.Select(f => f.SolutionItems).SelectMany(si => si.Items).Where(i => ".xaml".Equals(Path.GetExtension(i.Location), StringComparison.OrdinalIgnoreCase)))
interestingFileNames.Add(new FileName(Path.Combine(project.ParentSolution.Directory, item.Location)));
foreach (var item in project.ParentSolution.Projects.SelectMany(p => p.Items).OfType<FileProjectItem>().Where(i => ".xaml".Equals(Path.GetExtension(i.FileName), StringComparison.OrdinalIgnoreCase)))
interestingFileNames.Add(new FileName(item.FileName));
workAmount = interestingFileNames.Count;
workAmountInverse = 1.0 / workAmount;
}

public double WorkAmount {
get {
throw new NotImplementedException();
}
get { return workAmount; }
}

public Task FindReferencesAsync(SymbolSearchArgs searchArguments, Action<SearchedFile> callback)
{
throw new NotImplementedException();
if (callback == null)
throw new ArgumentNullException("callback");
var cancellationToken = searchArguments.ProgressMonitor.CancellationToken;
return Task.Run(
() => {
object progressLock = new object();
Parallel.ForEach(
interestingFileNames,
new ParallelOptions {
MaxDegreeOfParallelism = Environment.ProcessorCount,
CancellationToken = cancellationToken
},
delegate (FileName fileName) {
FindReferencesInFile(searchArguments, entity, fileName, callback, cancellationToken);
lock (progressLock)
searchArguments.ProgressMonitor.Progress += workAmountInverse;
});
}, cancellationToken
);
}

void FindReferencesInFile(SymbolSearchArgs searchArguments, IEntity entity, FileName fileName, Action<SearchedFile> callback, CancellationToken cancellationToken)
{
ITextSource textSource = searchArguments.ParseableFileContentFinder.Create(fileName);
if (textSource == null)
return;
int offset = textSource.IndexOf(entity.Name, 0, textSource.TextLength, StringComparison.Ordinal);
if (offset < 0)
return;

var parseInfo = ParserService.Parse(fileName, textSource) as XamlFullParseInformation;
if (parseInfo == null)
return;
ReadOnlyDocument document = null;
DocumentHighlighter highlighter = null;
List<Reference> results = new List<Reference>();
XamlResolver resolver = new XamlResolver();
do {
if (document == null) {
document = new ReadOnlyDocument(textSource);
var highlighting = HighlightingManager.Instance.GetDefinitionByExtension(Path.GetExtension(fileName));
if (highlighting != null)
highlighter = new DocumentHighlighter(document, highlighting.MainRuleSet);
else
highlighter = null;
}
var result = resolver.Resolve(parseInfo, document.GetLocation(offset + entity.Name.Length / 2 + 1), compilation, cancellationToken);
int length = entity.Name.Length;
if ((result is TypeResolveResult && ((TypeResolveResult)result).Type.Equals(entity)) || (result is MemberResolveResult && ((MemberResolveResult)result).Member.Equals(entity))) {
var region = new DomRegion(fileName, document.GetLocation(offset), document.GetLocation(offset + length));
var builder = SearchResultsPad.CreateInlineBuilder(region.Begin, region.End, document, highlighter);
results.Add(new Reference(region, result, offset, length, builder));
}
offset = textSource.IndexOf(entity.Name, offset + length, textSource.TextLength - offset - length, StringComparison.OrdinalIgnoreCase);
} while (offset > 0);
callback(new SearchedFile(fileName, results));
}
}
}
Expand Up @@ -68,13 +68,15 @@ void IObserver<SearchedFile>.OnNext(SearchedFile value)

void IObserver<SearchedFile>.OnError(Exception error)
{
if (error == null)
throw new ArgumentNullException("error");
// flatten AggregateException and
// filter OperationCanceledException
try {
if (error is AggregateException)
((AggregateException)error).Flatten().Handle(ex => ex is OperationCanceledException);
else if (!(error is OperationCanceledException))
throw error;
MessageService.ShowException(error);
} catch (Exception ex) {
MessageService.ShowException(ex);
}
Expand Down
Expand Up @@ -232,4 +232,32 @@ public interface ISymbolSearch

Task FindReferencesAsync(SymbolSearchArgs searchArguments, Action<SearchedFile> callback);
}

public sealed class CompositeSymbolSearch : ISymbolSearch
{
IEnumerable<ISymbolSearch> symbolSearches;

CompositeSymbolSearch(params ISymbolSearch[] symbolSearches)
{
this.symbolSearches = symbolSearches;
}

public static ISymbolSearch Create(ISymbolSearch symbolSearch1, ISymbolSearch symbolSearch2)
{
if (symbolSearch1 == null)
return symbolSearch2;
if (symbolSearch2 == null)
return symbolSearch1;
return new CompositeSymbolSearch(symbolSearch1, symbolSearch2);
}

public double WorkAmount {
get { return symbolSearches.Sum(s => s.WorkAmount); }
}

public Task FindReferencesAsync(SymbolSearchArgs searchArguments, Action<SearchedFile> callback)
{
return Task.WhenAll(symbolSearches.Select(s => s.FindReferencesAsync(searchArguments, callback)));
}
}
}

0 comments on commit bd32925

Please sign in to comment.