diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs b/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs index 960b5f7ea3..42fe828b26 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs @@ -189,7 +189,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver SearchScope additionalScope = null; switch (entity.EntityType) { case EntityType.TypeDefinition: - scope = FindTypeDefinitionReferences((ITypeDefinition)entity, this.FindTypeReferencesEvenIfAliased); + scope = FindTypeDefinitionReferences((ITypeDefinition)entity, this.FindTypeReferencesEvenIfAliased, out additionalScope); break; case EntityType.Field: if (entity.DeclaringTypeDefinition != null && entity.DeclaringTypeDefinition.Kind == TypeKind.Enum) @@ -353,14 +353,28 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver #endregion #region Find TypeDefinition References - SearchScope FindTypeDefinitionReferences(ITypeDefinition typeDefinition, bool findTypeReferencesEvenIfAliased) + SearchScope FindTypeDefinitionReferences(ITypeDefinition typeDefinition, bool findTypeReferencesEvenIfAliased, out SearchScope additionalScope) { string searchTerm = null; - if (!findTypeReferencesEvenIfAliased && ReflectionHelper.GetTypeCode(typeDefinition) == TypeCode.Empty) { - // not a built-in type + additionalScope = null; + if (!findTypeReferencesEvenIfAliased && KnownTypeReference.GetCSharpNameByTypeCode(typeDefinition.KnownTypeCode) == null) { + // We can optimize the search by looking only for the type references with the right identifier, + // but only if it's not a primitive type and we're not looking for indirect references (through an alias) searchTerm = typeDefinition.Name; + if (searchTerm.Length > 9 && searchTerm.EndsWith("Attribute", StringComparison.Ordinal)) { + // The type might be an attribute, so we also need to look for the short form: + string shortForm = searchTerm.Substring(0, searchTerm.Length - 9); + additionalScope = new SearchScope( + shortForm, + delegate (ICompilation compilation) { + ITypeDefinition imported = compilation.Import(typeDefinition); + if (imported != null) + return new FindTypeDefinitionReferencesNavigator(imported, shortForm); + else + return null; + }); + } } - return new SearchScope( searchTerm, delegate (ICompilation compilation) { @@ -404,7 +418,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (searchTerm == null && node is PrimitiveType) return true; - return node is TypeDeclaration || node is DelegateDeclaration; + TypeDeclaration typeDecl = node as TypeDeclaration; + if (typeDecl != null) + return searchTerm == null || typeDecl.Name == searchTerm; + + DelegateDeclaration delegateDecl = node as DelegateDeclaration; + if (delegateDecl != null) + return searchTerm == null || delegateDecl.Name == searchTerm; + + return false; } internal override bool IsMatch(ResolveResult rr) @@ -872,9 +894,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { ctor = (IMethod)ctor.MemberDefinition; string searchTerm = null; - if (ReflectionHelper.GetTypeCode(ctor.DeclaringTypeDefinition) == TypeCode.Empty) { + if (KnownTypeReference.GetCSharpNameByTypeCode(ctor.DeclaringTypeDefinition.KnownTypeCode) == null) { // not a built-in type searchTerm = ctor.DeclaringTypeDefinition.Name; + if (searchTerm.Length > 9 && searchTerm.EndsWith("Attribute", StringComparison.Ordinal)) { + // we also need to look for the short form + searchTerm = null; + } } return new SearchScope( searchTerm, @@ -898,7 +924,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver internal override bool CanMatch(AstNode node) { - return node is ObjectCreateExpression || node is ConstructorDeclaration; + return node is ObjectCreateExpression || node is ConstructorDeclaration || node is Attribute; } internal override bool IsMatch(ResolveResult rr) diff --git a/ICSharpCode.NRefactory.Demo/CSDemo.cs b/ICSharpCode.NRefactory.Demo/CSDemo.cs index b712f1149b..144b4723e1 100644 --- a/ICSharpCode.NRefactory.Demo/CSDemo.cs +++ b/ICSharpCode.NRefactory.Demo/CSDemo.cs @@ -312,10 +312,12 @@ namespace ICSharpCode.NRefactory.Demo FindReferences fr = new FindReferences(); int referenceCount = 0; FoundReferenceCallback callback = delegate(AstNode matchNode, ResolveResult result) { + Debug.WriteLine(matchNode.StartLocation + " - " + matchNode + " - " + result); referenceCount++; }; var searchScopes = fr.GetSearchScopes(entity); + Debug.WriteLine("Find references to " + entity.ReflectionName); fr.FindReferencesInFile(searchScopes, parsedFile, compilationUnit, compilation, callback, CancellationToken.None); MessageBox.Show("Found " + referenceCount + " references to " + entity.FullName); diff --git a/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs b/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs index 1746e1bfad..8fa9699ef7 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs @@ -252,16 +252,33 @@ namespace ICSharpCode.NRefactory.TypeSystem #endregion #region GetType/Member + /// + /// Gets all unresolved type definitions from the file. + /// For partial classes, each part is returned. + /// public static IEnumerable GetAllTypeDefinitions (this IParsedFile file) { return TreeTraversal.PreOrder(file.TopLevelTypeDefinitions, t => t.NestedTypes); } + /// + /// Gets all unresolved type definitions from the assembly. + /// For partial classes, each part is returned. + /// + public static IEnumerable GetAllTypeDefinitions (this IUnresolvedAssembly assembly) + { + return TreeTraversal.PreOrder(assembly.TopLevelTypeDefinitions, t => t.NestedTypes); + } + public static IEnumerable GetAllTypeDefinitions (this IAssembly assembly) { return TreeTraversal.PreOrder(assembly.TopLevelTypeDefinitions, t => t.NestedTypes); } + /// + /// Gets all type definitions in the compilation. + /// This may include types from referenced assemblies that are not accessible in the main assembly. + /// public static IEnumerable GetAllTypeDefinitions (this ICompilation compilation) { return compilation.MainAssembly.GetAllTypeDefinitions() diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultSolutionSnapshot.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultSolutionSnapshot.cs index 2114f0c4b3..f32676c220 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultSolutionSnapshot.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultSolutionSnapshot.cs @@ -24,7 +24,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Default implementation of ISolutionSnapshot. /// - public sealed class DefaultSolutionSnapshot : ISolutionSnapshot + public class DefaultSolutionSnapshot : ISolutionSnapshot { ConcurrentDictionary dictionary = new ConcurrentDictionary();