Browse Source

Implemented reference support in the text view.

pull/1/head
Daniel Grunwald 15 years ago
parent
commit
701a315b90
  1. 2
      ICSharpCode.Decompiler/GraphVizGraph.cs
  2. 38
      ILSpy/AssemblyList.cs
  3. 60
      ILSpy/CaretHighlightAdorner.cs
  4. 119
      ILSpy/Disassembler/DisassemblerHelpers.cs
  5. 4
      ILSpy/EventTreeNode.cs
  6. 4
      ILSpy/FieldTreeNode.cs
  7. 2
      ILSpy/ILSpy.csproj
  8. 32
      ILSpy/ITextOutput.cs
  9. 65
      ILSpy/MainWindow.xaml.cs
  10. 4
      ILSpy/PropertyTreeNode.cs
  11. 90
      ILSpy/ReferenceElementGenerator.cs

2
ICSharpCode.Decompiler/GraphVizGraph.cs

@ -93,7 +93,7 @@ namespace ICSharpCode.Decompiler
public void Save(TextWriter writer) public void Save(TextWriter writer)
{ {
writer.WriteLine("digraph G {"); writer.WriteLine("digraph G {");
writer.WriteLine("node [fontsize = 14.5];"); writer.WriteLine("node [fontsize = 16];");
WriteGraphAttribute(writer, "rankdir", rankdir); WriteGraphAttribute(writer, "rankdir", rankdir);
foreach (GraphVizNode node in nodes) { foreach (GraphVizNode node in nodes) {
node.Save(writer); node.Save(writer);

38
ILSpy/AssemblyList.cs

@ -43,6 +43,8 @@ namespace ICSharpCode.ILSpy
public TypeTreeNode FindTypeNode(TypeDefinition def) public TypeTreeNode FindTypeNode(TypeDefinition def)
{ {
if (def == null)
return null;
if (def.DeclaringType != null) { if (def.DeclaringType != null) {
TypeTreeNode decl = FindTypeNode(def.DeclaringType); TypeTreeNode decl = FindTypeNode(def.DeclaringType);
if (decl != null) { if (decl != null) {
@ -62,6 +64,42 @@ namespace ICSharpCode.ILSpy
return null; return null;
} }
public MethodTreeNode FindMethodNode(MethodDefinition def)
{
if (def == null)
return null;
TypeTreeNode typeNode = FindTypeNode(def.DeclaringType);
typeNode.EnsureLazyChildren();
return typeNode.Children.OfType<MethodTreeNode>().FirstOrDefault(m => m.MethodDefinition == def);
}
public FieldTreeNode FindFieldNode(FieldDefinition def)
{
if (def == null)
return null;
TypeTreeNode typeNode = FindTypeNode(def.DeclaringType);
typeNode.EnsureLazyChildren();
return typeNode.Children.OfType<FieldTreeNode>().FirstOrDefault(m => m.FieldDefinition == def);
}
public PropertyTreeNode FindPropertyNode(PropertyDefinition def)
{
if (def == null)
return null;
TypeTreeNode typeNode = FindTypeNode(def.DeclaringType);
typeNode.EnsureLazyChildren();
return typeNode.Children.OfType<PropertyTreeNode>().FirstOrDefault(m => m.PropertyDefinition == def);
}
public EventTreeNode FindEventNode(EventDefinition def)
{
if (def == null)
return null;
TypeTreeNode typeNode = FindTypeNode(def.DeclaringType);
typeNode.EnsureLazyChildren();
return typeNode.Children.OfType<EventTreeNode>().FirstOrDefault(m => m.EventDefinition == def);
}
public AssemblyTreeNode OpenAssembly(string file) public AssemblyTreeNode OpenAssembly(string file)
{ {
App.Current.Dispatcher.VerifyAccess(); App.Current.Dispatcher.VerifyAccess();

60
ILSpy/CaretHighlightAdorner.cs

@ -0,0 +1,60 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Threading;
using ICSharpCode.AvalonEdit.Editing;
namespace ICSharpCode.ILSpy
{
/// <summary>
/// Animated rectangle around the caret.
/// </summary>
sealed class CaretHighlightAdorner : Adorner
{
Pen pen;
RectangleGeometry geometry;
public CaretHighlightAdorner(TextArea textArea)
: base(textArea.TextView)
{
Rect min = textArea.Caret.CalculateCaretRectangle();
min.Offset(-textArea.TextView.ScrollOffset);
Rect max = min;
double size = Math.Max(min.Width, min.Height) * 0.25;
max.Inflate(size, size);
pen = new Pen(TextBlock.GetForeground(textArea.TextView).Clone(), 1);
geometry = new RectangleGeometry(min, 2, 2);
geometry.BeginAnimation(RectangleGeometry.RectProperty, new RectAnimation(min, max, new Duration(TimeSpan.FromMilliseconds(300))) { AutoReverse = true });
pen.Brush.BeginAnimation(Brush.OpacityProperty, new DoubleAnimation(1, 0, new Duration(TimeSpan.FromMilliseconds(200))) { BeginTime = TimeSpan.FromMilliseconds(450) });
}
public static void DisplayCaretHighlightAnimation(TextArea textArea)
{
AdornerLayer layer = AdornerLayer.GetAdornerLayer(textArea.TextView);
CaretHighlightAdorner adorner = new CaretHighlightAdorner(textArea);
layer.Add(adorner);
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += delegate {
timer.Stop();
layer.Remove(adorner);
};
timer.Start();
}
protected override void OnRender(DrawingContext drawingContext)
{
drawingContext.DrawGeometry(null, pen, geometry);
}
}
}

119
ILSpy/Disassembler/DisassemblerHelpers.cs

@ -25,20 +25,38 @@ namespace ICSharpCode.ILSpy.Disassembler
{ {
static class DisassemblerHelpers static class DisassemblerHelpers
{ {
#region Debug output(ToString helpers) static void WriteOffsetReference(ITextOutput writer, int offset)
{
writer.WriteReference(CecilExtensions.OffsetToString(offset), offset);
}
public static void WriteTo(this ExceptionHandler exceptionHandler, ITextOutput writer) public static void WriteTo(this ExceptionHandler exceptionHandler, ITextOutput writer)
{ {
writer.Write("Try IL_{0:x4}-IL_{1:x4} ", exceptionHandler.TryStart.Offset, exceptionHandler.TryEnd.Offset); writer.Write("Try ");
WriteOffsetReference(writer, exceptionHandler.TryStart.Offset);
writer.Write('-');
WriteOffsetReference(writer, exceptionHandler.TryEnd.Offset);
writer.Write(exceptionHandler.HandlerType.ToString()); writer.Write(exceptionHandler.HandlerType.ToString());
if (exceptionHandler.FilterStart != null) { if (exceptionHandler.FilterStart != null) {
writer.Write(" IL_{0:x4}-IL_{1:x4} handler ", exceptionHandler.FilterStart.Offset, exceptionHandler.FilterEnd.Offset); writer.Write(' ');
WriteOffsetReference(writer, exceptionHandler.FilterStart.Offset);
writer.Write('-');
WriteOffsetReference(writer, exceptionHandler.FilterEnd.Offset);
writer.Write(" handler ");
}
if (exceptionHandler.CatchType != null) {
writer.Write(' ');
exceptionHandler.CatchType.WriteTo(writer);
} }
writer.Write(" IL_{0:x4}-IL_{1:x4} ", exceptionHandler.HandlerStart.Offset, exceptionHandler.HandlerEnd.Offset); writer.Write(' ');
WriteOffsetReference(writer, exceptionHandler.HandlerStart.Offset);
writer.Write('-');
WriteOffsetReference(writer, exceptionHandler.HandlerEnd.Offset);
} }
public static void WriteTo(this Instruction instruction, ITextOutput writer) public static void WriteTo(this Instruction instruction, ITextOutput writer)
{ {
writer.Write(CecilExtensions.OffsetToString(instruction.Offset)); writer.WriteDefinition(CecilExtensions.OffsetToString(instruction.Offset), instruction.Offset);
writer.Write(": "); writer.Write(": ");
writer.Write(instruction.OpCode.Name); writer.Write(instruction.OpCode.Name);
if(null != instruction.Operand) { if(null != instruction.Operand) {
@ -52,7 +70,7 @@ namespace ICSharpCode.ILSpy.Disassembler
writer.Write("("); writer.Write("(");
for(int i = 0; i < instructions.Length; i++) { for(int i = 0; i < instructions.Length; i++) {
if(i != 0) writer.Write(", "); if(i != 0) writer.Write(", ");
writer.Write(CecilExtensions.OffsetToString(instructions [i].Offset)); WriteOffsetReference(writer, instructions[i].Offset);
} }
writer.Write(")"); writer.Write(")");
} }
@ -65,95 +83,99 @@ namespace ICSharpCode.ILSpy.Disassembler
: value.ToString(); : value.ToString();
} }
static void WriteMethodReference(ITextOutput writer, MethodReference method) static void WriteTo(this MethodReference method, ITextOutput writer)
{ {
writer.Write(FormatTypeReference(method.ReturnType)); method.ReturnType.WriteTo(writer);
writer.Write(' '); writer.Write(' ');
writer.Write(FormatTypeReference(method.DeclaringType)); method.DeclaringType.WriteTo(writer);
writer.Write("::"); writer.Write("::");
writer.Write(method.Name); writer.WriteReference(method.Name, method);
writer.Write("("); writer.Write("(");
var parameters = method.Parameters; var parameters = method.Parameters;
for(int i=0; i < parameters.Count; ++i) { for(int i = 0; i < parameters.Count; ++i) {
if(i > 0) writer.Write(", "); if (i > 0) writer.Write(", ");
writer.Write(FormatTypeReference(parameters [i].ParameterType)); parameters[i].ParameterType.WriteTo(writer);
} }
writer.Write(")"); writer.Write(")");
} }
static string FormatTypeReference(TypeReference type) static void WriteTo(this TypeReference type, ITextOutput writer)
{ {
string typeName = type.FullName; string name = ShortTypeName(type);
switch(typeName) { if (name != null)
case "System.Void": return "void"; writer.Write(name);
case "System.String": return "string"; else
case "System.Int32": return "int32"; writer.WriteReference(type.FullName, type);
case "System.Long": return "int64";
case "System.Boolean": return "bool";
case "System.Single": return "float32";
case "System.Double": return "float64";
}
return typeName;
} }
public static void WriteOperand(ITextOutput writer, object operand) public static void WriteOperand(ITextOutput writer, object operand)
{ {
if(null == operand) throw new ArgumentNullException("operand"); if (operand == null)
throw new ArgumentNullException("operand");
Instruction targetInstruction = operand as Instruction; Instruction targetInstruction = operand as Instruction;
if(null != targetInstruction) { if (targetInstruction != null) {
writer.Write(CecilExtensions.OffsetToString(targetInstruction.Offset)); WriteOffsetReference(writer, targetInstruction.Offset);
return; return;
} }
Instruction [] targetInstructions = operand as Instruction []; Instruction[] targetInstructions = operand as Instruction[];
if(null != targetInstructions) { if (targetInstructions != null) {
WriteLabelList(writer, targetInstructions); WriteLabelList(writer, targetInstructions);
return; return;
} }
VariableReference variableRef = operand as VariableReference; VariableReference variableRef = operand as VariableReference;
if(null != variableRef) { if (variableRef != null) {
writer.Write(variableRef.Index.ToString()); writer.WriteReference(variableRef.Index.ToString(), variableRef);
return; return;
} }
MethodReference methodRef = operand as MethodReference; MethodReference methodRef = operand as MethodReference;
if(null != methodRef) { if (methodRef != null) {
WriteMethodReference(writer, methodRef); methodRef.WriteTo(writer);
return;
}
TypeReference typeRef = operand as TypeReference;
if (typeRef != null) {
typeRef.WriteTo(writer);
return; return;
} }
string s = operand as string; string s = operand as string;
if(null != s) { if (s != null) {
writer.Write("\"" + s + "\""); writer.Write("\"" + s.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"");
return; return;
} }
s = ToInvariantCultureString(operand); s = ToInvariantCultureString(operand);
writer.Write(s); writer.Write(s);
} }
#endregion
public static string ShortTypeName(this TypeReference type) public static string ShortTypeName(this TypeReference type)
{ {
switch (type.FullName) { switch (type.FullName) {
case "System.SByte":
return "int8";
case "System.Int16": case "System.Int16":
return "short"; return "int16";
case "System.Int32": case "System.Int32":
return "int"; return "int32";
case "System.Int64": case "System.Int64":
return "long"; return "int65";
case "System.Byte":
return "uint8";
case "System.UInt16": case "System.UInt16":
return "ushort"; return "uint16";
case "System.UInt32": case "System.UInt32":
return "uint"; return "uint32";
case "System.UInt64": case "System.UInt64":
return "ulong"; return "uint64";
case "System.Single": case "System.Single":
return "float"; return "float32";
case "System.Double": case "System.Double":
return "double"; return "float64";
case "System.Void": case "System.Void":
return "void"; return "void";
case "System.Boolean": case "System.Boolean":
@ -165,12 +187,7 @@ namespace ICSharpCode.ILSpy.Disassembler
case "System.Object": case "System.Object":
return "object"; return "object";
default: default:
string name = type.Name; return null;
int pos = name.LastIndexOf('`');
if (pos >= 0)
return name.Substring(0, pos);
else
return name;
} }
} }
} }

4
ILSpy/EventTreeNode.cs

@ -37,6 +37,10 @@ namespace ICSharpCode.ILSpy
this.LazyLoading = true; this.LazyLoading = true;
} }
public EventDefinition EventDefinition {
get { return ev; }
}
public override object Text { public override object Text {
get { return ev.Name + " : " + Language.Current.TypeToString(ev.EventType); } get { return ev.Name + " : " + Language.Current.TypeToString(ev.EventType); }
} }

4
ILSpy/FieldTreeNode.cs

@ -29,6 +29,10 @@ namespace ICSharpCode.ILSpy
{ {
readonly FieldDefinition field; readonly FieldDefinition field;
public FieldDefinition FieldDefinition {
get { return field; }
}
public FieldTreeNode(FieldDefinition field) public FieldTreeNode(FieldDefinition field)
{ {
if (field == null) if (field == null)

2
ILSpy/ILSpy.csproj

@ -73,6 +73,7 @@
<Compile Include="AssemblyReferenceTreeNode.cs" /> <Compile Include="AssemblyReferenceTreeNode.cs" />
<Compile Include="AssemblyTreeNode.cs" /> <Compile Include="AssemblyTreeNode.cs" />
<Compile Include="BaseTypesTreeNode.cs" /> <Compile Include="BaseTypesTreeNode.cs" />
<Compile Include="CaretHighlightAdorner.cs" />
<Compile Include="CueBannerService.cs" /> <Compile Include="CueBannerService.cs" />
<Compile Include="Decompiler\CSharpLanguage.cs" /> <Compile Include="Decompiler\CSharpLanguage.cs" />
<Compile Include="Disassembler\DisassemblerHelpers.cs" /> <Compile Include="Disassembler\DisassemblerHelpers.cs" />
@ -103,6 +104,7 @@
</Compile> </Compile>
<Compile Include="PropertyTreeNode.cs" /> <Compile Include="PropertyTreeNode.cs" />
<Compile Include="ReferenceFolderTreeNode.cs" /> <Compile Include="ReferenceFolderTreeNode.cs" />
<Compile Include="ReferenceElementGenerator.cs" />
<Compile Include="SortableGridViewColumn.cs" /> <Compile Include="SortableGridViewColumn.cs" />
<Compile Include="TreeTraversal.cs" /> <Compile Include="TreeTraversal.cs" />
<Compile Include="TypeTreeNode.cs" /> <Compile Include="TypeTreeNode.cs" />

32
ILSpy/ITextOutput.cs

@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections.Generic;
using System.Text; using System.Text;
using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Document;
@ -31,7 +32,13 @@ namespace ICSharpCode.ILSpy
void WriteComment(string comment); void WriteComment(string comment);
void WriteLine(); void WriteLine();
void WriteDefinition(string text, object definition); void WriteDefinition(string text, object definition);
void WriteReference(string text, object definition); void WriteReference(string text, object reference);
}
sealed class ReferenceSegment : TextSegment
{
public object Reference;
public ILSpyTreeNode TreeNode;
} }
sealed class SmartTextOutput : ITextOutput sealed class SmartTextOutput : ITextOutput
@ -39,6 +46,23 @@ namespace ICSharpCode.ILSpy
readonly StringBuilder b = new StringBuilder(); readonly StringBuilder b = new StringBuilder();
int indent; int indent;
bool needsIndent; bool needsIndent;
Dictionary<object, int> definitions = new Dictionary<object, int>();
TextSegmentCollection<ReferenceSegment> references = new TextSegmentCollection<ReferenceSegment>();
public TextSegmentCollection<ReferenceSegment> References {
get { return references; }
}
public ILSpyTreeNode CurrentTreeNode;
public int GetDefinitionPosition(object definition)
{
int val;
if (definitions.TryGetValue(definition, out val))
return val;
else
return -1;
}
public override string ToString() public override string ToString()
{ {
@ -93,12 +117,16 @@ namespace ICSharpCode.ILSpy
{ {
WriteIndent(); WriteIndent();
b.Append(text); b.Append(text);
definitions[definition] = b.Length;
} }
public void WriteReference(string text, object definition) public void WriteReference(string text, object reference)
{ {
WriteIndent(); WriteIndent();
int start = b.Length;
b.Append(text); b.Append(text);
int end = b.Length;
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = reference, TreeNode = CurrentTreeNode });
} }
} }
} }

65
ILSpy/MainWindow.xaml.cs

@ -24,10 +24,12 @@ using System.Reflection;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Threading;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.FlowAnalysis; using ICSharpCode.Decompiler.FlowAnalysis;
using ICSharpCode.TreeView; using ICSharpCode.TreeView;
using Microsoft.Win32; using Microsoft.Win32;
using Mono.Cecil;
using Mono.Cecil.Rocks; using Mono.Cecil.Rocks;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
@ -39,6 +41,7 @@ namespace ICSharpCode.ILSpy
{ {
AssemblyList assemblyList = new AssemblyList(); AssemblyList assemblyList = new AssemblyList();
FilterSettings filterSettings = new FilterSettings(); FilterSettings filterSettings = new FilterSettings();
ReferenceElementGenerator referenceElementGenerator;
static readonly Assembly[] initialAssemblies = { static readonly Assembly[] initialAssemblies = {
typeof(object).Assembly, typeof(object).Assembly,
@ -64,6 +67,10 @@ namespace ICSharpCode.ILSpy
languageComboBox.SelectedItem = languageComboBox.Items[0]; languageComboBox.SelectedItem = languageComboBox.Items[0];
textEditor.Text = "Welcome to ILSpy!"; textEditor.Text = "Welcome to ILSpy!";
referenceElementGenerator = new ReferenceElementGenerator(this);
textEditor.TextArea.TextView.ElementGenerators.Add(referenceElementGenerator);
AssemblyListTreeNode assemblyListTreeNode = new AssemblyListTreeNode(assemblyList); AssemblyListTreeNode assemblyListTreeNode = new AssemblyListTreeNode(assemblyList);
assemblyListTreeNode.FilterSettings = filterSettings.Clone(); assemblyListTreeNode.FilterSettings = filterSettings.Clone();
filterSettings.PropertyChanged += delegate { filterSettings.PropertyChanged += delegate {
@ -73,15 +80,7 @@ namespace ICSharpCode.ILSpy
assemblyListTreeNode.FilterSettings = filterSettings.Clone(); assemblyListTreeNode.FilterSettings = filterSettings.Clone();
}; };
treeView.Root = assemblyListTreeNode; treeView.Root = assemblyListTreeNode;
assemblyListTreeNode.Select = delegate(SharpTreeNode obj) { assemblyListTreeNode.Select = SelectNode;
if (obj != null) {
foreach (SharpTreeNode node in obj.Ancestors())
node.IsExpanded = true;
treeView.SelectedItem = obj;
treeView.ScrollIntoView(obj);
}
};
foreach (Assembly asm in initialAssemblies) foreach (Assembly asm in initialAssemblies)
assemblyList.OpenAssembly(asm.Location); assemblyList.OpenAssembly(asm.Location);
@ -107,6 +106,17 @@ namespace ICSharpCode.ILSpy
#endif #endif
} }
void SelectNode(SharpTreeNode obj)
{
if (obj != null) {
foreach (SharpTreeNode node in obj.Ancestors())
node.IsExpanded = true;
treeView.SelectedItem = obj;
treeView.ScrollIntoView(obj);
}
}
#region Debugging CFG #region Debugging CFG
#if DEBUG #if DEBUG
void cfg_Click(object sender, RoutedEventArgs e) void cfg_Click(object sender, RoutedEventArgs e)
@ -196,14 +206,18 @@ namespace ICSharpCode.ILSpy
} }
} }
SmartTextOutput textOutput;
void TreeView_SelectionChanged(object sender, SelectionChangedEventArgs e) void TreeView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{ {
try { try {
textEditor.SyntaxHighlighting = ILSpy.Language.Current.SyntaxHighlighting; textEditor.SyntaxHighlighting = ILSpy.Language.Current.SyntaxHighlighting;
SmartTextOutput textOutput = new SmartTextOutput(); textOutput = new SmartTextOutput();
foreach (var node in treeView.SelectedItems.OfType<ILSpyTreeNode>()) { foreach (var node in treeView.SelectedItems.OfType<ILSpyTreeNode>()) {
textOutput.CurrentTreeNode = node;
node.Decompile(ILSpy.Language.Current, textOutput); node.Decompile(ILSpy.Language.Current, textOutput);
} }
referenceElementGenerator.References = textOutput.References;
textEditor.Text = textOutput.ToString(); textEditor.Text = textOutput.ToString();
} catch (Exception ex) { } catch (Exception ex) {
textEditor.SyntaxHighlighting = null; textEditor.SyntaxHighlighting = null;
@ -211,6 +225,37 @@ namespace ICSharpCode.ILSpy
} }
} }
internal void JumpToReference(ReferenceSegment referenceSegment)
{
object reference = referenceSegment.Reference;
if (textOutput != null) {
int pos = textOutput.GetDefinitionPosition(reference);
if (pos >= 0) {
textEditor.TextArea.Focus();
textEditor.Select(pos, 0);
textEditor.ScrollTo(textEditor.TextArea.Caret.Line, textEditor.TextArea.Caret.Column);
Dispatcher.Invoke(DispatcherPriority.Background, new Action(
delegate {
CaretHighlightAdorner.DisplayCaretHighlightAnimation(textEditor.TextArea);
}));
return;
}
}
if (reference is TypeReference) {
SelectNode(assemblyList.FindTypeNode(((TypeReference)reference).Resolve()));
} else if (reference is MethodReference) {
SelectNode(assemblyList.FindMethodNode(((MethodReference)reference).Resolve()));
} else if (reference is FieldReference) {
SelectNode(assemblyList.FindFieldNode(((FieldReference)reference).Resolve()));
} else if (reference is PropertyReference) {
SelectNode(assemblyList.FindPropertyNode(((PropertyReference)reference).Resolve()));
} else if (reference is EventReference) {
SelectNode(assemblyList.FindEventNode(((EventReference)reference).Resolve()));
} else if (reference is AssemblyDefinition) {
SelectNode(assemblyList.Assemblies.FirstOrDefault(node => node.AssemblyDefinition == reference));
}
}
void LanguageComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) void LanguageComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{ {
ILSpy.Language.Current = (ILSpy.Language)languageComboBox.SelectedItem; ILSpy.Language.Current = (ILSpy.Language)languageComboBox.SelectedItem;

4
ILSpy/PropertyTreeNode.cs

@ -39,6 +39,10 @@ namespace ICSharpCode.ILSpy
this.LazyLoading = true; this.LazyLoading = true;
} }
public PropertyDefinition PropertyDefinition {
get { return property; }
}
public override object Text { public override object Text {
get { return property.Name + " : " + Language.Current.TypeToString(property.PropertyType); } get { return property.Name + " : " + Language.Current.TypeToString(property.PropertyType); }
} }

90
ILSpy/ReferenceElementGenerator.cs

@ -0,0 +1,90 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using System.Windows.Input;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Rendering;
namespace ICSharpCode.ILSpy
{
sealed class ReferenceElementGenerator : VisualLineElementGenerator
{
MainWindow parentWindow;
public TextSegmentCollection<ReferenceSegment> References { get; set; }
public ReferenceElementGenerator(MainWindow parentWindow)
{
if (parentWindow == null)
throw new ArgumentNullException("parentWindow");
this.parentWindow = parentWindow;
}
public override int GetFirstInterestedOffset(int startOffset)
{
if (this.References == null)
return -1;
var segment = this.References.FindFirstSegmentWithStartAfter(startOffset);
return segment != null ? segment.StartOffset : -1;
}
public override VisualLineElement ConstructElement(int offset)
{
if (this.References == null)
return null;
foreach (var segment in this.References.FindSegmentsContaining(offset)) {
if (offset < segment.EndOffset) {
return new VisualLineReferenceText(CurrentContext.VisualLine, segment.EndOffset - offset, this, segment);
}
}
return null;
}
internal void JumpToReference(ReferenceSegment referenceSegment)
{
parentWindow.JumpToReference(referenceSegment);
}
}
/// <summary>
/// VisualLineElement that represents a piece of text and is a clickable link.
/// </summary>
sealed class VisualLineReferenceText : VisualLineText
{
ReferenceElementGenerator parent;
ReferenceSegment referenceSegment;
/// <summary>
/// Creates a visual line text element with the specified length.
/// It uses the <see cref="ITextRunConstructionContext.VisualLine"/> and its
/// <see cref="VisualLineElement.RelativeTextOffset"/> to find the actual text string.
/// </summary>
public VisualLineReferenceText(VisualLine parentVisualLine, int length, ReferenceElementGenerator parent, ReferenceSegment referenceSegment) : base(parentVisualLine, length)
{
this.parent = parent;
this.referenceSegment = referenceSegment;
}
/// <inheritdoc/>
protected override void OnQueryCursor(QueryCursorEventArgs e)
{
e.Handled = true;
e.Cursor = Cursors.Hand;
}
/// <inheritdoc/>
protected override void OnMouseDown(MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left && !e.Handled) {
parent.JumpToReference(referenceSegment);
e.Handled = true;
}
}
/// <inheritdoc/>
protected override VisualLineText CreateInstance(int length)
{
return new VisualLineReferenceText(ParentVisualLine, length, parent, referenceSegment);
}
}
}
Loading…
Cancel
Save