You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							247 lines
						
					
					
						
							7.6 KiB
						
					
					
				
			
		
		
	
	
							247 lines
						
					
					
						
							7.6 KiB
						
					
					
				// SharpDevelop samples | 
						|
// Copyright (c) 2006, AlphaSierraPapa | 
						|
// All rights reserved. | 
						|
// | 
						|
// Redistribution and use in source and binary forms, with or without modification, are | 
						|
// permitted provided that the following conditions are met: | 
						|
// | 
						|
// - Redistributions of source code must retain the above copyright notice, this list | 
						|
//   of conditions and the following disclaimer. | 
						|
// | 
						|
// - Redistributions in binary form must reproduce the above copyright notice, this list | 
						|
//   of conditions and the following disclaimer in the documentation and/or other materials | 
						|
//   provided with the distribution. | 
						|
// | 
						|
// - Neither the name of the SharpDevelop team nor the names of its contributors may be used to | 
						|
//   endorse or promote products derived from this software without specific prior written | 
						|
//   permission. | 
						|
// | 
						|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &AS IS& AND ANY EXPRESS | 
						|
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY | 
						|
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | 
						|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
						|
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
						|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER | 
						|
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | 
						|
// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
						|
 | 
						|
using System; | 
						|
using System.Collections; | 
						|
using System.Windows.Forms; | 
						|
using System.Reflection; | 
						|
 | 
						|
using ICSharpCode.NRefactory.Ast; | 
						|
using ICSharpCode.NRefactory; | 
						|
 | 
						|
