Skip to content

Commit

Permalink
Merge pull request #634 from bernd5/master
Browse files Browse the repository at this point in the history
Fix Symbol View In SyntaxTreeVizualizer
  • Loading branch information
jmarolf authored Oct 2, 2020
2 parents 90e6dc7 + e820661 commit 223d750
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.ComponentModel;

namespace Roslyn.SyntaxVisualizer.Control.SymbolDisplay
{
internal abstract class BasePropertyGridAdapter : ICustomTypeDescriptor
{
public virtual AttributeCollection GetAttributes() => TypeDescriptor.GetAttributes(this, true);
public virtual string GetClassName() => TypeDescriptor.GetClassName(this, true);
public virtual string GetComponentName() => TypeDescriptor.GetClassName(this, true);
public virtual TypeConverter GetConverter() => TypeDescriptor.GetConverter(this, true);
public virtual EventDescriptor GetDefaultEvent() => TypeDescriptor.GetDefaultEvent(this, true);
public virtual PropertyDescriptor GetDefaultProperty() => TypeDescriptor.GetDefaultProperty(this, true);
public virtual object GetEditor(Type editorBaseType) => TypeDescriptor.GetEditor(this, editorBaseType, true);
public virtual EventDescriptorCollection GetEvents() => TypeDescriptor.GetEvents(this, true);
public virtual EventDescriptorCollection GetEvents(Attribute[] attributes) => TypeDescriptor.GetEvents(this, attributes, true);
public virtual PropertyDescriptorCollection GetProperties() => TypeDescriptor.GetProperties(this, true);
public virtual PropertyDescriptorCollection GetProperties(Attribute[] attributes) => TypeDescriptor.GetProperties(this, attributes, true);
public virtual object GetPropertyOwner(PropertyDescriptor pd) => null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;

#nullable enable

namespace Roslyn.SyntaxVisualizer.Control.SymbolDisplay
{
internal class SymbolPropertyGridAdapter : BasePropertyGridAdapter
{
private readonly Dictionary<string, string> _dictionary;

public SymbolPropertyGridAdapter(object symbol) => _dictionary = CreateDictionary(symbol);

private static string GetStringValueOf(object obj)
{
var stringResult = obj switch
{
bool b => b.ToString(),
int i => i.ToString(),
string s => s.Length > 0 ? s : "None",
IEnumerable<object> e => string.Join(", ", e.Select(x => GetStringValueOf(x))),
null => "<null>",
object o => o.ToString(),
};
return stringResult;
}

private Dictionary<string, string> CreateDictionary(object symbol)
{
var dictionry = new Dictionary<string, string>();
var type = symbol.GetType();

foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
{

try
{
var value = property.GetValue(symbol, null);
var strVal = GetStringValueOf(value);
dictionry[property.Name] = strVal;
}
catch
{

}
}

var objectMethods = typeof(object).GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
{
if (method.GetParameters().Length == 0 && IsNotInObjectType(method, objectMethods))
{
try
{
var name = method.Name.Split('_').Last();
var result = method.Invoke(symbol, null);
var stringResult = GetStringValueOf(result);
dictionry[name] = stringResult == string.Empty ? "None" : stringResult;
}
catch
{
}
}
}
return dictionry;
}

private bool IsNotInObjectType(MethodInfo method, MethodInfo[] objectMethods)
{
return !objectMethods.Any(o => o.Name == method.Name);
}

public override object GetPropertyOwner(PropertyDescriptor pd)
{
return _dictionary;
}

public override PropertyDescriptor? GetDefaultProperty()
{
return null;
}

public override PropertyDescriptorCollection GetProperties()
{
return ((ICustomTypeDescriptor)this).GetProperties(new Attribute[0]);
}

public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
var properties = new List<DictionaryPropertyDescriptor>();
foreach (var e in _dictionary)
{
properties.Add(new DictionaryPropertyDescriptor(_dictionary, e.Key));
}

return new PropertyDescriptorCollection(properties.ToArray());
}

class DictionaryPropertyDescriptor : PropertyDescriptor
{
Dictionary<string, string> _dictionary;
string _key;

internal DictionaryPropertyDescriptor(Dictionary<string, string> d, string key)
: base(key.ToString(), null)
{
_dictionary = d;
_key = key;
}

public override Type PropertyType => (_dictionary[_key])?.GetType() ?? typeof(object);

public override void SetValue(object component, object value)
{
throw new InvalidOperationException("SetValue is not allowed!");
}

public override object GetValue(object component) => _dictionary[_key];

public override bool IsReadOnly => true;

public override Type? ComponentType => null;

public override bool CanResetValue(object component) => false;

public override void ResetValue(object component)
{
}

public override bool ShouldSerializeValue(object component) => false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Text.Adornments;
using Microsoft.VisualStudio.Text.Classification;
using Roslyn.SyntaxVisualizer.Control.SymbolDisplay;
using SystemInformation = System.Windows.Forms.SystemInformation;

namespace Roslyn.SyntaxVisualizer.Control
Expand Down Expand Up @@ -995,16 +996,18 @@ private void DisplaySymbolInPropertyGrid(ISymbol symbol)
kindTextLabel.Visibility = Visibility.Hidden;
typeValueLabel.Content = string.Empty;
kindValueLabel.Content = string.Empty;

_propertyGrid.SelectedObject = null;
}
else
{
typeTextLabel.Visibility = Visibility.Visible;
kindTextLabel.Visibility = Visibility.Visible;
typeValueLabel.Content = symbol.GetType().Name;
kindValueLabel.Content = symbol.Kind.ToString();
}

_propertyGrid.SelectedObject = symbol;
_propertyGrid.SelectedObject = new SymbolPropertyGridAdapter(symbol);
}
}

private static TreeViewItem FindTreeViewItem(DependencyObject source)
Expand Down

0 comments on commit 223d750

Please sign in to comment.