Browse Source

Reimplemented "Find derived classes"

newNRvisualizers
Daniel Grunwald 15 years ago
parent
commit
6b56440cb5
  1. 5
      TODOnewNR.txt
  2. 3
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/CSharpSymbolSearch.cs
  3. 1
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  4. 18
      src/Main/Base/Project/Src/Editor/Commands/FindDerivedClassesOrOverrides.cs
  5. 30
      src/Main/Base/Project/Src/Services/ParserService/ParserService.cs
  6. 44
      src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsHelper.cs
  7. 135
      src/Main/Base/Project/Src/Services/RefactoringService/FindReferenceService.cs
  8. 13
      src/Main/Base/Project/Src/Services/RefactoringService/GoToClassAction.cs
  9. 58
      src/Main/Base/Project/Src/Services/RefactoringService/TypeGraphNode.cs
  10. 21
      src/Main/Base/Project/Src/Util/TreeNode.cs

5
TODOnewNR.txt

@ -1,10 +1,7 @@
 
Commented code, needs to be ported and re-enabled: Commented code, needs to be ported and re-enabled:
AssemblyParserService
ParseProjectContent ParseProjectContent
ProjectContentRegistryDescriptor
Ambiences Ambiences
Tooltips (DebuggerService.GetText)
DefinitionViewPad DefinitionViewPad
Class Browser (removed from source tree; to be reimplemented using WPF) Class Browser (removed from source tree; to be reimplemented using WPF)
NRefactoryLanguageConverter NRefactoryLanguageConverter
@ -29,7 +26,7 @@ Stuff that was renamed/moved:
Functionality changes: Functionality changes:
The result of a parser run (ParseInformation) now may contain a fully parsed AST. The result of a parser run (ParseInformation) now may contain a fully parsed AST.
The ParserService may cache such full ASTs, but may also drop them from memory at any time. The ParserService may cache such full ASTs, but may also drop them from memory at any time.
This is implemented by keeping the last N accessed files in the cache. This will be implemented by keeping the last N accessed files in the cache. (currently we just keep the caches around forever)
Every parse information also contains an IParsedFile instance with the type system information. Every parse information also contains an IParsedFile instance with the type system information.
The IParsedFile is stored permanently (both in ParserService and in the IProjectContents). The IParsedFile is stored permanently (both in ParserService and in the IProjectContents).

3
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/CSharpSymbolSearch.cs