namespace NRefactoryDemo | 
						|
{ | 
						|
	public partial class AstView | 
						|
	{ | 
						|
		CompilationUnit unit; | 
						|
		 | 
						|
		public CompilationUnit Unit { | 
						|
			get { | 
						|
				return unit; | 
						|
			} | 
						|
			set { | 
						|
				unit = value; | 
						|
				UpdateTree(); | 
						|
			} | 
						|
		} | 
						|
		 | 
						|
		void UpdateTree() | 
						|
		{ | 
						|
			tree.Nodes.Clear(); | 
						|
			tree.Nodes.Add(new CollectionNode("CompilationUnit", unit.Children)); | 
						|
			tree.SelectedNode = tree.Nodes[0]; | 
						|
		} | 
						|
		 | 
						|
		public AstView() | 
						|
		{ | 
						|
			InitializeComponent(); | 
						|
		} | 
						|
		 | 
						|
		public void DeleteSelectedNode() | 
						|
		{ | 
						|
			if (tree.SelectedNode is ElementNode) { | 
						|
				INode element = (tree.SelectedNode as ElementNode).element; | 
						|
				if (tree.SelectedNode.Parent is CollectionNode) { | 
						|
					if (MessageBox.Show("Remove selected node from parent collection?", "Remove node", MessageBoxButtons.YesNo, MessageBoxIcon.Question) | 
						|
					    == DialogResult.Yes) | 
						|
					{ | 
						|
						IList col = (tree.SelectedNode.Parent as CollectionNode).collection; | 
						|
						col.Remove(element); | 
						|
						(tree.SelectedNode.Parent as CollectionNode).Update(); | 
						|
					} | 
						|
				} else if (tree.SelectedNode.Parent is ElementNode) { | 
						|
					if (MessageBox.Show("Set selected property to null?", "Remove node", MessageBoxButtons.YesNo, MessageBoxIcon.Question) | 
						|
					    == DialogResult.Yes) | 
						|
					{ | 
						|
						// get parent element | 
						|
						element = (tree.SelectedNode.Parent as ElementNode).element; | 
						|
						string propertyName = (string)tree.SelectedNode.Tag; | 
						|
						element.GetType().GetProperty(propertyName).SetValue(element, null, null); | 
						|
						(tree.SelectedNode.Parent as ElementNode).Update(); | 
						|
					} | 
						|
				} | 
						|
			} else if (tree.SelectedNode is CollectionNode) { | 
						|
				if (MessageBox.Show("Remove all elements from selected collection?", "Clear collection", MessageBoxButtons.YesNo, MessageBoxIcon.Question) | 
						|
				    == DialogResult.Yes) | 
						|
				{ | 
						|
					IList col = (tree.SelectedNode as CollectionNode).collection; | 
						|
					col.Clear(); | 
						|
					(tree.SelectedNode as CollectionNode).Update(); | 
						|
				} | 
						|
			} | 
						|
		} | 
						|
		 | 
						|
		public void EditSelectedNode() | 
						|
		{ | 
						|
			TreeNode node = tree.SelectedNode; | 
						|
			while (!(node is ElementNode)) { | 
						|
				if (node == null) { | 
						|
					return; | 
						|
				} | 
						|
				node = node.Parent; | 
						|
			} | 
						|
			INode element = ((ElementNode)node).element; | 
						|
			using (EditDialog dlg = new EditDialog(element)) { | 
						|
				dlg.ShowDialog(); | 
						|
			} | 
						|
			((ElementNode)node).Update(); | 
						|
		} | 
						|
		 | 
						|
		public void ApplyTransformation(IAstVisitor visitor) | 
						|
		{ | 
						|
			if (tree.SelectedNode == tree.Nodes[0]) { | 
						|
				unit.AcceptVisitor(visitor, null); | 
						|
				UpdateTree(); | 
						|
			} else { | 
						|
				string name = visitor.GetType().Name; | 
						|
				ElementNode elementNode = tree.SelectedNode as ElementNode; | 
						|
				CollectionNode collectionNode = tree.SelectedNode as CollectionNode; | 
						|
				if (elementNode != null) { | 
						|
					if (MessageBox.Show(("Apply " + name + " to selected element '" + elementNode.Text + "'?"), | 
						|
					                    "Apply transformation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) | 
						|
					    == DialogResult.Yes) | 
						|
					{ | 
						|
						elementNode.element.AcceptVisitor(visitor, null); | 
						|
						elementNode.Update(); | 
						|
					} | 
						|
				} else if (collectionNode != null) { | 
						|
					if (MessageBox.Show(("Apply " + name + " to all elements in selected collection '" + collectionNode.Text + "'?"), | 
						|
					                    "Apply transformation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) | 
						|
					    == DialogResult.Yes) | 
						|
					{ | 
						|
						foreach (TreeNode subNode in collectionNode.Nodes) { | 
						|
							if (subNode is ElementNode) { | 
						|
								(subNode as ElementNode).element.AcceptVisitor(visitor, null); | 
						|
							} | 
						|
						} | 
						|
						collectionNode.Update(); | 
						|
					} | 
						|
				} | 
						|
			} | 
						|
		} | 
						|
		 | 
						|
		static TreeNode CreateNode(object child) | 
						|
		{ | 
						|
			if (child == null) { | 
						|
				return new TreeNode("*null reference*"); | 
						|
			} else if (child is INode) { | 
						|
				return new ElementNode(child as INode); | 
						|
			} else { | 
						|
				return new TreeNode(child.ToString()); | 
						|
			} | 
						|
		} | 
						|
		 | 
						|
		class CollectionNode : TreeNode | 
						|
		{ | 
						|
			internal IList collection; | 
						|
			string baseName; | 
						|
			 | 
						|
			public CollectionNode(string text, IList children) : base(text) | 
						|
			{ | 
						|
				this.baseName = text; | 
						|
				this.collection = children; | 
						|
				Update(); | 
						|
			} | 
						|
			 | 
						|
			public void Update() | 
						|
			{ | 
						|
				if (collection.Count == 0) { | 
						|
					Text = baseName + " (empty collection)"; | 
						|
				} else if (collection.Count == 1) { | 
						|
					Text = baseName + " (collection with 1 element)"; | 
						|
				} else { | 
						|
					Text = baseName + " (collection with " + collection.Count + " elements)"; | 
						|
				} | 
						|
				Nodes.Clear(); | 
						|
				foreach (object child in collection) { | 
						|
					Nodes.Add(CreateNode(child)); | 
						|
				} | 
						|
				Expand(); | 
						|
			} | 
						|
		} | 
						|
		 | 
						|
		class ElementNode : TreeNode | 
						|
		{ | 
						|
			internal INode element; | 
						|
			 | 
						|
			public ElementNode(INode node) | 
						|
			{ | 
						|
				this.element = node; | 
						|
				Update(); | 
						|
			} | 
						|
			 | 
						|
			public void Update() | 
						|
			{ | 
						|
				Nodes.Clear(); | 
						|
				Type type = element.GetType(); | 
						|
				Text = type.Name; | 
						|
				if (Tag != null) { // HACK: after editing property element | 
						|
					Text = Tag.ToString() + " = " + Text; | 
						|
				} | 
						|
				if (!(element is INullable && (element as INullable).IsNull)) { | 
						|
					AddProperties(type, element); | 
						|
					if (element.Children.Count > 0) { | 
						|
						Nodes.Add(new CollectionNode("Children", element.Children)); | 
						|
					} | 
						|
				} | 
						|
			} | 
						|
			 | 
						|
			void AddProperties(Type type, INode node) | 
						|
			{ | 
						|
				if (type == typeof(AbstractNode)) | 
						|
					return; | 
						|
				foreach (PropertyInfo pi in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { | 
						|
					if (pi.DeclaringType != type) // don't add derived properties | 
						|
						continue; | 
						|
					if (pi.Name == "IsNull") | 
						|
						continue; | 
						|
					object value = pi.GetValue(node, null); | 
						|
					if (value is IList) { | 
						|
						Nodes.Add(new CollectionNode(pi.Name, (IList)value)); | 
						|
					} else if (value is string) { | 
						|
						Text += " " + pi.Name + "='" + value + "'"; | 
						|
					} else { | 
						|
						TreeNode treeNode = CreateNode(value); | 
						|
						treeNode.Text = pi.Name + " = " + treeNode.Text; | 
						|
						treeNode.Tag = pi.Name; | 
						|
						Nodes.Add(treeNode); | 
						|
					} | 
						|
				} | 
						|
				AddProperties(type.BaseType, node); | 
						|
			} | 
						|
		} | 
						|
		 | 
						|
		void TreeKeyDown(object sender, KeyEventArgs e) | 
						|
		{ | 
						|
			if (e.KeyData == Keys.Delete) { | 
						|
				DeleteSelectedNode(); | 
						|
			} else if (e.KeyData == Keys.Space || e.KeyData == Keys.Enter) { | 
						|
				EditSelectedNode(); | 
						|
			} | 
						|
		} | 
						|
	} | 
						|
}
 | 
						|
 |