/// <summary> /// collect members with the same signature/name(if overloads are included) as the specified member /// in the inheritance tree /// </summary> public static IEnumerable<IMember> CollectMembers (Solution solution, IMember member, ReferenceFinder.RefactoryScope scope, bool includeOverloads = true, bool matchDeclaringType = false) { if (solution == null || member.EntityType == EntityType.Destructor || member.EntityType == EntityType.Operator) return new [] { member }; if (member.EntityType == EntityType.Constructor) { if (includeOverloads) return member.DeclaringType.GetMembers (m => m.EntityType == EntityType.Constructor, GetMemberOptions.IgnoreInheritedMembers); return new [] { member }; } Func<IMember, bool> memberFilter = null; if (member is IParameterizedMember && !includeOverloads) memberFilter = m => MatchParameters (m, member); var declaringType = member.DeclaringTypeDefinition; // only collect members in declaringType if (matchDeclaringType) return GetMembers (declaringType, member.Name, true, memberFilter); if (declaringType.Kind != TypeKind.Class && declaringType.Kind != TypeKind.Interface) return GetMembers (declaringType, member.Name, false, memberFilter); var searchTypes = new List<ITypeDefinition> (); var interfaces = from t in declaringType.GetAllBaseTypeDefinitions () where t.Kind == TypeKind.Interface && GetMembers (t, member.Name, true, memberFilter).Any () select t; searchTypes.AddRange (GetBaseTypes (interfaces)); if (member.DeclaringType.Kind == TypeKind.Class) { var members = GetMembers (declaringType, member.Name, false, memberFilter).ToList (); if (members.Any (m => m.IsOverridable)) searchTypes.AddRange (GetBaseTypes (members.Select (m => m.DeclaringTypeDefinition))); else if (searchTypes.Count == 0) return members; } IList<ICompilation> compilations; if (scope == ReferenceFinder.RefactoryScope.Solution || scope == ReferenceFinder.RefactoryScope.Unknown) { var projects = SearchCollector.CollectProjects (solution, searchTypes); compilations = projects.Select (TypeSystemService.GetCompilation).ToList (); } else { compilations = new [] { member.Compilation }; } var result = new List<IMember> (); var mainAssemblies = new HashSet<string> (compilations.Select (c => c.MainAssembly.AssemblyName)); var searchedAssemblies = new HashSet<string> (); var searchedTypes = new HashSet<string> (); foreach (var compilation in compilations) { var baseTypeImports = Import(compilation, searchTypes).Where (t => t != null).ToList (); if (!baseTypeImports.Any ()) continue; foreach (var assembly in compilation.Assemblies) { // search main assemblies in their projects' own compilation, to avoid possible resolving problems if ((mainAssemblies.Contains(assembly.AssemblyName) && assembly != compilation.MainAssembly) || !searchedAssemblies.Add (assembly.AssemblyName)) continue; foreach (var type in assembly.GetAllTypeDefinitions ()) { // members in base types will also be added // because IsDerivedFrom return true for a type itself if (!searchedTypes.Add (type.ReflectionName) || !baseTypeImports.Any (baseType => type.IsDerivedFrom (baseType))) continue; result.AddRange (GetMembers (type, member.Name, true, memberFilter)); } } } return result; }
void Collect(Project sourceProject, IEntity entity, bool searchInProject = false) { if (searchedProjects.Contains(sourceProject)) { return; } if (searchProject != null && sourceProject != searchProject) { // searching for a entity not defined in the project AddProject(searchProject); return; } if (sourceProject == null) { if (entity == null) { foreach (var project in solution.GetAllProjects()) { AddProject(project); } return; } // entity is defined in a referenced assembly var assemblyName = entity.ParentAssembly.AssemblyName; if (!searchedAssemblies.Add(assemblyName)) { return; } foreach (var project in GetAllReferencingProjects(solution, assemblyName)) { AddProject(project); } return; } var declaringType = entity.DeclaringTypeDefinition; // TODO: possible optimization for protected switch (entity.Accessibility) { case Accessibility.Public: case Accessibility.Protected: case Accessibility.ProtectedOrInternal: case Accessibility.Internal: case Accessibility.ProtectedAndInternal: if (declaringType != null) { Collect(sourceProject, entity.DeclaringTypeDefinition, searchInProject); } else if (searchProject != null || searchInProject) { AddProject(sourceProject); } else { foreach (var project in ReferenceFinder.GetAllReferencingProjects(solution, sourceProject)) { if (entity.Accessibility == Accessibility.Internal || entity.Accessibility == Accessibility.ProtectedAndInternal) { if (!entity.ParentAssembly.InternalsVisibleTo(TypeSystemService.GetProjectContentWrapper(project).Compilation.MainAssembly)) { continue; } } AddProject(project); } } break; default: // private if (projectOnly) { AddProject(sourceProject); } else if (declaringType != null) { AddFiles(sourceProject, declaringType.Parts.Select(p => p.Region.FileName)); } break; } }