Skip to content

Commit 422e67c

Browse files
authored
app commands (#46)
* app commands * JitCommand * notes * jit command works once * mostly working * progress event * folders * key
1 parent 100555c commit 422e67c

19 files changed

+528
-260
lines changed

JitExplorer.Engine.UnitTests/DissassemblyBuilderTests.cs renamed to JitExplorer.Engine.UnitTests/DisassemblyBuilderTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66

77
namespace JitExplorer.Engine.UnitTests
88
{
9-
public class DissassemblyBuilderTests
9+
public class DisassemblyBuilderTests
1010
{
1111
[Fact]
1212
public void WhenAddingLinesTheAddressesAreCountedCorrectly()
1313
{
14-
var b = new DissassemblyBuilder();
14+
var b = new DisassemblyBuilder();
1515

1616
b.AddLine();
1717
b.AddLine("line2");
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44

55
namespace JitExplorer.Engine
66
{
7-
public class Dissassembly
7+
public class Disassembly
88
{
9-
public Dissassembly(string text)
9+
public Disassembly(string text)
1010
{
1111
this.IsSuccess = false;
1212
this.OutputText = text;
@@ -15,7 +15,7 @@ public Dissassembly(string text)
1515
this.AsmLineToAsmLineIndex = new Dictionary<int, int>();
1616
}
1717

18-
public Dissassembly(string text, Dictionary<int, string> lineAddressIndex, Dictionary<int, int> asmToSourceLineIndex, Dictionary<int, int> asmLineToAsmLineIndex)
18+
public Disassembly(string text, Dictionary<int, string> lineAddressIndex, Dictionary<int, int> asmToSourceLineIndex, Dictionary<int, int> asmLineToAsmLineIndex)
1919
{
2020
this.IsSuccess = true;
2121
this.AsmText = text;
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
namespace JitExplorer.Engine
88
{
9-
public class DissassemblyBuilder
9+
public class DisassemblyBuilder
1010
{
1111
private int lineNo = 1;
1212
private StringBuilder sb = new StringBuilder();
@@ -72,7 +72,7 @@ private void HandleMultiline(string text)
7272
}
7373
}
7474

75-
public Dissassembly Build()
75+
public Disassembly Build()
7676
{
7777
var asmLineToAsmLineIndex = new Dictionary<int, int>(this.linesContainingLabels.Count);
7878

@@ -84,7 +84,7 @@ public Dissassembly Build()
8484
}
8585
}
8686

87-
return new Dissassembly(
87+
return new Disassembly(
8888
sb.ToString(),
8989
asmLineToAddressIndex,
9090
asmToSourceLineIndex,

JitExplorer.Engine/RuntimeDisassembler.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public RuntimeDisassembler(string exeName)
3636
this.csFileName = "program.cs";
3737
}
3838

39-
public Dissassembly CompileJitAndDisassemble(string sourceCode, Config config)
39+
public Disassembly CompileJitAndDisassemble(string sourceCode, Config config)
4040
{
4141
this.Progress?.Invoke(this, new ProgressEventArgs() { StatusMessage = "Compiling..." });
4242
(ExtractMarkedMethod userMethod, Compile.Compilation compilation) = Compile(this.exeName, sourceCode, config);
@@ -56,7 +56,7 @@ public Dissassembly CompileJitAndDisassemble(string sourceCode, Config config)
5656
sb.AppendLine(e.ToString());
5757
}
5858

59-
return new Dissassembly(sb.ToString());
59+
return new Disassembly(sb.ToString());
6060
}
6161

6262
this.Progress?.Invoke(this, new ProgressEventArgs() { StatusMessage = "Writing to disk..." });
@@ -315,9 +315,9 @@ private DisassemblyResult AttachAndDecompile(int processId, string className, st
315315
return dissassembler.AttachAndDisassemble(settings);
316316
}
317317

318-
private static Dissassembly FormatResult(DisassemblyResult result)
318+
private static Disassembly FormatResult(DisassemblyResult result)
319319
{
320-
var builder = new DissassemblyBuilder();
320+
var builder = new DisassemblyBuilder();
321321

322322
int referenceIndex = 0;
323323
int methodIndex = 0;

JitExplorer/AppModel.cs

Lines changed: 0 additions & 69 deletions
This file was deleted.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
using ICSharpCode.AvalonEdit;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Text;
5+
using System.Windows;
6+
using System.Windows.Interactivity;
7+
8+
namespace JitExplorer.Behaviors
9+
{
10+
// https://stackoverflow.com/questions/18964176/two-way-binding-to-avalonedit-document-text-using-mvvm
11+
public sealed class AvalonEditBehaviour : Behavior<TextEditor>
12+
{
13+
public static readonly DependencyProperty EditorTextProperty =
14+
DependencyProperty.Register(nameof(EditorText), typeof(string), typeof(AvalonEditBehaviour),
15+
new FrameworkPropertyMetadata(default(string), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, PropertyChangedCallback));
16+
17+
public string EditorText
18+
{
19+
get { return (string)GetValue(EditorTextProperty); }
20+
set {
21+
SetValue(EditorTextProperty, value);
22+
}
23+
}
24+
25+
protected override void OnAttached()
26+
{
27+
base.OnAttached();
28+
if (AssociatedObject != null)
29+
AssociatedObject.TextChanged += AssociatedObjectOnTextChanged;
30+
}
31+
32+
protected override void OnDetaching()
33+
{
34+
base.OnDetaching();
35+
if (AssociatedObject != null)
36+
AssociatedObject.TextChanged -= AssociatedObjectOnTextChanged;
37+
}
38+
39+
private void AssociatedObjectOnTextChanged(object sender, EventArgs eventArgs)
40+
{
41+
var textEditor = sender as TextEditor;
42+
if (textEditor != null)
43+
{
44+
if (textEditor.Document != null)
45+
EditorText = textEditor.Document.Text;
46+
}
47+
}
48+
49+
private static void PropertyChangedCallback(
50+
DependencyObject dependencyObject,
51+
DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
52+
{
53+
var behavior = dependencyObject as AvalonEditBehaviour;
54+
if (behavior.AssociatedObject != null)
55+
{
56+
var editor = behavior.AssociatedObject as TextEditor;
57+
if (editor.Document != null)
58+
{
59+
var caretOffset = editor.CaretOffset;
60+
editor.Document.Text = dependencyPropertyChangedEventArgs.NewValue.ToString();
61+
editor.CaretOffset = caretOffset;
62+
}
63+
}
64+
}
65+
}
66+
}

JitExplorer/Commands/JitCommand.cs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using BitFaster.Caching.Lru;
2+
using JitExplorer.Engine;
3+
using JitExplorer.Model;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
using System.Windows;
9+
using System.Windows.Input;
10+
11+
namespace JitExplorer.Commands
12+
{
13+
public class JitCommand : ICommand
14+
{
15+
private readonly ClassicLru<JitKey, Disassembly> cache = new ClassicLru<JitKey, Disassembly>(100);
16+
17+
private bool canExecute = true;
18+
19+
public event EventHandler CanExecuteChanged;
20+
21+
public JitCommand()
22+
{
23+
}
24+
25+
public bool CanExecute(object parameter)
26+
{
27+
return this.canExecute;
28+
}
29+
30+
public void Execute(object parameter)
31+
{
32+
this.canExecute = false;
33+
RaiseCanExecuteChanged();
34+
35+
var model = parameter as AppModel;
36+
37+
Task.Run(() =>
38+
{
39+
model.StatusModel.SetRunning();
40+
41+
var dissassembler = new RuntimeDisassembler("test.exe");
42+
dissassembler.Progress += (object sender, ProgressEventArgs e) => { model.StatusModel.Status = e.StatusMessage; };
43+
44+
var jitKey = new JitKey(model.SourceCode, model.GetConfig());
45+
46+
var disassembly = this.cache.GetOrAdd(jitKey, k => dissassembler.CompileJitAndDisassemble(k.SourceCode, k.Config));
47+
48+
model.Disassembly = disassembly;
49+
50+
this.canExecute = true;
51+
Application.Current.Dispatcher.Invoke((() => { RaiseCanExecuteChanged(); }));
52+
model.StatusModel.SetReady();
53+
});
54+
}
55+
56+
private void RaiseCanExecuteChanged()
57+
{
58+
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
59+
}
60+
}
61+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
using System.Collections.Generic;
66
using System.Text;
77

8-
namespace JitExplorer
8+
namespace JitExplorer.Commands
99
{
1010
public class JitKey : IEquatable<JitKey>
1111
{

JitExplorer/Controls/AssemblyTextEditor.cs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,26 @@
99
using System.Windows;
1010
using ICSharpCode.AvalonEdit.Utils;
1111
using ICSharpCode.AvalonEdit.Highlighting;
12+
using Microsoft.CodeAnalysis.CSharp.Syntax;
13+
using Microsoft.CodeAnalysis.Wrapping;
1214

1315
namespace JitExplorer.Controls
1416
{
15-
public class AssemblyTextEditor : TextEditor
17+
public class AssemblyTextEditor : BindableTextEditor
1618
{
1719
private ILineAddressResolver lineAddressResolver = new EmptyAddressResolver();
1820

19-
public AssemblyTextEditor() : base(new TextArea())
21+
public AssemblyTextEditor()
2022
{
2123
this.IsReadOnly = true;
2224
this.WordWrap = true;
2325
this.ShowLineNumbers = false;
2426
this.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition("Asm");
2527
}
2628

27-
public void Update(string text, ILineAddressResolver addressResolver)
29+
public Dictionary<int, string> AsmLineAddressIndex
2830
{
29-
this.lineAddressResolver = addressResolver;
30-
this.Text = text;
31-
this.HookAddressResolver();
31+
set { this.lineAddressResolver = new LineAddressResolver(value); this.HookAddressResolver(); }
3232
}
3333

3434
protected override void OnDocumentChanged(EventArgs e)
@@ -44,6 +44,22 @@ private void HookAddressResolver()
4444
this.Document.ServiceProvider = wrapped;
4545
}
4646

47+
public static readonly DependencyProperty AsmLineAddressIndexProperty =
48+
DependencyProperty.Register("AsmLineAddressIndex", typeof(Dictionary<int, string>), typeof(TextEditor),
49+
new FrameworkPropertyMetadata(null, OnAsmLineAddressIndexChanged));
50+
51+
static void OnAsmLineAddressIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
52+
{
53+
AssemblyTextEditor editor = (AssemblyTextEditor)d;
54+
55+
var index = e.NewValue as Dictionary<int, string>;
56+
57+
if (index != null)
58+
{
59+
editor.AsmLineAddressIndex = index;
60+
}
61+
}
62+
4763
public static readonly DependencyProperty ShowMemoryAddressesProperty =
4864
DependencyProperty.Register("ShowMemoryAddresses", typeof(bool), typeof(TextEditor),
4965
new FrameworkPropertyMetadata(Boxes.False, OnShowMemoryAddressesChanged));
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using ICSharpCode.AvalonEdit;
2+
using ICSharpCode.AvalonEdit.Editing;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Text;
6+
using System.Windows;
7+
8+
namespace JitExplorer.Controls
9+
{
10+
public class BindableTextEditor : TextEditor
11+
{
12+
public BindableTextEditor() : base(new TextArea())
13+
{ }
14+
15+
public string EditorText
16+
{
17+
get { return this.Text;}
18+
set { this.Text = value; }
19+
}
20+
21+
public static readonly DependencyProperty EditorTextProperty =
22+
DependencyProperty.Register("EditorText", typeof(string), typeof(TextEditor),
23+
new FrameworkPropertyMetadata(string.Empty, OnEditorTextChanged));
24+
25+
static void OnEditorTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
26+
{
27+
BindableTextEditor editor = (BindableTextEditor)d;
28+
29+
var text = e.NewValue as string ?? string.Empty;
30+
31+
editor.Text = text;
32+
}
33+
}
34+
}

0 commit comments

Comments
 (0)