mirror of https://github.com/icsharpcode/ILSpy.git
15 changed files with 388 additions and 1 deletions
@ -0,0 +1,55 @@ |
|||||||
|
// 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.ComponentModel; |
||||||
|
|
||||||
|
namespace ICSharpCode.Decompiler |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Settings for the decompiler.
|
||||||
|
/// </summary>
|
||||||
|
public class DecompilerSettings : INotifyPropertyChanged |
||||||
|
{ |
||||||
|
bool anonymousMethods = true; |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decompile anonymous methods/lambdas.
|
||||||
|
/// </summary>
|
||||||
|
public bool AnonymousMethods { |
||||||
|
get { return anonymousMethods; } |
||||||
|
set { |
||||||
|
if (anonymousMethods != value) { |
||||||
|
anonymousMethods = value; |
||||||
|
OnPropertyChanged("AnonymousMethods"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
bool yieldReturn = true; |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decompile enumerators.
|
||||||
|
/// </summary>
|
||||||
|
public bool YieldReturn { |
||||||
|
get { return yieldReturn; } |
||||||
|
set { |
||||||
|
if (yieldReturn != value) { |
||||||
|
yieldReturn = value; |
||||||
|
OnPropertyChanged("YieldReturn"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public event EventHandler YieldReturnChanged; |
||||||
|
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged; |
||||||
|
|
||||||
|
protected virtual void OnPropertyChanged(string propertyName) |
||||||
|
{ |
||||||
|
if (PropertyChanged != null) { |
||||||
|
PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
// 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; |
||||||
|
|
||||||
|
namespace ICSharpCode.Decompiler.ILAst |
||||||
|
{ |
||||||
|
public class YieldReturnDecompiler |
||||||
|
{ |
||||||
|
// For a description on the code generated by the C# compiler for yield return:
|
||||||
|
// http://csharpindepth.com/Articles/Chapter6/IteratorBlockImplementation.aspx
|
||||||
|
|
||||||
|
// not implemented yet...
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,103 @@ |
|||||||
|
// 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.Collections.Generic; |
||||||
|
|
||||||
|
public static class YieldReturn |
||||||
|
{ |
||||||
|
public static IEnumerable<string> SimpleYieldReturn() |
||||||
|
{ |
||||||
|
yield return "A"; |
||||||
|
yield return "B"; |
||||||
|
yield return "C"; |
||||||
|
} |
||||||
|
|
||||||
|
public static IEnumerable<int> YieldReturnInLoop() |
||||||
|
{ |
||||||
|
for (int i = 0; i < 100; i++) { |
||||||
|
yield return i; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static IEnumerable<int> YieldReturnWithTryFinally() |
||||||
|
{ |
||||||
|
yield return 0; |
||||||
|
try { |
||||||
|
yield return 1; |
||||||
|
} finally { |
||||||
|
Console.WriteLine("Finally!"); |
||||||
|
} |
||||||
|
yield return 2; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public static IEnumerable<string> YieldReturnWithNestedTryFinally(bool breakInMiddle) |
||||||
|
{ |
||||||
|
Console.WriteLine("Start of method - 1"); |
||||||
|
yield return "Start of method"; |
||||||
|
Console.WriteLine("Start of method - 2"); |
||||||
|
try { |
||||||
|
Console.WriteLine("Within outer try - 1"); |
||||||
|
yield return "Within outer try"; |
||||||
|
Console.WriteLine("Within outer try - 2"); |
||||||
|
try { |
||||||
|
Console.WriteLine("Within inner try - 1"); |
||||||
|
yield return "Within inner try"; |
||||||
|
Console.WriteLine("Within inner try - 2"); |
||||||
|
if (breakInMiddle) |
||||||
|
yield break; |
||||||
|
Console.WriteLine("End of inner try - 1"); |
||||||
|
yield return "End of inner try"; |
||||||
|
Console.WriteLine("End of inner try - 2"); |
||||||
|
} finally { |
||||||
|
Console.WriteLine("Inner Finally"); |
||||||
|
} |
||||||
|
Console.WriteLine("End of outer try - 1"); |
||||||
|
yield return "End of outer try"; |
||||||
|
Console.WriteLine("End of outer try - 2"); |
||||||
|
} finally { |
||||||
|
Console.WriteLine("Outer Finally"); |
||||||
|
} |
||||||
|
Console.WriteLine("End of method - 1"); |
||||||
|
yield return "End of method"; |
||||||
|
Console.WriteLine("End of method - 2"); |
||||||
|
} |
||||||
|
|
||||||
|
public static IEnumerable<string> YieldReturnWithTwoNonNestedFinallyBlocks(IEnumerable<string> input) |
||||||
|
{ |
||||||
|
// outer try-finally block
|
||||||
|
foreach (string line in input) { |
||||||
|
// nested try-finally block
|
||||||
|
try { |
||||||
|
yield return line; |
||||||
|
} finally { |
||||||
|
Console.WriteLine("Processed " + line); |
||||||
|
} |
||||||
|
} |
||||||
|
yield return "A"; |
||||||
|
yield return "B"; |
||||||
|
yield return "C"; |
||||||
|
yield return "D"; |
||||||
|
yield return "E"; |
||||||
|
yield return "F"; |
||||||
|
// outer try-finally block
|
||||||
|
foreach (string line in input) |
||||||
|
yield return line.ToUpper(); |
||||||
|
} |
||||||
|
|
||||||
|
public static IEnumerable<Func<string>> YieldReturnWithAnonymousMethods1(IEnumerable<string> input) |
||||||
|
{ |
||||||
|
foreach (string line in input) { |
||||||
|
yield return () => line; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static IEnumerable<Func<string>> YieldReturnWithAnonymousMethods2(IEnumerable<string> input) |
||||||
|
{ |
||||||
|
foreach (string line in input) { |
||||||
|
string copy = line; |
||||||
|
yield return () => copy; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
<UserControl x:Class="ICSharpCode.ILSpy.DecompilerSettingsPanel" |
||||||
|
x:ClassModifier="internal" |
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
||||||
|
<StackPanel Margin="10"> |
||||||
|
<CheckBox IsChecked="{Binding AnonymousMethods}">Decompile anonymous methods/lambdas</CheckBox> |
||||||
|
<CheckBox IsChecked="{Binding YieldReturn}">Decompile enumerators (yield return)</CheckBox> |
||||||
|
</StackPanel> |
||||||
|
</UserControl> |
@ -0,0 +1,57 @@ |
|||||||
|
// 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.Collections.Generic; |
||||||
|
using System.Text; |
||||||
|
using System.Windows; |
||||||
|
using System.Windows.Controls; |
||||||
|
using System.Windows.Data; |
||||||
|
using System.Windows.Documents; |
||||||
|
using System.Windows.Input; |
||||||
|
using System.Windows.Media; |
||||||
|
using System.Xml.Linq; |
||||||
|
using ICSharpCode.Decompiler; |
||||||
|
|
||||||
|
namespace ICSharpCode.ILSpy |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for DecompilerSettingsPanel.xaml
|
||||||
|
/// </summary>
|
||||||
|
[ExportOptionPage("Decompiler")] |
||||||
|
partial class DecompilerSettingsPanel : UserControl, IOptionPage |
||||||
|
{ |
||||||
|
public DecompilerSettingsPanel() |
||||||
|
{ |
||||||
|
InitializeComponent(); |
||||||
|
} |
||||||
|
|
||||||
|
public void Load(ILSpySettings settings) |
||||||
|
{ |
||||||
|
this.DataContext = LoadDecompilerSettings(settings); |
||||||
|
} |
||||||
|
|
||||||
|
public static DecompilerSettings LoadDecompilerSettings(ILSpySettings settings) |
||||||
|
{ |
||||||
|
XElement e = settings["DecompilerSettings"]; |
||||||
|
DecompilerSettings s = new DecompilerSettings(); |
||||||
|
s.AnonymousMethods = (bool?)e.Attribute("anonymousMethods") ?? s.AnonymousMethods; |
||||||
|
s.YieldReturn = (bool?)e.Attribute("yieldReturn") ?? s.YieldReturn; |
||||||
|
return s; |
||||||
|
} |
||||||
|
|
||||||
|
public void Save(XElement root) |
||||||
|
{ |
||||||
|
DecompilerSettings s = (DecompilerSettings)this.DataContext; |
||||||
|
XElement section = new XElement("DecompilerSettings"); |
||||||
|
section.SetAttributeValue("anonymousMethods", s.AnonymousMethods); |
||||||
|
section.SetAttributeValue("yieldReturn", s.YieldReturn); |
||||||
|
|
||||||
|
XElement existingElement = root.Element("DecompilerSettings"); |
||||||
|
if (existingElement != null) |
||||||
|
existingElement.ReplaceWith(section); |
||||||
|
else |
||||||
|
root.Add(section); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
<Window x:Class="ICSharpCode.ILSpy.OptionsDialog" |
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||||
|
Style="{DynamicResource DialogWindow}" |
||||||
|
WindowStartupLocation="CenterOwner" |
||||||
|
ResizeMode="CanResizeWithGrip" |
||||||
|
Title="Options" Height="400" Width="500"> |
||||||
|
<Grid> |
||||||
|
<Grid.RowDefinitions> |
||||||
|
<RowDefinition |
||||||
|
Height="1*" /> |
||||||
|
<RowDefinition |
||||||
|
Height="Auto" /> |
||||||
|
</Grid.RowDefinitions> |
||||||
|
<TabControl Name="tabControl" /> |
||||||
|
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right" Margin="12,8"> |
||||||
|
<Button IsDefault="True" Margin="2,0" Name="okButton" Click="OKButton_Click">OK</Button> |
||||||
|
<Button IsCancel="True" Margin="2,0">Cancel</Button> |
||||||
|
</StackPanel> |
||||||
|
</Grid> |
||||||
|
</Window> |
@ -0,0 +1,93 @@ |
|||||||
|
// 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.Collections.Generic; |
||||||
|
using System.ComponentModel.Composition; |
||||||
|
using System.Text; |
||||||
|
using System.Windows; |
||||||
|
using System.Windows.Controls; |
||||||
|
using System.Windows.Data; |
||||||
|
using System.Windows.Documents; |
||||||
|
using System.Windows.Input; |
||||||
|
using System.Windows.Media; |
||||||
|
using System.Xml.Linq; |
||||||
|
|
||||||
|
namespace ICSharpCode.ILSpy |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for OptionsDialog.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class OptionsDialog : Window |
||||||
|
{ |
||||||
|
[ImportMany("OptionPages", typeof(UIElement), RequiredCreationPolicy = CreationPolicy.NonShared)] |
||||||
|
Lazy<UIElement, IOptionsMetadata>[] optionPages = null; |
||||||
|
|
||||||
|
public OptionsDialog() |
||||||
|
{ |
||||||
|
InitializeComponent(); |
||||||
|
App.CompositionContainer.ComposeParts(this); |
||||||
|
ILSpySettings settings = ILSpySettings.Load(); |
||||||
|
foreach (var optionPage in optionPages) { |
||||||
|
TabItem tabItem = new TabItem(); |
||||||
|
tabItem.Header = optionPage.Metadata.Title; |
||||||
|
tabItem.Content = optionPage.Value; |
||||||
|
tabControl.Items.Add(tabItem); |
||||||
|
|
||||||
|
IOptionPage page = optionPage.Value as IOptionPage; |
||||||
|
if (page != null) |
||||||
|
page.Load(settings); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void OKButton_Click(object sender, RoutedEventArgs e) |
||||||
|
{ |
||||||
|
ILSpySettings.Update( |
||||||
|
delegate (XElement root) { |
||||||
|
foreach (var optionPage in optionPages) { |
||||||
|
IOptionPage page = optionPage.Value as IOptionPage; |
||||||
|
if (page != null) |
||||||
|
page.Save(root); |
||||||
|
} |
||||||
|
}); |
||||||
|
this.DialogResult = true; |
||||||
|
Close(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public interface IOptionsMetadata |
||||||
|
{ |
||||||
|
string Title { get; } |
||||||
|
} |
||||||
|
|
||||||
|
public interface IOptionPage |
||||||
|
{ |
||||||
|
void Load(ILSpySettings settings); |
||||||
|
void Save(XElement root); |
||||||
|
} |
||||||
|
|
||||||
|
[MetadataAttribute] |
||||||
|
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false)] |
||||||
|
public class ExportOptionPageAttribute : ExportAttribute |
||||||
|
{ |
||||||
|
public ExportOptionPageAttribute(string title) |
||||||
|
: base("OptionPages", typeof(UIElement)) |
||||||
|
{ |
||||||
|
this.Title = title; |
||||||
|
} |
||||||
|
|
||||||
|
public string Title { get; private set; } |
||||||
|
} |
||||||
|
|
||||||
|
[ExportMainMenuCommand(Menu = "_View", Header = "_Options", MenuCategory = "Options", MenuOrder = 999)] |
||||||
|
sealed class ShowOptionsCommand : SimpleCommand |
||||||
|
{ |
||||||
|
public override void Execute(object parameter) |
||||||
|
{ |
||||||
|
OptionsDialog dlg = new OptionsDialog(); |
||||||
|
dlg.Owner = MainWindow.Instance; |
||||||
|
if (dlg.ShowDialog() == true) |
||||||
|
MainWindow.Instance.RefreshDecompiledView(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue