22 changed files with 939 additions and 65 deletions
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
// 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)
|
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
using System.Windows.Controls; |
||||
using ICSharpCode.Core.Presentation; |
||||
using ICSharpCode.TreeView; |
||||
using ICSharpCode.SharpDevelop.Workbench; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Dom.ClassBrowser |
||||
{ |
||||
public class ClassBrowserTreeView : SharpTreeView, IClassBrowserTreeView |
||||
{ |
||||
ClassBrowserWorkspace currentWorkspace; |
||||
|
||||
public ClassBrowserTreeView() |
||||
{ |
||||
Workspace = ClassBrowserSettings.LoadDefaultWorkspace(); |
||||
} |
||||
|
||||
public ClassBrowserWorkspace Workspace { |
||||
get { return currentWorkspace; } |
||||
set { |
||||
if (currentWorkspace == value) |
||||
return; |
||||
currentWorkspace = value; |
||||
if (currentWorkspace != null) { |
||||
this.Root = new WorkspaceTreeNode(currentWorkspace); |
||||
this.ShowRoot = currentWorkspace.LoadedAssemblies.Count > 0 || !currentWorkspace.IsAssigned; |
||||
} else { |
||||
this.Root = null; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
public interface IClassBrowserTreeView |
||||
{ |
||||
|
||||
} |
||||
} |
@ -0,0 +1,84 @@
@@ -0,0 +1,84 @@
|
||||
// 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)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.NRefactory; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.NRefactory.TypeSystem.Implementation; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Dom.ClassBrowser |
||||
{ |
||||
/// <summary>
|
||||
/// Description of ClassBrowserWorkspace.
|
||||
/// </summary>
|
||||
public class ClassBrowserWorkspace |
||||
{ |
||||
ISolution assignedSolution; |
||||
IModelCollection<IUnresolvedAssembly> loadedAssemblies; |
||||
string workspaceName; |
||||
|
||||
public ClassBrowserWorkspace(ISolution assignedSolution, IEnumerable<IUnresolvedAssembly> assemblies = null) |
||||
: this(assignedSolution.FileName, assemblies) |
||||
{ |
||||
this.assignedSolution = assignedSolution; |
||||
} |
||||
|
||||
public ClassBrowserWorkspace(string workspaceName, IEnumerable<IUnresolvedAssembly> assemblies = null) |
||||
{ |
||||
this.workspaceName = workspaceName; |
||||
this.loadedAssemblies = new SimpleModelCollection<IUnresolvedAssembly>(assemblies ?? EmptyList<IUnresolvedAssembly>.Instance); |
||||
} |
||||
|
||||
public bool IsAssigned { |
||||
get { return assignedSolution != null; } |
||||
} |
||||
|
||||
public ISolution AssignedSolution { |
||||
get { return assignedSolution; } |
||||
} |
||||
|
||||
public string Name { |
||||
get { return workspaceName; } |
||||
} |
||||
|
||||
public IModelCollection<IUnresolvedAssembly> LoadedAssemblies { |
||||
get { return loadedAssemblies; } |
||||
} |
||||
} |
||||
|
||||
public static class ClassBrowserSettings |
||||
{ |
||||
static IUnresolvedAssembly[] LoadAssemblyList(string name) |
||||
{ |
||||
var assemblyNames = Container.GetList<string>("AssemblyList." + name); |
||||
CecilLoader loader = new CecilLoader(); |
||||
return assemblyNames.Select(loader.LoadAssemblyFile).ToArray(); |
||||
} |
||||
|
||||
static readonly Properties Container = SD.PropertyService.NestedProperties(typeof(ClassBrowserSettings).FullName); |
||||
|
||||
public static ClassBrowserWorkspace LoadDefaultWorkspace() |
||||
{ |
||||
return LoadWorkspace("<default>"); |
||||
} |
||||
|
||||
public static ClassBrowserWorkspace LoadWorkspace(string name) |
||||
{ |
||||
return new ClassBrowserWorkspace(name, LoadAssemblyList(name)); |
||||
} |
||||
|
||||
public static ClassBrowserWorkspace LoadForSolution(ISolution solution) |
||||
{ |
||||
return new ClassBrowserWorkspace(solution, LoadAssemblyList(solution.FileName)); |
||||
} |
||||
|
||||
public static void SaveWorkspace(ClassBrowserWorkspace workspace) |
||||
{ |
||||
|
||||
} |
||||
} |
||||
} |
@ -0,0 +1,186 @@
@@ -0,0 +1,186 @@
|
||||
// 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)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Windows.Media; |
||||
using ICSharpCode.NRefactory.Utils; |
||||
using ICSharpCode.TreeView; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Dom.ClassBrowser |
||||
{ |
||||
/// <summary>
|
||||
/// Description of WorkspaceTreeNode.
|
||||
/// </summary>
|
||||
public class WorkspaceTreeNode : ModelCollectionTreeNode |
||||
{ |
||||
ClassBrowserWorkspace workspace; |
||||
|
||||
public WorkspaceTreeNode(ClassBrowserWorkspace workspace) |
||||
{ |
||||
if (workspace == null) |
||||
throw new ArgumentNullException("workspace"); |
||||
this.workspace = workspace; |
||||
} |
||||
|
||||
protected override IModelCollection<object> ModelChildren { |
||||
get { return workspace.LoadedAssemblies; } |
||||
} |
||||
|
||||
protected override IComparer<SharpTreeNode> NodeComparer { |
||||
get { return NodeTextComparer; } |
||||
} |
||||
|
||||
public override object Text { |
||||
get { |
||||
return "Workspace " + workspace.Name; |
||||
} |
||||
} |
||||
|
||||
protected override bool IsSpecialNode() |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
protected override void InsertSpecialNodes() |
||||
{ |
||||
if (workspace.IsAssigned) { |
||||
InsertChildren(new[] { workspace.AssignedSolution }); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public class SolutionTreeNode : ModelCollectionTreeNode |
||||
{ |
||||
ISolution solution; |
||||
|
||||
public SolutionTreeNode(ISolution solution) |
||||
{ |
||||
if (solution == null) |
||||
throw new ArgumentNullException("solution"); |
||||
this.solution = solution; |
||||
} |
||||
|
||||
public override object Text { |
||||
get { return "Solution " + solution.Name; } |
||||
} |
||||
|
||||
public override object Icon { |
||||
get { return IconService.GetImageSource("Icons.16x16.SolutionIcon"); } |
||||
} |
||||
|
||||
protected override IComparer<SharpTreeNode> NodeComparer { |
||||
get { return NodeTextComparer; } |
||||
} |
||||
|
||||
protected override IModelCollection<object> ModelChildren { |
||||
get { return solution.Projects; } |
||||
} |
||||
} |
||||
|
||||
public class ProjectTreeNode : ModelCollectionTreeNode |
||||
{ |
||||
IProject project; |
||||
|
||||
public ProjectTreeNode(IProject project) |
||||
{ |
||||
if (project == null) |
||||
throw new ArgumentNullException("project"); |
||||
this.project = project; |
||||
} |
||||
|
||||
public override object Text { |
||||
get { return project.Name; } |
||||
} |
||||
|
||||
public override object Icon { |
||||
get { return IconService.GetImageSource(IconService.GetImageForProjectType(project.Language)); } |
||||
} |
||||
|
||||
protected override IComparer<SharpTreeNode> NodeComparer { |
||||
get { return NodeTextComparer; } |
||||
} |
||||
|
||||
protected override IModelCollection<object> ModelChildren { |
||||
get { return project.AssemblyModel.Namespaces; } |
||||
} |
||||
} |
||||
|
||||
public class AssemblyTreeNode : ModelCollectionTreeNode |
||||
{ |
||||
IAssemblyModel model; |
||||
|
||||
public AssemblyTreeNode(IAssemblyModel model) |
||||
{ |
||||
if (model == null) |
||||
throw new ArgumentNullException("model"); |
||||
this.model = model; |
||||
} |
||||
|
||||
protected override IComparer<SharpTreeNode> NodeComparer { |
||||
get { return NodeTextComparer; } |
||||
} |
||||
|
||||
protected override IModelCollection<object> ModelChildren { |
||||
get { return model.Namespaces; } |
||||
} |
||||
} |
||||
|
||||
public class NamespaceTreeNode : ModelCollectionTreeNode |
||||
{ |
||||
INamespaceModel model; |
||||
|
||||
public NamespaceTreeNode(INamespaceModel model) |
||||
{ |
||||
if (model == null) |
||||
throw new ArgumentNullException("model"); |
||||
this.model = model; |
||||
} |
||||
|
||||
protected override IComparer<SharpTreeNode> NodeComparer { |
||||
get { return NodeTextComparer; } |
||||
} |
||||
|
||||
protected override IModelCollection<object> ModelChildren { |
||||
get { return model.Types; } |
||||
} |
||||
|
||||
public override object Icon { |
||||
get { return ClassBrowserIconService.Namespace.ImageSource; } |
||||
} |
||||
|
||||
public override object Text { |
||||
get { return model.FullName; } |
||||
} |
||||
} |
||||
|
||||
public class TypeDefinitionTreeNode : ModelCollectionTreeNode |
||||
{ |
||||
ITypeDefinitionModel definition; |
||||
|
||||
public TypeDefinitionTreeNode(ITypeDefinitionModel definition) |
||||
{ |
||||
if (definition == null) |
||||
throw new ArgumentNullException("definition"); |
||||
this.definition = definition; |
||||
} |
||||
|
||||
public override object Icon { |
||||
// TODO why do I have to resolve this?
|
||||
get { return ClassBrowserIconService.GetIcon(definition.Resolve()).ImageSource; } |
||||
} |
||||
|
||||
public override object Text { |
||||
get { return definition.Name; } |
||||
} |
||||
|
||||
protected override IComparer<SharpTreeNode> NodeComparer { |
||||
get { return NodeTextComparer; } |
||||
} |
||||
|
||||
protected override IModelCollection<object> ModelChildren { |
||||
get { return definition.Members; } |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,50 @@
@@ -0,0 +1,50 @@
|
||||
// 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)
|
||||
|
||||
using System; |
||||
using System.Linq; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Dom |
||||
{ |
||||
public interface IAssemblyModel |
||||
{ |
||||
string Name { get; } |
||||
|
||||
ITypeDefinitionModelCollection TopLevelTypeDefinitions { get; } |
||||
IModelCollection<INamespaceModel> Namespaces { get; } |
||||
INamespaceModel RootNamespace { get; } |
||||
} |
||||
|
||||
public interface IUpdateableAssemblyModel : IAssemblyModel |
||||
{ |
||||
void Update(IUnresolvedFile oldFile, IUnresolvedFile newFile); |
||||
} |
||||
|
||||
public sealed class EmptyAssemblyModel : IAssemblyModel |
||||
{ |
||||
public readonly static IAssemblyModel Instance = new EmptyAssemblyModel(); |
||||
|
||||
EmptyAssemblyModel() |
||||
{ |
||||
} |
||||
|
||||
public string Name { |
||||
get { return string.Empty; } |
||||
} |
||||
|
||||
public ITypeDefinitionModelCollection TopLevelTypeDefinitions { |
||||
get { return EmptyTypeDefinitionModelCollection.Instance; } |
||||
} |
||||
|
||||
public IModelCollection<INamespaceModel> Namespaces { |
||||
get { return ImmutableModelCollection<INamespaceModel>.Empty; } |
||||
} |
||||
|
||||
public INamespaceModel RootNamespace { |
||||
get { return EmptyNamespaceModel.Instance; } |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
// 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)using System;
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Dom |
||||
{ |
||||
public class KeyedModelCollection<TKey, TValue> : SimpleModelCollection<TValue> |
||||
{ |
||||
Func<TValue, TKey> getKeyForValue; |
||||
Dictionary<TKey, TValue> dict; |
||||
|
||||
public KeyedModelCollection(Func<TValue, TKey> getKeyForValue, IEqualityComparer<TKey> comparer = null) |
||||
{ |
||||
if (getKeyForValue == null) |
||||
throw new ArgumentNullException("getKeyForValue"); |
||||
this.getKeyForValue = getKeyForValue; |
||||
this.dict = new Dictionary<TKey, TValue>(comparer ?? EqualityComparer<TKey>.Default); |
||||
} |
||||
|
||||
protected override void OnAdd(TValue item) |
||||
{ |
||||
base.OnAdd(item); |
||||
dict.Add(getKeyForValue(item), item); |
||||
} |
||||
|
||||
protected override void OnRemove(TValue item) |
||||
{ |
||||
base.OnRemove(item); |
||||
dict.Remove(getKeyForValue(item)); |
||||
} |
||||
|
||||
public TValue this[TKey key] { |
||||
get { return dict[key]; } |
||||
} |
||||
|
||||
public bool TryGetValue(TKey key, out TValue value) |
||||
{ |
||||
return dict.TryGetValue(key, out value); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
|
@ -0,0 +1,116 @@
@@ -0,0 +1,116 @@
|
||||
// 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)
|
||||
|
||||
using System; |
||||
using System.Collections; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using ICSharpCode.NRefactory.Utils; |
||||
using ICSharpCode.TreeView; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Dom |
||||
{ |
||||
public abstract class ModelCollectionTreeNode : SharpTreeNode |
||||
{ |
||||
protected static readonly IComparer<SharpTreeNode> NodeTextComparer = KeyComparer.Create((SharpTreeNode n) => n.Text.ToString(), StringComparer.OrdinalIgnoreCase, StringComparer.OrdinalIgnoreCase); |
||||
|
||||
protected ModelCollectionTreeNode() |
||||
{ |
||||
this.LazyLoading = true; |
||||
} |
||||
|
||||
protected abstract IModelCollection<object> ModelChildren { get; } |
||||
protected abstract IComparer<SharpTreeNode> NodeComparer { get; } |
||||
|
||||
protected virtual bool IsSpecialNode() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
protected virtual void InsertSpecialNodes() |
||||
{ |
||||
throw new NotSupportedException("this node is not a special node!"); |
||||
} |
||||
|
||||
protected virtual void DetachEventHandlers() |
||||
{ |
||||
// If children loaded, also detach the collection change event handler
|
||||
if (!LazyLoading) { |
||||
ModelChildren.CollectionChanged -= ModelChildrenCollectionChanged; |
||||
} |
||||
} |
||||
|
||||
protected override void OnIsVisibleChanged() |
||||
{ |
||||
base.OnIsVisibleChanged(); |
||||
|
||||
if (IsVisible) { |
||||
if (!LazyLoading) { |
||||
ModelChildren.CollectionChanged += ModelChildrenCollectionChanged; |
||||
SynchronizeModelChildren(); |
||||
} |
||||
} else { |
||||
ModelChildren.CollectionChanged -= ModelChildrenCollectionChanged; |
||||
} |
||||
} |
||||
|
||||
#region Manage Children
|
||||
protected override void LoadChildren() |
||||
{ |
||||
Children.Clear(); |
||||
if (IsSpecialNode()) |
||||
InsertSpecialNodes(); |
||||
InsertChildren(ModelChildren); |
||||
ModelChildren.CollectionChanged += ModelChildrenCollectionChanged; |
||||
} |
||||
|
||||
protected void InsertChildren(IEnumerable children) |
||||
{ |
||||
foreach (object child in children) { |
||||
var treeNode = SD.TreeNodeFactory.CreateTreeNode(child); |
||||
if (treeNode != null) |
||||
Children.OrderedInsert(treeNode, NodeComparer); |
||||
} |
||||
} |
||||
|
||||
void SynchronizeModelChildren() |
||||
{ |
||||
HashSet<object> set = new HashSet<object>(ModelChildren); |
||||
Children.RemoveAll(n => !set.Contains(n.Model)); |
||||
set.ExceptWith(Children.Select(n => n.Model)); |
||||
InsertChildren(set); |
||||
} |
||||
|
||||
void ModelChildrenCollectionChanged(IReadOnlyCollection<object> removedItems, IReadOnlyCollection<object> addedItems) |
||||
{ |
||||
if (!IsVisible) { |
||||
SwitchBackToLazyLoading(); |
||||
return; |
||||
} |
||||
Children.RemoveAll(n => removedItems.Contains(n.Model)); |
||||
InsertChildren(addedItems); |
||||
} |
||||
|
||||
void SwitchBackToLazyLoading() |
||||
{ |
||||
ModelChildren.CollectionChanged -= ModelChildrenCollectionChanged; |
||||
Children.Clear(); |
||||
LazyLoading = true; |
||||
} |
||||
#endregion
|
||||
} |
||||
|
||||
public class WaitForSolutionLoadedTreeNode : SharpTreeNode |
||||
{ |
||||
public WaitForSolutionLoadedTreeNode() |
||||
{ |
||||
this.LazyLoading = false; |
||||
} |
||||
|
||||
public override object Text { |
||||
get { |
||||
return "Waiting for solution load to be completed..."; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,88 @@
@@ -0,0 +1,88 @@
|
||||
// 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)
|
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
using System.Windows.Controls; |
||||
using ICSharpCode.Core.Presentation; |
||||
using ICSharpCode.TreeView; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using ICSharpCode.SharpDevelop.Workbench; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Dom.ClassBrowser |
||||
{ |
||||
public class ClassBrowserPad : AbstractPadContent |
||||
{ |
||||
IProjectService projectService; |
||||
ClassBrowserTreeView treeView; |
||||
DockPanel panel; |
||||
ToolBar toolBar; |
||||
|
||||
public ClassBrowserPad() |
||||
: this(SD.GetRequiredService<IProjectService>()) |
||||
{ |
||||
} |
||||
|
||||
public ClassBrowserPad(IProjectService projectService) |
||||
{ |
||||
this.projectService = projectService; |
||||
|
||||
panel = new DockPanel(); |
||||
treeView = new ClassBrowserTreeView(); // treeView must be created first because it's used by CreateToolBar
|
||||
|
||||
toolBar = CreateToolBar("/SharpDevelop/Pads/ClassBrowser/Toolbar"); |
||||
panel.Children.Add(toolBar); |
||||
DockPanel.SetDock(toolBar, Dock.Top); |
||||
|
||||
panel.Children.Add(treeView); |
||||
|
||||
//treeView.ContextMenu = CreateContextMenu("/SharpDevelop/Pads/UnitTestsPad/ContextMenu");
|
||||
|
||||
projectService.CurrentSolutionChanged += ProjectServiceCurrentSolutionChanged; |
||||
ProjectServiceCurrentSolutionChanged(null, null); |
||||
} |
||||
|
||||
public override void Dispose() |
||||
{ |
||||
projectService.CurrentSolutionChanged -= ProjectServiceCurrentSolutionChanged; |
||||
base.Dispose(); |
||||
} |
||||
|
||||
public override object Control { |
||||
get { return panel; } |
||||
} |
||||
|
||||
public IClassBrowserTreeView TreeView { |
||||
get { return treeView; } |
||||
} |
||||
|
||||
void ProjectServiceCurrentSolutionChanged(object sender, EventArgs e) |
||||
{ |
||||
if (projectService.CurrentSolution == null) { |
||||
treeView.Workspace = ClassBrowserSettings.LoadDefaultWorkspace(); |
||||
} else { |
||||
treeView.Workspace = ClassBrowserSettings.LoadForSolution(projectService.CurrentSolution); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Virtual method so we can override this method and return
|
||||
/// a dummy ToolBar when testing.
|
||||
/// </summary>
|
||||
protected virtual ToolBar CreateToolBar(string name) |
||||
{ |
||||
Debug.Assert(treeView != null); |
||||
return ToolBarService.CreateToolBar(treeView, treeView, name); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Virtual method so we can override this method and return
|
||||
/// a dummy ContextMenu when testing.
|
||||
/// </summary>
|
||||
protected virtual ContextMenu CreateContextMenu(string name) |
||||
{ |
||||
Debug.Assert(treeView != null); |
||||
return MenuService.CreateContextMenu(treeView, name); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
// 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)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Windows.Media; |
||||
using ICSharpCode.NRefactory.Utils; |
||||
using ICSharpCode.TreeView; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Dom.ClassBrowser |
||||
{ |
||||
public class WorkspaceTreeNodesFactory : ITreeNodeFactory |
||||
{ |
||||
public Type GetSupportedType(object model) |
||||
{ |
||||
if (model is ISolution) |
||||
return typeof(ISolution); |
||||
if (model is IProject) |
||||
return typeof(IProject); |
||||
if (model is INamespaceModel) |
||||
return typeof(INamespaceModel); |
||||
if (model is ITypeDefinitionModel) |
||||
return typeof(ITypeDefinitionModel); |
||||
return null; |
||||
} |
||||
|
||||
public SharpTreeNode CreateTreeNode(object model) |
||||
{ |
||||
if (model is ISolution) |
||||
return new SolutionTreeNode((ISolution)model); |
||||
if (model is IProject) |
||||
return new ProjectTreeNode((IProject)model); |
||||
if (model is INamespaceModel) |
||||
return new NamespaceTreeNode((INamespaceModel)model); |
||||
if (model is ITypeDefinitionModel) |
||||
return new TypeDefinitionTreeNode((ITypeDefinitionModel)model); |
||||
return null; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
@ -0,0 +1,77 @@
@@ -0,0 +1,77 @@
|
||||
// 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)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.ComponentModel; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.SharpDevelop.Parser; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
namespace ICSharpCode.SharpDevelop.Dom |
||||
{ |
||||
sealed class NamespaceModel : INamespaceModel |
||||
{ |
||||
IEntityModelContext context; |
||||
string name; |
||||
NamespaceModel parent; |
||||
NullSafeSimpleModelCollection<NamespaceModel> childNamespaces; |
||||
NullSafeSimpleModelCollection<ITypeDefinitionModel> typeDefinitions; |
||||
|
||||
public NamespaceModel(IEntityModelContext context, NamespaceModel parent, string name) |
||||
{ |
||||
if (context == null) |
||||
throw new ArgumentNullException("context"); |
||||
this.context = context; |
||||
this.parent = parent; |
||||
this.name = name; |
||||
this.typeDefinitions = new NullSafeSimpleModelCollection<ITypeDefinitionModel>(); |
||||
this.childNamespaces = new NullSafeSimpleModelCollection<NamespaceModel>(); |
||||
} |
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged; |
||||
|
||||
public string FullName { |
||||
get { |
||||
if (parent == null || string.IsNullOrEmpty(parent.name)) |
||||
return name; |
||||
return parent.name + "." + name; |
||||
} |
||||
} |
||||
|
||||
public INamespaceModel ParentNamespace { |
||||
get { return parent; } |
||||
} |
||||
|
||||
IModelCollection<INamespaceModel> INamespaceModel.ChildNamespaces { |
||||
get { return childNamespaces; } |
||||
} |
||||
|
||||
IModelCollection<ITypeDefinitionModel> INamespaceModel.Types { |
||||
get { return typeDefinitions; } |
||||
} |
||||
|
||||
public IMutableModelCollection<NamespaceModel> ChildNamespaces { |
||||
get { return childNamespaces; } |
||||
} |
||||
|
||||
public IMutableModelCollection<ITypeDefinitionModel> Types { |
||||
get { return typeDefinitions; } |
||||
} |
||||
|
||||
public string Name { |
||||
get { return name; } |
||||
} |
||||
|
||||
public SymbolKind SymbolKind { |
||||
get { return SymbolKind.Namespace; } |
||||
} |
||||
|
||||
public IProject ParentProject { |
||||
get { return context.Project; } |
||||
} |
||||
|
||||
public DomRegion Region { |
||||
get { return DomRegion.Empty; } |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,98 @@
@@ -0,0 +1,98 @@
|
||||
// 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)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.ComponentModel; |
||||
using System.Linq; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.SharpDevelop.Parser; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Dom |
||||
{ |
||||
sealed class ProjectAssemblyModel : IUpdateableAssemblyModel |
||||
{ |
||||
IEntityModelContext context; |
||||
TopLevelTypeDefinitionModelCollection typeDeclarations; |
||||
KeyedModelCollection<string, NamespaceModel> namespaces; |
||||
NamespaceModel rootNamespace; |
||||
|
||||
public ProjectAssemblyModel(IEntityModelContext context) |
||||
{ |
||||
if (context == null) |
||||
throw new ArgumentNullException("context"); |
||||
this.context = context; |
||||
this.rootNamespace = new NamespaceModel(context, null, ""); |
||||
this.typeDeclarations = new TopLevelTypeDefinitionModelCollection(context); |
||||
this.typeDeclarations.CollectionChanged += TypeDeclarationsCollectionChanged; |
||||
this.namespaces = new KeyedModelCollection<string, NamespaceModel>(value => value.FullName); |
||||
} |
||||
|
||||
public string Name { |
||||
get { |
||||
return context.Project.AssemblyName; |
||||
} |
||||
} |
||||
|
||||
public ITypeDefinitionModelCollection TopLevelTypeDefinitions { |
||||
get { |
||||
return typeDeclarations; |
||||
} |
||||
} |
||||
|
||||
public IModelCollection<INamespaceModel> Namespaces { |
||||
get { |
||||
return namespaces; |
||||
} |
||||
} |
||||
|
||||
public INamespaceModel RootNamespace { |
||||
get { |
||||
return rootNamespace; |
||||
} |
||||
} |
||||
|
||||
public void Update(IUnresolvedFile oldFile, IUnresolvedFile newFile) |
||||
{ |
||||
typeDeclarations.Update(oldFile, newFile); |
||||
} |
||||
|
||||
void TypeDeclarationsCollectionChanged(IReadOnlyCollection<ITypeDefinitionModel> removedItems, IReadOnlyCollection<ITypeDefinitionModel> addedItems) |
||||
{ |
||||
NamespaceModel ns; |
||||
foreach (ITypeDefinitionModel removedItem in removedItems) { |
||||
if (namespaces.TryGetValue(removedItem.Namespace, out ns)) { |
||||
ns.Types.Remove(removedItem); |
||||
while (ns.ParentNamespace != null && ns.Types.Count == 0 && ns.ChildNamespaces.Count == 0) { |
||||
((NamespaceModel)ns.ParentNamespace).ChildNamespaces.Remove(ns); |
||||
namespaces.Remove(ns); |
||||
ns = (NamespaceModel)ns.ParentNamespace; |
||||
} |
||||
} |
||||
} |
||||
foreach (ITypeDefinitionModel addedItem in addedItems) { |
||||
if (!namespaces.TryGetValue(addedItem.Namespace, out ns)) { |
||||
string[] parts = addedItem.Namespace.Split('.'); |
||||
int level = 0; |
||||
ns = rootNamespace; |
||||
while (level < parts.Length) { |
||||
var nextNS = ns.ChildNamespaces |
||||
.FirstOrDefault(n => n.Name == parts[level]); |
||||
if (nextNS == null) break; |
||||
ns = nextNS; |
||||
level++; |
||||
} |
||||
while (level < parts.Length) { |
||||
ns = new NamespaceModel(context, ns, parts[level]); |
||||
namespaces.Add(ns); |
||||
level++; |
||||
} |
||||
ns.Types.Add(addedItem); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
Loading…
Reference in new issue