Browse Source

Add button for reloading all assemblies.

pull/1/head
Daniel Grunwald 15 years ago
parent
commit
af44dcb4c6
  1. 4
      ILSpy/AssemblyListManager.cs
  2. 13
      ILSpy/MainWindow.xaml
  3. 28
      ILSpy/MainWindow.xaml.cs
  4. 72
      ILSpy/TextView/DecompilerTextView.cs

4
ILSpy/AssemblyListManager.cs

@ -66,9 +66,11 @@ namespace ICSharpCode.ILSpy
if (firstList != null) if (firstList != null)
return new AssemblyList(firstList); return new AssemblyList(firstList);
else else
return new AssemblyList(listName ?? "(Default)"); return new AssemblyList(listName ?? DefaultListName);
} }
public const string DefaultListName = "(Default)";
/// <summary> /// <summary>
/// Saves the specifies assembly list into the config file. /// Saves the specifies assembly list into the config file.
/// </summary> /// </summary>

13
ILSpy/MainWindow.xaml

@ -15,6 +15,9 @@
<CommandBinding <CommandBinding
Command="Open" Command="Open"
Executed="OpenCommandExecuted" /> Executed="OpenCommandExecuted" />
<CommandBinding
Command="Refresh"
Executed="RefreshCommandExecuted" />
</Window.CommandBindings> </Window.CommandBindings>
<DockPanel> <DockPanel>
<!-- Main menu --> <!-- Main menu -->
@ -36,6 +39,11 @@
<MenuItem Header="E_xit" Click="ExitClick" /> <MenuItem Header="E_xit" Click="ExitClick" />
</MenuItem> </MenuItem>
<MenuItem Header="_View"> <MenuItem Header="_View">
<MenuItem Command="Refresh">
<MenuItem.Icon>
<Image Width="16" Height="16" Source="Images/Refresh.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Show _internal types and members" IsCheckable="True" IsChecked="{Binding FilterSettings.ShowInternalApi}"> <MenuItem Header="Show _internal types and members" IsCheckable="True" IsChecked="{Binding FilterSettings.ShowInternalApi}">
<MenuItem.Icon> <MenuItem.Icon>
<Image Width="16" Height="16" Source="Images/PrivateInternal.png" /> <Image Width="16" Height="16" Source="Images/PrivateInternal.png" />
@ -62,9 +70,12 @@
</Style.Triggers> </Style.Triggers>
</Style> </Style>
</ToolBar.Resources> </ToolBar.Resources>
<Button Command="Open"> <Button Command="Open" ToolTip="Open">
<Image Width="16" Height="16" Source="Images/Open.png" /> <Image Width="16" Height="16" Source="Images/Open.png" />
</Button> </Button>
<Button Command="Refresh" ToolTip="Reload all assemblies">
<Image Width="16" Height="16" Source="Images/Refresh.png" />
</Button>
<Separator /> <Separator />
<CheckBox IsChecked="{Binding FilterSettings.ShowInternalApi}" ToolTip="Show internal types and members"> <CheckBox IsChecked="{Binding FilterSettings.ShowInternalApi}" ToolTip="Show internal types and members">
<Image Width="16" Height="16" Source="Images/PrivateInternal.png" /> <Image Width="16" Height="16" Source="Images/PrivateInternal.png" />

28
ILSpy/MainWindow.xaml.cs

