Skip to content

Commit

Permalink
Add methods panel in CilView.UI
Browse files Browse the repository at this point in the history
  • Loading branch information
MSDN-WhiteKnight committed Sep 19, 2024
1 parent 2cfac8d commit 3abddc2
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 10 deletions.
43 changes: 43 additions & 0 deletions CilView.UI/AssemblyUrlProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* CIL Tools
* Copyright (c) 2024, MSDN.WhiteKnight (https://github.com/MSDN-WhiteKnight)
* License: BSD 2.0 */
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Text;
using CilTools.Visualization;

namespace CilView.UI
{
class AssemblyUrlProvider : UrlProviderBase
{
Assembly scope;

public AssemblyUrlProvider(Assembly ass)
{
this.scope = ass;
}

public override string GetMemberUrl(MemberInfo member)
{
if (member is MethodBase)
{
MethodBase mb = (MethodBase)member;

if (mb.DeclaringType == null) return string.Empty;

if (mb.DeclaringType.Assembly != this.scope) return string.Empty;
else return "?method=" + mb.MetadataToken.ToString("X", CultureInfo.InvariantCulture);
}
else if (member is Type)
{
Type t = (Type)member;

if (t.Assembly != this.scope) return string.Empty;
else return "?type=" + t.MetadataToken.ToString("X", CultureInfo.InvariantCulture);
}
else return string.Empty;
}
}
}
106 changes: 97 additions & 9 deletions CilView.UI/IndexPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text;
using CilTools.BytecodeAnalysis;
using CilTools.Reflection;
using CilTools.Syntax;
using CilTools.Visualization;
using CilView.Common;
Expand All @@ -17,8 +20,11 @@ namespace CilView.UI
{
class IndexPage : Page
{
ComboBox cbType;
AssemblySource source;
AssemblyUrlProvider urlProvider;
HtmlVisualizer vis = new HtmlVisualizer();
ComboBox cbType;
NavigationPanel panelMethods;

public IndexPage()
{
Expand All @@ -27,20 +33,91 @@ public IndexPage()

this.cbType = new ComboBox("cbType");
this.AddControl(this.cbType);

this.panelMethods = new NavigationPanel("panelMethods");
this.panelMethods.IsVertical = true;
this.AddControl(this.panelMethods);
}

protected override void OnLoad(LoadEventArgs args)
{
if (this.source.Assemblies.Count == 0) return;
if (this.source == null || this.source.Assemblies.Count == 0) return;

// Initially the assembly manifest is displayed
Assembly ass = this.source.Assemblies[0];
int token;

if (args.IsInitialLoad && args.HasQueryParam("method"))
{
// View method
string method = args.GetQueryParam("method");

if (!int.TryParse(method, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out token))
{
args.CustomResponse = ResponseData.FromContent("Invalid method token", ContentTypes.PlainText);
return;
}

MethodBase mb = ResolveMethod(ass, token);

if (mb == null)
{
args.CustomResponse = ResponseData.FromContent("Method not found!", ContentTypes.PlainText);
return;
}

CilGraph gr = CilGraph.Create(mb);
MethodDefSyntax mds = gr.ToSyntaxTree(new DisassemblerParams());
string rendered = this.vis.RenderToString(mds.GetChildNodes());
this.SetField("result-html", rendered);
return;
}
else if (args.IsInitialLoad && args.HasQueryParam("type"))
{
// View type
string type = args.GetQueryParam("type");

if (!int.TryParse(type, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out token))
{
args.CustomResponse = ResponseData.FromContent("Invalid type token", ContentTypes.PlainText);
return;
}

Type t = ResolveMember(ass, token) as Type;

if (t == null)
{
args.CustomResponse = ResponseData.FromContent("Type not found!", ContentTypes.PlainText);
return;
}

this.ViewTypeImpl(t);
return;
}

// View assembly manifest
IEnumerable<SyntaxNode> nodes = Disassembler.GetAssemblyManifestSyntaxNodes(ass);
HtmlVisualizer vis = new HtmlVisualizer();
string html = vis.RenderToString(nodes);
string html = this.vis.RenderToString(nodes);
this.SetField("result-html", html);
}

static MethodBase ResolveMethod(Assembly ass, int metadataToken)
{
return ResolveMember(ass, metadataToken) as MethodBase;
}

static MemberInfo ResolveMember(Assembly ass, int metadataToken)
{
if (ass is ITokenResolver)
{
ITokenResolver resolver = (ITokenResolver)ass;
return resolver.ResolveMember(metadataToken);
}
else
{
return ass.ManifestModule.ResolveMember(metadataToken);
}
}

internal void LoadSource(AssemblySource newval)
{
AssemblySource.TypeCacheClear();
Expand All @@ -63,17 +140,22 @@ internal void LoadSource(AssemblySource newval)
this.source.Methods.Clear();
this.source.Types = AssemblySource.LoadTypes(ass);
this.cbType.ItemsSource = this.source.Types;

//configure HTML rendering
this.urlProvider = new AssemblyUrlProvider(ass);
this.vis.RemoveAllProviders();
this.vis.AddUrlProvider(this.urlProvider);
}

void ViewTypeImpl(Type t)
{
// Render type definition IL
HtmlVisualizer vis = new HtmlVisualizer();
IEnumerable<SyntaxNode> nodes = SyntaxNode.GetTypeDefSyntax(t, false, new DisassemblerParams());
string rendered = vis.RenderToString(nodes);
string rendered = this.vis.RenderToString(nodes);
this.SetField("result-html", rendered);

// Load methods list
this.panelMethods.Clear();
MemberInfo[] members = t.GetMethods(Utils.AllMembers | BindingFlags.DeclaredOnly);
List<MethodBase> methods = new List<MethodBase>(members.Length);

Expand All @@ -96,7 +178,13 @@ void ViewTypeImpl(Type t)

return string.Compare(s1, s2, StringComparison.InvariantCulture);
});


for (int i = 0; i < methods.Count; i++)
{
this.panelMethods.AddLink(AssemblySource.MethodToString(methods[i]),
this.urlProvider.GetMemberUrl(methods[i]));
}

this.source.Methods = new ObservableCollection<MethodBase>(methods);
}

Expand Down
9 changes: 8 additions & 1 deletion CilView.UI/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@ <h1>CIL Tools</h1>
Type: <dn-control id="cbType"></dn-control>
<input type="button" value="View type" onclick="dotnet_action(this,'ViewType')" />
</div>
<div name="result-html"></div>
<table width="100%" cellpadding="5" cellspacing="5">
<tr>
<td width="200" valign="top">
<dn-control id="panelMethods"></dn-control>
</td>
<td valign="top"><div name="result-html"></div></td>
</tr>
</table>
</form>
</body>
</html>

0 comments on commit 3abddc2

Please sign in to comment.