5
// Mike KrĆ¼ger <mkrueger@xamarin.com>
7
// Copyright (c) 2011 Xamarin Inc. (http://xamarin.com)
9
// Permission is hereby granted, free of charge, to any person obtaining a copy
10
// of this software and associated documentation files (the "Software"), to deal
11
// in the Software without restriction, including without limitation the rights
12
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
// copies of the Software, and to permit persons to whom the Software is
14
// furnished to do so, subject to the following conditions:
16
// The above copyright notice and this permission notice shall be included in
17
// all copies or substantial portions of the Software.
19
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
using ICSharpCode.NRefactory.CSharp;
31
using System.Reflection;
32
using ICSharpCode.NRefactory.CSharp.Resolver;
33
using ICSharpCode.NRefactory.Semantics;
34
using System.Collections.Generic;
35
using ICSharpCode.NRefactory.TypeSystem;
36
using System.Threading.Tasks;
38
using System.Threading;
39
using System.Diagnostics;
41
namespace ICSharpCode.NRefactory.GtkDemo
43
public partial class MainWindow : Gtk.Window
45
TreeStore store = new TreeStore (typeof (string), typeof (string), typeof (AstNode), typeof (Pixbuf));
46
Dictionary<AstNode, TreeIter> iterDict = new Dictionary<AstNode, TreeIter> ();
47
// TextEditor editor = new TextEditor ();
50
Pixbuf comment = new Pixbuf (typeof (MainWindow).Assembly, "comment.png");
51
Pixbuf classPixbuf = new Pixbuf (typeof (MainWindow).Assembly, "class.png");
52
Pixbuf tokenPixbuf = new Pixbuf (typeof (MainWindow).Assembly, "token.png");
53
Pixbuf statementPixbuf = new Pixbuf (typeof (MainWindow).Assembly, "statement.png");
54
Pixbuf expressionPixbuf = new Pixbuf (typeof (MainWindow).Assembly, "expression.png");
55
Pixbuf namespacePixbuf = new Pixbuf (typeof (MainWindow).Assembly, "namespace.png");
57
public MainWindow () :
58
base(Gtk.WindowType.Toplevel)
61
this.BorderWidth = 12;
62
this.treeviewNodes.Model = store;
63
var col =new TreeViewColumn ();
65
var pb = new CellRendererPixbuf ();
66
col.PackStart (pb, false);
67
col.AddAttribute (pb, "pixbuf", 3);
69
var text = new CellRendererText ();
70
col.PackStart (text, true);
71
col.AddAttribute (text, "text", 0);
73
this.treeviewNodes.AppendColumn (col);
74
this.treeviewNodes.AppendColumn ("ResolveResult", new CellRendererText (), "text", 1);
75
this.treeviewNodes.Selection.Changed += SelectionChanged;
76
// this.treeviewNodes.HeadersVisible = false;
77
this.textview1.ModifyFont (Pango.FontDescription.FromString ("Mono 14"));
78
this.textview1.MoveCursor += HandleMoveCursor;
79
string path = System.IO.Path.Combine (System.IO.Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location), "CSharpDemo.cs");
80
this.textview1.Buffer.Text = File.ReadAllText (path);
81
buttonParse.Clicked += HandleClicked;
82
buttonGenerate.Clicked += CSharpGenerateCodeButtonClick;
83
HandleClicked (this, EventArgs.Empty);
85
protected override void OnDestroyed ()
91
void HandleMoveCursor (object o, MoveCursorArgs args)
93
int cp = textview1.Buffer.CursorPosition;
94
var textIter = textview1.Buffer.GetIterAtOffset (cp);
95
var node = unit.GetNodeAt (textIter.Line + 1, textIter.LineOffset + 1);
99
if (!iterDict.TryGetValue (node, out iter))
101
this.treeviewNodes.Selection.Changed -= SelectionChanged;
102
treeviewNodes.Selection.SelectIter (iter);
104
treeviewNodes.ScrollToCell (store.GetPath (iter), null, true, 0, 0);
105
this.treeviewNodes.Selection.Changed += SelectionChanged;
108
void CSharpGenerateCodeButtonClick(object sender, EventArgs e)
110
this.textview1.Buffer.Text = unit.GetText();
113
void SelectionChanged (object sender, EventArgs e)
117
if (!this.treeviewNodes.Selection.GetSelected (out iter))
119
var node = store.GetValue (iter, 2) as AstNode;
122
this.textview1.MoveCursor -= HandleMoveCursor;
123
if (node.StartLocation.IsEmpty || node.EndLocation.IsEmpty)
125
var textIter = this.textview1.Buffer.GetIterAtLineOffset (node.StartLocation.Line - 1, node.StartLocation.Column - 1);
126
this.textview1.ScrollToIter (textIter, 0, false, 0, 0);
127
this.textview1.Buffer.PlaceCursor (textIter);
128
this.textview1.Buffer.SelectRange (textIter, this.textview1.Buffer.GetIterAtLineOffset (node.EndLocation.Line -1, node.EndLocation.Column - 1));
129
this.textview1.MoveCursor += HandleMoveCursor;
133
public void ShowUnit (SyntaxTree unit, CSharpAstResolver visitor)
140
var iter = store.AppendValues (GetNodeTitle (unit), "", unit, GetIcon (unit));
141
AddChildren (unit, visitor, iter);
142
treeviewNodes.ExpandAll ();
145
public Pixbuf GetIcon (AstNode child)
147
if (child is Comment)
149
if (child is PreProcessorDirective)
151
if (child is EntityDeclaration)
153
if (child is CSharpTokenNode)
155
if (child is Identifier)
157
if (child is Statement)
158
return statementPixbuf;
159
if (child is Expression)
160
return expressionPixbuf;
161
if (child is UsingDeclaration)
162
return namespacePixbuf;
163
if (child is NamespaceDeclaration)
164
return namespacePixbuf;
169
public void AddChildren (AstNode node, CSharpAstResolver visitor, TreeIter iter)
173
iterDict [node] = iter;
174
foreach (var child in node.Children) {
175
ResolveResult result = null;
177
if (child is Expression)
178
result = visitor.Resolve (child, CancellationToken.None);
183
var childIter = store.AppendValues (iter, GetNodeTitle (child), result != null ? result.ToString () : "", child, GetIcon (child));
184
AddChildren (child, visitor, childIter);
188
string GetNodeTitle(AstNode node)
190
var b = new StringBuilder();
191
b.Append(node.Role.ToString());
193
b.Append(node.GetType().Name);
194
bool hasProperties = false;
195
foreach (PropertyInfo p in node.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) {
196
if (p.Name == "NodeType" || p.Name == "IsNull")
198
if (p.PropertyType == typeof(string) || p.PropertyType.IsEnum || p.PropertyType == typeof(bool)) {
199
if (!hasProperties) {
200
hasProperties = true;
208
object val = p.GetValue(node, null);
209
b.Append(val != null ? val.ToString() : "**null**");
210
} catch (TargetInvocationException ex) {
211
b.Append("**" + ex.InnerException.GetType().Name + "**");
217
b.Append (node.StartLocation + "-" + node.EndLocation);
218
// b.Append(" Start " + node.StartLocation);
219
// b.Append(" End " + node.EndLocation);
223
void HandleClicked (object sender, EventArgs e)
225
var parser = new CSharpParser ();
226
var unit = parser.Parse (textview1.Buffer.Text, "dummy.cs");
228
var unresolvedFile = unit.ToTypeSystem();
230
IProjectContent project = new CSharpProjectContent ();
231
project = project.AddOrUpdateFiles (unresolvedFile);
232
project = project.AddAssemblyReferences (builtInLibs.Value);
235
CSharpAstResolver resolver = new CSharpAstResolver(project.CreateCompilation (), unit, unresolvedFile);
236
ShowUnit (unit, resolver);
240
Lazy<IList<IUnresolvedAssembly>> builtInLibs = new Lazy<IList<IUnresolvedAssembly>>(
242
Assembly[] assemblies = new Assembly[] {
243
typeof(object).Assembly, // mscorlib
244
typeof(Uri).Assembly, // System.dll
245
typeof(System.Linq.Enumerable).Assembly, // System.Core.dll
246
// typeof(System.Xml.XmlDocument).Assembly, // System.Xml.dll
247
// typeof(System.Drawing.Bitmap).Assembly, // System.Drawing.dll
248
// typeof(Form).Assembly, // System.Windows.Forms.dll
249
typeof(ICSharpCode.NRefactory.TypeSystem.IProjectContent).Assembly,
251
IUnresolvedAssembly[] projectContents = new IUnresolvedAssembly[assemblies.Length];
253
0, assemblies.Length,
255
Stopwatch w = Stopwatch.StartNew();
256
CecilLoader loader = new CecilLoader();
257
projectContents[i] = loader.LoadAssemblyFile(assemblies[i].Location);
259
return projectContents;