diff --git a/ICSharpCode.Editor/TextChangeEventArgs.cs b/ICSharpCode.Editor/TextChangeEventArgs.cs
index cacf70aa09..a0320ace03 100644
--- a/ICSharpCode.Editor/TextChangeEventArgs.cs
+++ b/ICSharpCode.Editor/TextChangeEventArgs.cs
@@ -39,7 +39,7 @@ namespace ICSharpCode.Editor
}
///
- /// The text that was inserted.
+ /// The text that was removed.
///
public string RemovedText {
get { return removedText; }
diff --git a/ICSharpCode.NRefactory.Demo/CSDemo.cs b/ICSharpCode.NRefactory.Demo/CSDemo.cs
index ded7aeac74..a65040678a 100644
--- a/ICSharpCode.NRefactory.Demo/CSDemo.cs
+++ b/ICSharpCode.NRefactory.Demo/CSDemo.cs
@@ -282,10 +282,12 @@ namespace ICSharpCode.NRefactory.Demo
FindReferences fr = new FindReferences();
int referenceCount = 0;
- fr.ReferenceFound += delegate { referenceCount++; };
+ FoundReferenceCallback callback = delegate(AstNode matchNode, ResolveResult result) {
+ referenceCount++;
+ };
var searchScopes = fr.GetSearchScopes(entity);
- navigator = new CompositeResolveVisitorNavigator(searchScopes.ToArray());
+ navigator = new CompositeResolveVisitorNavigator(searchScopes.Select(s => s.GetNavigator(callback)).ToArray());
visitor = new ResolveVisitor(resolver, parsedFile, navigator);
visitor.Scan(compilationUnit);
diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/CompositeResolveVisitorNavigator.cs b/ICSharpCode.NRefactory/CSharp/Resolver/CompositeResolveVisitorNavigator.cs
index ec84362a91..4378267497 100644
--- a/ICSharpCode.NRefactory/CSharp/Resolver/CompositeResolveVisitorNavigator.cs
+++ b/ICSharpCode.NRefactory/CSharp/Resolver/CompositeResolveVisitorNavigator.cs
@@ -25,8 +25,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
IResolveVisitorNavigator[] navigators;
- public CompositeResolveVisitorNavigator(IResolveVisitorNavigator[] navigators)
+ public CompositeResolveVisitorNavigator(params IResolveVisitorNavigator[] navigators)
{
+ if (navigators == null)
+ throw new ArgumentNullException("navigators");
this.navigators = navigators;
}
diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/FindReferenceSearchScope.cs b/ICSharpCode.NRefactory/CSharp/Resolver/FindReferenceSearchScope.cs
new file mode 100644
index 0000000000..80cc8d7934
--- /dev/null
+++ b/ICSharpCode.NRefactory/CSharp/Resolver/FindReferenceSearchScope.cs
@@ -0,0 +1,51 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using ICSharpCode.NRefactory.TypeSystem;
+
+namespace ICSharpCode.NRefactory.CSharp.Resolver
+{
+ ///
+ /// Represents a scope in which references are searched.
+ ///
+ public interface IFindReferenceSearchScope
+ {
+ ///
+ /// Gets the search term. Only files that contain this identifier need to be parsed.
+ /// Can return null if all files need to be parsed.
+ ///
+ string SearchTerm { get; }
+
+ ///
+ /// Gets the accessibility that defines the search scope.
+ ///
+ Accessibility Accessibility { get; }
+
+ ///
+ /// Gets the top-level entity that defines the search scope.
+ ///
+ ITypeDefinition TopLevelTypeDefinition { get; }
+
+ ///
+ /// Creates a navigator that can find references to this entity and reports
+ /// them to the specified callback.
+ ///
+ IResolveVisitorNavigator GetNavigator(FoundReferenceCallback callback);
+ }
+}
diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/FindReferences.cs b/ICSharpCode.NRefactory/CSharp/Resolver/FindReferences.cs
index b8d27e32fd..8773852fed 100644
--- a/ICSharpCode.NRefactory/CSharp/Resolver/FindReferences.cs
+++ b/ICSharpCode.NRefactory/CSharp/Resolver/FindReferences.cs
@@ -26,6 +26,8 @@ using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.CSharp.Resolver
{
+ public delegate void FoundReferenceCallback(AstNode astNode, ResolveResult result);
+
///
/// 'Find references' implementation.
///
@@ -36,21 +38,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
///
public sealed class FindReferences
{
- CancellationToken cancellationToken;
-
+ #region Properties
///
- /// Callback that is invoked whenever a reference is found.
+ /// Gets/Sets the cancellation token.
///
- public event Action ReferenceFound;
-
- #region Constructor
- public FindReferences(CancellationToken cancellationToken = default(CancellationToken))
- {
- this.cancellationToken = cancellationToken;
- }
- #endregion
+ public CancellationToken CancellationToken { get; set; }
- #region Properties
///
/// Gets/Sets whether to find type references even if an alias is being used.
///
@@ -104,28 +97,32 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#endregion
#region class SearchScope
- public abstract class SearchScope : IResolveVisitorNavigator
+ abstract class SearchScope : IResolveVisitorNavigator, IFindReferenceSearchScope
{
protected string searchTerm;
internal Accessibility accessibility;
internal ITypeDefinition topLevelTypeDefinition;
- internal FindReferences findReferences;
- ///
- /// Gets the search term. Only files that contain this identifier need to be parsed.
- /// Can return null if all files need to be parsed.
- ///
- public string SearchTerm { get { return searchTerm; } }
+ FoundReferenceCallback callback;
- ///
- /// Gets the accessibility that defines the search scope.
- ///
- public Accessibility Accessibility { get { return accessibility; } }
+ IResolveVisitorNavigator IFindReferenceSearchScope.GetNavigator(FoundReferenceCallback callback)
+ {
+ SearchScope n = (SearchScope)MemberwiseClone();
+ n.callback = callback;
+ return n;
+ }
+
+ string IFindReferenceSearchScope.SearchTerm {
+ get { return searchTerm; }
+ }
- ///
- /// Gets the top-level entity that defines the search scope.
- ///
- public ITypeDefinition TopLevelTypeDefinition { get { return topLevelTypeDefinition; } }
+ Accessibility IFindReferenceSearchScope.Accessibility {
+ get { return accessibility; }
+ }
+
+ ITypeDefinition IFindReferenceSearchScope.TopLevelTypeDefinition {
+ get { return topLevelTypeDefinition; }
+ }
internal abstract bool CanMatch(AstNode node);
internal abstract bool IsMatch(ResolveResult rr);
@@ -156,15 +153,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
protected void ReportMatch(AstNode node, ResolveResult result)
{
- var referenceFound = findReferences.ReferenceFound;
- if (referenceFound != null)
- referenceFound(node, result);
+ if (callback != null)
+ callback(node, result);
}
}
#endregion
#region GetSearchScopes
- public IList GetSearchScopes(IEntity entity)
+ public IList GetSearchScopes(IEntity entity)
{
if (entity == null)
throw new ArgumentNullException("entity");
@@ -205,19 +201,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
additionalScope = new FindChainedConstructorReferences(ctor);
break;
case EntityType.Destructor:
- return EmptyList.Instance;
+ return EmptyList.Instance;
default:
throw new ArgumentException("Unknown entity type " + entity.EntityType);
}
if (scope.accessibility == Accessibility.None)
scope.accessibility = effectiveAccessibility;
scope.topLevelTypeDefinition = topLevelTypeDefinition;
- scope.findReferences = this;
if (additionalScope != null) {
if (additionalScope.accessibility == Accessibility.None)
additionalScope.accessibility = effectiveAccessibility;
additionalScope.topLevelTypeDefinition = topLevelTypeDefinition;
- additionalScope.findReferences = this;
return new[] { scope, additionalScope };
} else {
return new[] { scope };
@@ -229,7 +223,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
///
/// Gets the file names that possibly contain references to the element being searched for.
///
- public IEnumerable GetInterestingFileNames(SearchScope searchScope, ITypeResolveContext context)
+ public IList GetInterestingFileNames(IFindReferenceSearchScope searchScope, IEnumerable allTypes, ITypeResolveContext context)
{
IEnumerable interestingTypes;
if (searchScope.TopLevelTypeDefinition != null) {
@@ -239,41 +233,41 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
interestingTypes = new [] { searchScope.TopLevelTypeDefinition.GetDefinition() };
break;
case Accessibility.Protected:
- interestingTypes = GetInterestingTypesProtected(context, searchScope.TopLevelTypeDefinition);
+ interestingTypes = GetInterestingTypesProtected(allTypes, context, searchScope.TopLevelTypeDefinition);
break;
case Accessibility.Internal:
- interestingTypes = GetInterestingTypesInternal(context, searchScope.TopLevelTypeDefinition.ProjectContent);
+ interestingTypes = GetInterestingTypesInternal(allTypes, context, searchScope.TopLevelTypeDefinition.ProjectContent);
break;
case Accessibility.ProtectedAndInternal:
- interestingTypes = GetInterestingTypesProtected(context, searchScope.TopLevelTypeDefinition)
- .Intersect(GetInterestingTypesInternal(context, searchScope.TopLevelTypeDefinition.ProjectContent));
+ interestingTypes = GetInterestingTypesProtected(allTypes, context, searchScope.TopLevelTypeDefinition)
+ .Intersect(GetInterestingTypesInternal(allTypes, context, searchScope.TopLevelTypeDefinition.ProjectContent));
break;
case Accessibility.ProtectedOrInternal:
- interestingTypes = GetInterestingTypesProtected(context, searchScope.TopLevelTypeDefinition)
- .Union(GetInterestingTypesInternal(context, searchScope.TopLevelTypeDefinition.ProjectContent));
+ interestingTypes = GetInterestingTypesProtected(allTypes, context, searchScope.TopLevelTypeDefinition)
+ .Union(GetInterestingTypesInternal(allTypes, context, searchScope.TopLevelTypeDefinition.ProjectContent));
break;
default:
- interestingTypes = context.GetTypes();
+ interestingTypes = allTypes;
break;
}
} else {
- interestingTypes = context.GetTypes();
+ interestingTypes = allTypes;
}
return (from typeDef in interestingTypes
from part in typeDef.GetParts()
where part.ParsedFile != null
select part.ParsedFile.FileName
- ).Distinct(Platform.FileNameComparer);
+ ).Distinct(Platform.FileNameComparer).ToList();
}
- IEnumerable GetInterestingTypesProtected(ITypeResolveContext context, ITypeDefinition referencedTypeDefinition)
+ IEnumerable GetInterestingTypesProtected(IEnumerable allTypes, ITypeResolveContext context, ITypeDefinition referencedTypeDefinition)
{
- return referencedTypeDefinition.GetSubTypeDefinitions(context);
+ return allTypes.Where(t => t.IsDerivedFrom(referencedTypeDefinition, context));
}
- IEnumerable GetInterestingTypesInternal(ITypeResolveContext context, IProjectContent referencedProjectContent)
+ IEnumerable GetInterestingTypesInternal(IEnumerable allTypes, ITypeResolveContext context, IProjectContent referencedProjectContent)
{
- return context.GetTypes().Where(t => referencedProjectContent.InternalsVisibleTo(t.ProjectContent, context));
+ return allTypes.Where(t => referencedProjectContent.InternalsVisibleTo(t.ProjectContent, context));
}
#endregion
@@ -285,11 +279,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// The type system representation of the file being searched.
/// The compilation unit of the file being searched.
/// The type resolve context to use for resolving the file.
- public void FindReferencesInFile(SearchScope searchScope, CSharpParsedFile parsedFile, CompilationUnit compilationUnit, ITypeResolveContext context)
+ /// Callback used to report the references that were found.
+ public void FindReferencesInFile(IFindReferenceSearchScope searchScope, CSharpParsedFile parsedFile, CompilationUnit compilationUnit,
+ ITypeResolveContext context, FoundReferenceCallback callback)
{
if (searchScope == null)
throw new ArgumentNullException("searchScope");
- FindReferencesInFile(new[] { searchScope }, parsedFile, compilationUnit, context);
+ FindReferencesInFile(new[] { searchScope }, parsedFile, compilationUnit, context, callback);
}
///
@@ -299,7 +295,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// The type system representation of the file being searched.
/// The compilation unit of the file being searched.
/// The type resolve context to use for resolving the file.
- public void FindReferencesInFile(IList searchScopes, CSharpParsedFile parsedFile, CompilationUnit compilationUnit, ITypeResolveContext context)
+ /// Callback used to report the references that were found.
+ public void FindReferencesInFile(IList searchScopes, CSharpParsedFile parsedFile, CompilationUnit compilationUnit,
+ ITypeResolveContext context, FoundReferenceCallback callback)
{
if (searchScopes == null)
throw new ArgumentNullException("searchScopes");
@@ -309,21 +307,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
throw new ArgumentNullException("compilationUnit");
if (context == null)
throw new ArgumentNullException("context");
- cancellationToken.ThrowIfCancellationRequested();
+ this.CancellationToken.ThrowIfCancellationRequested();
if (searchScopes.Count == 0)
return;
- foreach (SearchScope scope in searchScopes) {
- if (scope.findReferences != this)
- throw new ArgumentException("Cannot use a search scope that was created by another FindReferences instance");
- }
using (var ctx = context.Synchronize()) {
IResolveVisitorNavigator navigator;
if (searchScopes.Count == 1)
- navigator = searchScopes[0];
+ navigator = searchScopes[0].GetNavigator(callback);
else
- navigator = new CompositeResolveVisitorNavigator(searchScopes.ToArray());
+ navigator = new CompositeResolveVisitorNavigator(searchScopes.Select(s => s.GetNavigator(callback)).ToArray());
navigator = new DetectSkippableNodesNavigator(navigator, compilationUnit);
- CSharpResolver resolver = new CSharpResolver(ctx, cancellationToken);
+ CSharpResolver resolver = new CSharpResolver(ctx, this.CancellationToken);
ResolveVisitor v = new ResolveVisitor(resolver, parsedFile, navigator);
v.Scan(compilationUnit);
}
diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/LocalResolveResult.cs b/ICSharpCode.NRefactory/CSharp/Resolver/LocalResolveResult.cs
index ef056230f9..57779ab2a6 100644
--- a/ICSharpCode.NRefactory/CSharp/Resolver/LocalResolveResult.cs
+++ b/ICSharpCode.NRefactory/CSharp/Resolver/LocalResolveResult.cs
@@ -68,5 +68,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
return string.Format("[LocalResolveResult {0}]", variable);
}
+
+ public override DomRegion GetDefinitionRegion()
+ {
+ return variable.Region;
+ }
}
}
diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/MemberResolveResult.cs b/ICSharpCode.NRefactory/CSharp/Resolver/MemberResolveResult.cs
index baaf504d7d..b47b4764c0 100644
--- a/ICSharpCode.NRefactory/CSharp/Resolver/MemberResolveResult.cs
+++ b/ICSharpCode.NRefactory/CSharp/Resolver/MemberResolveResult.cs
@@ -92,5 +92,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
return string.Format("[{0} {1}]", GetType().Name, member);
}
+
+ public override DomRegion GetDefinitionRegion()
+ {
+ return member.Region;
+ }
}
}
diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/ResolveAtLocation.cs b/ICSharpCode.NRefactory/CSharp/Resolver/ResolveAtLocation.cs
index 3b003e4882..d32f45cf5e 100644
--- a/ICSharpCode.NRefactory/CSharp/Resolver/ResolveAtLocation.cs
+++ b/ICSharpCode.NRefactory/CSharp/Resolver/ResolveAtLocation.cs
@@ -32,6 +32,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
CancellationToken cancellationToken = default(CancellationToken))
{
AstNode node = cu.GetNodeAt(location);
+ if (node == null)
+ return null;
AstNode resolvableNode;
if (node is Identifier) {
resolvableNode = node.Parent;
diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/ResolveResult.cs b/ICSharpCode.NRefactory/CSharp/Resolver/ResolveResult.cs
index 9f31e05720..40a9931e69 100644
--- a/ICSharpCode.NRefactory/CSharp/Resolver/ResolveResult.cs
+++ b/ICSharpCode.NRefactory/CSharp/Resolver/ResolveResult.cs
@@ -63,5 +63,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
return Enumerable.Empty();
}
+
+ public virtual DomRegion GetDefinitionRegion()
+ {
+ return DomRegion.Empty;
+ }
}
}
diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/TypeResolveResult.cs b/ICSharpCode.NRefactory/CSharp/Resolver/TypeResolveResult.cs
index 1336357ba6..79815d6565 100644
--- a/ICSharpCode.NRefactory/CSharp/Resolver/TypeResolveResult.cs
+++ b/ICSharpCode.NRefactory/CSharp/Resolver/TypeResolveResult.cs
@@ -30,5 +30,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
: base(type)
{
}
+
+ public override DomRegion GetDefinitionRegion()
+ {
+ ITypeDefinition def = this.Type.GetDefinition();
+ if (def != null)
+ return def.Region;
+ else
+ return DomRegion.Empty;
+ }
}
}
diff --git a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
index 5d0087768b..4d7ea32385 100644
--- a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
+++ b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
@@ -104,6 +104,7 @@
+
diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs
index 6b10615b5f..0189d3cca1 100644
--- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs
+++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs
@@ -38,7 +38,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public class SimpleProjectContent : AbstractAnnotatable, IProjectContent, ISerializable, IDeserializationCallback
{
readonly TypeStorage types = new TypeStorage();
- readonly ReaderWriterLockSlim readerWriterLock = new ReaderWriterLockSlim();
+ readonly ReaderWriterLockSlim readerWriterLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
readonly Dictionary fileDict = new Dictionary(Platform.FileNameComparer);
#region Constructor