Skip to content

Commit

Permalink
Improve SourceViewWindow
Browse files Browse the repository at this point in the history
- Don't reload all method's sequence points when navigating to previous/next point
- Remove SourceInfo and PdbUtils.GetSourceFromPdb
- Rework all UI to use PdbCodeProvider

Related to #98
  • Loading branch information
MSDN-WhiteKnight committed Jan 5, 2022
1 parent 3c6f7e9 commit 1137e18
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 230 deletions.
1 change: 0 additions & 1 deletion CilView/CilView.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@
<Compile Include="SourceCode\PdbCodeProvider.cs" />
<Compile Include="SourceCode\PdbUtils.cs" />
<Compile Include="SourceCode\SourceCodeUI.cs" />
<Compile Include="SourceCode\SourceInfo.cs" />
<Compile Include="SourceCode\SymbolsException.cs" />
<Compile Include="SourceCode\SymbolsQueryType.cs" />
<Compile Include="SourceCode\VbDecompiler.cs" />
Expand Down
15 changes: 2 additions & 13 deletions CilView/SourceCode/Decompiler.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* CIL Tools
* Copyright (c) 2021, MSDN.WhiteKnight (https://github.com/MSDN-WhiteKnight)
* Copyright (c) 2022, MSDN.WhiteKnight (https://github.com/MSDN-WhiteKnight)
* License: BSD 2.0 */
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -76,18 +76,7 @@ protected static string ProcessCommonTypes(Type t)
else if (Utils.TypeEquals(t, typeof(double))) return "double";
else return null;
}

public static SourceInfo GetSourceFromDecompiler(MethodBase m)
{
//stub implementation that only works for abstract methods
SourceInfo ret = new SourceInfo();
ret.SymbolsFile = "DECOMPILED";
ret.SourceFile = "DECOMPILED";
ret.SourceCode = DecompileMethodSignature(".cs", m);
ret.Method = m;
return ret;
}


protected static string GetGenericDefinitionName(string typeName)
{
int i = typeName.IndexOf('`');
Expand Down
68 changes: 5 additions & 63 deletions CilView/SourceCode/PdbUtils.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* CIL Tools
* Copyright (c) 2021, MSDN.WhiteKnight (https://github.com/MSDN-WhiteKnight)
* Copyright (c) 2022, MSDN.WhiteKnight (https://github.com/MSDN-WhiteKnight)
* License: BSD 2.0 */
using System;
using System.Collections.Generic;
Expand All @@ -12,8 +12,6 @@
using CilTools.Reflection;
using CilTools.SourceCode;
using CilView.Common;
using Internal.Pdb.Portable;
using Internal.Pdb.Windows;

namespace CilView.SourceCode
{
Expand Down Expand Up @@ -42,13 +40,8 @@ public static string GetCilText(MethodBase mb, uint startOffset, uint endOffset)

return sb.ToString();
}

public static string GetSourceFromPdb<T>(Predicate<T> match)
{
return GetSourceFromPdb(match.Method, 0, uint.MaxValue, SymbolsQueryType.RangeExact).SourceCode;
}

static SourceFragment FindFragment(IEnumerable<SourceFragment> fragments, uint offset)

public static SourceFragment FindFragment(IEnumerable<SourceFragment> fragments, uint offset)
{
SourceFragment fragment = null;

Expand All @@ -68,59 +61,8 @@ static SourceFragment FindFragment(IEnumerable<SourceFragment> fragments, uint o
if (fragment.CilStart > offset) return null;
else return fragment;
}

/// <summary>
/// Gets the source code for the specified bytecode fragment using PDB symbols
/// </summary>
/// <param name="m">Method for which to get the source code</param>
/// <param name="startOffset">Byte offset of the bytecode fragment's start</param>
/// <param name="endOffset">Byte offset of the bytecode fragment's end</param>
/// <param name="queryType"> Specifies how to determine the source bytecode fragment:
/// <see cref="SymbolsQueryType.RangeExact"/> to return the sources for exact specified bytecode fragment;
/// <see cref="SymbolsQueryType.SequencePoint"/> to get the sources
/// for the sequence point in which starting offset lies.
/// </param>
public static SourceInfo GetSourceFromPdb(MethodBase m,
uint startOffset,
uint endOffset,
SymbolsQueryType queryType)
{
PdbCodeProvider provider = PdbCodeProvider.Instance;
SourceDocument doc = provider.GetSourceCodeDocuments(m).FirstOrDefault();

if(doc == null) return SourceInfo.FromError(SourceInfoError.NoMatches);

SourceInfo ret = new SourceInfo();
ret.Method = m;
ret.SourceFile = doc.FilePath;
ret.SymbolsFile = doc.SymbolsFile;

if (queryType == SymbolsQueryType.RangeExact && startOffset == 0 && endOffset == uint.MaxValue)
{
//whole method
ret.SourceCode = doc.Text;
ret.CilStart = 0;
ret.CilEnd = (uint)Utils.GetMethodBodySize(m);
ret.LineStart = doc.LineStart;
ret.LineEnd = doc.LineEnd;
return ret;
}

//single sequence point
SourceFragment fragment = FindFragment(doc.Fragments, startOffset);

if (fragment == null) return SourceInfo.FromError(SourceInfoError.NoMatches);

ret.SourceCode = fragment.Text;
ret.CilStart = (uint)fragment.CilStart;
ret.CilEnd = (uint)fragment.CilEnd;
ret.LineStart = fragment.LineStart;
ret.LineEnd = fragment.LineEnd;

return ret;
}

internal static bool IsSourceValid(string file, Guid algo, byte[] hash)

public static bool IsSourceValid(string file, Guid algo, byte[] hash)
{
HashAlgorithm ha=null;

Expand Down
65 changes: 28 additions & 37 deletions CilView/SourceCode/SourceCodeUI.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
/* CIL Tools
* Copyright (c) 2021, MSDN.WhiteKnight (https://github.com/MSDN-WhiteKnight)
* Copyright (c) 2022, MSDN.WhiteKnight (https://github.com/MSDN-WhiteKnight)
* License: BSD 2.0 */
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows;
using System.Windows.Media;
using CilTools.SourceCode;
using CilView.Common;
using CilView.UI.Dialogs;

Expand All @@ -17,11 +19,10 @@ static class SourceCodeUI
{
static void ShowDecompiledSource(MethodBase method)
{
SourceInfo srcinfo;
srcinfo = Decompiler.GetSourceFromDecompiler(method);
//stub implementation that only works for abstract methods
string src = Decompiler.DecompileMethodSignature(".cs", method);

//build display string
string src = srcinfo.SourceCode;
StringBuilder sb = new StringBuilder(src.Length * 2);
sb.AppendLine(src);

Expand All @@ -48,65 +49,47 @@ public static void ShowSource(MethodBase method, uint byteOffset, bool wholeMeth
{
try
{
SourceInfo srcinfo;

if (method.IsAbstract)
{
//abstract method has no sequence points in PDB, just use decompiler
ShowDecompiledSource(method);
return;
}

//from PDB
if (wholeMethod)
{
srcinfo = PdbUtils.GetSourceFromPdb(method,
0, uint.MaxValue, SymbolsQueryType.RangeExact);
}
else
{
srcinfo = PdbUtils.GetSourceFromPdb(method,
byteOffset, byteOffset, SymbolsQueryType.SequencePoint);
}

string src = srcinfo.SourceCode;

if (string.IsNullOrWhiteSpace(src))
//from PDB
PdbCodeProvider provider = PdbCodeProvider.Instance;
SourceDocument doc = provider.GetSourceCodeDocuments(method).FirstOrDefault();

if (doc == null)
{
string str = "Failed to get source code";

if (srcinfo.Error != SourceInfoError.Success)
{
str += ": "+srcinfo.Error.ToString();
}

MessageBox.Show(str, "Error");
MessageBox.Show("Failed to get source code: line info not found for this method", "Error");
return;
}

if (wholeMethod)
{
string src = doc.Text;
string methodstr = string.Empty;
string ext = Path.GetExtension(srcinfo.SourceFile);
string ext = Path.GetExtension(doc.FilePath);

try
{
if (!Utils.IsConstructor(srcinfo.Method) && !Utils.IsPropertyMethod(srcinfo.Method))
if (!Utils.IsConstructor(doc.Method) && !Utils.IsPropertyMethod(doc.Method))
{
methodstr = Decompiler.DecompileMethodSignature(ext, srcinfo.Method);
methodstr = Decompiler.DecompileMethodSignature(ext, doc.Method);
}
}
catch (Exception ex)
{
//don't error out if we can't build good signature string
ErrorHandler.Current.Error(ex, "PdbUtils.GetMethodSigString", silent: true);
methodstr = CilVisualization.MethodToString(srcinfo.Method);
methodstr = CilVisualization.MethodToString(doc.Method);
}

//build display string
StringBuilder sb = new StringBuilder(src.Length * 2);
sb.AppendFormat("({0}, ", srcinfo.SourceFile);
sb.AppendFormat("lines {0}-{1})", srcinfo.LineStart, srcinfo.LineEnd);
sb.AppendFormat("({0}, ", doc.FilePath);
sb.AppendFormat("lines {0}-{1})", doc.LineStart, doc.LineEnd);
sb.AppendLine();
sb.AppendLine();
sb.AppendLine(methodstr);
Expand All @@ -131,7 +114,15 @@ public static void ShowSource(MethodBase method, uint byteOffset, bool wholeMeth
}
else
{
SourceViewWindow srcwnd = new SourceViewWindow(srcinfo);
SourceFragment f = PdbUtils.FindFragment(doc.Fragments, byteOffset);

if (f == null)
{
MessageBox.Show("Failed to get source code: sequence point not found", "Error");
return;
}

SourceViewWindow srcwnd = new SourceViewWindow(f);
srcwnd.ShowDialog();
}
}
Expand Down
85 changes: 0 additions & 85 deletions CilView/SourceCode/SourceInfo.cs

This file was deleted.

Loading

0 comments on commit 1137e18

Please sign in to comment.