From 106b4414d04dc386e567e17afed3c654a2521e6a Mon Sep 17 00:00:00 2001 From: VladD2 Date: Thu, 14 May 2015 22:48:56 +0300 Subject: [PATCH] [Nitra.Visualizer] Improve visualization of dependent properties. --- Grammars/CSharp/CSharp.Grammar/Utils.n | 19 +++--- Nitra.Visualizer/MainWindow.xaml | 9 ++- .../MainWindow.xaml.Declarations.cs | 57 +++++++++++++++--- Nitra/Nitra.Runtime/Binding/Scope.n | 58 ++++++++++++++++--- 4 files changed, 114 insertions(+), 29 deletions(-) diff --git a/Grammars/CSharp/CSharp.Grammar/Utils.n b/Grammars/CSharp/CSharp.Grammar/Utils.n index 26aa5af04..878397e73 100644 --- a/Grammars/CSharp/CSharp.Grammar/Utils.n +++ b/Grammars/CSharp/CSharp.Grammar/Utils.n @@ -13,30 +13,27 @@ namespace CSharp { module Utils { - public EnterNamespace(mutable scope : Scope.Table, path : Reference.IAstList, namespaceDeclaration : Namespace) : Scope.Table + public EnterNamespace(mutable ns : NamespaceSymbol, path : Reference.IAstList, namespaceDeclaration : Namespace) : NamespaceSymbol { def lastIndex = path.Count - 1; foreach (name in path with i) { mutable symbol; - unless (scope.NameTable.TryGetValue(name, out symbol)) - { - symbol = NamespaceSymbol(name); - scope.Define(symbol); - } + unless (ns.Scope.NameTable.TryGetValue(name, out symbol)) + symbol = NamespaceSymbol(name, ns); when (i == lastIndex) symbol.Declarations ::= namespaceDeclaration; - scope = (symbol :> NamespaceSymbol).Scope; + ns = (symbol :> NamespaceSymbol); } - scope + ns } - public ExitNamespace(scopeIn : Scope.Table, scopeOut : Scope) : Scope.Table + public ExitNamespace(nsIn : NamespaceSymbol, nsOut : NamespaceSymbol) : NamespaceSymbol { - _ = scopeOut; - scopeIn + _ = nsOut; + nsIn } } } diff --git a/Nitra.Visualizer/MainWindow.xaml b/Nitra.Visualizer/MainWindow.xaml index bd069267b..93d390954 100644 --- a/Nitra.Visualizer/MainWindow.xaml +++ b/Nitra.Visualizer/MainWindow.xaml @@ -181,7 +181,14 @@ - + + + + + + + + diff --git a/Nitra.Visualizer/MainWindow.xaml.Declarations.cs b/Nitra.Visualizer/MainWindow.xaml.Declarations.cs index 78331495a..7eea4ad58 100644 --- a/Nitra.Visualizer/MainWindow.xaml.Declarations.cs +++ b/Nitra.Visualizer/MainWindow.xaml.Declarations.cs @@ -23,6 +23,9 @@ public partial class MainWindow { public TreeViewItem ObjectToItem(PropertyInfo prop, object obj) { + if (obj is Symbol2) + { + } string name = prop == null ? "" : prop.Name; var tvi = new TreeViewItem { Tag = obj, FontWeight = FontWeights.Normal }; tvi.MouseDoubleClick += TviOnMouseDoubleClick; @@ -81,6 +84,12 @@ public TreeViewItem ObjectToItem(PropertyInfo prop, object obj) { var xaml = RenderXamlForValue(prop, obj); tvi.Header = XamlReader.Parse(xaml); + + var t = obj.GetType(); + var props = t.GetProperties(); + if (!(obj is string || t.IsPrimitive) && props.Any(p => !IsIgnoredProperty(p))) + tvi.Items.Add(obj); + return tvi; } } @@ -134,6 +143,30 @@ private void TviOnExpanded(object sender, RoutedEventArgs routedEventArgs) tvi.Items.Add(ObjectToItem(null, item)); return; } + + { + var t = obj.GetType(); + + if (obj is string || t.IsPrimitive) + return; + + var props = t.GetProperties(); + + foreach (var prop in props) //.OrderBy(p => p.Name)) + { + if (IsIgnoredProperty(prop)) + continue; + try + { + var value = prop.GetValue(obj, null); + tvi.Items.Add(ObjectToItem(prop, value)); + } + catch (Exception e) + { + tvi.Items.Add(ObjectToItem(prop, e.Message)); + } + } + } } private static bool IsIgnoredProperty(PropertyInfo prop) @@ -157,7 +190,7 @@ private void UpdateDeclarations(AstRoot astRoot) dynamic ast = astRoot.Content; try { - ast.DefScopeIn = new Scope.Table(); + ast.NamespaceIn = NamespaceSymbol.RootNamespace; } catch { } astRoot.EvalProperties(new DebugCompilerMessages()); // TODO: display messages in GUI @@ -171,13 +204,18 @@ private void UpdateDeclarations(AstRoot astRoot) //} } + public static string Escape(string str) + { + return str.Replace("&", "&").Replace("<", "<").Replace(">", ">"); + } + private static string RenderXamlForDeclaration(string name, IAst ast) { var declatation = ast as IDeclaration; - var suffix = declatation == null ? null : (": " + declatation.Name); + var suffix = declatation == null ? null : (": " + Escape(declatation.Name.Text)); return @" -" + (string.IsNullOrWhiteSpace(name) ? null : ("" + name + ": ")) +" + (string.IsNullOrWhiteSpace(name) ? null : ("" + Escape(name) + ": ")) + ast.ToXaml() + suffix + @" "; } @@ -188,8 +226,8 @@ private static string RenderXamlForValue(PropertyInfo prop, object obj) var color = isDependent ? "green" : "SlateBlue"; return @" -" + (prop == null ? null : ("" + prop.Name + ": ")) - + obj + @" +" + (prop == null ? null : ("" + Escape(prop.Name) + ": ")) + + Escape(obj.ToString()) + @" "; } @@ -197,7 +235,7 @@ private static string RenderXamlForlist(string name, IAstList items) { return @" -" + name + @"* Count: " + items.Count + @" +" + Escape(name) + @"* Count: " + items.Count + @" "; } @@ -206,14 +244,17 @@ private static string RenderXamlForSeq(string name, int count) { return @" -" + name + @" (List) Count: " + count + @" +" + Escape(name) + @" (List) Count: " + count + @" "; } private void _declarationsTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs e) { if (e.NewValue != null) - _propertyGrid.SelectedObject = ((TreeViewItem)e.NewValue).Tag; + { + _propertyGrid.SelectedObject = ((TreeViewItem) e.NewValue).Tag; + _objectType.Text = _propertyGrid.SelectedObject.GetType().FullName; + } } private void TviOnMouseDoubleClick(object sender, MouseButtonEventArgs e) diff --git a/Nitra/Nitra.Runtime/Binding/Scope.n b/Nitra/Nitra.Runtime/Binding/Scope.n index 24af6ff10..88fe88081 100644 --- a/Nitra/Nitra.Runtime/Binding/Scope.n +++ b/Nitra/Nitra.Runtime/Binding/Scope.n @@ -16,21 +16,61 @@ namespace Nitra.Runtime.Binding [Record] public class Symbol2 { - public Name : IReference; - [RecordIgnore] public mutable Declarations : list [IDeclaration] = [] + public Name : IReference { get; } + [RecordIgnore] public Declarations : list [IDeclaration] { get; set; default []; } + + public override ToString() : string { Name?.Text + " (symbol)" } } - [Record] public class NamespaceSymbol : Symbol2 { - [RecordIgnore] public Scope : Scope.Table = Scope.Table(); + public static RootNamespace : NamespaceSymbol = NamespaceSymbol(null, null); + + public Parent : NamespaceSymbol { get; } + [RecordIgnore] public Scope : Scope.Table { get; set; default Scope.Table(); } + + public this(name : IReference, parent : NamespaceSymbol) + { + base(name); + + assert2(name == null && parent == null || name != null && parent != null); + + when (parent != null) + { + Parent = parent; + parent.Scope.Define(this); + } + } + + public FullName : string + { + get + { + def loop(ns : NamespaceSymbol, sb : Text.StringBuilder) : void + { + when (ns.Parent != null) + { + loop(ns.Parent, sb); + when (ns.Parent.Parent != null) + _ = sb.Append('.'); + _ = sb.Append(ns.Name); + } + } + + def sb = Text.StringBuilder(); + loop(this, sb); + sb.ToString() + } + } + + public override ToString() : string { (if (Name == null) "" else FullName) + " (namespace)" } } public variant Scope { | Table { - NameTable : Hashtable[IReference, Symbol2]; + public NameTable : Hashtable[IReference, Symbol2] { get; } public this() { NameTable = Hashtable(); } @@ -50,12 +90,12 @@ namespace Nitra.Runtime.Binding public override ToString() : string { - $"..$(NameTable.Keys)" + $"Scope.Table: { ..$(NameTable.Keys) }" } } - | Union { Scopes : list[Scope] } - | Hide { Scope : Scope; Hidden : Scope; } - | Filter { Scope : Scope; Predicate : Symbol -> bool; } + | Union { public Scopes : list[Scope] { get; } } + | Hide { public Scope : Scope { get; } public Hidden : Scope { get; } } + | Filter { public Scope : Scope { get; } public Predicate : Symbol -> bool { get; } } | Nil } }