@ -63,8 +63,7 @@ namespace CSharpBinding
} }
if (canReferenceEntity) { if (canReferenceEntity) {
var allTypesInPC = TreeTraversal.PreOrder(ctx.GetTypes().Where(t => t.ProjectContent == pc), t => t.NestedTypes); interestingFileNames[i] = fr.GetInterestingFileNames(searchScopes[i], pc.GetAllTypes(), ctx);
interestingFileNames[i] = fr.GetInterestingFileNames(searchScopes[i], allTypesInPC, ctx);
workAmount += interestingFileNames[i].Count; workAmount += interestingFileNames[i].Count;
} else { } else {
interestingFileNames[i] = new string[0]; interestingFileNames[i] = new string[0];

1
src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj

@ -369,6 +369,7 @@
<Compile Include="Src\Services\RefactoringService\FindReferenceService.cs" /> <Compile Include="Src\Services\RefactoringService\FindReferenceService.cs" />
<Compile Include="Src\Services\RefactoringService\GoToClassAction.cs" /> <Compile Include="Src\Services\RefactoringService\GoToClassAction.cs" />
<Compile Include="Src\Services\RefactoringService\GoToMemberAction.cs" /> <Compile Include="Src\Services\RefactoringService\GoToMemberAction.cs" />
<Compile Include="Src\Services\RefactoringService\TypeGraphNode.cs" />
<Compile Include="Src\Services\Tasks\ErrorPainter.cs" /> <Compile Include="Src\Services\Tasks\ErrorPainter.cs" />
<Compile Include="Src\Services\Tasks\TagComment.cs" /> <Compile Include="Src\Services\Tasks\TagComment.cs" />
<Compile Include="Src\Services\Tasks\Task.cs" /> <Compile Include="Src\Services\Tasks\Task.cs" />

18
src/Main/Base/Project/Src/Editor/Commands/FindDerivedClassesOrOverrides.cs

@ -1,9 +1,10 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
/*
using System; using System;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Refactoring; using ICSharpCode.SharpDevelop.Refactoring;
@ -16,15 +17,13 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands
{ {
protected override void RunImpl(ITextEditor editor, int offset, ResolveResult symbol) protected override void RunImpl(ITextEditor editor, int offset, ResolveResult symbol)
{ {
var classUnderCaret = GetClass(symbol); IEntity entityUnderCaret = GetEntity(symbol);
if (classUnderCaret != null) { if (entityUnderCaret is ITypeDefinition && !entityUnderCaret.IsSealed) {
ContextActionsHelper.MakePopupWithDerivedClasses(classUnderCaret).OpenAtCaretAndFocus(); ContextActionsHelper.MakePopupWithDerivedClasses((ITypeDefinition)entityUnderCaret).OpenAtCaretAndFocus();
return; return;
} }
var memberUnderCaret = GetMember(symbol); if (entityUnderCaret is IMember && ((IMember)entityUnderCaret).IsOverridable) {
if (memberUnderCaret != null && memberUnderCaret.IsOverridable) ContextActionsHelper.MakePopupWithOverrides((IMember)entityUnderCaret).OpenAtCaretAndFocus();
{
ContextActionsHelper.MakePopupWithOverrides(memberUnderCaret).OpenAtCaretAndFocus();
return; return;
} }
MessageService.ShowError("${res:ICSharpCode.Refactoring.NoClassOrOverridableSymbolUnderCursorError}"); MessageService.ShowError("${res:ICSharpCode.Refactoring.NoClassOrOverridableSymbolUnderCursorError}");
@ -42,4 +41,3 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands
// } // }
} }
} }
*/

30
src/Main/Base/Project/Src/Services/ParserService/ParserService.cs

@ -66,15 +66,33 @@ namespace ICSharpCode.SharpDevelop.Parser
/// </remarks> /// </remarks>
public static ITypeResolveContext CurrentTypeResolveContext { public static ITypeResolveContext CurrentTypeResolveContext {
get { get {
IProject currentProject = ProjectService.CurrentProject; return GetTypeResolveContext(ProjectService.CurrentProject);
if (currentProject != null) { }
return currentProject.TypeResolveContext ?? GetDefaultTypeResolveContext(); }
} else {
return GetDefaultTypeResolveContext(); public static ITypeResolveContext GetTypeResolveContext(IProject project)
} {
if (project != null) {
return project.TypeResolveContext;
} else {
return GetDefaultTypeResolveContext();
} }
} }
/// <summary>
/// Gets a type resolve context that includes all referenced assemblies for the specified project content.
/// </summary>
public static ITypeResolveContext GetTypeResolveContext(IProjectContent projectContent)
{
if (projectContent == null)
return GetDefaultTypeResolveContext();
IProject p = GetProject(projectContent);
if (p != null)
return p.TypeResolveContext;
else
return projectContent;
}
[Obsolete("Use project.ProjectContent instead")] [Obsolete("Use project.ProjectContent instead")]
public static IProjectContent GetProjectContent(IProject project) public static IProjectContent GetProjectContent(IProject project)
{ {

44
src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsHelper.cs

@ -5,29 +5,33 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.Core.Presentation; using ICSharpCode.Core.Presentation;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Refactoring; using ICSharpCode.SharpDevelop.Refactoring;
/*
namespace ICSharpCode.SharpDevelop.Refactoring namespace ICSharpCode.SharpDevelop.Refactoring
{ {
public class ContextActionsHelper public class ContextActionsHelper
{ {
public static ContextActionsPopup MakePopupWithDerivedClasses(IClass baseClass) public static ContextActionsPopup MakePopupWithDerivedClasses(ITypeDefinition baseClass)
{ {
var derivedClassesTree = RefactoringService.FindDerivedClassesTree(baseClass); var derivedClassesTree = FindReferenceService.BuildDerivedTypesGraph(baseClass).ConvertToDerivedTypeTree();
var popupViewModel = new ContextActionsViewModel { Title = MenuService.ConvertLabel(StringParser.Parse( var popupViewModel = new ContextActionsViewModel { Title = MenuService.ConvertLabel(StringParser.Parse(
"${res:SharpDevelop.Refactoring.ClassesDerivingFrom}", new StringTagPair("Name", baseClass.Name)))}; "${res:SharpDevelop.Refactoring.ClassesDerivingFrom}", new StringTagPair("Name", baseClass.Name)))};
popupViewModel.Actions = new PopupTreeViewModelBuilder().BuildTreeViewModel(derivedClassesTree); popupViewModel.Actions = new PopupTreeViewModelBuilder().BuildTreeViewModel(derivedClassesTree.Children);
return new ContextActionsPopup { Actions = popupViewModel, Symbol = baseClass }; return new ContextActionsPopup { Actions = popupViewModel, Symbol = baseClass };
} }
public static ContextActionsPopup MakePopupWithBaseClasses(IClass @class) public static ContextActionsPopup MakePopupWithBaseClasses(ITypeDefinition @class)
{ {
var baseClassList = @class.ClassInheritanceTree.Where( List<ITypeDefinition> baseClassList;
baseClass => (baseClass != @class) && (baseClass.CompilationUnit != null) && (baseClass.CompilationUnit.FileName != null)); using (var context = ParserService.GetTypeResolveContext(@class.ProjectContent).Synchronize()) {
@class = @class.GetDefinition();
baseClassList = @class.GetAllBaseTypeDefinitions(context).Where(
baseClass => (baseClass != @class) && (baseClass.ParsedFile != null)).ToList();
}
var popupViewModel = new ContextActionsViewModel { Title = MenuService.ConvertLabel(StringParser.Parse( var popupViewModel = new ContextActionsViewModel { Title = MenuService.ConvertLabel(StringParser.Parse(
"${res:SharpDevelop.Refactoring.BaseClassesOf}", new StringTagPair("Name", @class.Name)))}; "${res:SharpDevelop.Refactoring.BaseClassesOf}", new StringTagPair("Name", @class.Name)))};
popupViewModel.Actions = new PopupListViewModelBuilder().BuildListViewModel(baseClassList); popupViewModel.Actions = new PopupListViewModelBuilder().BuildListViewModel(baseClassList);
@ -36,14 +40,16 @@ namespace ICSharpCode.SharpDevelop.Refactoring
public static ContextActionsPopup MakePopupWithOverrides(IMember member) public static ContextActionsPopup MakePopupWithOverrides(IMember member)
{ {
var derivedClassesTree = RefactoringService.FindDerivedClassesTree(member.DeclaringType); #warning Reimplement MakePopupWithOverrides
throw new NotImplementedException();
/*var derivedClassesTree = RefactoringService.FindDerivedClassesTree(member.DeclaringType);
var popupViewModel = new ContextActionsViewModel { var popupViewModel = new ContextActionsViewModel {
Title = MenuService.ConvertLabel(StringParser.Parse( Title = MenuService.ConvertLabel(StringParser.Parse(
"${res:SharpDevelop.Refactoring.OverridesOf}", "${res:SharpDevelop.Refactoring.OverridesOf}",
new StringTagPair("Name", member.FullyQualifiedName)) new StringTagPair("Name", member.FullyQualifiedName))
)}; )};
popupViewModel.Actions = new OverridesPopupTreeViewModelBuilder(member).BuildTreeViewModel(derivedClassesTree); popupViewModel.Actions = new OverridesPopupTreeViewModelBuilder(member).BuildTreeViewModel(derivedClassesTree);
return new ContextActionsPopup { Actions = popupViewModel, Symbol = member }; return new ContextActionsPopup { Actions = popupViewModel, Symbol = member };*/
} }
class PopupViewModelBuilder class PopupViewModelBuilder
@ -56,10 +62,10 @@ namespace ICSharpCode.SharpDevelop.Refactoring
this.LabelAmbience.ConversionFlags = ConversionFlags.ShowTypeParameterList; this.LabelAmbience.ConversionFlags = ConversionFlags.ShowTypeParameterList;
} }
protected ContextActionViewModel MakeGoToClassAction(IClass @class, ObservableCollection<ContextActionViewModel> childActions) protected ContextActionViewModel MakeGoToClassAction(ITypeDefinition @class, ObservableCollection<ContextActionViewModel> childActions)
{ {
return new ContextActionViewModel { return new ContextActionViewModel {
Action = new GoToClassAction(@class, this.LabelAmbience), Action = new GoToClassAction(@class, this.LabelAmbience.ConvertEntity(@class)),
Image = ClassBrowserIconService.GetIcon(@class).ImageSource, Image = ClassBrowserIconService.GetIcon(@class).ImageSource,
Comment = string.Format("(in {0})", @class.Namespace), Comment = string.Format("(in {0})", @class.Namespace),
ChildActions = childActions ChildActions = childActions
@ -69,7 +75,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
class PopupListViewModelBuilder : PopupViewModelBuilder class PopupListViewModelBuilder : PopupViewModelBuilder
{ {
public ObservableCollection<ContextActionViewModel> BuildListViewModel(IEnumerable<IClass> classList) public ObservableCollection<ContextActionViewModel> BuildListViewModel(IEnumerable<ITypeDefinition> classList)
{ {
return new ObservableCollection<ContextActionViewModel>( return new ObservableCollection<ContextActionViewModel>(
classList.Select(@class => MakeGoToClassAction(@class, null))); classList.Select(@class => MakeGoToClassAction(@class, null)));
@ -78,7 +84,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
class PopupTreeViewModelBuilder : PopupViewModelBuilder class PopupTreeViewModelBuilder : PopupViewModelBuilder
{ {
public ObservableCollection<ContextActionViewModel> BuildTreeViewModel(IEnumerable<ITreeNode<IClass>> classTree) public ObservableCollection<ContextActionViewModel> BuildTreeViewModel(IEnumerable<ITreeNode<ITypeDefinition>> classTree)
{ {
return new ObservableCollection<ContextActionViewModel>( return new ObservableCollection<ContextActionViewModel>(
classTree.Select( classTree.Select(
@ -86,6 +92,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
} }
} }
/*
class OverridesPopupTreeViewModelBuilder : PopupViewModelBuilder class OverridesPopupTreeViewModelBuilder : PopupViewModelBuilder
{ {
IMember member; IMember member;
@ -97,7 +104,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
this.member = member; this.member = member;
} }
protected ContextActionViewModel MakeGoToMemberAction(IClass containingClass, ObservableCollection<ContextActionViewModel> childActions) protected ContextActionViewModel MakeGoToMemberAction(ITypeDefinition containingClass, ObservableCollection<ContextActionViewModel> childActions)
{ {
var overridenMember = MemberLookupHelper.FindSimilarMember(containingClass, this.member); var overridenMember = MemberLookupHelper.FindSimilarMember(containingClass, this.member);
if (overridenMember == null || overridenMember.Region.IsEmpty) if (overridenMember == null || overridenMember.Region.IsEmpty)
@ -106,18 +113,17 @@ namespace ICSharpCode.SharpDevelop.Refactoring
return new ContextActionViewModel { return new ContextActionViewModel {
Action = new GoToMemberAction(overridenMember, this.LabelAmbience), Action = new GoToMemberAction(overridenMember, this.LabelAmbience),
Image = ClassBrowserIconService.GetIcon(overridenMember).ImageSource, Image = ClassBrowserIconService.GetIcon(overridenMember).ImageSource,
Comment = string.Format("(in {0})", containingClass.FullyQualifiedName), Comment = string.Format("(in {0})", containingClass.FullName),
ChildActions = childActions ChildActions = childActions
}; };
} }
public ObservableCollection<ContextActionViewModel> BuildTreeViewModel(IEnumerable<ITreeNode<IClass>> classTree) public ObservableCollection<ContextActionViewModel> BuildTreeViewModel(IEnumerable<ITreeNode<ITypeDefinition>> classTree)
{ {
return new ObservableCollection<ContextActionViewModel>( return new ObservableCollection<ContextActionViewModel>(
classTree.Select( classTree.Select(
node => MakeGoToMemberAction(node.Content, BuildTreeViewModel(node.Children))).Where(action => action != null)); node => MakeGoToMemberAction(node.Content, BuildTreeViewModel(node.Children))).Where(action => action != null));
} }
} }*/
} }
} }
*/

135
src/Main/Base/Project/Src/Services/RefactoringService/FindReferenceService.cs

@ -3,9 +3,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading; using System.Threading;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
@ -17,20 +19,26 @@ namespace ICSharpCode.SharpDevelop.Refactoring
/// </summary> /// </summary>
public static class FindReferenceService public static class FindReferenceService
{ {
public static void FindReferences(IEntity entity, IProgressMonitor progressMonitor, Action<Reference> callback) #region FindReferences
static IEnumerable<IProject> GetProjectsThatCouldReferenceEntity(IEntity entity)
{ {
if (ParserService.LoadSolutionProjectsThreadRunning) { Solution solution = ProjectService.OpenSolution;
if (progressMonitor != null) progressMonitor.ShowingDialog = true; if (solution == null)
MessageService.ShowMessage("${res:SharpDevelop.Refactoring.LoadSolutionProjectsThreadRunning}"); yield break;
if (progressMonitor != null) progressMonitor.ShowingDialog = false; foreach (IProject project in solution.Projects) {
return; IProjectContent pc = project.ProjectContent;
if (pc == null)
continue;
yield return project;
} }
if (ProjectService.OpenSolution == null) }
return;
static List<ISymbolSearch> PrepareSymbolSearch(IEntity entity, CancellationToken cancellationToken, out double totalWorkAmount)
{
totalWorkAmount = 0;
List<ISymbolSearch> symbolSearches = new List<ISymbolSearch>(); List<ISymbolSearch> symbolSearches = new List<ISymbolSearch>();
double totalWorkAmount = 0; foreach (IProject project in GetProjectsThatCouldReferenceEntity(entity)) {
foreach (IProject project in ProjectService.OpenSolution.Projects) { cancellationToken.ThrowIfCancellationRequested();
progressMonitor.CancellationToken.ThrowIfCancellationRequested();
ISymbolSearch symbolSearch = project.PrepareSymbolSearch(entity); ISymbolSearch symbolSearch = project.PrepareSymbolSearch(entity);
if (symbolSearch != null) { if (symbolSearch != null) {
symbolSearches.Add(symbolSearch); symbolSearches.Add(symbolSearch);
@ -39,6 +47,19 @@ namespace ICSharpCode.SharpDevelop.Refactoring
} }
if (totalWorkAmount < 1) if (totalWorkAmount < 1)
totalWorkAmount = 1; totalWorkAmount = 1;
return symbolSearches;
}
public static void FindReferences(IEntity entity, IProgressMonitor progressMonitor, Action<Reference> callback)
{
if (ParserService.LoadSolutionProjectsThreadRunning) {
progressMonitor.ShowingDialog = true;
MessageService.ShowMessage("${res:SharpDevelop.Refactoring.LoadSolutionProjectsThreadRunning}");
progressMonitor.ShowingDialog = false;
return;
}
double totalWorkAmount;
List<ISymbolSearch> symbolSearches = PrepareSymbolSearch(entity, progressMonitor.CancellationToken, out totalWorkAmount);
double workDone = 0; double workDone = 0;
ParseableFileContentFinder parseableFileContentFinder = new ParseableFileContentFinder(); ParseableFileContentFinder parseableFileContentFinder = new ParseableFileContentFinder();
foreach (ISymbolSearch s in symbolSearches) { foreach (ISymbolSearch s in symbolSearches) {
@ -51,6 +72,98 @@ namespace ICSharpCode.SharpDevelop.Refactoring
progressMonitor.Progress = workDone / totalWorkAmount; progressMonitor.Progress = workDone / totalWorkAmount;
} }
} }
#endregion
#region FindDerivedTypes
/// <summary>
/// Finds all types that are derived from the given base type.
/// </summary>
public static IList<ITypeDefinition> FindDerivedTypes(ITypeDefinition baseType, bool directDerivationOnly)
{
if (baseType == null)
throw new ArgumentNullException("baseType");
baseType = baseType.GetDefinition(); // ensure we use the compound class
List<ITypeDefinition> results = new List<ITypeDefinition>();
foreach (IProject project in GetProjectsThatCouldReferenceEntity(baseType)) {
using (var ctx = project.TypeResolveContext.Synchronize()) {
foreach (ITypeDefinition typeDef in project.ProjectContent.GetAllTypes()) {
bool isDerived;
if (directDerivationOnly) {
isDerived = false;
foreach (IType t in typeDef.GetBaseTypes(ctx)) {
ITypeDefinition tdef = baseType.GetDefinition();
if (tdef == baseType) {
isDerived = true;
break;
}
}
} else {
isDerived = typeDef.IsDerivedFrom(baseType, ctx);
}
if (isDerived)
results.Add(typeDef);
}
}
}
return results;
}
/// <summary>
/// Builds a graph of derived type definitions.
/// </summary>
public static TypeGraphNode BuildDerivedTypesGraph(ITypeDefinition baseType)
{
if (baseType == null)
throw new ArgumentNullException("baseType");
IEnumerable<IProjectContent> projectContents = GetProjectsThatCouldReferenceEntity(baseType).Select(p => p.ProjectContent);
projectContents = projectContents.Union(new [] { baseType.ProjectContent });
var graph = BuildTypeInheritanceGraph(projectContents);
TypeGraphNode node;
if (graph.TryGetValue(baseType, out node)) {
node.BaseTypes.Clear(); // only derived types were requested, so don't return the base types
return node;
} else {
return new TypeGraphNode(baseType);
}
}
/// <summary>
/// Builds a graph of all type definitions in the specified set of project contents.
/// </summary>
/// <remarks>The resulting graph may be cyclic if there are cyclic type definitions.</remarks>
public static Dictionary<ITypeDefinition, TypeGraphNode> BuildTypeInheritanceGraph(IEnumerable<IProjectContent> projectContents)
{
if (projectContents == null)
throw new ArgumentNullException("projectContents");
Dictionary<ITypeDefinition, TypeGraphNode> dict = new Dictionary<ITypeDefinition, TypeGraphNode>();
using (var allContexts = new CompositeTypeResolveContext(projectContents).Synchronize()) { // lock all project contents
foreach (ITypeDefinition typeDef in allContexts.GetAllTypes()) {
dict.Add(typeDef, new TypeGraphNode(typeDef));
}
foreach (IProjectContent pc in projectContents) {
using (var context = ParserService.GetTypeResolveContext(pc).Synchronize()) {
foreach (ITypeDefinition typeDef in pc.GetAllTypes()) {
TypeGraphNode typeNode = dict[typeDef];
foreach (IType baseType in typeDef.GetBaseTypes(context)) {
ITypeDefinition baseTypeDef = baseType.GetDefinition();
if (baseTypeDef != null) {
TypeGraphNode baseTypeNode;
if (dict.TryGetValue(baseTypeDef, out baseTypeNode)) {
typeNode.BaseTypes.Add(baseTypeNode);
baseTypeNode.DerivedTypes.Add(typeNode);
}
}
}
}
}
}
}
return dict;
}
#endregion
} }
public class SymbolSearchArgs public class SymbolSearchArgs

13
src/Main/Base/Project/Src/Services/RefactoringService/GoToClassAction.cs

@ -2,23 +2,23 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.SharpDevelop.Refactoring namespace ICSharpCode.SharpDevelop.Refactoring
{ {
/*
public class GoToClassAction : IContextAction public class GoToClassAction : IContextAction
{ {
public string Title { get; private set; } public string Title { get; private set; }
public IClass Class { get; private set; } public ITypeDefinition Class { get; private set; }
public GoToClassAction(IClass c, IAmbience ambience) public GoToClassAction(ITypeDefinition c, string title)
{ {
if (ambience == null)
throw new ArgumentNullException("ambience");
if (c == null) if (c == null)
throw new ArgumentNullException("c"); throw new ArgumentNullException("c");
if (title == null)
throw new ArgumentNullException("title");
this.Class = c; this.Class = c;
this.Title = ambience.Convert(c); this.Title = title;
} }
public void Execute() public void Execute()
@ -26,5 +26,4 @@ namespace ICSharpCode.SharpDevelop.Refactoring
NavigationService.NavigateTo(this.Class); NavigationService.NavigateTo(this.Class);
} }
} }
*/
} }

58
src/Main/Base/Project/Src/Services/RefactoringService/TypeGraphNode.cs

@ -0,0 +1,58 @@
// 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 System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.SharpDevelop.Refactoring
{
public sealed class TypeGraphNode
{
internal readonly ITypeDefinition typeDef;
readonly List<TypeGraphNode> baseTypes = new List<TypeGraphNode>();
readonly List<TypeGraphNode> derivedTypes = new List<TypeGraphNode>();
public TypeGraphNode(ITypeDefinition typeDef)
{
this.typeDef = typeDef;
}
public ITypeDefinition TypeDefinition {
get { return typeDef; }
}
public IList<TypeGraphNode> DerivedTypes {
get { return derivedTypes; }
}
public IList<TypeGraphNode> BaseTypes {
get { return baseTypes; }
}
public ITreeNode<ITypeDefinition> ConvertToBaseTypeTree()
{
return TreeNode<ITypeDefinition>.FromGraph(this, n => n.baseTypes, n => n.typeDef);
}
public ITreeNode<ITypeDefinition> ConvertToDerivedTypeTree()
{
return TreeNode<ITypeDefinition>.FromGraph(this, n => n.derivedTypes, n => n.typeDef);
}
}
}

21
src/Main/Base/Project/Src/Util/TreeNode.cs

@ -16,7 +16,7 @@ namespace ICSharpCode.SharpDevelop
IEnumerable<ITreeNode<TContent>> Children { get; } IEnumerable<ITreeNode<TContent>> Children { get; }
} }
public class TreeNode<TContent> : ITreeNode<TContent> sealed class TreeNode<TContent> : ITreeNode<TContent>
{ {
public TreeNode(TContent content) public TreeNode(TContent content)
{ {
@ -33,5 +33,24 @@ namespace ICSharpCode.SharpDevelop
{ {
return string.Format("[TreeNode {0}]", this.Content.ToString()); return string.Format("[TreeNode {0}]", this.Content.ToString());
} }
public static TreeNode<TContent> FromGraph<GraphNode>(GraphNode rootNode, Func<GraphNode, IEnumerable<GraphNode>> children, Func<GraphNode, TContent> content)
{
HashSet<GraphNode> visited = new HashSet<GraphNode>();
return FromGraph(visited, rootNode, children, content);
}
static TreeNode<TContent> FromGraph<GraphNode>(HashSet<GraphNode> visited, GraphNode graphNode, Func<GraphNode, IEnumerable<GraphNode>> children, Func<GraphNode, TContent> content)
{
TreeNode<TContent> treeNode = new TreeNode<TContent>(content(graphNode));
List<TreeNode<TContent>> childList = new List<TreeNode<TContent>>();
foreach (GraphNode graphChild in children(graphNode)) {
if (visited.Add(graphChild)) { // every graph node may appear only once in the tree
childList.Add(FromGraph(visited, graphChild, children, content));
}
}
treeNode.Children = childList;
return treeNode;
}
} }
} }

Loading…
Cancel
Save