Permalink
Browse files

implement XamlSymbolSearch

  • Loading branch information...
1 parent a45a631 commit bd32925e074b926986bf47706c9ef73a2e905d3e @siegfriedpammer siegfriedpammer committed Mar 22, 2012
@@ -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));
}
}
}
@@ -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));
}
}
@@ -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>
@@ -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
@@ -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));
}
}
}
@@ -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);
}
@@ -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.