@ -78,10 +78,7 @@ namespace ICSharpCode.ILSpy
this.assemblyList = assemblyListManager.LoadList(this.spySettings, sessionSettings.ActiveAssemblyList); this.assemblyList = assemblyListManager.LoadList(this.spySettings, sessionSettings.ActiveAssemblyList);
this.spySettings = null; this.spySettings = null;
assemblyListTreeNode = new AssemblyListTreeNode(assemblyList); ShowAssemblyList(this.assemblyList);
assemblyListTreeNode.FilterSettings = sessionSettings.FilterSettings.Clone();
assemblyListTreeNode.Select = SelectNode;
treeView.Root = assemblyListTreeNode;
string[] args = Environment.GetCommandLineArgs(); string[] args = Environment.GetCommandLineArgs();
for (int i = 1; i < args.Length; i++) { for (int i = 1; i < args.Length; i++) {
@ -93,6 +90,21 @@ namespace ICSharpCode.ILSpy
SelectNode(FindNodeByPath(sessionSettings.ActiveTreeViewPath, true)); SelectNode(FindNodeByPath(sessionSettings.ActiveTreeViewPath, true));
} }
void ShowAssemblyList(AssemblyList assemblyList)
{
this.assemblyList = assemblyList;
assemblyListTreeNode = new AssemblyListTreeNode(assemblyList);
assemblyListTreeNode.FilterSettings = sessionSettings.FilterSettings.Clone();
assemblyListTreeNode.Select = SelectNode;
treeView.Root = assemblyListTreeNode;
if (assemblyList.ListName == AssemblyListManager.DefaultListName)
this.Title = "ILSpy";
else
this.Title = "ILSpy - " + assemblyList.ListName;
}
void LoadInitialAssemblies() void LoadInitialAssemblies()
{ {
// Called when loading an empty assembly list; so that // Called when loading an empty assembly list; so that
@ -266,6 +278,14 @@ namespace ICSharpCode.ILSpy
treeView.ScrollIntoView(lastNode); treeView.ScrollIntoView(lastNode);
} }
void RefreshCommandExecuted(object sender, ExecutedRoutedEventArgs e)
{
e.Handled = true;
var path = GetPathForNode(treeView.SelectedItem as SharpTreeNode);
ShowAssemblyList(assemblyListManager.LoadList(ILSpySettings.Load(), assemblyList.ListName));
SelectNode(FindNodeByPath(path, true));
}
void ExitClick(object sender, RoutedEventArgs e) void ExitClick(object sender, RoutedEventArgs e)
{ {
Close(); Close();

72
ILSpy/TextView/DecompilerTextView.cs

@ -166,26 +166,54 @@ namespace ICSharpCode.ILSpy.TextView
const int defaultOutputLengthLimit = 5000000; // more than 5M characters is too slow to output (when user browses treeview) const int defaultOutputLengthLimit = 5000000; // more than 5M characters is too slow to output (when user browses treeview)
const int extendedOutputLengthLimit = 75000000; // more than 75M characters can get us into trouble with memory usage const int extendedOutputLengthLimit = 75000000; // more than 75M characters can get us into trouble with memory usage
DecompilationContext nextDecompilationRun;
/// <summary> /// <summary>
/// Starts the decompilation of the given nodes. /// Starts the decompilation of the given nodes.
/// The result is displayed in the text view. /// The result is displayed in the text view.
/// </summary> /// </summary>
public void Decompile(ILSpy.Language language, IEnumerable<ILSpyTreeNodeBase> treeNodes, DecompilationOptions options) public void Decompile(ILSpy.Language language, IEnumerable<ILSpyTreeNodeBase> treeNodes, DecompilationOptions options)
{ {
Decompile(language, treeNodes.ToArray(), defaultOutputLengthLimit, options); // Some actions like loading an assembly list cause several selection changes in the tree view,
// and each of those will start a decompilation action.
bool isDecompilationScheduled = this.nextDecompilationRun != null;
this.nextDecompilationRun = new DecompilationContext(language, treeNodes.ToArray(), options);
if (!isDecompilationScheduled) {
Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(
delegate {
var context = this.nextDecompilationRun;
this.nextDecompilationRun = null;
DoDecompile(context, defaultOutputLengthLimit);
}
));
}
}
sealed class DecompilationContext
{
public readonly ILSpy.Language Language;
public readonly ILSpyTreeNodeBase[] TreeNodes;
public readonly DecompilationOptions Options;
public DecompilationContext(ILSpy.Language language, ILSpyTreeNodeBase[] treeNodes, DecompilationOptions options)
{
this.Language = language;
this.TreeNodes = treeNodes;
this.Options = options;
}
} }
void Decompile(ILSpy.Language language, ILSpyTreeNodeBase[] treeNodes, int outputLengthLimit, DecompilationOptions options) void DoDecompile(DecompilationContext context, int outputLengthLimit)
{ {
RunWithCancellation( RunWithCancellation(
delegate (CancellationToken ct) { // creation of the background task delegate (CancellationToken ct) { // creation of the background task
options.CancellationToken = ct; context.Options.CancellationToken = ct;
return RunDecompiler(language, treeNodes, options, outputLengthLimit); return RunDecompiler(context, outputLengthLimit);
}, },
delegate (Task<AvalonEditTextOutput> task) { // handling the result delegate (Task<AvalonEditTextOutput> task) { // handling the result
try { try {
AvalonEditTextOutput textOutput = task.Result; AvalonEditTextOutput textOutput = task.Result;
ShowOutput(textOutput, language); ShowOutput(textOutput, context.Language);
} catch (AggregateException aggregateException) { } catch (AggregateException aggregateException) {
textEditor.SyntaxHighlighting = null; textEditor.SyntaxHighlighting = null;
Debug.WriteLine("Decompiler crashed: " + aggregateException.ToString()); Debug.WriteLine("Decompiler crashed: " + aggregateException.ToString());
@ -196,7 +224,7 @@ namespace ICSharpCode.ILSpy.TextView
ex = ex.InnerException; ex = ex.InnerException;
AvalonEditTextOutput output = new AvalonEditTextOutput(); AvalonEditTextOutput output = new AvalonEditTextOutput();
if (ex is OutputLengthExceededException) { if (ex is OutputLengthExceededException) {
WriteOutputLengthExceededMessage(output, language, treeNodes, options, outputLengthLimit == defaultOutputLengthLimit); WriteOutputLengthExceededMessage(output, context, outputLengthLimit == defaultOutputLengthLimit);
} else { } else {
output.WriteLine(ex.ToString()); output.WriteLine(ex.ToString());
} }
@ -205,11 +233,11 @@ namespace ICSharpCode.ILSpy.TextView
}); });
} }
static Task<AvalonEditTextOutput> RunDecompiler(ILSpy.Language language, ILSpyTreeNodeBase[] nodes, DecompilationOptions options, int outputLengthLimit) static Task<AvalonEditTextOutput> RunDecompiler(DecompilationContext context, int outputLengthLimit)
{ {
Debug.WriteLine("Start decompilation of {0} nodes", nodes.Length); Debug.WriteLine("Start decompilation of {0} tree nodes", context.TreeNodes.Length);
if (nodes.Length == 0) { if (context.TreeNodes.Length == 0) {
// If there's nothing to be decompiled, don't bother starting up a thread. // If there's nothing to be decompiled, don't bother starting up a thread.
// (Improves perf in some cases since we don't have to wait for the thread-pool to accept our task) // (Improves perf in some cases since we don't have to wait for the thread-pool to accept our task)
TaskCompletionSource<AvalonEditTextOutput> tcs = new TaskCompletionSource<AvalonEditTextOutput>(); TaskCompletionSource<AvalonEditTextOutput> tcs = new TaskCompletionSource<AvalonEditTextOutput>();
@ -221,20 +249,21 @@ namespace ICSharpCode.ILSpy.TextView
delegate { delegate {
AvalonEditTextOutput textOutput = new AvalonEditTextOutput(); AvalonEditTextOutput textOutput = new AvalonEditTextOutput();
textOutput.LengthLimit = outputLengthLimit; textOutput.LengthLimit = outputLengthLimit;
DecompileNodes(language, nodes, options, textOutput); DecompileNodes(context, textOutput);
textOutput.PrepareDocument(); textOutput.PrepareDocument();
return textOutput; return textOutput;
}); });
} }
static void DecompileNodes(ILSpy.Language language, ILSpyTreeNodeBase[] nodes, DecompilationOptions options, ITextOutput textOutput) static void DecompileNodes(DecompilationContext context, ITextOutput textOutput)
{ {
var nodes = context.TreeNodes;
for (int i = 0; i < nodes.Length; i++) { for (int i = 0; i < nodes.Length; i++) {
if (i > 0) if (i > 0)
textOutput.WriteLine(); textOutput.WriteLine();
options.CancellationToken.ThrowIfCancellationRequested(); context.Options.CancellationToken.ThrowIfCancellationRequested();
nodes[i].Decompile(language, textOutput, options); nodes[i].Decompile(context.Language, textOutput, context.Options);
} }
} }
#endregion #endregion
@ -244,10 +273,7 @@ namespace ICSharpCode.ILSpy.TextView
/// Creates a message that the decompiler output was too long. /// Creates a message that the decompiler output was too long.
/// The message contains buttons that allow re-trying (with larger limit) or saving to a file. /// The message contains buttons that allow re-trying (with larger limit) or saving to a file.
/// </summary> /// </summary>
void WriteOutputLengthExceededMessage( void WriteOutputLengthExceededMessage(ISmartTextOutput output, DecompilationContext context, bool wasNormalLimit)
ISmartTextOutput output,
ILSpy.Language language, ILSpyTreeNodeBase[] treeNodes, DecompilationOptions options,
bool wasNormalLimit)
{ {
if (wasNormalLimit) { if (wasNormalLimit) {
output.WriteLine("You have selected too much code for it to be displayed automatically."); output.WriteLine("You have selected too much code for it to be displayed automatically.");
@ -259,7 +285,7 @@ namespace ICSharpCode.ILSpy.TextView
output.AddUIElement(MakeButton( output.AddUIElement(MakeButton(
Images.ViewCode, "Display Code", Images.ViewCode, "Display Code",
delegate { delegate {
Decompile(language, treeNodes, extendedOutputLengthLimit, options); DoDecompile(context, extendedOutputLengthLimit);
})); }));
output.WriteLine(); output.WriteLine();
} }
@ -267,7 +293,7 @@ namespace ICSharpCode.ILSpy.TextView
output.AddUIElement(MakeButton( output.AddUIElement(MakeButton(
Images.Save, "Save Code", Images.Save, "Save Code",
delegate { delegate {
SaveToDisk(language, treeNodes, options); SaveToDisk(context.Language, context.TreeNodes, context.Options);
})); }));
output.WriteLine(); output.WriteLine();
} }
@ -349,7 +375,7 @@ namespace ICSharpCode.ILSpy.TextView
dlg.Filter = language.Name + "|*" + language.FileExtension + "|All Files|*.*"; dlg.Filter = language.Name + "|*" + language.FileExtension + "|All Files|*.*";
dlg.FileName = CleanUpName(treeNodes.First().ToString()) + language.FileExtension; dlg.FileName = CleanUpName(treeNodes.First().ToString()) + language.FileExtension;
if (dlg.ShowDialog() == true) { if (dlg.ShowDialog() == true) {
SaveToDisk(language, treeNodes.ToArray(), options, dlg.FileName); SaveToDisk(new DecompilationContext(language, treeNodes.ToArray(), options), dlg.FileName);
} }
} }
@ -357,16 +383,16 @@ namespace ICSharpCode.ILSpy.TextView
/// Starts the decompilation of the given nodes. /// Starts the decompilation of the given nodes.
/// The result will be saved to the given file name. /// The result will be saved to the given file name.
/// </summary> /// </summary>
public void SaveToDisk(ILSpy.Language language, ILSpyTreeNodeBase[] nodes, DecompilationOptions options, string fileName) void SaveToDisk(DecompilationContext context, string fileName)
{ {
RunWithCancellation( RunWithCancellation(
delegate (CancellationToken ct) { delegate (CancellationToken ct) {
options.CancellationToken = ct; context.Options.CancellationToken = ct;
return Task.Factory.StartNew( return Task.Factory.StartNew(
delegate { delegate {
using (StreamWriter w = new StreamWriter(fileName)) { using (StreamWriter w = new StreamWriter(fileName)) {
try { try {
DecompileNodes(language, nodes, options, new PlainTextOutput(w)); DecompileNodes(context, new PlainTextOutput(w));
} catch (OperationCanceledException) { } catch (OperationCanceledException) {
w.WriteLine(); w.WriteLine();
w.WriteLine("Decompiled was cancelled."); w.WriteLine("Decompiled was cancelled.");

Loading…
Cancel
Save