diff options
author | Michael Hutchinson <m.j.hutchinson@gmail.com> | 2015-02-08 10:48:29 +0300 |
---|---|---|
committer | Michael Hutchinson <m.j.hutchinson@gmail.com> | 2015-02-08 10:48:29 +0300 |
commit | ab8578c529046e566c00fcb9ae147dedd3544f99 (patch) | |
tree | a95e1da18d13bc97e3bfb04630170d13b1fca4cd /main/src | |
parent | 0207771005e73f4f585783e0b6ae368daf25d490 (diff) |
[Refactoring] Fix Find Derived Symbols
It wasn't searching types in referencing projects.
Re-use the Find Derived Classes logic.
Diffstat (limited to 'main/src')
3 files changed, 98 insertions, 134 deletions
diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindDerivedClassesHandler.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindDerivedClassesHandler.cs index 2c599e0dd8..b4ade2688d 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindDerivedClassesHandler.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindDerivedClassesHandler.cs @@ -1,21 +1,21 @@ -// +// // FindDerivedClassesHandler.cs -// +// // Author: // Mike Krüger <mkrueger@novell.com> -// +// // Copyright (c) 2010 Novell, Inc (http://www.novell.com) -// +// // 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 @@ -39,6 +39,7 @@ using MonoDevelop.Ide.FindInFiles; using Mono.TextEditor; using ICSharpCode.NRefactory.Semantics; using System.Threading.Tasks; +using System.Linq; namespace MonoDevelop.Refactoring { @@ -46,64 +47,68 @@ namespace MonoDevelop.Refactoring { public static void FindDerivedClasses (ITypeDefinition cls) { + FindDerivedSymbols (cls, null); + } + + public static void FindDerivedMembers (IMember member) + { + var cls = member.DeclaringTypeDefinition; + if (cls == null) + return; + FindDerivedSymbols (cls, member); + } + + static void FindDerivedSymbols (ITypeDefinition cls, IMember member) + { var solution = IdeApp.ProjectOperations.CurrentSelectedSolution; if (solution == null) return; - + var sourceProject = TypeSystemService.GetProject (cls); if (sourceProject == null) return; - + var projects = ReferenceFinder.GetAllReferencingProjects (solution, sourceProject); ThreadPool.QueueUserWorkItem (delegate { using (var monitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true)) { var cache = new Dictionary<string, TextEditorData> (); - monitor.BeginTask (GettextCatalog.GetString ("Searching for derived classes in solution..."), projects.Count); + var label = member == null + ? GettextCatalog.GetString ("Searching for derived classes in solution...") + : GettextCatalog.GetString ("Searching for derived members in solution..."); + monitor.BeginTask (label, projects.Count); Parallel.ForEach (projects, p => { var comp = TypeSystemService.GetCompilation (p); if (comp == null) return; + var importedType = comp.Import (cls); if (importedType == null) { return; } - foreach (var type in comp.MainAssembly.GetAllTypeDefinitions ()) { - if (!type.IsDerivedFrom (importedType)) - continue; - TextEditorData textFile; - if (!cache.TryGetValue (type.Region.FileName, out textFile)) { - cache [type.Region.FileName] = textFile = TextFileProvider.Instance.GetTextEditorData (type.Region.FileName); - } - int position = textFile.LocationToOffset (type.Region.Begin); - string keyword; - switch (type.Kind) { - case TypeKind.Interface: - keyword = "interface"; - break; - case TypeKind.Struct: - keyword = "struct"; - break; - case TypeKind.Delegate: - keyword = "delegate"; - break; - case TypeKind.Enum: - keyword = "enum"; - break; - default: - keyword = "class"; - break; + + IMember impMember = null; + if (member != null) { + impMember = comp.Import (member); + if (impMember == null) { + return; } - while (position < textFile.Length - keyword.Length) { - if (textFile.GetTextAt (position, keyword.Length) == keyword) { - position += keyword.Length; - while (position < textFile.Length && textFile.GetCharAt (position) == ' ' || textFile.GetCharAt (position) == '\t') - position++; - break; - } - position++; + } + + foreach (var derivedType in comp.MainAssembly.GetAllTypeDefinitions ()) { + if (!derivedType.IsDerivedFrom (importedType)) + continue; + + IEntity result; + if (member != null) { + result = FindDerivedMember (impMember, derivedType); + if (result == null) + continue; + } else { + result = derivedType; } - monitor.ReportResult (new MonoDevelop.Ide.FindInFiles.SearchResult (new FileProvider (type.Region.FileName, p), position, 0)); + + ReportResult (monitor, result, cache); } monitor.Step (1); }); @@ -115,7 +120,40 @@ namespace MonoDevelop.Refactoring } }); } - + + static IMember FindDerivedMember (IMember importedMember, ITypeDefinition derivedType) + { + IMember derivedMember; + if (importedMember.DeclaringTypeDefinition.Kind == TypeKind.Interface) { + derivedMember = derivedType.GetMembers (null, GetMemberOptions.IgnoreInheritedMembers) + .FirstOrDefault (m => m.ImplementedInterfaceMembers.Any (im => im.Region == importedMember.Region)); + } + else { + derivedMember = InheritanceHelper.GetDerivedMember (importedMember, derivedType); + } + return derivedMember; + } + + static void ReportResult (ISearchProgressMonitor monitor, IEntity result, Dictionary<string, TextEditorData> cache) + { + string filename = result.Region.FileName; + if (string.IsNullOrEmpty (filename)) + return; + + TextEditorData textFile; + if (!cache.TryGetValue (filename, out textFile)) { + cache [filename] = textFile = TextFileProvider.Instance.GetTextEditorData (filename); + } + + var start = textFile.LocationToOffset (result.Region.Begin); + textFile.SearchRequest.SearchPattern = result.Name; + var sr = textFile.SearchForward (start); + if (sr != null) + start = sr.Offset; + + monitor.ReportResult (new MemberReference (result, result.Region, start, result.Name.Length)); + } + protected override void Run (object data) { var doc = IdeApp.Workbench.ActiveDocument; @@ -132,8 +170,8 @@ namespace MonoDevelop.Refactoring } var member = item as IMember; - if (member != null && (member.IsVirtual || member.IsAbstract || member.DeclaringType.Kind == TypeKind.Interface)) { - var handler = new FindDerivedSymbolsHandler (doc, member); + var handler = new FindDerivedSymbolsHandler (member); + if (handler.IsValid) { handler.Run (); return; } diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindDerivedSymbolsHandler.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindDerivedSymbolsHandler.cs index a034b677f0..50c204a767 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindDerivedSymbolsHandler.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindDerivedSymbolsHandler.cs @@ -41,98 +41,26 @@ namespace MonoDevelop.Refactoring { class FindDerivedSymbolsHandler { - Ide.Gui.Document doc; - readonly IMember entity; + readonly IMember member; - - public FindDerivedSymbolsHandler (Ide.Gui.Document doc, IMember entity) - { - this.doc = doc; - this.entity = entity; - } - - static bool IsReferenced (Project project, Project referencedProject) + public FindDerivedSymbolsHandler (IMember member) { - return project == referencedProject || - project.GetReferencedItems (IdeApp.Workspace.ActiveConfiguration).Contains (referencedProject); - } - - Task<HashSet<IAssembly>> GetAllAssemblies (Project referencedProject) - { - var solution = IdeApp.ProjectOperations.CurrentSelectedSolution; - return Task.Factory.StartNew (delegate { - var assemblies = new HashSet<IAssembly> (); - foreach (var project in solution.GetAllProjects ()) { - if (!IsReferenced (project, referencedProject)) - continue; - var comp = TypeSystemService.GetCompilation (project); - if (comp == null) - continue; - assemblies.Add (comp.MainAssembly); - } - return assemblies; - }); + this.member = member; } public bool IsValid { get { - return true; + if (IdeApp.ProjectOperations.CurrentSelectedSolution == null) + return false; + if (TypeSystemService.GetProject (member) == null) + return false; + return member.IsVirtual || member.IsAbstract || member.DeclaringType.Kind == TypeKind.Interface; } } public void Run () { - var assemblies = GetAllAssemblies (doc.Project); - assemblies.ContinueWith (delegate(Task<HashSet<IAssembly>> arg) { - var monitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true); - monitor.BeginTask (GettextCatalog.GetString ("Building type graph in solution ..."), 1); - var tg = new TypeGraph (arg.Result); - var node = tg.GetNode (entity.DeclaringTypeDefinition); - monitor.EndTask (); - if (node == null) { - monitor.Dispose (); - return; - } - Gtk.Application.Invoke (delegate { - try { - Stack<IList<TypeGraphNode>> derivedTypes = new Stack<IList<TypeGraphNode>> (); - derivedTypes.Push (node.DerivedTypes); - HashSet<ITypeDefinition> visitedType = new HashSet<ITypeDefinition> (); - while (derivedTypes.Count > 0) { - foreach (var derived in derivedTypes.Pop ()) { - if (visitedType.Contains (derived.TypeDefinition)) - continue; - derivedTypes.Push (tg.GetNode (derived.TypeDefinition).DerivedTypes); - visitedType.Add (derived.TypeDefinition); - var impMember = derived.TypeDefinition.Compilation.Import (entity); - if (impMember == null) - continue; - IMember derivedMember; - if (entity.DeclaringTypeDefinition.Kind == TypeKind.Interface) { - derivedMember = derived.TypeDefinition.GetMembers (null, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault ( - m => m.ImplementedInterfaceMembers.Any (im => im.Region == entity.Region) - ); - } else { - derivedMember = InheritanceHelper.GetDerivedMember (impMember, derived.TypeDefinition); - } - if (derivedMember == null || string.IsNullOrEmpty (derivedMember.Region.FileName)) - continue; - var tf = TextFileProvider.Instance.GetReadOnlyTextEditorData (derivedMember.Region.FileName); - var start = tf.LocationToOffset (derivedMember.Region.Begin); - tf.SearchRequest.SearchPattern = derivedMember.Name; - var sr = tf.SearchForward (start); - if (sr != null) - start = sr.Offset; - - monitor.ReportResult (new MemberReference (derivedMember, derivedMember.Region, start, derivedMember.Name.Length)); - } - } - } finally { - monitor.Dispose (); - } - }); - }); - + FindDerivedClassesHandler.FindDerivedMembers (member); } } } diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoryCommands.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoryCommands.cs index a02fe48305..2f5ac1f714 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoryCommands.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoryCommands.cs @@ -350,13 +350,11 @@ namespace MonoDevelop.Refactoring if (item is IMember) { var member = (IMember)item; - if (member.IsVirtual || member.IsAbstract || member.DeclaringType.Kind == TypeKind.Interface) { - var handler = new FindDerivedSymbolsHandler (doc, member); - if (handler.IsValid) { - var a = ainfo.Add (GettextCatalog.GetString ("Find Derived Symbols"), new Action (handler.Run)); - a.AccelKey = IdeApp.CommandService.GetCommandInfo (RefactoryCommands.FindDerivedClasses).AccelKey; - added = true; - } + var handler = new FindDerivedSymbolsHandler (member); + if (handler.IsValid) { + var a = ainfo.Add (GettextCatalog.GetString ("Find Derived Symbols"), new Action (handler.Run)); + a.AccelKey = IdeApp.CommandService.GetCommandInfo (RefactoryCommands.FindDerivedClasses).AccelKey; + added = true; } } if (item is IMember) { |