diff options
author | Mike Krüger <mkrueger@xamarin.com> | 2015-02-08 11:38:13 +0300 |
---|---|---|
committer | Mike Krüger <mkrueger@xamarin.com> | 2015-02-08 11:38:13 +0300 |
commit | 9c6b75f690aca613f96d394b1fba7b91ec09cec8 (patch) | |
tree | 58552ee1d3c98841936aa61c1596750c61e74968 /main | |
parent | b97c166e7e4228a3fdf5f8e6f1420f44fc809938 (diff) | |
parent | 1c124233f582672b5184226bdbcaed0e33c62998 (diff) |
Merge pull request #733 from mhutch/fix-find-derived-symbols
Fix find derived symbols
Diffstat (limited to 'main')
4 files changed, 131 insertions, 181 deletions
diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.addin.xml b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.addin.xml index d20c6f8c42..aa4e755af5 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.addin.xml +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.addin.xml @@ -90,7 +90,7 @@ _label = "_Find References of All Overloads" /> <Command id = "MonoDevelop.Refactoring.RefactoryCommands.FindDerivedClasses" defaultHandler = "MonoDevelop.Refactoring.FindDerivedClassesHandler" - _label = "Find _Derived Classes" /> + _label = "Find _Derived Symbols" /> </Category> <Category _name = "Refactoring" id = "Refactoring"> diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindDerivedClassesHandler.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindDerivedClassesHandler.cs index d1d99c2b41..63b5365aeb 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 @@ -28,7 +28,6 @@ using System; using MonoDevelop.Core; using MonoDevelop.Ide.Gui; using MonoDevelop.Components.Commands; -using MonoDevelop.Ide.Gui.Content; using MonoDevelop.Refactoring; using MonoDevelop.Ide; using ICSharpCode.NRefactory.TypeSystem; @@ -37,12 +36,11 @@ using System.Collections.Generic; using System.Threading; using MonoDevelop.Projects; using MonoDevelop.Ide.FindInFiles; -using ICSharpCode.NRefactory.CSharp.Resolver; -using ICSharpCode.NRefactory.TypeSystem.Implementation; -using System.Linq; using Mono.TextEditor; using ICSharpCode.NRefactory.Semantics; using System.Threading.Tasks; +using System.Linq; +using System.Collections.Concurrent; namespace MonoDevelop.Refactoring { @@ -50,102 +48,125 @@ 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); - - Parallel.ForEach (projects, p => { - var comp = TypeSystemService.GetCompilation (p); - if (comp == null) - return; - var importedType = comp.Import (cls); - if (importedType == null) { + + var compilations = ReferenceFinder.GetAllReferencingProjects (solution, sourceProject) + .Select (TypeSystemService.GetCompilation).Where (c => c != null).ToList (); + + using (var monitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true)) { + var label = member == null + ? GettextCatalog.GetString ("Searching for derived classes in solution...") + : GettextCatalog.GetString ("Searching for derived members in solution..."); + monitor.BeginTask (label, compilations.Count); + + Parallel.ForEach (compilations, comp => { + var importedType = comp.Import (cls); + if (importedType == null) { + return; + } + + IMember impMember = null; + if (member != null) { + impMember = comp.Import (member); + if (impMember == null) { return; } - foreach (var type in comp.MainAssembly.GetAllTypeDefinitions ()) { - if (!type.IsDerivedFrom (importedType)) + } + + 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; - 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; - } - 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++; - } - monitor.ReportResult (new MonoDevelop.Ide.FindInFiles.SearchResult (new FileProvider (type.Region.FileName, p), position, 0)); + } else { + result = derivedType; } - monitor.Step (1); - }); - foreach (var tf in cache.Values) { - if (tf.Parent == null) - tf.Dispose (); + + ReportResult (monitor, result); } - monitor.EndTask (); - } - }); + monitor.Step (1); + }); + + monitor.EndTask (); + }; + } + + 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) + { + string filename = result.Region.FileName; + if (string.IsNullOrEmpty (filename)) + return; + + var 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; + + if (textFile.Parent == null) + textFile.Dispose (); + + monitor.ReportResult (new MemberReference (result, result.Region, start, result.Name.Length)); + } + protected override void Run (object data) { -// var doc = IdeApp.Workbench.ActiveDocument; -// if (doc == null || doc.FileName == FilePath.Null) -// return; -// ResolveResult resolveResult; -// var item = CurrentRefactoryOperationsHandler.GetItem (doc, out resolveResult); -// -// IMember eitem = resolveResult != null ? (resolveResult.CallingMember ?? resolveResult.CallingType) : null; -// string itemName = null; -// if (item is IMember) -// itemName = ((IMember)item).FullName; -// if (item != null && eitem != null && (eitem.Equals (item) || (eitem.FullName == itemName && !(eitem is IProperty) && !(eitem is IMethod)))) { -// item = eitem; -// eitem = null; -// } -// ITypeDefinition eclass = null; -// if (item is ITypeDefinition) { -// if (((ITypeDefinition)item).Kind == TypeKind.Interface) -// eclass = CurrentRefactoryOperationsHandler.FindEnclosingClass (ctx, editor.Name, line, column); else -// eclass = (IType)item; -// if (eitem is IMethod && ((IMethod)eitem).IsConstructor && eitem.DeclaringType.Equals (item)) { -// item = eitem; -// eitem = null; -// } -// } + var doc = IdeApp.Workbench.ActiveDocument; + if (doc == null || doc.FileName == FilePath.Null) + return; + + ResolveResult resolveResult; + var item = CurrentRefactoryOperationsHandler.GetItem (doc, out resolveResult); + + var typeDef = item as ITypeDefinition; + if (typeDef != null && ((typeDef.Kind == TypeKind.Class && !typeDef.IsSealed) || typeDef.Kind == TypeKind.Interface)) { + FindDerivedClasses (typeDef); + return; + } + + var member = item as IMember; + 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 375ea3edf1..2f5ac1f714 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoryCommands.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoryCommands.cs @@ -350,12 +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) { - ainfo.Add (GettextCatalog.GetString ("Find Derived Symbols"), new System.Action (handler.Run)); - 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) { @@ -378,7 +377,9 @@ namespace MonoDevelop.Refactoring } } if ((cls.Kind == TypeKind.Class && !cls.IsSealed) || cls.Kind == TypeKind.Interface) { - ainfo.Add (cls.Kind != TypeKind.Interface ? GettextCatalog.GetString ("Find _derived classes") : GettextCatalog.GetString ("Find _implementor classes"), new System.Action (new FindDerivedClasses (cls).Run)); + var label = cls.Kind != TypeKind.Interface ? GettextCatalog.GetString ("Find _derived classes") : GettextCatalog.GetString ("Find _implementor classes"); + var a = ainfo.Add (label, new System.Action (new FindDerivedClasses (cls).Run)); + a.AccelKey = IdeApp.CommandService.GetCommandInfo (RefactoryCommands.FindDerivedClasses).AccelKey; } ainfo.Add (GettextCatalog.GetString ("Find Extension Methods"), new System.Action (new FindExtensionMethodHandler (doc, cls).Run)); added = true; |