Browse Source

Merge pull request #1 from icsharpcode/master

Update from original
pull/668/head
OndrejPetrzilka 9 years ago committed by GitHub
parent
commit
d935d03cbd
  1. 5
      BuildTools/Automated.proj
  2. 2
      BuildTools/buildAndCreatePackage.bat
  3. 3
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  4. 32
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  5. 16
      ICSharpCode.Decompiler/Ast/DecompilerContext.cs
  6. 2
      ICSharpCode.Decompiler/Ast/NameVariables.cs
  7. 9
      ICSharpCode.Decompiler/Ast/TextTokenWriter.cs
  8. 2
      ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
  9. 56
      ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs
  10. 10
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  11. 19
      ICSharpCode.Decompiler/ILAst/StateRange.cs
  12. 4
      ICSharpCode.Decompiler/Tests/Async.cs
  13. 5
      ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs
  14. 30
      ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpPatternTests.cs
  15. 38
      ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs
  16. 64
      ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Debug.cs
  17. 344
      ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Debug.il
  18. 64
      ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Release.cs
  19. 311
      ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Release.il
  20. 87
      ICSharpCode.Decompiler/Tests/FSharpPatterns/TestHelpers.cs
  21. 99
      ICSharpCode.Decompiler/Tests/FSharpPatterns/ToolLocator.cs
  22. 44
      ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
  23. 28
      ICSharpCode.Decompiler/Tests/NotUsingBlock.cs
  24. 7
      ICSharpCode.Decompiler/Tests/TestRunner.cs
  25. 1
      ICSharpCode.Decompiler/Tests/packages.config
  26. 269
      ILSpy.AddIn/CodeElementXmlDocKeyProvider.cs
  27. 2
      ILSpy.AddIn/ILSpy.AddIn.csproj
  28. 14
      ILSpy.AddIn/ILSpyAddIn.vsct
  29. 141
      ILSpy.AddIn/ILSpyAddInPackage.cs
  30. 1
      ILSpy.AddIn/PkgCmdID.cs
  31. 4
      ILSpy.AddIn/Properties/AssemblyInfo.cs
  32. 414
      ILSpy.AddIn/Samples/ILSpyAddInSamples.cs
  33. 6
      ILSpy.AddIn/Utils.cs
  34. 2
      ILSpy.AddIn/license.txt
  35. 6
      ILSpy.AddIn/source.extension.vsixmanifest
  36. 19
      ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs
  37. 10
      ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj
  38. 4
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs
  39. 10
      ILSpy.BamlDecompiler/Tests/ILSpy.BamlDecompiler.Tests.csproj
  40. 1
      ILSpy.BamlDecompiler/Tests/TestRunner.cs
  41. 3
      ILSpy.sln
  42. 41
      ILSpy/AboutPage.cs
  43. 22
      ILSpy/AssemblyList.cs
  44. 31
      ILSpy/Commands/CheckForUpdatesCommand.cs
  45. 2
      ILSpy/Commands/OpenCommand.cs
  46. 2
      ILSpy/Commands/OpenFromGacCommand.cs
  47. 2
      ILSpy/Commands/OpenListCommand.cs
  48. 2
      ILSpy/Commands/RefreshCommand.cs
  49. 39
      ILSpy/Commands/SortAssemblyListCommand.cs
  50. 2
      ILSpy/ContextMenuEntry.cs
  51. 26
      ILSpy/ILSpy.csproj
  52. BIN
      ILSpy/Images/Library.png
  53. BIN
      ILSpy/Images/OverlayStatic.png
  54. BIN
      ILSpy/Images/SearchMsdn.png
  55. BIN
      ILSpy/Images/Sort.png
  56. 95
      ILSpy/Languages/CSharpLanguage.cs
  57. 30
      ILSpy/Languages/IResourceFileHandler.cs
  58. 96
      ILSpy/Languages/Language.cs
  59. 14
      ILSpy/LoadedAssembly.cs
  60. 8
      ILSpy/MainWindow.xaml
  61. 72
      ILSpy/MainWindow.xaml.cs
  62. 2
      ILSpy/Options/OptionsDialog.xaml.cs
  63. 6
      ILSpy/Properties/AssemblyInfo.template.cs
  64. 48
      ILSpy/SearchPane.cs
  65. 2
      ILSpy/SearchPane.xaml
  66. 79
      ILSpy/SearchStrategies.cs
  67. 4
      ILSpy/TextView/DecompilerTextView.cs
  68. 2
      ILSpy/TextView/DecompilerTextView.xaml
  69. 28
      ILSpy/TextView/EditorCommands.cs
  70. 2
      ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs
  71. 2
      ILSpy/TreeNodes/Analyzer/RemoveAnalyzeContextMenuEntry.cs
  72. 38
      ILSpy/TreeNodes/AssemblyTreeNode.cs
  73. 4
      ILSpy/TreeNodes/MethodTreeNode.cs
  74. 30
      ILSpy/TreeNodes/PropertyTreeNode.cs
  75. 2
      ILSpy/TreeNodes/SearchMsdnContextMenuEntry.cs
  76. 40
      ILSpy/VB/ILSpyEnvironmentProvider.cs
  77. 94
      ILSpy/VB/VBLanguage.cs
  78. 63
      ILSpy/VB/VBTextOutputFormatter.cs
  79. 7
      NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/ICSharpCode.NRefactory.VB.Tests.csproj
  80. 3
      NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerContextTests.cs
  81. 2
      NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/ImportsStatementTests.cs
  82. 3
      NRefactory.VB/ICSharpCode.NRefactory.VB/Ast/AstNodeCollection.cs
  83. 4
      NRefactory.VB/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj
  84. 114
      NRefactory.VB/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs
  85. 263
      NRefactory.VB/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs
  86. 28
      README.md
  87. 2
      README.txt
  88. 22
      Rebracer.xml
  89. 21
      SharpTreeView/SharpTreeView.cs
  90. 12
      TestPlugin/TestPlugin.csproj
  91. 2
      appveyor.yml
  92. 2
      debugbuild.bat
  93. 2
      releasebuild.bat

5
BuildTools/Automated.proj

@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
<ProjectDir Condition=" '$(ProjectDir)' == '' ">$(MSBuildProjectDirectory)\..</ProjectDir>
<ILSpyBin>$(ProjectDir)\ILSpy\bin\Release</ILSpyBin>
<VsixBin>$(ProjectDir)\ILSpy.AddIn\bin\Release</VsixBin>
<MSBuildCommunityTasksPath>$(ProjectDir)\BuildTools\MSBuildCommunityTasks</MSBuildCommunityTasksPath>
<ArtefactPrefix>ILSpy_</ArtefactPrefix>
@ -17,7 +18,7 @@ @@ -17,7 +18,7 @@
properties available for the projects inside the solution
(but this works using the command line) -->
<!-- C) We need to use MSBuild 4.0, but the build server uses MSBuild 2.0 -->
<MSBuildExecutable>&quot;$(MSBuildBinPath)\..\v4.0.30319\msbuild.exe&quot;</MSBuildExecutable>
<MSBuildExecutable>&quot;$(MSBuildBinPath)\msbuild.exe&quot;</MSBuildExecutable>
<BuildProperties>/p:Configuration=Release &quot;/p:Platform=Any CPU&quot;</BuildProperties>
<BuildProperties>$(BuildProperties) &quot;/p:BranchName=$(BranchName)&quot;</BuildProperties>
<BuildProperties>$(BuildProperties) $(AdditionalBuildProperties)</BuildProperties>
@ -92,6 +93,8 @@ @@ -92,6 +93,8 @@
ZipLevel="9"
WorkingDirectory="$(ILSpyBin)"
ZipFileName="$(ArtefactsOutputDir)\$(ArtefactPrefix)$(BuildNumber)_Binaries.zip"/>
<Copy SourceFiles="$(VsixBin)\ILSpy.AddIn.vsix"
DestinationFiles="$(ArtefactsOutputDir)\$(ArtefactPrefix)$(BuildNumber)_Addin.vsix"/>
</Target>
<Target Name="zipsource">

2
BuildTools/buildAndCreatePackage.bat

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
@echo This script simulates what the build server is doing
@rem /p:AdditionalBuildProperties="/v:d /p:MSBuildTargetsVerbose=true"
%windir%\microsoft.net\framework\v4.0.30319\msbuild Automated.proj /p:ArtefactsOutputDir="%CD%\build" /p:TestReportsDir="%CD%\build"
"%ProgramFiles(x86)%\MSBuild\14.0\Bin\msbuild.exe" Automated.proj /p:ArtefactsOutputDir="%CD%\build" /p:TestReportsDir="%CD%\build"
@IF %ERRORLEVEL% NEQ 0 GOTO err
@exit /B 0
:err

3
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -1521,7 +1521,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -1521,7 +1521,8 @@ namespace ICSharpCode.Decompiler.Ast
}
var type = argument.Type.Resolve();
if (type != null && type.IsEnum) {
return MakePrimitive(Convert.ToInt64(argument.Value), type);
long val = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, argument.Value, false);
return MakePrimitive(val, type);
} else if (argument.Value is TypeReference) {
return CreateTypeOfExpression((TypeReference)argument.Value);
} else {

32
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -754,26 +754,28 @@ namespace ICSharpCode.Decompiler.Ast @@ -754,26 +754,28 @@ namespace ICSharpCode.Decompiler.Ast
return ace;
}
}
if (declaringType.IsAnonymousType()) {
MethodDefinition ctor = ((MethodReference)operand).Resolve();
if (methodDef != null) {
AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression();
if (CanInferAnonymousTypePropertyNamesFromArguments(args, ctor.Parameters)) {
atce.Initializers.AddRange(args);
} else {
for (int i = 0; i < args.Count; i++) {
atce.Initializers.Add(
new NamedExpression {
Name = ctor.Parameters[i].Name,
Expression = args[i]
});
}
MethodDefinition ctor = ((MethodReference)operand).Resolve();
if (declaringType.IsAnonymousType() && methodDef != null) {
AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression();
if (CanInferAnonymousTypePropertyNamesFromArguments(args, ctor.Parameters)) {
atce.Initializers.AddRange(args);
} else {
for (int i = 0; i < args.Count; i++) {
atce.Initializers.Add(
new NamedExpression {
Name = ctor.Parameters[i].Name,
Expression = args[i]
});
}
return atce;
}
return atce;
}
var oce = new Ast.ObjectCreateExpression();
oce.Type = AstBuilder.ConvertType(declaringType);
// seems like IsIn/IsOut information for parameters is only correct on the ctor's MethodDefinition
if (ctor != null) {
AdjustArgumentsForMethodCall(ctor, args);
}
oce.Arguments.AddRange(args);
return oce.WithAnnotation(operand);
}

16
ICSharpCode.Decompiler/Ast/DecompilerContext.cs

@ -35,25 +35,11 @@ namespace ICSharpCode.Decompiler @@ -35,25 +35,11 @@ namespace ICSharpCode.Decompiler
public DecompilerSettings Settings = new DecompilerSettings();
public bool CurrentMethodIsAsync;
// public ITypeResolveContext TypeResolveContext;
// public IProjectContent ProjectContent;
public DecompilerContext(ModuleDefinition currentModule)
{
if (currentModule == null)
throw new ArgumentNullException("currentModule");
throw new ArgumentNullException(nameof(currentModule));
this.CurrentModule = currentModule;
// this.ProjectContent = new CecilTypeResolveContext(currentModule);
// List<ITypeResolveContext> resolveContexts = new List<ITypeResolveContext>();
// resolveContexts.Add(this.ProjectContent);
// foreach (AssemblyNameReference r in currentModule.AssemblyReferences) {
// AssemblyDefinition d = currentModule.AssemblyResolver.Resolve(r);
// if (d != null) {
// resolveContexts.Add(new CecilTypeResolveContext(d.MainModule));
// }
// }
// this.TypeResolveContext = new CompositeTypeResolveContext(resolveContexts);
}
/// <summary>

2
ICSharpCode.Decompiler/Ast/NameVariables.cs

@ -335,7 +335,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -335,7 +335,7 @@ namespace ICSharpCode.Decompiler.Ast
// remove field prefix:
if (name.Length > 2 && name.StartsWith("m_", StringComparison.Ordinal))
name = name.Substring(2);
else if (name.Length > 1 && name[0] == '_')
else if (name.Length > 1 && name[0] == '_' && (char.IsLetter(name[1]) || name[1] == '_'))
name = name.Substring(1);
if (name.Length == 0)

9
ICSharpCode.Decompiler/Ast/TextTokenWriter.cs

@ -188,6 +188,15 @@ namespace ICSharpCode.Decompiler.Ast @@ -188,6 +188,15 @@ namespace ICSharpCode.Decompiler.Ast
public override void WriteKeyword(Role role, string keyword)
{
//To make reference for 'this' and 'base' keywords in the ClassName():this() expression
if (role == ConstructorInitializer.ThisKeywordRole || role == ConstructorInitializer.BaseKeywordRole) {
var reference = GetCurrentMemberReference();
if (reference != null) {
output.WriteReference(keyword, reference);
return;
}
}
output.Write(keyword);
}

2
ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs

@ -194,7 +194,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -194,7 +194,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
ame.Body = body;
replacement = ame;
}
var expectedType = objectCreateExpression.Annotation<TypeInformation>().ExpectedType.Resolve();
var expectedType = objectCreateExpression.Annotation<TypeInformation>()?.ExpectedType?.Resolve();
if (expectedType != null && !expectedType.IsDelegate()) {
var simplifiedDelegateCreation = (ObjectCreateExpression)objectCreateExpression.Clone();
simplifiedDelegateCreation.Arguments.Clear();

56
ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs

@ -58,11 +58,12 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -58,11 +58,12 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
public override AstNode VisitExpressionStatement(ExpressionStatement expressionStatement, object data)
{
AstNode result;
if (context.Settings.UsingStatement) {
result = TransformUsings(expressionStatement);
if (context.Settings.UsingStatement)
{
result = TransformNonGenericForEach(expressionStatement);
if (result != null)
return result;
result = TransformNonGenericForEach(expressionStatement);
result = TransformUsings(expressionStatement);
if (result != null)
return result;
}
@ -156,7 +157,9 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -156,7 +157,9 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
};
}
static readonly AstNode usingTryCatchPattern = new TryCatchStatement {
static readonly AstNode usingTryCatchPattern = new Choice {
{ "c#/vb",
new TryCatchStatement {
TryBlock = new AnyNode(),
FinallyBlock = new BlockStatement {
new Choice {
@ -177,6 +180,33 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -177,6 +180,33 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
}
}.ToStatement()
}
}
},
{ "f#",
new TryCatchStatement {
TryBlock = new AnyNode(),
FinallyBlock =
new BlockStatement {
new ExpressionStatement(
new AssignmentExpression(left: new NamedNode("disposable", new IdentifierExpression(Pattern.AnyString)),
right: new AsExpression(expression: new NamedNode("ident", new IdentifierExpression(Pattern.AnyString)),
type: new TypePattern(typeof(IDisposable))
)
)
),
new IfElseStatement {
Condition = new BinaryOperatorExpression(
new Backreference("disposable"),
BinaryOperatorType.InEquality,
new NullReferenceExpression()
),
TrueStatement = new BlockStatement {
new ExpressionStatement(InvokeDispose(new Backreference("disposable")))
}
}
}
}
}
};
public UsingStatement TransformUsings(ExpressionStatement node)
@ -214,6 +244,17 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -214,6 +244,17 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
if (!IsVariableValueUnused(varDecl, tryCatch))
return null;
if (m2.Has("f#")) {
string variableNameDisposable = m2.Get<IdentifierExpression>("disposable").Single().Identifier;
VariableDeclarationStatement varDeclDisposable = FindVariableDeclaration(node, variableNameDisposable);
if (varDeclDisposable == null || !(varDeclDisposable.Parent is BlockStatement))
return null;
// Validate that the variable is not used after the using statement:
if (!IsVariableValueUnused(varDeclDisposable, tryCatch))
return null;
}
node.Remove();
UsingStatement usingStatement = new UsingStatement();
@ -379,6 +420,13 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -379,6 +420,13 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
if (declarationPoint != loop)
return null;
// Make sure that the enumerator variable is not used inside the body
var enumeratorId = Identifier.Create(enumeratorVar.Name);
foreach (Statement stmt in m.Get<Statement>("statement")) {
if (stmt.Descendants.OfType<Identifier>().Any(id => enumeratorId.IsMatch(id)))
return null;
}
BlockStatement newBody = new BlockStatement();
foreach (Statement stmt in m.Get<Statement>("variablesInsideLoop"))
newBody.Add(stmt.Detach());

10
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -139,16 +139,16 @@ @@ -139,16 +139,16 @@
<None Include="Properties\AssemblyInfo.template.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\cecil\Mono.Cecil.csproj" Condition=" '$(BuildNuGetPackage)' != 'True' ">
<Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
<ProjectReference Include="..\cecil\Mono.Cecil.csproj" Condition=" '$(BuildNuGetPackage)' != 'True' ">
<Project>{d68133bd-1e63-496e-9ede-4fbdbf77b486}</Project>
<Name>Mono.Cecil</Name>
</ProjectReference>
<ProjectReference Include="..\NRefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj" Condition=" '$(BuildNuGetPackage)' != 'True' ">
<Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project>
<ProjectReference Include="..\NRefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj" Condition=" '$(BuildNuGetPackage)' != 'True' ">
<Project>{53dca265-3c3c-42f9-b647-f72ba678122b}</Project>
<Name>ICSharpCode.NRefactory.CSharp</Name>
</ProjectReference>
<ProjectReference Include="..\NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj" Condition=" '$(BuildNuGetPackage)' != 'True' ">
<Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project>
<Project>{3b2a5653-ec97-4001-bb9b-d90f1af2c371}</Project>
<Name>ICSharpCode.NRefactory</Name>
</ProjectReference>
</ItemGroup>

19
ICSharpCode.Decompiler/ILAst/StateRange.cs

@ -273,14 +273,23 @@ namespace ICSharpCode.Decompiler.ILAst @@ -273,14 +273,23 @@ namespace ICSharpCode.Decompiler.ILAst
{
if (pos > 0 && body[pos - 1] is ILLabel) {
pos--;
return; // label found
}
// ensure that the first element at body[pos] is a label:
ILLabel newLabel = new ILLabel();
newLabel.Name = "YieldReturnEntryPoint";
ILExpression expr = pos == 1 && body.Count == 1 ? body[0] as ILExpression : null;
if (expr != null && expr.Code == ILCode.Leave && expr.Operand is ILLabel) {
ranges[newLabel] = ranges[(ILLabel)expr.Operand];
pos = 0;
} else {
// ensure that the first element at body[pos] is a label:
ILLabel newLabel = new ILLabel();
newLabel.Name = "YieldReturnEntryPoint";
ranges[newLabel] = ranges[body[pos]]; // give the label the range of the instruction at body[pos]
body.Insert(pos, newLabel);
bodyLength++;
}
body.Insert(pos, newLabel);
bodyLength++;
}
public LabelRangeMapping CreateLabelRangeMapping(List<ILNode> body, int pos, int bodyLength)

4
ICSharpCode.Decompiler/Tests/Async.cs

@ -37,6 +37,10 @@ public class Async @@ -37,6 +37,10 @@ public class Async
Console.WriteLine("No Await");
}
public async void EmptyVoidMethod()
{
}
public async void AwaitYield()
{
await Task.Yield();

5
ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs

@ -39,6 +39,11 @@ namespace aa @@ -39,6 +39,11 @@ namespace aa
{
}
}
[CustomAttributes.MyAttribute(CustomAttributes.ULongEnum.MaxUInt64)]
public enum ULongEnum : ulong
{
MaxUInt64 = 18446744073709551615uL
}
[CustomAttributes.MyAttribute(CustomAttributes.EnumWithFlag.Item1 | CustomAttributes.EnumWithFlag.Item2)]
private static int field;
[CustomAttributes.MyAttribute(CustomAttributes.EnumWithFlag.All)]

30
ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpPatternTests.cs

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.Tests.FSharpPatterns
{
[TestFixture]
public class FSharpPatternTests
{
[Test]
public void FSharpUsingDecompilesToCSharpUsing_Debug()
{
var ilCode = TestHelpers.FuzzyReadResource("FSharpUsing.fs.Debug.il");
var csharpCode = TestHelpers.FuzzyReadResource("FSharpUsing.fs.Debug.cs");
TestHelpers.RunIL(ilCode, csharpCode);
}
[Test]
public void FSharpUsingDecompilesToCSharpUsing_Release()
{
var ilCode = TestHelpers.FuzzyReadResource("FSharpUsing.fs.Release.il");
var csharpCode = TestHelpers.FuzzyReadResource("FSharpUsing.fs.Release.cs");
TestHelpers.RunIL(ilCode, csharpCode);
}
}
}

38
ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
module FSharpUsingPatterns
open System
open System.IO
let sample1() =
use fs = File.Create("x.txt")
fs.WriteByte(byte 1)
let sample2() =
Console.WriteLine("some text")
use fs = File.Create("x.txt")
fs.WriteByte(byte 2)
Console.WriteLine("some text")
let sample3() =
Console.WriteLine("some text")
do use fs = File.Create("x.txt")
fs.WriteByte(byte 3)
Console.WriteLine("some text")
let sample4() =
Console.WriteLine("some text")
let firstByte =
use fs = File.OpenRead("x.txt")
fs.ReadByte()
Console.WriteLine("read:" + firstByte.ToString())
let sample5() =
Console.WriteLine("some text")
let firstByte =
use fs = File.OpenRead("x.txt")
fs.ReadByte()
let secondByte =
use fs = File.OpenRead("x.txt")
fs.ReadByte() |> ignore
fs.ReadByte()
Console.WriteLine("read: {0}, {1}", firstByte, secondByte)

64
ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Debug.cs

@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
using System;
using System.IO;
public static class FSharpUsingPatterns
{
public static void sample1()
{
using (FileStream fs = File.Create("x.txt"))
{
fs.WriteByte((byte)1);
}
}
public static void sample2()
{
Console.WriteLine("some text");
using (FileStream fs = File.Create("x.txt"))
{
fs.WriteByte((byte)2);
Console.WriteLine("some text");
}
}
public static void sample3()
{
Console.WriteLine("some text");
using (FileStream fs = File.Create("x.txt"))
{
fs.WriteByte((byte)3);
}
Console.WriteLine("some text");
}
public static void sample4()
{
Console.WriteLine("some text");
int num;
using (FileStream fs = File.OpenRead("x.txt"))
{
num = fs.ReadByte();
}
int firstByte = num;
Console.WriteLine("read:" + firstByte.ToString());
}
public static void sample5()
{
Console.WriteLine("some text");
int num;
using (FileStream fs = File.OpenRead("x.txt"))
{
num = fs.ReadByte();
}
int firstByte = num;
int num3;
using (FileStream fs = File.OpenRead("x.txt"))
{
int num2 = fs.ReadByte();
num3 = fs.ReadByte();
}
int secondByte = num3;
Console.WriteLine("read: {0}, {1}", firstByte, secondByte);
}
}

344
ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Debug.il

@ -0,0 +1,344 @@ @@ -0,0 +1,344 @@
.class public auto ansi abstract sealed FSharpUsingPatterns
extends [mscorlib]System.Object
{
// Methods
.method public static
void sample1 () cil managed
{
// Method begins at RVA 0x2050
// Code size 53 (0x35)
.maxstack 4
.locals init (
[0] class [mscorlib]System.IO.FileStream fs,
[1] class [mscorlib]System.Object,
[2] class [mscorlib]System.IDisposable
)
IL_0000: nop
IL_0001: ldstr "x.txt"
IL_0006: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::Create(string)
IL_000b: stloc.0
.try
{
IL_000c: ldloc.0
IL_000d: ldc.i4.1
IL_000e: conv.u1
IL_000f: callvirt instance void [mscorlib]System.IO.Stream::WriteByte(uint8)
IL_0014: ldnull
IL_0015: stloc.1
IL_0016: leave.s IL_0032
} // end .try
finally
{
IL_0018: ldloc.0
IL_0019: isinst [mscorlib]System.IDisposable
IL_001e: stloc.2
IL_001f: ldloc.2
IL_0020: brfalse.s IL_0024
IL_0022: br.s IL_0026
IL_0024: br.s IL_002f
IL_0026: ldloc.2
IL_0027: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_002c: ldnull
IL_002d: pop
IL_002e: endfinally
IL_002f: ldnull
IL_0030: pop
IL_0031: endfinally
} // end handler
IL_0032: ldloc.1
IL_0033: pop
IL_0034: ret
} // end of method FSharpUsingPatterns::sample1
.method public static
void sample2 () cil managed
{
// Method begins at RVA 0x20a4
// Code size 73 (0x49)
.maxstack 4
.locals init (
[0] class [mscorlib]System.IO.FileStream fs,
[1] class [mscorlib]System.Object,
[2] class [mscorlib]System.IDisposable
)
IL_0000: nop
IL_0001: ldstr "some text"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: ldstr "x.txt"
IL_0010: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::Create(string)
IL_0015: stloc.0
.try
{
IL_0016: ldloc.0
IL_0017: ldc.i4.2
IL_0018: conv.u1
IL_0019: callvirt instance void [mscorlib]System.IO.Stream::WriteByte(uint8)
IL_001e: ldstr "some text"
IL_0023: call void [mscorlib]System.Console::WriteLine(string)
IL_0028: ldnull
IL_0029: stloc.1
IL_002a: leave.s IL_0046
} // end .try
finally
{
IL_002c: ldloc.0
IL_002d: isinst [mscorlib]System.IDisposable
IL_0032: stloc.2
IL_0033: ldloc.2
IL_0034: brfalse.s IL_0038
IL_0036: br.s IL_003a
IL_0038: br.s IL_0043
IL_003a: ldloc.2
IL_003b: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0040: ldnull
IL_0041: pop
IL_0042: endfinally
IL_0043: ldnull
IL_0044: pop
IL_0045: endfinally
} // end handler
IL_0046: ldloc.1
IL_0047: pop
IL_0048: ret
} // end of method FSharpUsingPatterns::sample2
.method public static
void sample3 () cil managed
{
// Method begins at RVA 0x210c
// Code size 73 (0x49)
.maxstack 4
.locals init (
[0] class [mscorlib]System.IO.FileStream fs,
[1] class [mscorlib]System.Object,
[2] class [mscorlib]System.IDisposable
)
IL_0000: nop
IL_0001: ldstr "some text"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: ldstr "x.txt"
IL_0010: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::Create(string)
IL_0015: stloc.0
.try
{
IL_0016: ldloc.0
IL_0017: ldc.i4.3
IL_0018: conv.u1
IL_0019: callvirt instance void [mscorlib]System.IO.Stream::WriteByte(uint8)
IL_001e: ldnull
IL_001f: stloc.1
IL_0020: leave.s IL_003c
} // end .try
finally
{
IL_0022: ldloc.0
IL_0023: isinst [mscorlib]System.IDisposable
IL_0028: stloc.2
IL_0029: ldloc.2
IL_002a: brfalse.s IL_002e
IL_002c: br.s IL_0030
IL_002e: br.s IL_0039
IL_0030: ldloc.2
IL_0031: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0036: ldnull
IL_0037: pop
IL_0038: endfinally
IL_0039: ldnull
IL_003a: pop
IL_003b: endfinally
} // end handler
IL_003c: ldloc.1
IL_003d: pop
IL_003e: ldstr "some text"
IL_0043: call void [mscorlib]System.Console::WriteLine(string)
IL_0048: ret
} // end of method FSharpUsingPatterns::sample3
.method public static
void sample4 () cil managed
{
// Method begins at RVA 0x2174
// Code size 89 (0x59)
.maxstack 4
.locals init (
[0] int32 firstByte,
[1] class [mscorlib]System.IO.FileStream fs,
[2] int32,
[3] class [mscorlib]System.IDisposable
)
IL_0000: nop
IL_0001: ldstr "some text"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ldstr "x.txt"
IL_0011: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::OpenRead(string)
IL_0016: stloc.1
.try
{
IL_0017: ldloc.1
IL_0018: callvirt instance int32 [mscorlib]System.IO.Stream::ReadByte()
IL_001d: stloc.2
IL_001e: leave.s IL_003a
} // end .try
finally
{
IL_0020: ldloc.1
IL_0021: isinst [mscorlib]System.IDisposable
IL_0026: stloc.3
IL_0027: ldloc.3
IL_0028: brfalse.s IL_002c
IL_002a: br.s IL_002e
IL_002c: br.s IL_0037
IL_002e: ldloc.3
IL_002f: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0034: ldnull
IL_0035: pop
IL_0036: endfinally
IL_0037: ldnull
IL_0038: pop
IL_0039: endfinally
} // end handler
IL_003a: ldloc.2
IL_003b: stloc.0
IL_003c: ldstr "read:"
IL_0041: ldloca.s firstByte
IL_0043: constrained. [mscorlib]System.Int32
IL_0049: callvirt instance string [mscorlib]System.Object::ToString()
IL_004e: call string [mscorlib]System.String::Concat(string, string)
IL_0053: call void [mscorlib]System.Console::WriteLine(string)
IL_0058: ret
} // end of method FSharpUsingPatterns::sample4
.method public static
void sample5 () cil managed
{
// Method begins at RVA 0x21ec
// Code size 155 (0x9b)
.maxstack 5
.locals init (
[0] int32 firstByte,
[1] class [mscorlib]System.IO.FileStream fs,
[2] int32,
[3] class [mscorlib]System.IDisposable,
[4] int32 secondByte,
[5] class [mscorlib]System.IO.FileStream fs,
[6] int32,
[7] int32,
[8] int32,
[9] class [mscorlib]System.IDisposable
)
IL_0000: nop
IL_0001: ldstr "some text"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ldstr "x.txt"
IL_0011: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::OpenRead(string)
IL_0016: stloc.1
.try
{
IL_0017: ldloc.1
IL_0018: callvirt instance int32 [mscorlib]System.IO.Stream::ReadByte()
IL_001d: stloc.2
IL_001e: leave.s IL_003a
} // end .try
finally
{
IL_0020: ldloc.1
IL_0021: isinst [mscorlib]System.IDisposable
IL_0026: stloc.3
IL_0027: ldloc.3
IL_0028: brfalse.s IL_002c
IL_002a: br.s IL_002e
IL_002c: br.s IL_0037
IL_002e: ldloc.3
IL_002f: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0034: ldnull
IL_0035: pop
IL_0036: endfinally
IL_0037: ldnull
IL_0038: pop
IL_0039: endfinally
} // end handler
IL_003a: ldloc.2
IL_003b: stloc.0
IL_003c: nop
IL_003d: ldstr "x.txt"
IL_0042: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::OpenRead(string)
IL_0047: stloc.s fs
.try
{
IL_0049: ldloc.s fs
IL_004b: callvirt instance int32 [mscorlib]System.IO.Stream::ReadByte()
IL_0050: stloc.s 7
IL_0052: ldloc.s 7
IL_0054: stloc.s 8
IL_0056: ldloc.s fs
IL_0058: callvirt instance int32 [mscorlib]System.IO.Stream::ReadByte()
IL_005d: stloc.s 6
IL_005f: leave.s IL_007f
} // end .try
finally
{
IL_0061: ldloc.s fs
IL_0063: isinst [mscorlib]System.IDisposable
IL_0068: stloc.s 9
IL_006a: ldloc.s 9
IL_006c: brfalse.s IL_0070
IL_006e: br.s IL_0072
IL_0070: br.s IL_007c
IL_0072: ldloc.s 9
IL_0074: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0079: ldnull
IL_007a: pop
IL_007b: endfinally
IL_007c: ldnull
IL_007d: pop
IL_007e: endfinally
} // end handler
IL_007f: ldloc.s 6
IL_0081: stloc.s secondByte
IL_0083: ldstr "read: {0}, {1}"
IL_0088: ldloc.0
IL_0089: box [mscorlib]System.Int32
IL_008e: ldloc.s secondByte
IL_0090: box [mscorlib]System.Int32
IL_0095: call void [mscorlib]System.Console::WriteLine(string, object, object)
IL_009a: ret
} // end of method FSharpUsingPatterns::sample5
} // end of class FSharpUsingPatterns

64
ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Release.cs

@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
using System;
using System.IO;
public static class FSharpUsingPatterns
{
public static void sample1()
{
using (FileStream fs = File.Create("x.txt"))
{
fs.WriteByte(1);
}
}
public static void sample2()
{
Console.WriteLine("some text");
using (FileStream fs = File.Create("x.txt"))
{
fs.WriteByte(2);
Console.WriteLine("some text");
}
}
public static void sample3()
{
Console.WriteLine("some text");
using (FileStream fs = File.Create("x.txt"))
{
fs.WriteByte(3);
}
Console.WriteLine("some text");
}
public static void sample4()
{
Console.WriteLine("some text");
int num;
using (FileStream fs = File.OpenRead("x.txt"))
{
num = fs.ReadByte();
}
int firstByte = num;
Console.WriteLine("read:" + firstByte.ToString());
}
public static void sample5()
{
Console.WriteLine("some text");
int secondByte;
using (FileStream fs = File.OpenRead("x.txt"))
{
secondByte = fs.ReadByte();
}
int firstByte = secondByte;
int num2;
using (FileStream fs = File.OpenRead("x.txt"))
{
int num = fs.ReadByte();
num2 = fs.ReadByte();
}
secondByte = num2;
Console.WriteLine("read: {0}, {1}", firstByte, secondByte);
}
}

311
ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Release.il

@ -0,0 +1,311 @@ @@ -0,0 +1,311 @@
.class public auto ansi abstract sealed FSharpUsingPatterns
extends [mscorlib]System.Object
{
// Methods
.method public static
void sample1 () cil managed
{
// Method begins at RVA 0x2050
// Code size 48 (0x30)
.maxstack 4
.locals init (
[0] class [mscorlib]System.IO.FileStream fs,
[1] class [mscorlib]System.Object,
[2] class [mscorlib]System.IDisposable
)
IL_0000: nop
IL_0001: ldstr "x.txt"
IL_0006: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::Create(string)
IL_000b: stloc.0
.try
{
IL_000c: ldloc.0
IL_000d: ldc.i4.1
IL_000e: callvirt instance void [mscorlib]System.IO.Stream::WriteByte(uint8)
IL_0013: ldnull
IL_0014: stloc.1
IL_0015: leave.s IL_002d
} // end .try
finally
{
IL_0017: ldloc.0
IL_0018: isinst [mscorlib]System.IDisposable
IL_001d: stloc.2
IL_001e: ldloc.2
IL_001f: brfalse.s IL_002a
IL_0021: ldloc.2
IL_0022: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0027: ldnull
IL_0028: pop
IL_0029: endfinally
IL_002a: ldnull
IL_002b: pop
IL_002c: endfinally
} // end handler
IL_002d: ldloc.1
IL_002e: pop
IL_002f: ret
} // end of method FSharpUsingPatterns::sample1
.method public static
void sample2 () cil managed
{
// Method begins at RVA 0x209c
// Code size 68 (0x44)
.maxstack 4
.locals init (
[0] class [mscorlib]System.IO.FileStream fs,
[1] class [mscorlib]System.Object,
[2] class [mscorlib]System.IDisposable
)
IL_0000: nop
IL_0001: ldstr "some text"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: ldstr "x.txt"
IL_0010: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::Create(string)
IL_0015: stloc.0
.try
{
IL_0016: ldloc.0
IL_0017: ldc.i4.2
IL_0018: callvirt instance void [mscorlib]System.IO.Stream::WriteByte(uint8)
IL_001d: ldstr "some text"
IL_0022: call void [mscorlib]System.Console::WriteLine(string)
IL_0027: ldnull
IL_0028: stloc.1
IL_0029: leave.s IL_0041
} // end .try
finally
{
IL_002b: ldloc.0
IL_002c: isinst [mscorlib]System.IDisposable
IL_0031: stloc.2
IL_0032: ldloc.2
IL_0033: brfalse.s IL_003e
IL_0035: ldloc.2
IL_0036: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_003b: ldnull
IL_003c: pop
IL_003d: endfinally
IL_003e: ldnull
IL_003f: pop
IL_0040: endfinally
} // end handler
IL_0041: ldloc.1
IL_0042: pop
IL_0043: ret
} // end of method FSharpUsingPatterns::sample2
.method public static
void sample3 () cil managed
{
// Method begins at RVA 0x20fc
// Code size 68 (0x44)
.maxstack 4
.locals init (
[0] class [mscorlib]System.IO.FileStream fs,
[1] class [mscorlib]System.Object,
[2] class [mscorlib]System.IDisposable
)
IL_0000: nop
IL_0001: ldstr "some text"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: ldstr "x.txt"
IL_0010: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::Create(string)
IL_0015: stloc.0
.try
{
IL_0016: ldloc.0
IL_0017: ldc.i4.3
IL_0018: callvirt instance void [mscorlib]System.IO.Stream::WriteByte(uint8)
IL_001d: ldnull
IL_001e: stloc.1
IL_001f: leave.s IL_0037
} // end .try
finally
{
IL_0021: ldloc.0
IL_0022: isinst [mscorlib]System.IDisposable
IL_0027: stloc.2
IL_0028: ldloc.2
IL_0029: brfalse.s IL_0034
IL_002b: ldloc.2
IL_002c: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0031: ldnull
IL_0032: pop
IL_0033: endfinally
IL_0034: ldnull
IL_0035: pop
IL_0036: endfinally
} // end handler
IL_0037: ldloc.1
IL_0038: pop
IL_0039: ldstr "some text"
IL_003e: call void [mscorlib]System.Console::WriteLine(string)
IL_0043: ret
} // end of method FSharpUsingPatterns::sample3
.method public static
void sample4 () cil managed
{
// Method begins at RVA 0x215c
// Code size 85 (0x55)
.maxstack 4
.locals init (
[0] int32 firstByte,
[1] class [mscorlib]System.IO.FileStream fs,
[2] int32,
[3] class [mscorlib]System.IDisposable
)
IL_0000: nop
IL_0001: ldstr "some text"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ldstr "x.txt"
IL_0011: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::OpenRead(string)
IL_0016: stloc.1
.try
{
IL_0017: ldloc.1
IL_0018: callvirt instance int32 [mscorlib]System.IO.Stream::ReadByte()
IL_001d: stloc.2
IL_001e: leave.s IL_0036
} // end .try
finally
{
IL_0020: ldloc.1
IL_0021: isinst [mscorlib]System.IDisposable
IL_0026: stloc.3
IL_0027: ldloc.3
IL_0028: brfalse.s IL_0033
IL_002a: ldloc.3
IL_002b: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0030: ldnull
IL_0031: pop
IL_0032: endfinally
IL_0033: ldnull
IL_0034: pop
IL_0035: endfinally
} // end handler
IL_0036: ldloc.2
IL_0037: stloc.0
IL_0038: ldstr "read:"
IL_003d: ldloca.s firstByte
IL_003f: constrained. [mscorlib]System.Int32
IL_0045: callvirt instance string [mscorlib]System.Object::ToString()
IL_004a: call string [mscorlib]System.String::Concat(string, string)
IL_004f: call void [mscorlib]System.Console::WriteLine(string)
IL_0054: ret
} // end of method FSharpUsingPatterns::sample4
.method public static
void sample5 () cil managed
{
// Method begins at RVA 0x21d0
// Code size 134 (0x86)
.maxstack 5
.locals init (
[0] int32 firstByte,
[1] class [mscorlib]System.IO.FileStream fs,
[2] int32 secondByte,
[3] class [mscorlib]System.IDisposable,
[4] int32,
[5] int32
)
IL_0000: nop
IL_0001: ldstr "some text"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ldstr "x.txt"
IL_0011: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::OpenRead(string)
IL_0016: stloc.1
.try
{
IL_0017: ldloc.1
IL_0018: callvirt instance int32 [mscorlib]System.IO.Stream::ReadByte()
IL_001d: stloc.2
IL_001e: leave.s IL_0036
} // end .try
finally
{
IL_0020: ldloc.1
IL_0021: isinst [mscorlib]System.IDisposable
IL_0026: stloc.3
IL_0027: ldloc.3
IL_0028: brfalse.s IL_0033
IL_002a: ldloc.3
IL_002b: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0030: ldnull
IL_0031: pop
IL_0032: endfinally
IL_0033: ldnull
IL_0034: pop
IL_0035: endfinally
} // end handler
IL_0036: ldloc.2
IL_0037: stloc.0
IL_0038: nop
IL_0039: ldstr "x.txt"
IL_003e: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::OpenRead(string)
IL_0043: stloc.1
.try
{
IL_0044: ldloc.1
IL_0045: callvirt instance int32 [mscorlib]System.IO.Stream::ReadByte()
IL_004a: stloc.s 5
IL_004c: ldloc.1
IL_004d: callvirt instance int32 [mscorlib]System.IO.Stream::ReadByte()
IL_0052: stloc.s 4
IL_0054: leave.s IL_006c
} // end .try
finally
{
IL_0056: ldloc.1
IL_0057: isinst [mscorlib]System.IDisposable
IL_005c: stloc.3
IL_005d: ldloc.3
IL_005e: brfalse.s IL_0069
IL_0060: ldloc.3
IL_0061: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0066: ldnull
IL_0067: pop
IL_0068: endfinally
IL_0069: ldnull
IL_006a: pop
IL_006b: endfinally
} // end handler
IL_006c: ldloc.s 4
IL_006e: stloc.2
IL_006f: ldstr "read: {0}, {1}"
IL_0074: ldloc.0
IL_0075: box [mscorlib]System.Int32
IL_007a: ldloc.2
IL_007b: box [mscorlib]System.Int32
IL_0080: call void [mscorlib]System.Console::WriteLine(string, object, object)
IL_0085: ret
} // end of method FSharpUsingPatterns::sample5
} // end of class FSharpUsingPatterns

87
ICSharpCode.Decompiler/Tests/FSharpPatterns/TestHelpers.cs

@ -0,0 +1,87 @@ @@ -0,0 +1,87 @@
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.Decompiler.Tests.Helpers;
using ICSharpCode.NRefactory.CSharp;
using Mono.Cecil;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.Tests.FSharpPatterns
{
public class TestHelpers
{
public static string FuzzyReadResource(string resourceName)
{
var asm = Assembly.GetExecutingAssembly();
var allResources = asm.GetManifestResourceNames();
var fullResourceName = allResources.Single(r => r.EndsWith(resourceName, StringComparison.OrdinalIgnoreCase));
return new StreamReader(asm.GetManifestResourceStream(fullResourceName)).ReadToEnd();
}
static Lazy<string> ilasm = new Lazy<string>(() => ToolLocator.FindTool("ilasm.exe"));
static Lazy<string> ildasm = new Lazy<string>(() => ToolLocator.FindTool("ildasm.exe"));
public static string CompileIL(string source)
{
if (ilasm.Value == null)
Assert.NotNull(ilasm.Value, "Could not find ILASM.exe");
var tmp = Path.GetTempFileName();
File.Delete(tmp);
var sourceFile = Path.ChangeExtension(tmp, ".il");
File.WriteAllText(sourceFile, source);
var asmFile = Path.ChangeExtension(sourceFile, ".dll");
var args = string.Format("{0} /dll /debug /output:{1}", sourceFile, asmFile);
using (var proc = Process.Start(new ProcessStartInfo(ilasm.Value, args) { UseShellExecute = false, }))
{
proc.WaitForExit();
Assert.AreEqual(0, proc.ExitCode);
}
File.Delete(sourceFile);
Assert.True(File.Exists(asmFile), "Assembly File does not exist");
return asmFile;
}
public static void RunIL(string ilCode, string expectedCSharpCode)
{
var asmFilePath = CompileIL(ilCode);
CompareAssemblyAgainstCSharp(expectedCSharpCode, asmFilePath);
}
private static void CompareAssemblyAgainstCSharp(string expectedCSharpCode, string asmFilePath)
{
var module = ModuleDefinition.ReadModule(asmFilePath);
try
{
try { module.ReadSymbols(); } catch { }
AstBuilder decompiler = new AstBuilder(new DecompilerContext(module));
decompiler.AddAssembly(module);
new Helpers.RemoveCompilerAttribute().Run(decompiler.SyntaxTree);
StringWriter output = new StringWriter();
// the F# assembly contains a namespace `<StartupCode$tmp6D55>` where the part after tmp is randomly generated.
// remove this from the ast to simplify the diff
var startupCodeNode = decompiler.SyntaxTree.Children.OfType<NamespaceDeclaration>().SingleOrDefault(d => d.Name.StartsWith("<StartupCode$", StringComparison.Ordinal));
if (startupCodeNode != null)
startupCodeNode.Remove();
decompiler.GenerateCode(new PlainTextOutput(output));
var fullCSharpCode = output.ToString();
CodeAssert.AreEqual(expectedCSharpCode, output.ToString());
}
finally
{
File.Delete(asmFilePath);
File.Delete(Path.ChangeExtension(asmFilePath, ".pdb"));
}
}
}
}

99
ICSharpCode.Decompiler/Tests/FSharpPatterns/ToolLocator.cs

@ -0,0 +1,99 @@ @@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.Tests.FSharpPatterns
{
public class ToolLocator
{
public static string FindTool(string fileName)
{
var allPaths = FindPathForDotNetFramework().Concat(FindPathForWindowsSdk());
return allPaths.Select(dir => Path.Combine(dir, fileName)).FirstOrDefault(File.Exists);
}
private static IEnumerable<string> FindPathForWindowsSdk()
{
string[] windowsSdkPaths = new[]
{
@"Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\",
@"Microsoft SDKs\Windows\v8.0A\bin\",
@"Microsoft SDKs\Windows\v8.0\bin\NETFX 4.0 Tools\",
@"Microsoft SDKs\Windows\v8.0\bin\",
@"Microsoft SDKs\Windows\v7.1A\bin\NETFX 4.0 Tools\",
@"Microsoft SDKs\Windows\v7.1A\bin\",
@"Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 Tools\",
@"Microsoft SDKs\Windows\v7.0A\bin\",
@"Microsoft SDKs\Windows\v6.1A\bin\",
@"Microsoft SDKs\Windows\v6.0A\bin\",
@"Microsoft SDKs\Windows\v6.0\bin\",
@"Microsoft.NET\FrameworkSDK\bin"
};
foreach (var possiblePath in windowsSdkPaths)
{
string fullPath = string.Empty;
// Check alternate program file paths as well as 64-bit versions.
if (Environment.Is64BitProcess)
{
fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), possiblePath, "x64");
if (Directory.Exists(fullPath))
{
yield return fullPath;
}
fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), possiblePath, "x64");
if (Directory.Exists(fullPath))
{
yield return fullPath;
}
}
fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), possiblePath);
if (Directory.Exists(fullPath))
{
yield return fullPath;
}
fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), possiblePath);
if (Directory.Exists(fullPath))
{
yield return fullPath;
}
}
}
private static IEnumerable<string> FindPathForDotNetFramework()
{
string[] frameworkPaths = new[]
{
@"Microsoft.NET\Framework\v4.0.30319",
@"Microsoft.NET\Framework\v2.0.50727"
};
foreach (var possiblePath in frameworkPaths)
{
string fullPath = string.Empty;
if (Environment.Is64BitProcess)
{
fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), possiblePath.Replace(@"\Framework\", @"\Framework64\"));
if (Directory.Exists(fullPath))
{
yield return fullPath;
}
}
fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), possiblePath);
if (Directory.Exists(fullPath))
{
yield return fullPath;
}
}
}
}
}

44
ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj

@ -49,10 +49,26 @@ @@ -49,10 +49,26 @@
<Reference Include="DiffLib">
<HintPath>..\..\packages\DiffLib.1.0.0.55\lib\net35-Client\DiffLib.dll</HintPath>
</Reference>
<Reference Include="nunit.core, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<HintPath>..\..\packages\NUnitTestAdapter.2.0.0\lib\nunit.core.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="nunit.core.interfaces, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<HintPath>..\..\packages\NUnitTestAdapter.2.0.0\lib\nunit.core.interfaces.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="nunit.framework">
<SpecificVersion>False</SpecificVersion>
<HintPath>.\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="nunit.util, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<HintPath>..\..\packages\NUnitTestAdapter.2.0.0\lib\nunit.util.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="NUnit.VisualStudio.TestAdapter, Version=2.0.0.0, Culture=neutral, PublicKeyToken=4cb40d35494691ac, processorArchitecture=MSIL">
<HintPath>..\..\packages\NUnitTestAdapter.2.0.0\lib\NUnit.VisualStudio.TestAdapter.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
@ -69,13 +85,19 @@ @@ -69,13 +85,19 @@
<Compile Include="ControlFlow.cs" />
<Compile Include="DoubleConstants.cs" />
<Compile Include="ExpressionTrees.cs" />
<EmbeddedResource Include="FSharpPatterns\FSharpUsing.fs.Debug.il" />
<None Include="IL\SequenceOfNestedIfs.Output.cs" />
<Compile Include="FSharpPatterns\FSharpPatternTests.cs" />
<EmbeddedResource Include="FSharpPatterns\FSharpUsing.fs.Debug.cs" />
<Compile Include="FSharpPatterns\TestHelpers.cs" />
<Compile Include="FSharpPatterns\ToolLocator.cs" />
<Compile Include="IL\ILTests.cs" />
<Compile Include="LiftedOperators.cs" />
<Compile Include="CustomShortCircuitOperators.cs" />
<Compile Include="Helpers\CodeAssert.cs" />
<Compile Include="IncrementDecrement.cs" />
<Compile Include="Lock.cs" />
<Compile Include="NotUsingBlock.cs" />
<Compile Include="PInvoke.cs" />
<Compile Include="QueryExpressions.cs" />
<Compile Include="Switch.cs" />
@ -112,28 +134,40 @@ @@ -112,28 +134,40 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\cecil\Mono.Cecil.csproj">
<Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
<Project>{d68133bd-1e63-496e-9ede-4fbdbf77b486}</Project>
<Name>Mono.Cecil</Name>
</ProjectReference>
<ProjectReference Include="..\..\cecil\symbols\pdb\Mono.Cecil.Pdb.csproj">
<Project>{63e6915c-7ea4-4d76-ab28-0d7191eea626}</Project>
<Name>Mono.Cecil.Pdb</Name>
</ProjectReference>
<ProjectReference Include="..\..\NRefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj">
<Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project>
<Project>{53dca265-3c3c-42f9-b647-f72ba678122b}</Project>
<Name>ICSharpCode.NRefactory.CSharp</Name>
</ProjectReference>
<ProjectReference Include="..\..\NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
<Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project>
<Project>{3b2a5653-ec97-4001-bb9b-d90f1af2c371}</Project>
<Name>ICSharpCode.NRefactory</Name>
</ProjectReference>
<ProjectReference Include="..\ICSharpCode.Decompiler.csproj">
<Project>{984CC812-9470-4A13-AFF9-CC44068D666C}</Project>
<Project>{984cc812-9470-4a13-aff9-cc44068d666c}</Project>
<Name>ICSharpCode.Decompiler</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<ItemGroup>
<EmbeddedResource Include="FSharpPatterns\FSharpUsing.fs" />
</ItemGroup>
<ItemGroup>
<None Include="BooleanConsumedAsInteger.il" />
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="FSharpPatterns\FSharpUsing.fs.Release.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="FSharpPatterns\FSharpUsing.fs.Release.il" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
</Project>

28
ICSharpCode.Decompiler/Tests/NotUsingBlock.cs

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
using System;
using System.IO;
namespace ICSharpCode.Decompiler.Tests
{
public class NotUsingBlock
{
public void ThisIsNotAUsingBlock()
{
object obj = File.OpenRead("...");
IDisposable disposable;
try
{
(obj as FileStream).WriteByte(2);
Console.WriteLine("some text");
}
finally
{
disposable = (obj as IDisposable);
if (disposable != null)
{
disposable.Dispose();
}
}
Console.WriteLine(disposable);
}
}
}

7
ICSharpCode.Decompiler/Tests/TestRunner.cs

@ -187,6 +187,13 @@ namespace ICSharpCode.Decompiler.Tests @@ -187,6 +187,13 @@ namespace ICSharpCode.Decompiler.Tests
TestFile(@"..\..\Tests\TypeAnalysisTests.cs");
}
// see https://github.com/icsharpcode/ILSpy/pull/671
[Test]
public void NotUsingBlock()
{
TestFile(@"..\..\Tests\NotUsingBlock.cs");
}
static void TestFile(string fileName, bool useDebug = false, int compilerVersion = 4)
{
AssertRoundtripCode(fileName, optimize: false, useDebug: useDebug, compilerVersion: compilerVersion);

1
ICSharpCode.Decompiler/Tests/packages.config

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="DiffLib" version="1.0.0.55" />
<package id="NUnitTestAdapter" version="2.0.0" targetFramework="net45" />
</packages>

269
ILSpy.AddIn/CodeElementXmlDocKeyProvider.cs

@ -0,0 +1,269 @@ @@ -0,0 +1,269 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ICSharpCode.ILSpy.AddIn
{
/// <summary>
/// Provides XML documentation tags for Visual Studio CodeElements.
/// </summary>
/// <remarks>
/// Used to support the "/navigateTo" command line option when opening ILSpy. Must match
/// the logic of ICSharpCode.ILSpy.XmlDoc.XmlDocKeyProvider, which does the same thing for
/// a Mono.Cecil.MemberReference. See "ID string format" in Appendix A of the C# language
/// specification for formatting requirements, and Samples/ILSpyAddInSamples.cs for examples.
/// </remarks>
public static class CodeElementXmlDocKeyProvider
{
#region GetKey
public static string GetKey(EnvDTE.CodeElement member)
{
StringBuilder b = new StringBuilder();
if ((member.Kind == EnvDTE.vsCMElement.vsCMElementDelegate) ||
(member.Kind == EnvDTE.vsCMElement.vsCMElementEnum) ||
(member.Kind == EnvDTE.vsCMElement.vsCMElementInterface) ||
(member.Kind == EnvDTE.vsCMElement.vsCMElementStruct) ||
(member.Kind == EnvDTE.vsCMElement.vsCMElementClass)) {
b.Append("T:");
AppendTypeName(b, member.FullName, true, false);
}
else if (member.Kind == EnvDTE.vsCMElement.vsCMElementNamespace){
b.Append("N:");
b.Append(member.FullName);
}
else {
if (member.Kind == EnvDTE.vsCMElement.vsCMElementVariable)
b.Append("F:");
else if (member.Kind == EnvDTE.vsCMElement.vsCMElementProperty)
b.Append("P:");
else if (member.Kind == EnvDTE.vsCMElement.vsCMElementEvent)
b.Append("E:");
else if (member.Kind == EnvDTE.vsCMElement.vsCMElementFunction)
b.Append("M:");
int nameIndex = member.FullName.LastIndexOf(member.Name);
string typeName = member.FullName.Substring(0, nameIndex - 1);
string memberName = member.FullName.Substring(nameIndex);
// Name substitutions for special cases.
if (member.Kind == EnvDTE.vsCMElement.vsCMElementFunction) {
EnvDTE80.CodeFunction2 mr = (EnvDTE80.CodeFunction2)member;
if (mr.FunctionKind == EnvDTE.vsCMFunction.vsCMFunctionConstructor) {
memberName = memberName.Replace(member.Name, "#ctor");
}
else if (mr.FunctionKind == EnvDTE.vsCMFunction.vsCMFunctionDestructor) {
memberName = memberName.Replace(member.Name, "Finalize");
}
else if (mr.FunctionKind == EnvDTE.vsCMFunction.vsCMFunctionOperator) {
if (memberName.StartsWith("implicit operator")) {
memberName = "op_Implicit";
}
else if (memberName.StartsWith("explicit operator")) {
memberName = "op_Explicit";
}
else {
// NRefactory has a handy mapping we can make use of, just need to extract the operator sybol first.
string[] memberNameWords = member.Name.Split(' ');
if (memberNameWords.Length >= 2) {
string operatorSymbol = memberNameWords[1];
string operatorName = ICSharpCode.NRefactory.MonoCSharp.Operator.GetMetadataName(operatorSymbol);
if (operatorName != null) {
memberName = memberName.Replace(member.Name, operatorName);
}
}
}
}
}
else if (member.Kind == EnvDTE.vsCMElement.vsCMElementProperty) {
if (member.Name == "this") {
memberName = memberName.Replace(member.Name, "Item");
}
}
string[] genericTypeParameters = AppendTypeName(b, typeName, true, false);
b.Append('.');
string[] genericMethodParameters = AppendTypeName(b, memberName.Replace('.', '#'), true, true);
EnvDTE.CodeElements parameters;
EnvDTE.CodeTypeRef explicitReturnType = null;
if (member.Kind == EnvDTE.vsCMElement.vsCMElementProperty) {
parameters = ((EnvDTE.CodeProperty)member).Getter.Parameters;
}
else if (member.Kind == EnvDTE.vsCMElement.vsCMElementFunction) {
EnvDTE80.CodeFunction2 mr = (EnvDTE80.CodeFunction2)member;
parameters = mr.Parameters;
if (memberName == "op_Implicit" || memberName == "op_Explicit") {
explicitReturnType = mr.Type;
}
}
else {
parameters = null;
}
if (parameters != null && parameters.Count > 0) {
b.Append('(');
int i = 0;
foreach (EnvDTE80.CodeParameter2 parameter in parameters) {
if (i > 0) b.Append(',');
AppendParameterTypeName(b, parameter, genericTypeParameters, genericMethodParameters);
++i;
}
b.Append(')');
}
if (explicitReturnType != null) {
b.Append('~');
AppendTypeName(b, explicitReturnType.AsFullName, true, false);
}
}
return b.ToString();
}
static string[] AppendTypeName(StringBuilder b, string typeName, bool appendGenericParameterCount, bool isMethod)
{
List<string> allGenericParameters = new List<string>();
StringBuilder genericParameterName = new StringBuilder();
bool inGenericParameters = false;
int genericParameterCount = 0;
foreach (char ch in typeName) {
if (inGenericParameters) {
switch (ch) {
case ',':
++genericParameterCount;
allGenericParameters.Add(genericParameterName.ToString());
genericParameterName.Clear();
break;
case '>':
++genericParameterCount;
allGenericParameters.Add(genericParameterName.ToString());
genericParameterName.Clear();
if (appendGenericParameterCount) {
b.Append(genericParameterCount);
}
inGenericParameters = false;
break;
case ' ':
break;
default:
genericParameterName.Append(ch);
break;
}
}
else {
switch (ch) {
case '<':
if (appendGenericParameterCount) {
b.Append('`');
if (isMethod) {
b.Append('`');
}
}
inGenericParameters = true;
genericParameterCount = 0;
break;
case '[':
case ']':
break;
default:
b.Append(ch);
break;
}
}
}
return allGenericParameters.ToArray();
}
private static void AppendParameterTypeName(StringBuilder b, EnvDTE80.CodeParameter2 parameter, string[] genericTypeParameters, string[] genericMethodParameters)
{
EnvDTE80.CodeTypeRef2 parameterTypeRef = (EnvDTE80.CodeTypeRef2)parameter.Type;
string parameterTypeString = parameterTypeRef.AsFullName;
int substringStart = 0;
for (int i = 0; i < parameterTypeString.Length; ++i) {
char ch = parameterTypeString[i];
switch (ch) {
case '<':
AppendParameterTypeSubstring(b, parameterTypeString, substringStart, i, genericTypeParameters, genericMethodParameters);
substringStart = i + 1;
b.Append('{');
break;
case '>':
AppendParameterTypeSubstring(b, parameterTypeString, substringStart, i, genericTypeParameters, genericMethodParameters);
substringStart = i + 1;
b.Append('}');
break;
case '[':
AppendParameterTypeSubstring(b, parameterTypeString, substringStart, i, genericTypeParameters, genericMethodParameters);
b.Append('[');
// Skip ahead to the closing bracket, counting commas to determine array rank.
int rank = 1;
do {
++i;
ch = parameterTypeString[i];
if (ch == ',') {
++rank;
}
}
while (ch != ']');
substringStart = i + 1;
// For multi-dimensional arrays, add "0:" default array bounds. Note that non-standard bounds are not possible via C# declaration.
if (rank > 1) {
for (int r = 0; r < rank; ++r) {
if (r != 0) {
b.Append(',');
}
b.Append("0:");
}
}
b.Append(']');
break;
case ',':
AppendParameterTypeSubstring(b, parameterTypeString, substringStart, i, genericTypeParameters, genericMethodParameters);
substringStart = i + 1;
// Skip space after comma if present. (e.g. System.Collections.Generic.KeyValuePair`2{System.String,System.String}.)
if (parameterTypeString[substringStart] == ' ') {
++substringStart;
}
b.Append(',');
break;
}
}
AppendParameterTypeSubstring(b, parameterTypeString, substringStart, parameterTypeString.Length, genericTypeParameters, genericMethodParameters);
// Append ref / out indicator if needed.
if ((parameter.ParameterKind == EnvDTE80.vsCMParameterKind.vsCMParameterKindRef) ||
(parameter.ParameterKind == EnvDTE80.vsCMParameterKind.vsCMParameterKindOut)) {
b.Append('@');
}
// Note there is no need to append a '*' for pointers, as this is included in the full name of the type.
// Multi-dimensional and jagged arrays are handled above during string parsing.
}
private static void AppendParameterTypeSubstring(StringBuilder b, string parameterTypeString, int substringStart, int substringStop, string[] genericTypeParameters, string[] genericMethodParameters)
{
if (substringStart < substringStop) {
string substring = parameterTypeString.Substring(substringStart, substringStop - substringStart);
int indexOfGenericTypeParameter = Array.IndexOf(genericTypeParameters, substring);
int indexOfGenericMethodParameter = Array.IndexOf(genericMethodParameters, substring);
if (indexOfGenericTypeParameter >= 0) {
b.Append("`");
b.Append(indexOfGenericTypeParameter);
}
else if (indexOfGenericMethodParameter >= 0) {
b.Append("``");
b.Append(indexOfGenericMethodParameter);
}
else {
b.Append(substring);
}
}
}
#endregion
}
}

2
ILSpy.AddIn/ILSpy.AddIn.csproj

@ -138,6 +138,7 @@ @@ -138,6 +138,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Guids.cs" />
<Compile Include="CodeElementXmlDocKeyProvider.cs" />
<Compile Include="Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
@ -147,6 +148,7 @@ @@ -147,6 +148,7 @@
<Compile Include="ILSpyAddInPackage.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PkgCmdID.cs" />
<None Include="Samples\ILSpyAddInSamples.cs" />
<Compile Include="Utils.cs" />
</ItemGroup>
<ItemGroup>

14
ILSpy.AddIn/ILSpyAddIn.vsct

@ -47,6 +47,10 @@ @@ -47,6 +47,10 @@
<Group guid="guidILSpyAddInCmdSet" id="OpenILSpyProjGroup" priority="0x0200">
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_PROJNODE"/>
</Group>
<Group guid="guidILSpyAddInCmdSet" id="OpenILSpyCodeItemGroup" priority="0x0200">
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_CODEWIN"/>
</Group>
</Groups>
<!--Buttons section. -->
@ -77,6 +81,14 @@ @@ -77,6 +81,14 @@
</Strings>
</Button>
<Button guid="guidILSpyAddInCmdSet" id="cmdidOpenCodeItemInILSpy" priority="0x0600" type="Button">
<Parent guid="guidILSpyAddInCmdSet" id="OpenILSpyCodeItemGroup" />
<Icon guid="guidImages" id="bmpLogo" />
<Strings>
<ButtonText>Open code in ILSpy</ButtonText>
</Strings>
</Button>
<Button guid="guidILSpyAddInCmdSet" id="cmdidOpenILSpy" priority="0x0600" type="Button">
<Parent guid="guidILSpyAddInCmdSet" id="OpenILSpyGroup" />
<Icon guid="guidImages" id="bmpLogo" />
@ -114,9 +126,11 @@ @@ -114,9 +126,11 @@
<IDSymbol name="OpenILSpyGroup" value="0x1010" />
<IDSymbol name="OpenILSpyRefGroup" value="0x1020" />
<IDSymbol name="OpenILSpyProjGroup" value="0x1030" />
<IDSymbol name="OpenILSpyCodeItemGroup" value="0x1040" />
<IDSymbol name="cmdidOpenILSpy" value="0x0100" />
<IDSymbol name="cmdidOpenReferenceInILSpy" value="0x0200" />
<IDSymbol name="cmdidOpenProjectOutputInILSpy" value="0x0300" />
<IDSymbol name="cmdidOpenCodeItemInILSpy" value="0x0400" />
</GuidSymbol>
<GuidSymbol name="guidImages" value="{2f654db9-4641-4638-9937-27c6202b2a6a}" >

141
ILSpy.AddIn/ILSpyAddInPackage.cs

@ -66,20 +66,26 @@ namespace ICSharpCode.ILSpy.AddIn @@ -66,20 +66,26 @@ namespace ICSharpCode.ILSpy.AddIn
// Add our command handlers for menu (commands must exist in the .vsct file)
OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
if (null != mcs) {
// Create the command for the menu item.
// Create the command for the References context menu.
CommandID menuCommandID = new CommandID(GuidList.guidILSpyAddInCmdSet, (int)PkgCmdIDList.cmdidOpenReferenceInILSpy);
MenuCommand menuItem = new MenuCommand(OpenReferenceInILSpyCallback, menuCommandID);
mcs.AddCommand(menuItem);
// Create the command for the menu item.
// Create the command for the Project context menu, to open the output assembly.
CommandID menuCommandID2 = new CommandID(GuidList.guidILSpyAddInCmdSet, (int)PkgCmdIDList.cmdidOpenProjectOutputInILSpy);
MenuCommand menuItem2 = new MenuCommand(OpenProjectOutputInILSpyCallback, menuCommandID2);
mcs.AddCommand(menuItem2);
// Create the command for the menu item.
CommandID menuCommandID3 = new CommandID(GuidList.guidILSpyAddInCmdSet, (int)PkgCmdIDList.cmdidOpenILSpy);
MenuCommand menuItem3 = new MenuCommand(OpenILSpyCallback, menuCommandID3);
// Create the command for the code window context menu.
CommandID menuCommandID3 = new CommandID(GuidList.guidILSpyAddInCmdSet, (int)PkgCmdIDList.cmdidOpenCodeItemInILSpy);
OleMenuCommand menuItem3 = new OleMenuCommand(OpenCodeItemInILSpyCallback, menuCommandID3);
menuItem3.BeforeQueryStatus += OpenCodeItemInILSpyCallback_BeforeQueryStatus;
mcs.AddCommand(menuItem3);
// Create the command for the Tools menu item.
CommandID menuCommandID4 = new CommandID(GuidList.guidILSpyAddInCmdSet, (int)PkgCmdIDList.cmdidOpenILSpy);
MenuCommand menuItem4 = new MenuCommand(OpenILSpyCallback, menuCommandID4);
mcs.AddCommand(menuItem4);
}
}
#endregion
@ -92,14 +98,14 @@ namespace ICSharpCode.ILSpy.AddIn @@ -92,14 +98,14 @@ namespace ICSharpCode.ILSpy.AddIn
private void OpenReferenceInILSpyCallback(object sender, EventArgs e)
{
var explorer = ((EnvDTE80.DTE2)GetGlobalService(typeof(EnvDTE.DTE))).ToolWindows.SolutionExplorer;
var items =(object[]) explorer.SelectedItems;
var items = (object[])explorer.SelectedItems;
foreach (EnvDTE.UIHierarchyItem item in items) {
dynamic reference = item.Object;
var reference = GetReference(item.Object);
string path = null;
if (reference.PublicKeyToken != "") {
if (!string.IsNullOrEmpty(reference.PublicKeyToken)) {
var token = Utils.HexStringToBytes(reference.PublicKeyToken);
path = GacInterop.FindAssemblyInNetGac(new AssemblyNameReference(reference.Identity, new Version(reference.Version)) { PublicKeyToken = token });
path = GacInterop.FindAssemblyInNetGac(new AssemblyNameReference(reference.Name, reference.Version) { PublicKeyToken = token });
}
if (path == null)
path = reference.Path;
@ -107,6 +113,38 @@ namespace ICSharpCode.ILSpy.AddIn @@ -107,6 +113,38 @@ namespace ICSharpCode.ILSpy.AddIn
}
}
class ReferenceInfo
{
public string Name { get; set; }
public string PublicKeyToken { get; set; }
public string Path { get; set; }
public Version Version { get; set; }
}
private ReferenceInfo GetReference(object o)
{
dynamic obj = o;
string referenceType = o.GetType().FullName;
// C++
if (referenceType.StartsWith("Microsoft.VisualStudio.PlatformUI", StringComparison.Ordinal)) {
return new ReferenceInfo { Path = obj.Name };
}
// F#
if (referenceType.StartsWith("Microsoft.VisualStudio.FSharp", StringComparison.Ordinal)) {
obj = obj.Object;
}
// C# and VB
return new ReferenceInfo {
Name = obj.Identity,
PublicKeyToken = obj.PublicKeyToken,
Path = obj.Path,
Version = new Version(obj.Version)
};
}
private void OpenProjectOutputInILSpyCallback(object sender, EventArgs e)
{
var explorer = ((EnvDTE80.DTE2)GetGlobalService(typeof(EnvDTE.DTE))).ToolWindows.SolutionExplorer;
@ -114,14 +152,70 @@ namespace ICSharpCode.ILSpy.AddIn @@ -114,14 +152,70 @@ namespace ICSharpCode.ILSpy.AddIn
foreach (EnvDTE.UIHierarchyItem item in items) {
EnvDTE.Project project = (EnvDTE.Project)item.Object;
EnvDTE.Configuration config = project.ConfigurationManager.ActiveConfiguration;
string projectPath = Path.GetDirectoryName(project.FileName);
string outputPath = config.Properties.Item("OutputPath").Value.ToString();
string assemblyFileName = project.Properties.Item("OutputFileName").Value.ToString();
OpenAssemblyInILSpy(Path.Combine(projectPath, outputPath, assemblyFileName));
OpenProjectInILSpy(project);
}
}
// Called when the menu is popped, determines whether "Open code in ILSpy" option is available.
private void OpenCodeItemInILSpyCallback_BeforeQueryStatus(object sender, EventArgs e)
{
OleMenuCommand menuItem = sender as OleMenuCommand;
if (menuItem != null) {
var document = (EnvDTE.Document)(((EnvDTE80.DTE2)GetGlobalService(typeof(EnvDTE.DTE))).ActiveDocument);
menuItem.Enabled =
(document != null) &&
(document.ProjectItem != null) &&
(document.ProjectItem.ContainingProject != null) &&
(document.ProjectItem.ContainingProject.ConfigurationManager != null) &&
!string.IsNullOrEmpty(document.ProjectItem.ContainingProject.FileName);
}
}
private void OpenCodeItemInILSpyCallback(object sender, EventArgs e)
{
var document = (EnvDTE.Document)(((EnvDTE80.DTE2)GetGlobalService(typeof(EnvDTE.DTE))).ActiveDocument);
var selection = (EnvDTE.TextPoint)((EnvDTE.TextSelection)document.Selection).ActivePoint;
// Search code elements in desired order, working from innermost to outermost.
// Should eventually find something, and if not we'll just open the assembly itself.
var codeElement = GetSelectedCodeElement(selection,
EnvDTE.vsCMElement.vsCMElementFunction,
EnvDTE.vsCMElement.vsCMElementEvent,
EnvDTE.vsCMElement.vsCMElementVariable, // There is no vsCMElementField, fields are just variables outside of function scope.
EnvDTE.vsCMElement.vsCMElementProperty,
EnvDTE.vsCMElement.vsCMElementDelegate,
EnvDTE.vsCMElement.vsCMElementEnum,
EnvDTE.vsCMElement.vsCMElementInterface,
EnvDTE.vsCMElement.vsCMElementStruct,
EnvDTE.vsCMElement.vsCMElementClass,
EnvDTE.vsCMElement.vsCMElementNamespace);
if (codeElement != null) {
OpenCodeItemInILSpy(codeElement);
}
else {
OpenProjectInILSpy(document.ProjectItem.ContainingProject);
}
}
private EnvDTE.CodeElement GetSelectedCodeElement(EnvDTE.TextPoint selection, params EnvDTE.vsCMElement[] elementTypes)
{
foreach (var elementType in elementTypes) {
var codeElement = selection.CodeElement[elementType];
if (codeElement != null) {
return codeElement;
}
}
return null;
}
private void OpenCodeItemInILSpy(EnvDTE.CodeElement codeElement)
{
string codeElementKey = CodeElementXmlDocKeyProvider.GetKey(codeElement);
OpenProjectInILSpy(codeElement.ProjectItem.ContainingProject, "/navigateTo:" + codeElementKey);
}
private void OpenILSpyCallback(object sender, EventArgs e)
{
Process.Start(GetILSpyPath());
@ -133,13 +227,28 @@ namespace ICSharpCode.ILSpy.AddIn @@ -133,13 +227,28 @@ namespace ICSharpCode.ILSpy.AddIn
return Path.Combine(basePath, "ILSpy.exe");
}
private void OpenAssemblyInILSpy(string assemblyFileName)
private void OpenProjectInILSpy(EnvDTE.Project project, params string[] arguments)
{
EnvDTE.Configuration config = project.ConfigurationManager.ActiveConfiguration;
string projectPath = Path.GetDirectoryName(project.FileName);
string outputPath = config.Properties.Item("OutputPath").Value.ToString();
string assemblyFileName = project.Properties.Item("OutputFileName").Value.ToString();
OpenAssemblyInILSpy(Path.Combine(projectPath, outputPath, assemblyFileName), arguments);
}
private void OpenAssemblyInILSpy(string assemblyFileName, params string[] arguments)
{
if (!File.Exists(assemblyFileName)) {
ShowMessage("Could not find assembly '{0}', please ensure the project and all references were built correctly!", assemblyFileName);
return;
}
Process.Start(GetILSpyPath(), Utils.ArgumentArrayToCommandLine(assemblyFileName));
string commandLineArguments = Utils.ArgumentArrayToCommandLine(assemblyFileName);
if (arguments != null) {
commandLineArguments = string.Concat(commandLineArguments, " ", Utils.ArgumentArrayToCommandLine(arguments));
}
Process.Start(GetILSpyPath(), commandLineArguments);
}
private void ShowMessage(string format, params object[] items)

1
ILSpy.AddIn/PkgCmdID.cs

@ -9,5 +9,6 @@ namespace ICSharpCode.ILSpy.AddIn @@ -9,5 +9,6 @@ namespace ICSharpCode.ILSpy.AddIn
public const uint cmdidOpenILSpy = 0x100;
public const uint cmdidOpenReferenceInILSpy = 0x200;
public const uint cmdidOpenProjectOutputInILSpy = 0x300;
public const uint cmdidOpenCodeItemInILSpy = 0x0400;
};
}

4
ILSpy.AddIn/Properties/AssemblyInfo.cs

@ -29,8 +29,8 @@ using System.Runtime.InteropServices; @@ -29,8 +29,8 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.5.0.0")]
[assembly: AssemblyFileVersion("1.5.0.0")]
[assembly: InternalsVisibleTo("ILSpy.AddIn_IntegrationTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100653c4a319be4f524972c3c5bba5fd243330f8e900287d9022d7821a63fd0086fd3801e3683dbe9897f2ecc44727023e9b40adcf180730af70c81c54476b3e5ba8b0f07f5132b2c3cc54347a2c1a9d64ebaaaf3cbffc1a18c427981e2a51d53d5ab02536b7550e732f795121c38a0abfdb38596353525d034baf9e6f1fd8ac4ac")]
[assembly: InternalsVisibleTo("ILSpy.AddIn_UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100653c4a319be4f524972c3c5bba5fd243330f8e900287d9022d7821a63fd0086fd3801e3683dbe9897f2ecc44727023e9b40adcf180730af70c81c54476b3e5ba8b0f07f5132b2c3cc54347a2c1a9d64ebaaaf3cbffc1a18c427981e2a51d53d5ab02536b7550e732f795121c38a0abfdb38596353525d034baf9e6f1fd8ac4ac")]

414
ILSpy.AddIn/Samples/ILSpyAddInSamples.cs

@ -0,0 +1,414 @@ @@ -0,0 +1,414 @@
using System;
using System.Collections;
using System.Collections.Generic;
/// Sample source file indicating a wide variety of code elements that should work
/// with the "Open code in ILSpy" Visual Studio add-in feature. Each code element is
/// commented with the string generated by CodeElementXmlDocKeyProvider.GetKey and
/// used with the ILSpy /navigateTo command line option.
///
/// Note that this code is not compiled or used in the project in any way, it is
/// only provided for reference.
// N:ILSpy.AddIn.Tests
namespace ILSpy.AddIn.Tests
{
// T:ILSpy.AddIn.Tests.SomeClass
public class SomeClass
{
// E:ILSpy.AddIn.Tests.SomeClass.OnEvent
public event Action OnEvent;
// F:ILSpy.AddIn.Tests.SomeClass.mField
private int mField;
// P:ILSpy.AddIn.Tests.SomeClass.Property
private int Property
{
get
{
return mField;
}
set
{
mField = value;
}
}
// P:ILSpy.AddIn.Tests.SomeClass.Item(System.Int32,System.Int32)
public int this[int x, int y]
{
get { return x + y + mField; }
}
// M:ILSpy.AddIn.Tests.SomeClass.#ctor
public SomeClass()
{
mField = 0;
}
// M:ILSpy.AddIn.Tests.SomeClass.#ctor(System.Int32)
public SomeClass(int x)
{
mField = x;
}
// M:ILSpy.AddIn.Tests.SomeClass.#ctor(System.Int32,System.Int32)
public SomeClass(int x, int y)
{
mField = x + y;
}
// M:ILSpy.AddIn.Tests.SomeClass.Method
public int Method()
{
return mField;
}
// M:ILSpy.AddIn.Tests.SomeClass.MethodWithGenericParameter(System.IEquatable{System.String})
public void MethodWithGenericParameter(IEquatable<string> x)
{
}
// M:ILSpy.AddIn.Tests.SomeClass.MethodWithGenericParameter(System.IEquatable{System.String},System.Int32)
public void MethodWithGenericParameter(IEquatable<string> x, int y)
{
}
// M:ILSpy.AddIn.Tests.SomeClass.GenericMethod``1(``0)
public int GenericMethod<T>(T x)
{
return mField + x.GetHashCode();
}
// M:ILSpy.AddIn.Tests.SomeClass.GenericOverloadedMethod``1(System.Int32,``0)
public int GenericOverloadedMethod<T1>(int x, T1 y)
{
return mField + x + y.GetHashCode();
}
// M:ILSpy.AddIn.Tests.SomeClass.GenericOverloadedMethod``2(System.Int32,``0,``1)
public int GenericOverloadedMethod<T1, T2>(int x, T1 y, T2 z)
{
return mField + x + y.GetHashCode() + z.GetHashCode();
}
// M:ILSpy.AddIn.Tests.SomeClass.OverloadedMethod
public int OverloadedMethod()
{
return mField * mField;
}
// M:ILSpy.AddIn.Tests.SomeClass.OverloadedMethod(System.Int32)
public int OverloadedMethod(int m)
{
return mField * m;
}
// M:ILSpy.AddIn.Tests.SomeClass.OverloadedMethod(System.Int32,System.Int32)
public int OverloadedMethod(int m1, int m2)
{
return mField * m1 * m2;
}
// M:ILSpy.AddIn.Tests.SomeClass.OverloadedGenericMethod``1
public int OverloadedGenericMethod<T>()
{
return mField * mField;
}
// M:ILSpy.AddIn.Tests.SomeClass.OverloadedGenericMethod``1(System.Int32)
public int OverloadedGenericMethod<T>(int m)
{
return mField * m;
}
// M:ILSpy.AddIn.Tests.SomeClass.OverloadedGenericMethod``1(System.Int32,System.Int32)
public int OverloadedGenericMethod<T>(int m1, int m2)
{
return mField * m1 * m2;
}
// M:ILSpy.AddIn.Tests.SomeClass.OverloadedGenericMethod``1(System.Int32,System.Int32,System.Collections.IEnumerable)
public int OverloadedGenericMethod<T>(int m1, int m2, IEnumerable m3)
{
return mField * m1 * m2;
}
// M:ILSpy.AddIn.Tests.SomeClass.OverloadedGenericMethod``1(System.Int32,System.Int32,System.Collections.Generic.IEnumerable{``0})
public int OverloadedGenericMethod<T>(int m1, int m2, IEnumerable<T> m3)
{
return mField * m1 * m2;
}
// M:ILSpy.AddIn.Tests.SomeClass.OverloadedGenericMethod``1(System.Int32,System.Int32,System.Collections.Generic.IEnumerable{System.String})
public int OverloadedGenericMethod<T>(int m1, int m2, IEnumerable<string> m3)
{
return mField * m1 * m2;
}
// M:ILSpy.AddIn.Tests.SomeClass.OverloadedGenericMethod``1(System.Collections.Generic.IEnumerable{System.Collections.Generic.IEnumerable{ILSpy.AddIn.Tests.SomeGenericClass{System.String,``0}}})
public int OverloadedGenericMethod<T>(IEnumerable<IEnumerable<SomeGenericClass<string, T>>> m3)
{
return mField;
}
// M:ILSpy.AddIn.Tests.SomeClass.OverloadedGenericMethod``1(ILSpy.AddIn.Tests.SomeGenericClass{``0,ILSpy.AddIn.Tests.SomeGenericClass{``0,``0}}.NestedGeneric{System.String,``0})
public void OverloadedGenericMethod<T>(SomeGenericClass<T, SomeGenericClass<T, T>>.NestedGeneric<string, T> wow)
{
}
// T:ILSpy.AddIn.Tests.SomeClass.NestedEnum
public enum NestedEnum
{
// F:ILSpy.AddIn.Tests.SomeClass.NestedEnum.First
First = 1,
Second = 2,
Third = 3
}
// T:ILSpy.AddIn.Tests.SomeClass.NestedInterface
public interface NestedInterface
{
// P:ILSpy.AddIn.Tests.SomeClass.NestedInterface.SomeProperty
int SomeProperty { get; }
// M:ILSpy.AddIn.Tests.SomeClass.NestedInterface.SomeMethod
int SomeMethod();
}
// T:ILSpy.AddIn.Tests.SomeClass.NestedClass
public class NestedClass : NestedInterface
{
// F:ILSpy.AddIn.Tests.SomeClass.NestedClass.mX
private int mX;
// M:ILSpy.AddIn.Tests.SomeClass.NestedClass.#ctor(System.Int32)
public NestedClass(int x)
{
mX = x;
}
// M:ILSpy.AddIn.Tests.SomeClass.NestedClass.#ctor(ILSpy.AddIn.Tests.SomeClass.NestedEnum)
public NestedClass(NestedEnum x)
{
mX = (int)x;
}
// P:ILSpy.AddIn.Tests.SomeClass.NestedClass.SomeProperty
public int SomeProperty
{
get { return mX; }
}
// M:ILSpy.AddIn.Tests.SomeClass.NestedClass.SomeMethod
public int SomeMethod()
{
return mX * mX;
}
}
// T:ILSpy.AddIn.Tests.SomeClass.NestedStruct
public struct NestedStruct : NestedInterface
{
// F:ILSpy.AddIn.Tests.SomeClass.NestedStruct.X
public int X;
// F:ILSpy.AddIn.Tests.SomeClass.NestedStruct.Y
public int Y;
// P:ILSpy.AddIn.Tests.SomeClass.NestedStruct.SomeProperty
public int SomeProperty
{
get { return X + Y; }
}
// M:ILSpy.AddIn.Tests.SomeClass.NestedStruct.SomeMethod
public int SomeMethod()
{
return X * Y;
}
}
}
// T:ILSpy.AddIn.Tests.SomeGenericClass`2
public class SomeGenericClass<T1, T2>
{
// F:ILSpy.AddIn.Tests.SomeGenericClass`2.mField1
T1 mField1;
// F:ILSpy.AddIn.Tests.SomeGenericClass`2.mField2
T2 mField2;
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.#ctor(`0,`1)
public SomeGenericClass(T1 a, T2 b)
{
mField1 = a;
mField2 = b;
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.#ctor(`0)
public SomeGenericClass(T1 a)
{
mField1 = a;
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.#ctor
public SomeGenericClass()
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.Finalize
~SomeGenericClass()
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassMethod(`0,`1)
public void GenericClassMethod(T1 a, T2 b)
{
mField1 = a;
mField2 = b;
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassMethod(System.Int32*)
unsafe public void GenericClassMethod(int* x)
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassMethod(System.Int32*[])
unsafe public void GenericClassMethod(int*[] x)
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassMethod(`0[]@)
unsafe public void GenericClassMethod(out T1[] x)
{
x = null;
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassMethod(System.Int32@)
public void GenericClassMethod(ref int a)
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassGenericMethod``1(``0@)
public T3 GenericClassGenericMethod<T3>(ref T3 x)
{
return x;
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassGenericMethod``1
public T3 GenericClassGenericMethod<T3>()
{
return default(T3);
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassGenericMethod``1(System.Int32)
public void GenericClassGenericMethod<T3>(int x)
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassGenericMethod``2(`0,``1,System.Int32,`1@)
public T4 GenericClassGenericMethod<T3, T4>(T1 x, T4 y, int z, out T2 result)
{
mField1 = x;
string foo = y.ToString() + z.ToString();
result = mField2;
return y;
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassGenericMethod``2(`0,``0,System.Int32[])
public T3 GenericClassGenericMethod<T3, T4>(T1 x, T3 y, int[] z)
{
mField1 = x;
string foo = y.ToString() + z.ToString();
return y;
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.ArrayMethod(`0[],System.Int32[])
public void ArrayMethod(T1[] x, int[] y)
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.ArrayMethod(`0[0:,0:],System.Int32[0:,0:])
public void ArrayMethod(T1[,] x, int[,] y)
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.ArrayMethod(System.Int32[0:,0:],System.Int32[0:,0:])
public void ArrayMethod(int[,] x, int[,] y)
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.ArrayMethod(`0[][],System.Int32[][])
public void ArrayMethod(T1[][] x, int[][] y)
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassGenericMethod``2(`0,``0,ILSpy.AddIn.Tests.SomeClass)
public T3 GenericClassGenericMethod<T3, T4>(T1 x, T3 y, SomeClass z)
{
return y;
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassGenericMethod``2(`0,``0,ILSpy.AddIn.Tests.SomeClass[]@)
public T3 GenericClassGenericMethod<T3, T4>(T1 x, T3 y, out SomeClass[] z)
{
z = null;
return y;
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassGenericMethod``2(System.Int32[],ILSpy.AddIn.Tests.SomeGenericClass{``0[],``1[0:,0:,0:]}[0:,0:,0:])
public void GenericClassGenericMethod<T3, T4>(int[] x, SomeGenericClass<T3[], T4[,,]>[,,] y)
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.op_Addition(ILSpy.AddIn.Tests.SomeGenericClass{`0,`1},ILSpy.AddIn.Tests.SomeGenericClass{`0,`1})
public static SomeGenericClass<T1, T2> operator +(SomeGenericClass<T1, T2> a, SomeGenericClass<T1, T2> b)
{
return new SomeGenericClass<T1, T2>();
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.op_Explicit(ILSpy.AddIn.Tests.SomeGenericClass{`0,`1})~ILSpy.AddIn.Tests.SomeGenericClass`2.NestedGeneric`2
public static explicit operator NestedGeneric<T1, T2>(SomeGenericClass<T1, T2> sgc)
{
return new NestedGeneric<T1, T2>();
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.op_Implicit(ILSpy.AddIn.Tests.SomeGenericClass{`0,`1})~ILSpy.AddIn.Tests.SomeGenericClass`2.NestedGeneric`2
public static implicit operator NestedGeneric<T2, T1>(SomeGenericClass<T1, T2> sgc)
{
return new NestedGeneric<T2, T1>();
}
// T:ILSpy.AddIn.Tests.SomeGenericClass`2.NestedGeneric`2
public class NestedGeneric<T3, T4>
{
// T:ILSpy.AddIn.Tests.SomeGenericClass`2.NestedGeneric`2.NestedDelegate
public delegate int NestedDelegate(T3 x, IEnumerable<T4> y);
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.NestedGeneric`2.NestedGenericMethod``1(`0,``0)
public void NestedGenericMethod<T5>(T1 x, T5 y)
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.NestedGeneric`2.NestedGenericMethod``3(`0,`3,``0[],System.Collections.Generic.IEnumerable{``2})
public void NestedGenericMethod<T5, T6, T7>(T1 x, T4 y, T5[] z, IEnumerable<T7> w)
{
}
}
}
}
// T:SpaceFreeClass
class SpaceFreeClass
{
// F:SpaceFreeClass.mField
int mField;
// M:SpaceFreeClass.Method
private void Method()
{
}
}

6
ILSpy.AddIn/Utils.cs

@ -74,6 +74,10 @@ namespace ICSharpCode.ILSpy.AddIn @@ -74,6 +74,10 @@ namespace ICSharpCode.ILSpy.AddIn
static void AppendArgument(StringBuilder b, string arg)
{
if (arg == null) {
return;
}
if (arg.Length > 0 && arg.IndexOfAny(charsNeedingQuoting) < 0) {
b.Append(arg);
} else {
@ -102,6 +106,8 @@ namespace ICSharpCode.ILSpy.AddIn @@ -102,6 +106,8 @@ namespace ICSharpCode.ILSpy.AddIn
public static byte[] HexStringToBytes(string hex)
{
if (hex == null)
throw new ArgumentNullException(nameof(hex));
var result = new byte[hex.Length / 2];
for (int i = 0; i < hex.Length / 2; i++) {
result[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);

2
ILSpy.AddIn/license.txt

@ -3,7 +3,7 @@ The following MIT license applies to ILSpy, NRefactory and ICSharpCode.Decompile @@ -3,7 +3,7 @@ The following MIT license applies to ILSpy, NRefactory and ICSharpCode.Decompile
MIT license:
Copyright (c) 2011-2014 AlphaSierraPapa for the SharpDevelop team
Copyright (c) 2011-2016 AlphaSierraPapa for the SharpDevelop team
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

6
ILSpy.AddIn/source.extension.vsixmanifest

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
<Identifier Id="a9120dbe-164a-4891-842f-fb7829273838">
<Name>ILSpy</Name>
<Author>IC#Code</Author>
<Version>1.3</Version>
<Version>1.5</Version>
<Description xml:space="preserve">Integrates the ILSpy decompiler into Visual Studio.</Description>
<Icon>ILSpy-Large.ico</Icon>
<License>license.txt</License>
@ -24,6 +24,10 @@ @@ -24,6 +24,10 @@
<VisualStudio Version="14.0">
<Edition>Pro</Edition>
</VisualStudio>
<VisualStudio Version="15.0">
<Edition>Pro</Edition>
<Edition>Community</Edition>
</VisualStudio>
</SupportedProducts>
</Identifier>
<Content>

19
ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs

@ -7,6 +7,10 @@ using System.ComponentModel.Composition; @@ -7,6 +7,10 @@ using System.ComponentModel.Composition;
using System.IO;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy;
using System.Resources;
using System.Collections;
using System.Linq;
namespace ILSpy.BamlDecompiler
{
@ -26,4 +30,19 @@ namespace ILSpy.BamlDecompiler @@ -26,4 +30,19 @@ namespace ILSpy.BamlDecompiler
return null;
}
}
[Export(typeof(IResourceFileHandler))]
public sealed class BamlResourceFileHandler : IResourceFileHandler
{
public string EntryType => "Page";
public bool CanHandle(string name, DecompilationOptions options) => name.EndsWith(".baml", StringComparison.OrdinalIgnoreCase);
public string WriteResourceToFile(LoadedAssembly assembly, string fileName, Stream stream, DecompilationOptions options)
{
var document = BamlResourceEntryNode.LoadIntoDocument(assembly.GetAssemblyResolver(), assembly.AssemblyDefinition, stream);
fileName = Path.ChangeExtension(fileName, ".xaml");
document.Save(Path.Combine(options.SaveAsProjectDirectory, fileName));
return fileName;
}
}
}

10
ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj

@ -101,27 +101,27 @@ @@ -101,27 +101,27 @@
<ItemGroup />
<ItemGroup>
<ProjectReference Include="..\AvalonEdit\ICSharpCode.AvalonEdit\ICSharpCode.AvalonEdit.csproj">
<Project>{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}</Project>
<Project>{6c55b776-26d4-4db3-a6ab-87e783b2f3d1}</Project>
<Name>ICSharpCode.AvalonEdit</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.csproj">
<Project>{984CC812-9470-4A13-AFF9-CC44068D666C}</Project>
<Project>{984cc812-9470-4a13-aff9-cc44068d666c}</Project>
<Name>ICSharpCode.Decompiler</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\ILSpy\ILSpy.csproj">
<Project>{1E85EFF9-E370-4683-83E4-8A3D063FF791}</Project>
<Project>{1e85eff9-e370-4683-83e4-8a3d063ff791}</Project>
<Name>ILSpy</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\cecil\Mono.Cecil.csproj">
<Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
<Project>{d68133bd-1e63-496e-9ede-4fbdbf77b486}</Project>
<Name>Mono.Cecil</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\SharpTreeView\ICSharpCode.TreeView.csproj">
<Project>{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}</Project>
<Project>{dde2a481-8271-4eac-a330-8fa6a38d13d1}</Project>
<Name>ICSharpCode.TreeView</Name>
<Private>False</Private>
</ProjectReference>

4
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs

@ -488,6 +488,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -488,6 +488,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
case BamlRecordType.PresentationOptionsAttribute:
this.ReadPresentationOptionsAttribute();
break;
case BamlRecordType.TypeSerializerInfo:
this.ReadTypeInfo();
break;
default:
throw new NotImplementedException("UnsupportedNode: " + currentType);
}
@ -526,6 +529,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -526,6 +529,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
case BamlRecordType.TypeInfo:
case BamlRecordType.AttributeInfo:
case BamlRecordType.StringInfo:
case BamlRecordType.TypeSerializerInfo:
bytesToSkip = reader.ReadCompressedInt32();
break;
}

10
ILSpy.BamlDecompiler/Tests/ILSpy.BamlDecompiler.Tests.csproj

@ -97,23 +97,23 @@ @@ -97,23 +97,23 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\ICSharpCode.Decompiler\Tests\ICSharpCode.Decompiler.Tests.csproj">
<Project>{FEC0DA52-C4A6-4710-BE36-B484A20C5E22}</Project>
<Project>{fec0da52-c4a6-4710-be36-b484a20c5e22}</Project>
<Name>ICSharpCode.Decompiler.Tests</Name>
</ProjectReference>
<ProjectReference Include="..\..\ILSpy\ILSpy.csproj">
<Project>{1E85EFF9-E370-4683-83E4-8A3D063FF791}</Project>
<Project>{1e85eff9-e370-4683-83e4-8a3d063ff791}</Project>
<Name>ILSpy</Name>
</ProjectReference>
<ProjectReference Include="..\..\cecil\Mono.Cecil.csproj">
<Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
<Project>{d68133bd-1e63-496e-9ede-4fbdbf77b486}</Project>
<Name>Mono.Cecil</Name>
</ProjectReference>
<ProjectReference Include="..\..\SharpTreeView\ICSharpCode.TreeView.csproj">
<Project>{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}</Project>
<Project>{dde2a481-8271-4eac-a330-8fa6a38d13d1}</Project>
<Name>ICSharpCode.TreeView</Name>
</ProjectReference>
<ProjectReference Include="..\ILSpy.BamlDecompiler.csproj">
<Project>{A6BAD2BA-76BA-461C-8B6D-418607591247}</Project>
<Project>{a6bad2ba-76ba-461c-8b6d-418607591247}</Project>
<Name>ILSpy.BamlDecompiler</Name>
</ProjectReference>
</ItemGroup>

1
ILSpy.BamlDecompiler/Tests/TestRunner.cs

@ -38,6 +38,7 @@ namespace ILSpy.BamlDecompiler.Tests @@ -38,6 +38,7 @@ namespace ILSpy.BamlDecompiler.Tests
}
[Test]
[Ignore("Broken on AppVeyor CI (extra x:ConnectionId attribute)")]
public void SimpleNames()
{
RunTest("cases/simplenames");

3
ILSpy.sln

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
# Visual Studio 2012
# SharpDevelop 5.1
VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "doc", "doc", "{F45DB999-7E72-4000-B5AD-3A7B485A0896}"

41
ILSpy/AboutPage.cs

@ -289,20 +289,7 @@ namespace ICSharpCode.ILSpy @@ -289,20 +289,7 @@ namespace ICSharpCode.ILSpy
|| s.LastSuccessfulUpdateCheck < DateTime.UtcNow.AddDays(-7)
|| s.LastSuccessfulUpdateCheck > DateTime.UtcNow)
{
GetLatestVersionAsync().ContinueWith(
delegate (Task<AvailableVersionInfo> task) {
try {
s.LastSuccessfulUpdateCheck = DateTime.UtcNow;
AvailableVersionInfo v = task.Result;
if (v.Version > currentVersion)
tcs.SetResult(v.DownloadUrl);
else
tcs.SetResult(null);
} catch (AggregateException) {
// ignore errors getting the version info
tcs.SetResult(null);
}
});
CheckForUpdateInternal(tcs, s);
} else {
tcs.SetResult(null);
}
@ -311,6 +298,32 @@ namespace ICSharpCode.ILSpy @@ -311,6 +298,32 @@ namespace ICSharpCode.ILSpy
}
return tcs.Task;
}
public static Task<string> CheckForUpdatesAsync(ILSpySettings spySettings)
{
var tcs = new TaskCompletionSource<string>();
UpdateSettings s = new UpdateSettings(spySettings);
CheckForUpdateInternal(tcs, s);
return tcs.Task;
}
static void CheckForUpdateInternal(TaskCompletionSource<string> tcs, UpdateSettings s)
{
GetLatestVersionAsync().ContinueWith(
delegate (Task<AvailableVersionInfo> task) {
try {
s.LastSuccessfulUpdateCheck = DateTime.UtcNow;
AvailableVersionInfo v = task.Result;
if (v.Version > currentVersion)
tcs.SetResult(v.DownloadUrl);
else
tcs.SetResult(null);
} catch (AggregateException) {
// ignore errors getting the version info
tcs.SetResult(null);
}
});
}
}
/// <summary>

22
ILSpy/AssemblyList.cs

@ -178,8 +178,26 @@ namespace ICSharpCode.ILSpy @@ -178,8 +178,26 @@ namespace ICSharpCode.ILSpy
var index = this.assemblies.IndexOf(target);
var newAsm = new LoadedAssembly(this, file, stream);
newAsm.IsAutoLoaded = target.IsAutoLoaded;
lock (assemblies)
{
lock (assemblies) {
this.assemblies.Remove(target);
this.assemblies.Insert(index, newAsm);
}
return newAsm;
}
public LoadedAssembly ReloadAssembly(string file)
{
App.Current.Dispatcher.VerifyAccess();
file = Path.GetFullPath(file);
var target = this.assemblies.FirstOrDefault(asm => file.Equals(asm.FileName, StringComparison.OrdinalIgnoreCase));
if (target == null)
return null;
var index = this.assemblies.IndexOf(target);
var newAsm = new LoadedAssembly(this, file);
newAsm.IsAutoLoaded = target.IsAutoLoaded;
lock (assemblies) {
this.assemblies.Remove(target);
this.assemblies.Insert(index, newAsm);
}

31
ILSpy/Commands/CheckForUpdatesCommand.cs

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(Menu = "_Help", Header = "_Check for Updates", MenuOrder = 5000)]
sealed class CheckForUpdatesCommand : SimpleCommand
{
public override void Execute(object parameter)
{
MainWindow.Instance.ShowMessageIfUpdatesAvailableAsync(ILSpySettings.Load(), forceCheck: true);
}
}
}

2
ILSpy/Commands/OpenCommand.cs

@ -22,7 +22,7 @@ using System.Windows.Input; @@ -22,7 +22,7 @@ using System.Windows.Input;
namespace ICSharpCode.ILSpy
{
[ExportToolbarCommand(ToolTip = "Open", ToolbarIcon = "Images/Open.png", ToolbarCategory = "Open", ToolbarOrder = 0)]
[ExportMainMenuCommand(Menu = "_File", MenuIcon = "Images/Open.png", MenuCategory = "Open", MenuOrder = 0)]
[ExportMainMenuCommand(Menu = "_File", Header = "_Open...", MenuIcon = "Images/Open.png", MenuCategory = "Open", MenuOrder = 0)]
sealed class OpenCommand : CommandWrapper
{
public OpenCommand()

2
ILSpy/Commands/OpenFromGacCommand.cs

@ -20,7 +20,7 @@ using System; @@ -20,7 +20,7 @@ using System;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(Menu = "_File", Header = "Open from _GAC", MenuIcon = "Images/AssemblyListGAC.png", MenuCategory = "Open", MenuOrder = 1)]
[ExportMainMenuCommand(Menu = "_File", Header = "Open from _GAC...", MenuIcon = "Images/AssemblyListGAC.png", MenuCategory = "Open", MenuOrder = 1)]
sealed class OpenFromGacCommand : SimpleCommand
{
public override void Execute(object parameter)

2
ILSpy/Commands/OpenListCommand.cs

@ -20,7 +20,7 @@ using System; @@ -20,7 +20,7 @@ using System;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(Menu = "_File", Header = "Open _List", MenuIcon = "Images/AssemblyList.png", MenuCategory = "Open", MenuOrder = 1.7)]
[ExportMainMenuCommand(Menu = "_File", Header = "Open _List...", MenuIcon = "Images/AssemblyList.png", MenuCategory = "Open", MenuOrder = 1.7)]
sealed class OpenListCommand : SimpleCommand
{
public override void Execute(object parameter)

2
ILSpy/Commands/RefreshCommand.cs

@ -22,7 +22,7 @@ using System.Windows.Input; @@ -22,7 +22,7 @@ using System.Windows.Input;
namespace ICSharpCode.ILSpy
{
[ExportToolbarCommand(ToolTip = "Reload all assemblies", ToolbarIcon = "Images/Refresh.png", ToolbarCategory = "Open", ToolbarOrder = 2)]
[ExportMainMenuCommand(Menu = "_File", Header = "Reload", MenuIcon = "Images/Refresh.png", MenuCategory = "Open", MenuOrder = 2)]
[ExportMainMenuCommand(Menu = "_File", Header = "_Reload", MenuIcon = "Images/Refresh.png", MenuCategory = "Open", MenuOrder = 2)]
sealed class RefreshCommand : CommandWrapper
{
public RefreshCommand()

39
ILSpy/Commands/SortAssemblyListCommand.cs

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(Menu = "_View", Header = "Sort assembly list by name", MenuIcon = "Images/Sort.png", MenuCategory = "View")]
[ExportToolbarCommand(ToolTip = "Sort assembly list by name", ToolbarIcon = "Images/Sort.png", ToolbarCategory = "View")]
class SortAssemblyListCommand : SimpleCommand, IComparer<LoadedAssembly>
{
public override void Execute(object parameter)
{
using (MainWindow.Instance.treeView.LockUpdates())
MainWindow.Instance.CurrentAssemblyList.Sort(this);
}
int IComparer<LoadedAssembly>.Compare(LoadedAssembly x, LoadedAssembly y)
{
return string.Compare(x.ShortName, y.ShortName, StringComparison.CurrentCulture);
}
}
}

2
ILSpy/ContextMenuEntry.cs

@ -110,6 +110,8 @@ namespace ICSharpCode.ILSpy @@ -110,6 +110,8 @@ namespace ICSharpCode.ILSpy
public ExportContextMenuEntryAttribute()
: base(typeof(IContextMenuEntry))
{
// entries default to end of menu unless given specific order position
Order = double.MaxValue;
}
public string Icon { get; set; }

26
ILSpy/ILSpy.csproj

@ -101,12 +101,14 @@ @@ -101,12 +101,14 @@
<Compile Include="AssemblyListManager.cs" />
<Compile Include="AvalonEdit\ITextMarker.cs" />
<Compile Include="AvalonEdit\TextMarkerService.cs" />
<Compile Include="Commands\CheckForUpdatesCommand.cs" />
<Compile Include="Commands\BrowseBackCommand.cs" />
<Compile Include="Commands\BrowseForwardCommand.cs" />
<Compile Include="CommandLineArguments.cs" />
<Compile Include="Commands\ExitCommand.cs" />
<Compile Include="Commands\CommandWrapper.cs" />
<Compile Include="Commands\OpenListCommand.cs" />
<Compile Include="Commands\SortAssemblyListCommand.cs" />
<Compile Include="Controls\MarkupExtensions.cs" />
<Compile Include="Controls\ResourceObjectTable.xaml.cs">
<DependentUpon>ResourceObjectTable.xaml</DependentUpon>
@ -137,6 +139,7 @@ @@ -137,6 +139,7 @@
<Compile Include="Images\TypeIcon.cs" />
<Compile Include="IPane.cs" />
<Compile Include="ISmartTextOutput.cs" />
<Compile Include="Languages\IResourceFileHandler.cs" />
<Compile Include="Languages\Language.cs" />
<Compile Include="Images\Images.cs" />
<Compile Include="Languages\Languages.cs" />
@ -367,35 +370,35 @@ @@ -367,35 +370,35 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.csproj">
<Project>{984CC812-9470-4A13-AFF9-CC44068D666C}</Project>
<Project>{984cc812-9470-4a13-aff9-cc44068d666c}</Project>
<Name>ICSharpCode.Decompiler</Name>
</ProjectReference>
<ProjectReference Include="..\cecil\Mono.Cecil.csproj">
<Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
<Project>{d68133bd-1e63-496e-9ede-4fbdbf77b486}</Project>
<Name>Mono.Cecil</Name>
</ProjectReference>
<ProjectReference Include="..\AvalonEdit\ICSharpCode.AvalonEdit\ICSharpCode.AvalonEdit.csproj">
<Project>{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}</Project>
<Project>{6c55b776-26d4-4db3-a6ab-87e783b2f3d1}</Project>
<Name>ICSharpCode.AvalonEdit</Name>
</ProjectReference>
<ProjectReference Include="..\cecil\symbols\pdb\Mono.Cecil.Pdb.csproj">
<Project>{63E6915C-7EA4-4D76-AB28-0D7191EEA626}</Project>
<Project>{63e6915c-7ea4-4d76-ab28-0d7191eea626}</Project>
<Name>Mono.Cecil.Pdb</Name>
</ProjectReference>
<ProjectReference Include="..\NRefactory.VB\ICSharpCode.NRefactory.VB\ICSharpCode.NRefactory.VB.csproj">
<Project>{7B82B671-419F-45F4-B778-D9286F996EFA}</Project>
<Project>{7b82b671-419f-45f4-b778-d9286f996efa}</Project>
<Name>ICSharpCode.NRefactory.VB</Name>
</ProjectReference>
<ProjectReference Include="..\NRefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj">
<Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project>
<Project>{53dca265-3c3c-42f9-b647-f72ba678122b}</Project>
<Name>ICSharpCode.NRefactory.CSharp</Name>
</ProjectReference>
<ProjectReference Include="..\NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
<Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project>
<Project>{3b2a5653-ec97-4001-bb9b-d90f1af2c371}</Project>
<Name>ICSharpCode.NRefactory</Name>
</ProjectReference>
<ProjectReference Include="..\SharpTreeView\ICSharpCode.TreeView.csproj">
<Project>{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}</Project>
<Project>{dde2a481-8271-4eac-a330-8fa6a38d13d1}</Project>
<Name>ICSharpCode.TreeView</Name>
</ProjectReference>
</ItemGroup>
@ -404,6 +407,11 @@ @@ -404,6 +407,11 @@
<Resource Include="Images\ResourceXsd.png" />
<Resource Include="Images\ResourceXslt.png" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Resource Include="Images\Sort.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Images\SearchMsdn.png" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
</Project>

BIN
ILSpy/Images/Library.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 B

After

Width:  |  Height:  |  Size: 417 B

BIN
ILSpy/Images/OverlayStatic.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 315 B

After

Width:  |  Height:  |  Size: 347 B

BIN
ILSpy/Images/SearchMsdn.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 710 B

BIN
ILSpy/Images/Sort.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 B

95
ILSpy/Languages/CSharpLanguage.cs

@ -17,12 +17,10 @@ @@ -17,12 +17,10 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Resources;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml;
@ -203,7 +201,7 @@ namespace ICSharpCode.ILSpy @@ -203,7 +201,7 @@ namespace ICSharpCode.ILSpy
public override void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options)
{
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: type);
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentModule: type.Module);
codeDomBuilder.AddType(type);
RunTransformsAndGenerateCode(codeDomBuilder, output, options);
}
@ -508,84 +506,6 @@ namespace ICSharpCode.ILSpy @@ -508,84 +506,6 @@ namespace ICSharpCode.ILSpy
}
#endregion
#region WriteResourceFilesInProject
IEnumerable<Tuple<string, string>> WriteResourceFilesInProject(LoadedAssembly assembly, DecompilationOptions options, HashSet<string> directories)
{
//AppDomain bamlDecompilerAppDomain = null;
//try {
foreach (EmbeddedResource r in assembly.ModuleDefinition.Resources.OfType<EmbeddedResource>()) {
string fileName;
Stream s = r.GetResourceStream();
s.Position = 0;
if (r.Name.EndsWith(".g.resources", StringComparison.OrdinalIgnoreCase)) {
IEnumerable<DictionaryEntry> rs = null;
try {
rs = new ResourceSet(s).Cast<DictionaryEntry>();
}
catch (ArgumentException) {
}
if (rs != null && rs.All(e => e.Value is Stream)) {
foreach (var pair in rs) {
fileName = Path.Combine(((string)pair.Key).Split('/').Select(p => TextView.DecompilerTextView.CleanUpName(p)).ToArray());
string dirName = Path.GetDirectoryName(fileName);
if (!string.IsNullOrEmpty(dirName) && directories.Add(dirName)) {
Directory.CreateDirectory(Path.Combine(options.SaveAsProjectDirectory, dirName));
}
Stream entryStream = (Stream)pair.Value;
entryStream.Position = 0;
if (fileName.EndsWith(".baml", StringComparison.OrdinalIgnoreCase)) {
// MemoryStream ms = new MemoryStream();
// entryStream.CopyTo(ms);
// TODO implement extension point
// var decompiler = Baml.BamlResourceEntryNode.CreateBamlDecompilerInAppDomain(ref bamlDecompilerAppDomain, assembly.FileName);
// string xaml = null;
// try {
// xaml = decompiler.DecompileBaml(ms, assembly.FileName, new ConnectMethodDecompiler(assembly), new AssemblyResolver(assembly));
// }
// catch (XamlXmlWriterException) { } // ignore XAML writer exceptions
// if (xaml != null) {
// File.WriteAllText(Path.Combine(options.SaveAsProjectDirectory, Path.ChangeExtension(fileName, ".xaml")), xaml);
// yield return Tuple.Create("Page", Path.ChangeExtension(fileName, ".xaml"));
// continue;
// }
}
using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write)) {
entryStream.CopyTo(fs);
}
yield return Tuple.Create("Resource", fileName);
}
continue;
}
}
fileName = GetFileNameForResource(r.Name, directories);
using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write)) {
s.CopyTo(fs);
}
yield return Tuple.Create("EmbeddedResource", fileName);
}
//}
//finally {
// if (bamlDecompilerAppDomain != null)
// AppDomain.Unload(bamlDecompilerAppDomain);
//}
}
string GetFileNameForResource(string fullName, HashSet<string> directories)
{
string[] splitName = fullName.Split('.');
string fileName = TextView.DecompilerTextView.CleanUpName(fullName);
for (int i = splitName.Length - 1; i > 0; i--) {
string ns = string.Join(".", splitName, 0, i);
if (directories.Contains(ns)) {
string name = string.Join(".", splitName, i, splitName.Length - i);
fileName = Path.Combine(ns, TextView.DecompilerTextView.CleanUpName(name));
break;
}
}
return fileName;
}
#endregion
AstBuilder CreateAstBuilder(DecompilationOptions options, ModuleDefinition currentModule = null, TypeDefinition currentType = null, bool isSingleMember = false)
{
if (currentModule == null)
@ -628,10 +548,13 @@ namespace ICSharpCode.ILSpy @@ -628,10 +548,13 @@ namespace ICSharpCode.ILSpy
((ComposedType)astType).PointerRank--;
}
astType.AcceptVisitor(new CSharpOutputVisitor(w, FormattingOptionsFactory.CreateAllman()));
astType.AcceptVisitor(new CSharpOutputVisitor(w, TypeToStringFormattingOptions));
return w.ToString();
}
static readonly CSharpFormattingOptions TypeToStringFormattingOptions = FormattingOptionsFactory.CreateEmpty();
public override string FormatPropertyName(PropertyDefinition property, bool? isIndexer)
{
if (property == null)
@ -663,6 +586,14 @@ namespace ICSharpCode.ILSpy @@ -663,6 +586,14 @@ namespace ICSharpCode.ILSpy
return property.Name;
}
public override string FormatMethodName(MethodDefinition method)
{
if (method == null)
throw new ArgumentNullException("method");
return (method.IsConstructor) ? method.DeclaringType.Name : method.Name;
}
public override string FormatTypeName(TypeDefinition type)
{
if (type == null)

30
ILSpy/Languages/IResourceFileHandler.cs

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.IO;
namespace ICSharpCode.ILSpy
{
public interface IResourceFileHandler
{
string EntryType { get; }
bool CanHandle(string name, DecompilationOptions options);
string WriteResourceToFile(LoadedAssembly assembly, string fileName, Stream stream, DecompilationOptions options);
}
}

96
ILSpy/Languages/Language.cs

@ -17,7 +17,11 @@ @@ -17,7 +17,11 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Resources;
using ICSharpCode.Decompiler;
using Mono.Cecil;
@ -135,6 +139,13 @@ namespace ICSharpCode.ILSpy @@ -135,6 +139,13 @@ namespace ICSharpCode.ILSpy
return property.Name;
}
public virtual string FormatMethodName(MethodDefinition method)
{
if (method == null)
throw new ArgumentNullException("method");
return method.Name;
}
public virtual string FormatTypeName(TypeDefinition type)
{
if (type == null)
@ -162,5 +173,90 @@ namespace ICSharpCode.ILSpy @@ -162,5 +173,90 @@ namespace ICSharpCode.ILSpy
{
return member;
}
#region WriteResourceFilesInProject
protected virtual IEnumerable<Tuple<string, string>> WriteResourceFilesInProject(LoadedAssembly assembly, DecompilationOptions options, HashSet<string> directories)
{
foreach (EmbeddedResource r in assembly.ModuleDefinition.Resources.OfType<EmbeddedResource>()) {
Stream stream = r.GetResourceStream();
stream.Position = 0;
IEnumerable<DictionaryEntry> entries;
if (r.Name.EndsWith(".resources", StringComparison.OrdinalIgnoreCase)) {
if (GetEntries(stream, out entries) && entries.All(e => e.Value is Stream)) {
foreach (var pair in entries) {
string fileName = Path.Combine(((string)pair.Key).Split('/').Select(p => TextView.DecompilerTextView.CleanUpName(p)).ToArray());
string dirName = Path.GetDirectoryName(fileName);
if (!string.IsNullOrEmpty(dirName) && directories.Add(dirName)) {
Directory.CreateDirectory(Path.Combine(options.SaveAsProjectDirectory, dirName));
}
Stream entryStream = (Stream)pair.Value;
bool handled = false;
foreach (var handler in App.CompositionContainer.GetExportedValues<IResourceFileHandler>()) {
if (handler.CanHandle(fileName, options)) {
handled = true;
entryStream.Position = 0;
yield return Tuple.Create(handler.EntryType, handler.WriteResourceToFile(assembly, fileName, entryStream, options));
break;
}
}
if (!handled) {
using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write)) {
entryStream.Position = 0;
entryStream.CopyTo(fs);
}
yield return Tuple.Create("EmbeddedResource", fileName);
}
}
} else {
stream.Position = 0;
string fileName = GetFileNameForResource(Path.ChangeExtension(r.Name, ".resx"), directories);
using (ResourceReader reader = new ResourceReader(stream))
using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write))
using (ResXResourceWriter writer = new ResXResourceWriter(fs)) {
foreach (DictionaryEntry entry in reader) {
writer.AddResource((string)entry.Key, entry.Value);
}
}
yield return Tuple.Create("EmbeddedResource", fileName);
}
} else {
string fileName = GetFileNameForResource(r.Name, directories);
using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write)) {
stream.Position = 0;
stream.CopyTo(fs);
}
yield return Tuple.Create("EmbeddedResource", fileName);
}
}
}
string GetFileNameForResource(string fullName, HashSet<string> directories)
{
string[] splitName = fullName.Split('.');
string fileName = TextView.DecompilerTextView.CleanUpName(fullName);
for (int i = splitName.Length - 1; i > 0; i--) {
string ns = string.Join(".", splitName, 0, i);
if (directories.Contains(ns)) {
string name = string.Join(".", splitName, i, splitName.Length - i);
fileName = Path.Combine(ns, TextView.DecompilerTextView.CleanUpName(name));
break;
}
}
return fileName;
}
bool GetEntries(Stream stream, out IEnumerable<DictionaryEntry> entries)
{
try {
entries = new ResourceSet(stream).Cast<DictionaryEntry>();
return true;
} catch (ArgumentException) {
entries = null;
return false;
}
}
#endregion
}
}

14
ILSpy/LoadedAssembly.cs

@ -139,6 +139,20 @@ namespace ICSharpCode.ILSpy @@ -139,6 +139,20 @@ namespace ICSharpCode.ILSpy
private void LoadSymbols(ModuleDefinition module)
{
if (!module.HasDebugHeader) {
return;
}
byte[] headerBytes;
var debugHeader = module.GetDebugHeader(out headerBytes);
if (debugHeader.Type != 2) {
// the debug type is not IMAGE_DEBUG_TYPE_CODEVIEW
return;
}
if (debugHeader.MajorVersion != 0 || debugHeader.MinorVersion != 0) {
// the PDB type is not compatible with PdbReaderProvider. It is probably a Portable PDB
return;
}
// search for pdb in same directory as dll
string pdbName = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName) + ".pdb");
if (File.Exists(pdbName)) {

8
ILSpy/MainWindow.xaml

@ -141,12 +141,12 @@ @@ -141,12 +141,12 @@
<RowDefinition Height="0" />
<RowDefinition Height="0" Name="bottomPaneRow" />
</Grid.RowDefinitions>
<Border BorderBrush="Black" BorderThickness="1" Name="updateAvailablePanel" Visibility="Collapsed">
<Border BorderBrush="Black" BorderThickness="1" Name="updatePanel" Visibility="Collapsed">
<DockPanel>
<Button DockPanel.Dock="Right" Click="updateAvailablePanelCloseButtonClick" MinWidth="0">X</Button>
<Button DockPanel.Dock="Right" Click="updatePanelCloseButtonClick" MinWidth="0">X</Button>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="4,0" VerticalAlignment="Center">A new ILSpy version is available.</TextBlock>
<Button Click="downloadUpdateButtonClick">Download</Button>
<TextBlock Name="updatePanelMessage" Margin="4,0" VerticalAlignment="Center">A new ILSpy version is available.</TextBlock>
<Button Name="downloadOrCheckUpdateButton" Click="downloadOrCheckUpdateButtonClick">Download</Button>
</StackPanel>
</DockPanel>
</Border>

72
ILSpy/MainWindow.xaml.cs

@ -257,7 +257,15 @@ namespace ICSharpCode.ILSpy @@ -257,7 +257,15 @@ namespace ICSharpCode.ILSpy
void HandleCommandLineArgumentsAfterShowList(CommandLineArguments args)
{
if (args.NavigateTo != null) {
// if a SaveDirectory is given, do not start a second concurrent decompilation
// by executing JumpoToReference (leads to https://github.com/icsharpcode/ILSpy/issues/710)
if (!string.IsNullOrEmpty(args.SaveDirectory)) {
foreach (var x in commandLineLoadedAssemblies) {
x.ContinueWhenLoaded((Task<ModuleDefinition> moduleTask) => {
OnExportAssembly(moduleTask, args.SaveDirectory);
}, TaskScheduler.FromCurrentSynchronizationContext());
}
} else if (args.NavigateTo != null) {
bool found = false;
if (args.NavigateTo.StartsWith("N:", StringComparison.Ordinal)) {
string namespaceName = args.NavigateTo.Substring(2);
@ -300,13 +308,6 @@ namespace ICSharpCode.ILSpy @@ -300,13 +308,6 @@ namespace ICSharpCode.ILSpy
SearchPane.Instance.SearchTerm = args.Search;
SearchPane.Instance.Show();
}
if (!string.IsNullOrEmpty(args.SaveDirectory)) {
foreach (var x in commandLineLoadedAssemblies) {
x.ContinueWhenLoaded( (Task<ModuleDefinition> moduleTask) => {
OnExportAssembly(moduleTask, args.SaveDirectory);
}, TaskScheduler.FromCurrentSynchronizationContext());
}
}
commandLineLoadedAssemblies.Clear(); // clear references once we don't need them anymore
}
@ -398,27 +399,44 @@ namespace ICSharpCode.ILSpy @@ -398,27 +399,44 @@ namespace ICSharpCode.ILSpy
#region Update Check
string updateAvailableDownloadUrl;
void ShowMessageIfUpdatesAvailableAsync(ILSpySettings spySettings)
public void ShowMessageIfUpdatesAvailableAsync(ILSpySettings spySettings, bool forceCheck = false)
{
AboutPage.CheckForUpdatesIfEnabledAsync(spySettings).ContinueWith(
delegate (Task<string> task) {
if (task.Result != null) {
updateAvailableDownloadUrl = task.Result;
updateAvailablePanel.Visibility = Visibility.Visible;
}
},
TaskScheduler.FromCurrentSynchronizationContext()
);
Task<string> result;
if (forceCheck) {
result = AboutPage.CheckForUpdatesAsync(spySettings);
} else {
result = AboutPage.CheckForUpdatesIfEnabledAsync(spySettings);
}
result.ContinueWith(task => AdjustUpdateUIAfterCheck(task, forceCheck), TaskScheduler.FromCurrentSynchronizationContext());
}
void updateAvailablePanelCloseButtonClick(object sender, RoutedEventArgs e)
void updatePanelCloseButtonClick(object sender, RoutedEventArgs e)
{
updateAvailablePanel.Visibility = Visibility.Collapsed;
updatePanel.Visibility = Visibility.Collapsed;
}
void downloadUpdateButtonClick(object sender, RoutedEventArgs e)
void downloadOrCheckUpdateButtonClick(object sender, RoutedEventArgs e)
{
Process.Start(updateAvailableDownloadUrl);
if (updateAvailableDownloadUrl != null) {
Process.Start(updateAvailableDownloadUrl);
} else {
updatePanel.Visibility = Visibility.Collapsed;
AboutPage.CheckForUpdatesAsync(spySettings ?? ILSpySettings.Load())
.ContinueWith(task => AdjustUpdateUIAfterCheck(task, true), TaskScheduler.FromCurrentSynchronizationContext());
}
}
void AdjustUpdateUIAfterCheck(Task<string> task, bool displayMessage)
{
updateAvailableDownloadUrl = task.Result;
updatePanel.Visibility = displayMessage ? Visibility.Visible : Visibility.Collapsed;
if (task.Result != null) {
updatePanelMessage.Text = "A new ILSpy version is available.";
downloadOrCheckUpdateButton.Content = "Download";
} else {
updatePanelMessage.Text = "No update for ILSpy found.";
downloadOrCheckUpdateButton.Content = "Check again";
}
}
#endregion
@ -532,6 +550,14 @@ namespace ICSharpCode.ILSpy @@ -532,6 +550,14 @@ namespace ICSharpCode.ILSpy
}
}
public void SelectNodes(IEnumerable<SharpTreeNode> nodes)
{
if (nodes.Any() && nodes.All(n => !n.AncestorsAndSelf().Any(a => a.IsHidden))) {
treeView.FocusNode(nodes.First());
treeView.SetSelectedNodes(nodes);
}
}
/// <summary>
/// Retrieves a node using the .ToString() representations of its ancestors.
/// </summary>
@ -557,7 +583,7 @@ namespace ICSharpCode.ILSpy @@ -557,7 +583,7 @@ namespace ICSharpCode.ILSpy
/// <summary>
/// Gets the .ToString() representation of the node's ancestors.
/// </summary>
public string[] GetPathForNode(SharpTreeNode node)
public static string[] GetPathForNode(SharpTreeNode node)
{
if (node == null)
return null;

2
ILSpy/Options/OptionsDialog.xaml.cs

@ -89,7 +89,7 @@ namespace ICSharpCode.ILSpy.Options @@ -89,7 +89,7 @@ namespace ICSharpCode.ILSpy.Options
public int Order { get; set; }
}
[ExportMainMenuCommand(Menu = "_View", Header = "_Options", MenuCategory = "Options", MenuOrder = 999)]
[ExportMainMenuCommand(Menu = "_View", Header = "_Options...", MenuCategory = "Options", MenuOrder = 999)]
sealed class ShowOptionsCommand : SimpleCommand
{
public override void Execute(object parameter)

6
ILSpy/Properties/AssemblyInfo.template.cs

@ -15,7 +15,7 @@ using System.Runtime.InteropServices; @@ -15,7 +15,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyDescription(".NET assembly inspector and decompiler")]
[assembly: AssemblyCompany("ic#code")]
[assembly: AssemblyProduct("ILSpy")]
[assembly: AssemblyCopyright("Copyright 2011-2014 AlphaSierraPapa for the SharpDevelop Team")]
[assembly: AssemblyCopyright("Copyright 2011-2016 AlphaSierraPapa for the SharpDevelop Team")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@ -35,8 +35,8 @@ using System.Runtime.InteropServices; @@ -35,8 +35,8 @@ using System.Runtime.InteropServices;
internal static class RevisionClass
{
public const string Major = "2";
public const string Minor = "3";
public const string Build = "1";
public const string Minor = "4";
public const string Build = "0";
public const string Revision = "$INSERTREVISION$";
public const string VersionName = null;

48
ILSpy/SearchPane.cs

@ -58,10 +58,15 @@ namespace ICSharpCode.ILSpy @@ -58,10 +58,15 @@ namespace ICSharpCode.ILSpy
private SearchPane()
{
InitializeComponent();
searchModeComboBox.Items.Add(new { Image = Images.Library, Name = "Types and Members" });
searchModeComboBox.Items.Add(new { Image = Images.Class, Name = "Type" });
searchModeComboBox.Items.Add(new { Image = Images.Property, Name = "Member" });
searchModeComboBox.Items.Add(new { Image = Images.Method, Name = "Method" });
searchModeComboBox.Items.Add(new { Image = Images.Field, Name = "Field" });
searchModeComboBox.Items.Add(new { Image = Images.Property, Name = "Property" });
searchModeComboBox.Items.Add(new { Image = Images.Event, Name = "Event" });
searchModeComboBox.Items.Add(new { Image = Images.Literal, Name = "Constant" });
searchModeComboBox.SelectedIndex = (int)SearchMode.Type;
searchModeComboBox.SelectedIndex = (int)SearchMode.TypeAndMember;
ContextMenuProvider.Add(listBox);
MainWindow.Instance.CurrentAssemblyListChanged += MainWindow_Instance_CurrentAssemblyListChanged;
@ -249,23 +254,49 @@ namespace ICSharpCode.ILSpy @@ -249,23 +254,49 @@ namespace ICSharpCode.ILSpy
AbstractSearchStrategy GetSearchStrategy(SearchMode mode, string[] terms)
{
if (terms.Length == 1) {
if (terms[0].StartsWith("t:"))
if (terms[0].StartsWith("tm:", StringComparison.Ordinal))
return new TypeAndMemberSearchStrategy(terms[0].Substring(3));
if (terms[0].StartsWith("t:", StringComparison.Ordinal))
return new TypeSearchStrategy(terms[0].Substring(2));
if (terms[0].StartsWith("m:"))
if (terms[0].StartsWith("m:", StringComparison.Ordinal))
return new MemberSearchStrategy(terms[0].Substring(2));
if (terms[0].StartsWith("c:"))
if (terms[0].StartsWith("md:", StringComparison.Ordinal))
return new MemberSearchStrategy(terms[0].Substring(3), MemberSearchKind.Method);
if (terms[0].StartsWith("f:", StringComparison.Ordinal))
return new MemberSearchStrategy(terms[0].Substring(2), MemberSearchKind.Field);
if (terms[0].StartsWith("p:", StringComparison.Ordinal))
return new MemberSearchStrategy(terms[0].Substring(2), MemberSearchKind.Property);
if (terms[0].StartsWith("e:", StringComparison.Ordinal))
return new MemberSearchStrategy(terms[0].Substring(2), MemberSearchKind.Event);
if (terms[0].StartsWith("c:", StringComparison.Ordinal))
return new LiteralSearchStrategy(terms[0].Substring(2));
}
switch (mode) {
switch (mode)
{
case SearchMode.TypeAndMember:
return new TypeAndMemberSearchStrategy(terms);
case SearchMode.Type:
return new TypeSearchStrategy(terms);
case SearchMode.Member:
return new MemberSearchStrategy(terms);
case SearchMode.Literal:
return new LiteralSearchStrategy(terms);
case SearchMode.Method:
return new MemberSearchStrategy(terms, MemberSearchKind.Method);
case SearchMode.Field:
return new MemberSearchStrategy(terms, MemberSearchKind.Field);
case SearchMode.Property:
return new MemberSearchStrategy(terms, MemberSearchKind.Property);
case SearchMode.Event:
return new MemberSearchStrategy(terms, MemberSearchKind.Event);
}
return null;
@ -293,7 +324,7 @@ namespace ICSharpCode.ILSpy @@ -293,7 +324,7 @@ namespace ICSharpCode.ILSpy
}
}
[ExportMainMenuCommand(Menu = "_View", Header = "_Search", MenuIcon = "Images/Find.png", MenuCategory = "ShowPane", MenuOrder = 100)]
[ExportMainMenuCommand(Menu = "_View", Header = "_Search...", MenuIcon = "Images/Find.png", MenuCategory = "View", MenuOrder = 100)]
[ExportToolbarCommand(ToolTip = "Search (Ctrl+Shift+F or Ctrl+E)", ToolbarIcon = "Images/Find.png", ToolbarCategory = "View", ToolbarOrder = 100)]
sealed class ShowSearchCommand : CommandWrapper
{
@ -308,8 +339,13 @@ namespace ICSharpCode.ILSpy @@ -308,8 +339,13 @@ namespace ICSharpCode.ILSpy
public enum SearchMode
{
TypeAndMember,
Type,
Member,
Method,
Field,
Property,
Event,
Literal
}
}

2
ILSpy/SearchPane.xaml

@ -19,7 +19,7 @@ @@ -19,7 +19,7 @@
Text="{Binding SearchTerm, ElementName=self}" ToolTip="Search" UpdateDelay="0:0:0.1"
WatermarkColor="Gray" WatermarkText="Search for t:TypeName, m:Member or c:Constant; use /reg(ular)?Ex(pressions)?/ or both - t:/Type(Name)?/..." />
<StackPanel Grid.Column="1" Grid.Row="0" Orientation="Horizontal">
<Label Margin="0,-1">Search _for:</Label>
<Label Margin="0,-1" Target="searchModeComboBox">_Search for:</Label>
<ComboBox Width="100" Name="searchModeComboBox" Margin="1"
SelectionChanged="SearchModeComboBox_SelectionChanged">
<ComboBox.ItemTemplate>

79
ILSpy/SearchStrategies.cs

@ -21,7 +21,7 @@ namespace ICSharpCode.ILSpy @@ -21,7 +21,7 @@ namespace ICSharpCode.ILSpy
{
if (terms.Length == 1 && terms[0].Length > 2) {
var search = terms[0];
if (search.StartsWith("/") && search.EndsWith("/") && search.Length > 4)
if (search.StartsWith("/", StringComparison.Ordinal) && search.EndsWith("/", StringComparison.Ordinal) && search.Length > 4)
regex = SafeNewRegex(search.Substring(1, search.Length - 2));
terms[0] = search;
@ -38,6 +38,7 @@ namespace ICSharpCode.ILSpy @@ -38,6 +38,7 @@ namespace ICSharpCode.ILSpy
for (int i = 0; i < searchTerm.Length; ++i) {
// How to handle overlapping matches?
var term = searchTerm[i];
if (string.IsNullOrEmpty(term)) continue;
switch (term[0])
{
case '+': // must contain
@ -302,31 +303,48 @@ namespace ICSharpCode.ILSpy @@ -302,31 +303,48 @@ namespace ICSharpCode.ILSpy
}
}
enum MemberSearchKind
{
All,
Field,
Property,
Event,
Method
}
class MemberSearchStrategy : AbstractSearchStrategy
{
public MemberSearchStrategy(params string[] terms)
MemberSearchKind searchKind;
public MemberSearchStrategy(string term, MemberSearchKind searchKind = MemberSearchKind.All)
: this(new[] { term }, searchKind)
{
}
public MemberSearchStrategy(string[] terms, MemberSearchKind searchKind = MemberSearchKind.All)
: base(terms)
{
this.searchKind = searchKind;
}
protected override bool IsMatch(FieldDefinition field)
{
return IsMatch(field.Name);
return (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Field) && IsMatch(field.Name);
}
protected override bool IsMatch(PropertyDefinition property)
{
return IsMatch(property.Name);
return (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Property) && IsMatch(property.Name);
}
protected override bool IsMatch(EventDefinition ev)
{
return IsMatch(ev.Name);
return (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Event) && IsMatch(ev.Name);
}
protected override bool IsMatch(MethodDefinition m)
{
return IsMatch(m.Name);
return (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Method) && IsMatch(m.Name);
}
}
@ -355,4 +373,53 @@ namespace ICSharpCode.ILSpy @@ -355,4 +373,53 @@ namespace ICSharpCode.ILSpy
}
}
class TypeAndMemberSearchStrategy : AbstractSearchStrategy
{
public TypeAndMemberSearchStrategy(params string[] terms)
: base(terms)
{
}
public override void Search(TypeDefinition type, Language language, Action<SearchResult> addResult)
{
if (IsMatch(type.Name) || IsMatch(type.FullName))
{
addResult(new SearchResult
{
Member = type,
Image = TypeTreeNode.GetIcon(type),
Name = language.TypeToString(type, includeNamespace: false),
LocationImage = type.DeclaringType != null ? TypeTreeNode.GetIcon(type.DeclaringType) : Images.Namespace,
Location = type.DeclaringType != null ? language.TypeToString(type.DeclaringType, includeNamespace: true) : type.Namespace
});
}
foreach (TypeDefinition nestedType in type.NestedTypes)
{
Search(nestedType, language, addResult);
}
base.Search(type, language, addResult);
}
protected override bool IsMatch(FieldDefinition field)
{
return IsMatch(field.Name);
}
protected override bool IsMatch(PropertyDefinition property)
{
return IsMatch(property.Name);
}
protected override bool IsMatch(EventDefinition ev)
{
return IsMatch(ev.Name);
}
protected override bool IsMatch(MethodDefinition m)
{
return IsMatch(m.Name);
}
}
}

4
ILSpy/TextView/DecompilerTextView.cs

@ -233,6 +233,9 @@ namespace ICSharpCode.ILSpy.TextView @@ -233,6 +233,9 @@ namespace ICSharpCode.ILSpy.TextView
{
if (waitAdorner.Visibility != Visibility.Visible) {
waitAdorner.Visibility = Visibility.Visible;
// Work around a WPF bug by setting IsIndeterminate only while the progress bar is visible.
// https://github.com/icsharpcode/ILSpy/issues/593
progressBar.IsIndeterminate = true;
waitAdorner.BeginAnimation(OpacityProperty, new DoubleAnimation(0, 1, new Duration(TimeSpan.FromSeconds(0.5)), FillBehavior.Stop));
var taskBar = MainWindow.Instance.TaskbarItemInfo;
if (taskBar != null) {
@ -260,6 +263,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -260,6 +263,7 @@ namespace ICSharpCode.ILSpy.TextView
if (currentCancellationTokenSource == myCancellationTokenSource) {
currentCancellationTokenSource = null;
waitAdorner.Visibility = Visibility.Collapsed;
progressBar.IsIndeterminate = false;
var taskBar = MainWindow.Instance.TaskbarItemInfo;
if (taskBar != null) {
taskBar.ProgressState = System.Windows.Shell.TaskbarItemProgressState.None;

2
ILSpy/TextView/DecompilerTextView.xaml

@ -19,7 +19,7 @@ @@ -19,7 +19,7 @@
<Border Name="waitAdorner" Background="#C0FFFFFF" Visibility="Collapsed">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock FontSize="14pt">Decompiling...</TextBlock>
<ProgressBar IsIndeterminate="True" Height="16" Margin="0, 4" />
<ProgressBar Name="progressBar" Height="16" Margin="0, 4" />
<Button Click="cancelButton_Click" HorizontalAlignment="Center">Cancel</Button>
</StackPanel>
</Border>

28
ILSpy/TextView/EditorCommands.cs

@ -16,15 +16,10 @@ @@ -16,15 +16,10 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ICSharpCode.ILSpy.TextView
{
[ExportContextMenuEntryAttribute(Header = "Copy", Category = "Editor")]
internal sealed class CopyContextMenuEntry : IContextMenuEntry
[ExportContextMenuEntry(Header = "Copy", Category = "Editor")]
sealed class CopyContextMenuEntry : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)
{
@ -41,4 +36,23 @@ namespace ICSharpCode.ILSpy.TextView @@ -41,4 +36,23 @@ namespace ICSharpCode.ILSpy.TextView
context.TextView.textEditor.Copy();
}
}
[ExportContextMenuEntry(Header = "Select All", Category = "Editor")]
sealed class SelectAllContextMenuEntry : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)
{
return context.TextView != null;
}
public bool IsEnabled(TextViewContext context)
{
return context.TextView != null;
}
public void Execute(TextViewContext context)
{
context.TextView.textEditor.SelectAll();
}
}
}

2
ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs

@ -24,7 +24,7 @@ using Mono.Cecil; @@ -24,7 +24,7 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
[ExportContextMenuEntryAttribute(Header = "Analyze", Icon = "images/Search.png")]
[ExportContextMenuEntry(Header = "Analyze", Icon = "images/Search.png", Category = "Analyze", Order = 100)]
internal sealed class AnalyzeContextMenuEntry : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)

2
ILSpy/TreeNodes/Analyzer/RemoveAnalyzeContextMenuEntry.cs

@ -20,7 +20,7 @@ using System.Linq; @@ -20,7 +20,7 @@ using System.Linq;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
[ExportContextMenuEntryAttribute(Header = "Remove", Icon = "images/Delete.png")]
[ExportContextMenuEntry(Header = "Remove", Icon = "images/Delete.png", Category = "Analyze", Order = 200)]
internal sealed class RemoveAnalyzeContextMenuEntry : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)

38
ILSpy/TreeNodes/AssemblyTreeNode.cs

@ -293,7 +293,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -293,7 +293,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
[ExportContextMenuEntryAttribute(Header = "_Remove", Icon = "images/Delete.png")]
[ExportContextMenuEntry(Header = "_Remove", Icon = "images/Delete.png")]
sealed class RemoveAssembly : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)
@ -318,7 +318,39 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -318,7 +318,39 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
[ExportContextMenuEntryAttribute(Header = "_Load Dependencies")]
[ExportContextMenuEntry(Header = "_Reload", Icon = "images/Refresh.png")]
sealed class ReloadAssembly : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)
{
if (context.SelectedTreeNodes == null)
return false;
return context.SelectedTreeNodes.All(n => n is AssemblyTreeNode);
}
public bool IsEnabled(TextViewContext context)
{
return true;
}
public void Execute(TextViewContext context)
{
if (context.SelectedTreeNodes == null)
return;
var paths = new List<string[]>();
using (context.TreeView.LockUpdates()) {
foreach (var node in context.SelectedTreeNodes) {
paths.Add(MainWindow.GetPathForNode(node));
var la = ((AssemblyTreeNode)node).LoadedAssembly;
la.AssemblyList.ReloadAssembly(la.FileName);
}
}
MainWindow.Instance.SelectNodes(paths.Select(p => MainWindow.Instance.FindNodeByPath(p, true)).ToArray());
MainWindow.Instance.RefreshDecompiledView();
}
}
[ExportContextMenuEntry(Header = "_Load Dependencies", Category = "Dependencies")]
sealed class LoadDependencies : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)
@ -349,7 +381,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -349,7 +381,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
[ExportContextMenuEntryAttribute(Header = "_Add To Main List")]
[ExportContextMenuEntry(Header = "_Add To Main List", Category = "Dependencies")]
sealed class AddToMainList : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)

4
ILSpy/TreeNodes/MethodTreeNode.cs

@ -69,7 +69,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -69,7 +69,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
b.Append(") : ");
b.Append(language.TypeToString(method.ReturnType, false, method.MethodReturnType));
b.Append(method.MetadataToken.ToSuffixString());
return HighlightSearchMatch(method.Name, b.ToString());
return HighlightSearchMatch(language.FormatMethodName(method), b.ToString());
}
public override object Icon
@ -93,7 +93,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -93,7 +93,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
if (method.IsSpecialName &&
(method.Name == ".ctor" || method.Name == ".cctor")) {
return Images.GetIcon(MemberIcon.Constructor, GetOverlayIcon(method.Attributes), false);
return Images.GetIcon(MemberIcon.Constructor, GetOverlayIcon(method.Attributes), method.IsStatic);
}
if (method.HasPInvokeInfo)

30
ILSpy/TreeNodes/PropertyTreeNode.cs

@ -62,7 +62,35 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -62,7 +62,35 @@ namespace ICSharpCode.ILSpy.TreeNodes
public static object GetText(PropertyDefinition property, Language language, bool? isIndexer = null)
{
return HighlightSearchMatch(language.FormatPropertyName(property, isIndexer), " : " + language.TypeToString(property.PropertyType, false, property));
string name = language.FormatPropertyName(property, isIndexer);
var b = new System.Text.StringBuilder();
if (property.HasParameters)
{
b.Append('(');
for (int i = 0; i < property.Parameters.Count; i++)
{
if (i > 0)
b.Append(", ");
b.Append(language.TypeToString(property.Parameters[i].ParameterType, false, property.Parameters[i]));
}
var method = property.GetMethod ?? property.SetMethod;
if (method.CallingConvention == MethodCallingConvention.VarArg)
{
if (property.HasParameters)
b.Append(", ");
b.Append("...");
}
b.Append(") : ");
}
else
{
b.Append(" : ");
}
b.Append(language.TypeToString(property.PropertyType, false, property));
b.Append(property.MetadataToken.ToSuffixString());
return HighlightSearchMatch(name, b.ToString());
}
public override object Icon

2
ILSpy/TreeNodes/SearchMsdnContextMenuEntry.cs

@ -26,7 +26,7 @@ using ICSharpCode.ILSpy.TreeNodes.Analyzer; @@ -26,7 +26,7 @@ using ICSharpCode.ILSpy.TreeNodes.Analyzer;
namespace ICSharpCode.ILSpy.TreeNodes
{
[ExportContextMenuEntryAttribute(Header = "Search MSDN...", Icon = "images/Search.png")]
[ExportContextMenuEntry(Header = "Search MSDN...", Icon = "images/SearchMsdn.png", Order = 9999)]
internal sealed class SearchMsdnContextMenuEntry : IContextMenuEntry
{
private static string msdnAddress = "http://msdn.microsoft.com/en-us/library/{0}";

40
ILSpy/VB/ILSpyEnvironmentProvider.cs

@ -38,7 +38,7 @@ namespace ICSharpCode.ILSpy.VB @@ -38,7 +38,7 @@ namespace ICSharpCode.ILSpy.VB
//readonly CecilLoader loader = new CecilLoader();
public string GetTypeNameForAttribute(ICSharpCode.NRefactory.CSharp.Attribute attribute)
public string GetTypeNameForAttribute(NRefactory.CSharp.Attribute attribute)
{
return attribute.Type.Annotations
.OfType<Mono.Cecil.MemberReference>()
@ -63,7 +63,7 @@ namespace ICSharpCode.ILSpy.VB @@ -63,7 +63,7 @@ namespace ICSharpCode.ILSpy.VB
return SpecialType.UnknownType;
}
public TypeKind GetTypeKindForAstType(ICSharpCode.NRefactory.CSharp.AstType type)
public TypeKind GetTypeKindForAstType(NRefactory.CSharp.AstType type)
{
var annotation = type.Annotation<TypeReference>();
if (annotation == null)
@ -84,7 +84,7 @@ namespace ICSharpCode.ILSpy.VB @@ -84,7 +84,7 @@ namespace ICSharpCode.ILSpy.VB
return TypeKind.Unknown;
}
public TypeCode ResolveExpression(ICSharpCode.NRefactory.CSharp.Expression expression)
public TypeCode ResolveExpression(NRefactory.CSharp.Expression expression)
{
var annotation = expression.Annotations.OfType<TypeInformation>().FirstOrDefault();
@ -106,9 +106,9 @@ namespace ICSharpCode.ILSpy.VB @@ -106,9 +106,9 @@ namespace ICSharpCode.ILSpy.VB
return TypeCode.Object;
}
public Nullable<bool> IsReferenceType(ICSharpCode.NRefactory.CSharp.Expression expression)
public bool? IsReferenceType(NRefactory.CSharp.Expression expression)
{
if (expression is ICSharpCode.NRefactory.CSharp.NullReferenceExpression)
if (expression is NRefactory.CSharp.NullReferenceExpression)
return true;
var annotation = expression.Annotations.OfType<TypeInformation>().FirstOrDefault();
@ -129,7 +129,7 @@ namespace ICSharpCode.ILSpy.VB @@ -129,7 +129,7 @@ namespace ICSharpCode.ILSpy.VB
foreach (var type in interfaces) {
var def = type.Annotation<TypeReference>().Resolve();
if (def == null) continue;
foreach (var method in def.Methods.Where(m => !m.Name.StartsWith("get_") && !m.Name.StartsWith("set_"))) {
foreach (var method in def.Methods.Where(m => !m.Name.StartsWith("get_", StringComparison.Ordinal) && !m.Name.StartsWith("set_", StringComparison.Ordinal))) {
yield return new NRefactory.VB.Ast.InterfaceMemberSpecifier((NRefactory.VB.Ast.AstType)type.Clone(), method.Name);
}
@ -144,14 +144,34 @@ namespace ICSharpCode.ILSpy.VB @@ -144,14 +144,34 @@ namespace ICSharpCode.ILSpy.VB
return expression.Annotation<EventDefinition>() != null;
}
public bool IsMethodGroup(ICSharpCode.NRefactory.CSharp.Expression expression)
public bool IsMethodGroup(NRefactory.CSharp.Expression expression)
{
var annotation = expression.Annotation<MethodDefinition>();
if (annotation != null) {
return true;
var methodInfo = expression.Annotation<MethodReference>()?.Resolve();
if (methodInfo != null) {
return !methodInfo.IsGetter && !methodInfo.IsSetter && !methodInfo.IsAddOn && !methodInfo.IsRemoveOn;
}
return false;
}
public NRefactory.CSharp.ParameterDeclaration[] GetParametersForProperty(NRefactory.CSharp.PropertyDeclaration property)
{
var propInfo = property.Annotation<PropertyReference>();
if (propInfo == null)
return new NRefactory.CSharp.ParameterDeclaration[0];
return propInfo.Parameters.Select(p => new NRefactory.CSharp.ParameterDeclaration(AstBuilder.ConvertType(p.ParameterType), p.Name, GetModifiers(p))).ToArray();
}
NRefactory.CSharp.ParameterModifier GetModifiers(ParameterDefinition p)
{
if (p.IsOut && p.IsIn)
return NRefactory.CSharp.ParameterModifier.Ref;
if (p.IsOut)
return NRefactory.CSharp.ParameterModifier.Out;
return NRefactory.CSharp.ParameterModifier.None;
}
}
}

94
ILSpy/VB/VBLanguage.cs

@ -17,12 +17,10 @@ @@ -17,12 +17,10 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Resources;
using System.Threading.Tasks;
using System.Xml;
@ -30,12 +28,10 @@ using ICSharpCode.Decompiler; @@ -30,12 +28,10 @@ using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.Decompiler.Ast.Transforms;
using ICSharpCode.ILSpy.XmlDoc;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using CSharp = ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.VB;
using ICSharpCode.NRefactory.VB.Visitors;
using Mono.Cecil;
using CSharp = ICSharpCode.NRefactory.CSharp;
namespace ICSharpCode.ILSpy.VB
{
@ -321,84 +317,6 @@ namespace ICSharpCode.ILSpy.VB @@ -321,84 +317,6 @@ namespace ICSharpCode.ILSpy.VB
}
#endregion
#region WriteResourceFilesInProject
IEnumerable<Tuple<string, string>> WriteResourceFilesInProject(LoadedAssembly assembly, DecompilationOptions options, HashSet<string> directories)
{
//AppDomain bamlDecompilerAppDomain = null;
//try {
foreach (EmbeddedResource r in assembly.ModuleDefinition.Resources.OfType<EmbeddedResource>()) {
string fileName;
Stream s = r.GetResourceStream();
s.Position = 0;
if (r.Name.EndsWith(".g.resources", StringComparison.OrdinalIgnoreCase)) {
IEnumerable<DictionaryEntry> rs = null;
try {
rs = new ResourceSet(s).Cast<DictionaryEntry>();
}
catch (ArgumentException) {
}
if (rs != null && rs.All(e => e.Value is Stream)) {
foreach (var pair in rs) {
fileName = Path.Combine(((string)pair.Key).Split('/').Select(p => TextView.DecompilerTextView.CleanUpName(p)).ToArray());
string dirName = Path.GetDirectoryName(fileName);
if (!string.IsNullOrEmpty(dirName) && directories.Add(dirName)) {
Directory.CreateDirectory(Path.Combine(options.SaveAsProjectDirectory, dirName));
}
Stream entryStream = (Stream)pair.Value;
entryStream.Position = 0;
if (fileName.EndsWith(".baml", StringComparison.OrdinalIgnoreCase)) {
//MemoryStream ms = new MemoryStream();
//entryStream.CopyTo(ms);
// TODO implement extension point
// var decompiler = Baml.BamlResourceEntryNode.CreateBamlDecompilerInAppDomain(ref bamlDecompilerAppDomain, assembly.FileName);
// string xaml = null;
// try {
// xaml = decompiler.DecompileBaml(ms, assembly.FileName, new ConnectMethodDecompiler(assembly), new AssemblyResolver(assembly));
// }
// catch (XamlXmlWriterException) { } // ignore XAML writer exceptions
// if (xaml != null) {
// File.WriteAllText(Path.Combine(options.SaveAsProjectDirectory, Path.ChangeExtension(fileName, ".xaml")), xaml);
// yield return Tuple.Create("Page", Path.ChangeExtension(fileName, ".xaml"));
// continue;
// }
}
using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write)) {
entryStream.CopyTo(fs);
}
yield return Tuple.Create("Resource", fileName);
}
continue;
}
}
fileName = GetFileNameForResource(r.Name, directories);
using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write)) {
s.CopyTo(fs);
}
yield return Tuple.Create("EmbeddedResource", fileName);
}
//}
//finally {
// if (bamlDecompilerAppDomain != null)
// AppDomain.Unload(bamlDecompilerAppDomain);
//}
}
string GetFileNameForResource(string fullName, HashSet<string> directories)
{
string[] splitName = fullName.Split('.');
string fileName = TextView.DecompilerTextView.CleanUpName(fullName);
for (int i = splitName.Length - 1; i > 0; i--) {
string ns = string.Join(".", splitName, 0, i);
if (directories.Contains(ns)) {
string name = string.Join(".", splitName, i, splitName.Length - i);
fileName = Path.Combine(ns, TextView.DecompilerTextView.CleanUpName(name));
break;
}
}
return fileName;
}
#endregion
public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options)
{
WriteCommentLine(output, TypeToString(method.DeclaringType, includeNamespace: true));
@ -433,7 +351,7 @@ namespace ICSharpCode.ILSpy.VB @@ -433,7 +351,7 @@ namespace ICSharpCode.ILSpy.VB
public override void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options)
{
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: type);
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentModule: type.Module);
codeDomBuilder.AddType(type);
RunTransformsAndGenerateCode(codeDomBuilder, output, options, type.Module);
}
@ -484,6 +402,14 @@ namespace ICSharpCode.ILSpy.VB @@ -484,6 +402,14 @@ namespace ICSharpCode.ILSpy.VB
});
}
public override string FormatMethodName(MethodDefinition method)
{
if (method == null)
throw new ArgumentNullException("method");
return (method.IsConstructor) ? method.DeclaringType.Name : method.Name;
}
public override string FormatTypeName(TypeDefinition type)
{
if (type == null)

63
ILSpy/VB/VBTextOutputFormatter.cs

@ -34,6 +34,8 @@ namespace ICSharpCode.ILSpy.VB @@ -34,6 +34,8 @@ namespace ICSharpCode.ILSpy.VB
readonly ITextOutput output;
readonly Stack<AstNode> nodeStack = new Stack<AstNode>();
bool firstImport, lastImport;
public VBTextOutputFormatter(ITextOutput output)
{
if (output == null)
@ -43,28 +45,36 @@ namespace ICSharpCode.ILSpy.VB @@ -43,28 +45,36 @@ namespace ICSharpCode.ILSpy.VB
public void StartNode(AstNode node)
{
// var ranges = node.Annotation<List<ILRange>>();
// if (ranges != null && ranges.Count > 0)
// {
// // find the ancestor that has method mapping as annotation
// if (node.Ancestors != null && node.Ancestors.Count() > 0)
// {
// var n = node.Ancestors.FirstOrDefault(a => a.Annotation<MemberMapping>() != null);
// if (n != null) {
// MemberMapping mapping = n.Annotation<MemberMapping>();
//
// // add all ranges
// foreach (var range in ranges) {
// mapping.MemberCodeMappings.Add(new SourceCodeMapping {
// ILInstructionOffset = range,
// SourceCodeLine = output.CurrentLine,
// MemberMapping = mapping
// });
// }
// }
// }
// }
// var ranges = node.Annotation<List<ILRange>>();
// if (ranges != null && ranges.Count > 0)
// {
// // find the ancestor that has method mapping as annotation
// if (node.Ancestors != null && node.Ancestors.Count() > 0)
// {
// var n = node.Ancestors.FirstOrDefault(a => a.Annotation<MemberMapping>() != null);
// if (n != null) {
// MemberMapping mapping = n.Annotation<MemberMapping>();
//
// // add all ranges
// foreach (var range in ranges) {
// mapping.MemberCodeMappings.Add(new SourceCodeMapping {
// ILInstructionOffset = range,
// SourceCodeLine = output.CurrentLine,
// MemberMapping = mapping
// });
// }
// }
// }
// }
if (nodeStack.Count == 0) {
if (node is ImportsStatement) {
firstImport = !(node.PrevSibling is ImportsStatement);
lastImport = !(node.NextSibling is ImportsStatement);
} else {
firstImport = false;
lastImport = false;
}
}
nodeStack.Push(node);
}
@ -100,6 +110,11 @@ namespace ICSharpCode.ILSpy.VB @@ -100,6 +110,11 @@ namespace ICSharpCode.ILSpy.VB
return;
}
if (firstImport) {
output.MarkFoldStart(defaultCollapsed: true);
firstImport = false;
}
output.Write(identifier);
}
@ -198,6 +213,10 @@ namespace ICSharpCode.ILSpy.VB @@ -198,6 +213,10 @@ namespace ICSharpCode.ILSpy.VB
public void NewLine()
{
if (lastImport) {
output.MarkFoldEnd();
lastImport = false;
}
output.WriteLine();
}

7
NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/ICSharpCode.NRefactory.VB.Tests.csproj

@ -94,13 +94,16 @@ @@ -94,13 +94,16 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ICSharpCode.NRefactory.VB\ICSharpCode.NRefactory.VB.csproj">
<Project>{7B82B671-419F-45F4-B778-D9286F996EFA}</Project>
<Project>{7b82b671-419f-45f4-b778-d9286f996efa}</Project>
<Name>ICSharpCode.NRefactory.VB</Name>
</ProjectReference>
<ProjectReference Include="..\..\NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
<Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project>
<Project>{3b2a5653-ec97-4001-bb9b-d90f1af2c371}</Project>
<Name>ICSharpCode.NRefactory</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
</Project>

3
NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerContextTests.cs

@ -568,7 +568,8 @@ exit Global @@ -568,7 +568,8 @@ exit Global
Assert.IsEmpty(p.Errors);
Assert.AreEqual(expectedOutput, p.Output);
Assert.AreEqual(expectedOutput.Replace("\r", ""),
p.Output.Replace("\r", ""));
}
}
}

2
NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/ImportsStatementTests.cs

@ -27,6 +27,7 @@ namespace ICSharpCode.NRefactory.VB.Tests.Ast @@ -27,6 +27,7 @@ namespace ICSharpCode.NRefactory.VB.Tests.Ast
}
[Test]
[Ignore("Collection pattern matching is not implemented")]
public void SimpleImportsStatement()
{
string program = "Imports System\n";
@ -42,6 +43,7 @@ namespace ICSharpCode.NRefactory.VB.Tests.Ast @@ -42,6 +43,7 @@ namespace ICSharpCode.NRefactory.VB.Tests.Ast
}
[Test]
[Ignore("Collection pattern matching is not implemented")]
public void QualifiedTypeImportsStatement()
{
string program = "Imports My.Name.Space\n";

3
NRefactory.VB/ICSharpCode.NRefactory.VB/Ast/AstNodeCollection.cs

@ -182,7 +182,8 @@ namespace ICSharpCode.NRefactory.VB @@ -182,7 +182,8 @@ namespace ICSharpCode.NRefactory.VB
// if (success && cur2 == null)
// return true;
// }
return false;
// return false;
throw new NotImplementedException();
}
public void InsertAfter(T existingItem, T newItem)

4
NRefactory.VB/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj

@ -211,11 +211,11 @@ @@ -211,11 +211,11 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\NRefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj">
<Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project>
<Project>{53dca265-3c3c-42f9-b647-f72ba678122b}</Project>
<Name>ICSharpCode.NRefactory.CSharp</Name>
</ProjectReference>
<ProjectReference Include="..\..\NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
<Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project>
<Project>{3b2a5653-ec97-4001-bb9b-d90f1af2c371}</Project>
<Name>ICSharpCode.NRefactory</Name>
</ProjectReference>
</ItemGroup>

114
NRefactory.VB/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs

@ -67,11 +67,17 @@ namespace ICSharpCode.NRefactory.VB @@ -67,11 +67,17 @@ namespace ICSharpCode.NRefactory.VB
public object VisitBlockStatement(BlockStatement blockStatement, object data)
{
// prepare new block
NewLine();
Indent();
StartNode(blockStatement);
foreach (var stmt in blockStatement) {
stmt.AcceptVisitor(this, data);
NewLine();
}
// finish block
Unindent();
return EndNode(blockStatement);
}
@ -238,6 +244,7 @@ namespace ICSharpCode.NRefactory.VB @@ -238,6 +244,7 @@ namespace ICSharpCode.NRefactory.VB
WriteModifiers(typeDeclaration.ModifierTokens);
WriteClassTypeKeyword(typeDeclaration);
WriteIdentifier(typeDeclaration.Name.Name);
WriteTypeParameters(typeDeclaration.TypeParameters);
MarkFoldStart();
NewLine();
@ -519,12 +526,7 @@ namespace ICSharpCode.NRefactory.VB @@ -519,12 +526,7 @@ namespace ICSharpCode.NRefactory.VB
WriteKeyword("New");
WriteCommaSeparatedListInParenthesis(constructorDeclaration.Parameters, false);
MarkFoldStart();
NewLine();
Indent();
WriteBlock(constructorDeclaration.Body);
Unindent();
WriteKeyword("End");
WriteKeyword("Sub");
MarkFoldEnd();
@ -556,10 +558,7 @@ namespace ICSharpCode.NRefactory.VB @@ -556,10 +558,7 @@ namespace ICSharpCode.NRefactory.VB
WriteImplementsClause(methodDeclaration.ImplementsClause);
if (!methodDeclaration.Body.IsNull) {
MarkFoldStart();
NewLine();
Indent();
WriteBlock(methodDeclaration.Body);
Unindent();
WriteKeyword("End");
if (methodDeclaration.IsSub)
WriteKeyword("Sub");
@ -854,17 +853,17 @@ namespace ICSharpCode.NRefactory.VB @@ -854,17 +853,17 @@ namespace ICSharpCode.NRefactory.VB
void WriteIdentifier(string identifier, Role<Identifier> identifierRole = null)
{
WriteSpecialsUpToRole(identifierRole ?? AstNode.Roles.Identifier);
if (IsKeyword(identifier, containerStack.Peek())) {
if (lastWritten == LastWritten.KeywordOrIdentifier)
Space(); // this space is not strictly required, so we call Space()
if (lastWritten == LastWritten.KeywordOrIdentifier)
Space(); // this space is not strictly required, so we call Space()
if (IsKeyword(identifier, containerStack.Peek()))
formatter.WriteToken("[");
} else if (lastWritten == LastWritten.KeywordOrIdentifier) {
formatter.Space(); // this space is strictly required, so we directly call the formatter
}
formatter.WriteIdentifier(identifier);
if (IsKeyword(identifier, containerStack.Peek())) {
if (IsKeyword(identifier, containerStack.Peek()))
formatter.WriteToken("]");
}
lastWritten = LastWritten.KeywordOrIdentifier;
}
@ -1013,7 +1012,7 @@ namespace ICSharpCode.NRefactory.VB @@ -1013,7 +1012,7 @@ namespace ICSharpCode.NRefactory.VB
"GetType", "GetXmlNamespace", "Global", "GoSub", "GoTo", "Handles", "If", "Implements",
"Imports", "In", "Inherits", "Integer", "Interface", "Is", "IsNot", "Let", "Lib", "Like",
"Long", "Loop", "Me", "Mod", "Module", "MustInherit", "MustOverride", "MyBase", "MyClass",
"Namespace", "Narrowing", "New", "Next", "Not", "Nothing", "NotInheritable", "NotOverridable",
"Namespace", "Narrowing", "Next", "Not", "Nothing", "NotInheritable", "NotOverridable",
"Object", "Of", "On", "Operator", "Option", "Optional", "Or", "OrElse", "Overloads",
"Overridable", "Overrides", "ParamArray", "Partial", "Private", "Property", "Protected",
"Public", "RaiseEvent", "ReadOnly", "ReDim", "REM", "RemoveHandler", "Resume", "Return",
@ -1032,6 +1031,11 @@ namespace ICSharpCode.NRefactory.VB @@ -1032,6 +1031,11 @@ namespace ICSharpCode.NRefactory.VB
/// </summary>
public static bool IsKeyword(string identifier, AstNode context)
{
if (identifier == "New") {
if (context.PrevSibling is InstanceExpression)
return false;
return true;
}
if (unconditionalKeywords.Contains(identifier))
return true;
// if (context.Ancestors.Any(a => a is QueryExpression)) {
@ -1109,9 +1113,12 @@ namespace ICSharpCode.NRefactory.VB @@ -1109,9 +1113,12 @@ namespace ICSharpCode.NRefactory.VB
void WriteBlock(BlockStatement body)
{
if (body.IsNull)
if (body.IsNull) {
NewLine();
else
Indent();
NewLine();
Unindent();
} else
VisitBlockStatement(body, null);
}
@ -1236,16 +1243,15 @@ namespace ICSharpCode.NRefactory.VB @@ -1236,16 +1243,15 @@ namespace ICSharpCode.NRefactory.VB
lastWritten = LastWritten.KeywordOrIdentifier;
} else if (val is IFormattable) {
StringBuilder b = new StringBuilder();
// if (primitiveExpression.LiteralFormat == LiteralFormat.HexadecimalNumber) {
// b.Append("0x");
// b.Append(((IFormattable)val).ToString("x", NumberFormatInfo.InvariantInfo));
// } else {
b.Append(((IFormattable)val).ToString(null, NumberFormatInfo.InvariantInfo));
// }
if (val is uint || val is ulong) {
if (val is ushort || val is ulong) {
b.Append("U");
}
if (val is long || val is ulong) {
if (val is short || val is ushort) {
b.Append("S");
} else if (val is uint) {
b.Append("UI");
} else if (val is long || val is ulong) {
b.Append("L");
}
formatter.WriteToken(b.ToString());
@ -1307,10 +1313,7 @@ namespace ICSharpCode.NRefactory.VB @@ -1307,10 +1313,7 @@ namespace ICSharpCode.NRefactory.VB
}
if (accessor.Parameters.Any())
WriteCommaSeparatedListInParenthesis(accessor.Parameters, false);
NewLine();
Indent();
WriteBlock(accessor.Body);
Unindent();
WriteKeyword("End");
if (accessor.Role == PropertyDeclaration.GetterRole) {
@ -1356,10 +1359,7 @@ namespace ICSharpCode.NRefactory.VB @@ -1356,10 +1359,7 @@ namespace ICSharpCode.NRefactory.VB
StartNode(withStatement);
WriteKeyword("With");
withStatement.Expression.AcceptVisitor(this, data);
NewLine();
Indent();
withStatement.Body.AcceptVisitor(this, data);
Unindent();
WriteKeyword("End");
WriteKeyword("With");
return EndNode(withStatement);
@ -1370,10 +1370,7 @@ namespace ICSharpCode.NRefactory.VB @@ -1370,10 +1370,7 @@ namespace ICSharpCode.NRefactory.VB
StartNode(syncLockStatement);
WriteKeyword("SyncLock");
syncLockStatement.Expression.AcceptVisitor(this, data);
NewLine();
Indent();
syncLockStatement.Body.AcceptVisitor(this, data);
Unindent();
WriteKeyword("End");
WriteKeyword("SyncLock");
return EndNode(syncLockStatement);
@ -1383,19 +1380,13 @@ namespace ICSharpCode.NRefactory.VB @@ -1383,19 +1380,13 @@ namespace ICSharpCode.NRefactory.VB
{
StartNode(tryStatement);
WriteKeyword("Try");
NewLine();
Indent();
tryStatement.Body.AcceptVisitor(this, data);
Unindent();
foreach (var clause in tryStatement.CatchBlocks) {
clause.AcceptVisitor(this, data);
}
if (!tryStatement.FinallyBlock.IsNull) {
WriteKeyword("Finally");
NewLine();
Indent();
tryStatement.FinallyBlock.AcceptVisitor(this, data);
Unindent();
}
WriteKeyword("End");
WriteKeyword("Try");
@ -1445,19 +1436,17 @@ namespace ICSharpCode.NRefactory.VB @@ -1445,19 +1436,17 @@ namespace ICSharpCode.NRefactory.VB
ifElseStatement.Condition.AcceptVisitor(this, data);
Space();
WriteKeyword("Then");
NewLine();
Indent();
bool needsEndIf = ifElseStatement.Body is BlockStatement;
ifElseStatement.Body.AcceptVisitor(this, data);
Unindent();
if (!ifElseStatement.ElseBlock.IsNull) {
WriteKeyword("Else");
NewLine();
Indent();
needsEndIf = ifElseStatement.ElseBlock is BlockStatement;
ifElseStatement.ElseBlock.AcceptVisitor(this, data);
Unindent();
}
WriteKeyword("End");
WriteKeyword("If");
if (needsEndIf) {
WriteKeyword("End");
WriteKeyword("If");
}
return EndNode(ifElseStatement);
}
@ -1635,7 +1624,8 @@ namespace ICSharpCode.NRefactory.VB @@ -1635,7 +1624,8 @@ namespace ICSharpCode.NRefactory.VB
WriteKeyword("New");
Space();
arrayCreateExpression.Type.AcceptVisitor(this, data);
WriteCommaSeparatedListInParenthesis(arrayCreateExpression.Arguments, false);
if (arrayCreateExpression.Arguments.Any())
WriteCommaSeparatedListInParenthesis(arrayCreateExpression.Arguments, false);
foreach (var specifier in arrayCreateExpression.AdditionalArraySpecifiers) {
specifier.AcceptVisitor(this, data);
}
@ -1881,10 +1871,7 @@ namespace ICSharpCode.NRefactory.VB @@ -1881,10 +1871,7 @@ namespace ICSharpCode.NRefactory.VB
WriteKeyword("While");
Space();
whileStatement.Condition.AcceptVisitor(this, data);
NewLine();
Indent();
whileStatement.Body.AcceptVisitor(this, data);
Unindent();
WriteKeyword("End");
WriteKeyword("While");
@ -1942,10 +1929,7 @@ namespace ICSharpCode.NRefactory.VB @@ -1942,10 +1929,7 @@ namespace ICSharpCode.NRefactory.VB
Space();
forStatement.StepExpression.AcceptVisitor(this, data);
}
NewLine();
Indent();
forStatement.Body.AcceptVisitor(this, data);
Unindent();
WriteKeyword("Next");
return EndNode(forStatement);
@ -1961,10 +1945,7 @@ namespace ICSharpCode.NRefactory.VB @@ -1961,10 +1945,7 @@ namespace ICSharpCode.NRefactory.VB
Space();
WriteKeyword("In");
forEachStatement.InExpression.AcceptVisitor(this, data);
NewLine();
Indent();
forEachStatement.Body.AcceptVisitor(this, data);
Unindent();
WriteKeyword("Next");
return EndNode(forEachStatement);
@ -2064,10 +2045,7 @@ namespace ICSharpCode.NRefactory.VB @@ -2064,10 +2045,7 @@ namespace ICSharpCode.NRefactory.VB
}
if (!operatorDeclaration.Body.IsNull) {
MarkFoldStart();
NewLine();
Indent();
WriteBlock(operatorDeclaration.Body);
Unindent();
WriteKeyword("End");
WriteKeyword("Operator");
MarkFoldEnd();
@ -2109,10 +2087,7 @@ namespace ICSharpCode.NRefactory.VB @@ -2109,10 +2087,7 @@ namespace ICSharpCode.NRefactory.VB
Space();
WriteCommaSeparatedList(caseStatement.Clauses);
}
NewLine();
Indent();
caseStatement.Body.AcceptVisitor(this, data);
Unindent();
return EndNode(caseStatement);
}
@ -2238,10 +2213,7 @@ namespace ICSharpCode.NRefactory.VB @@ -2238,10 +2213,7 @@ namespace ICSharpCode.NRefactory.VB
WriteKeyword("While");
doLoopStatement.Expression.AcceptVisitor(this, data);
}
NewLine();
Indent();
doLoopStatement.Body.AcceptVisitor(this, data);
Unindent();
WriteKeyword("Loop");
if (doLoopStatement.ConditionType == ConditionType.LoopUntil) {
WriteKeyword("Until");
@ -2261,10 +2233,7 @@ namespace ICSharpCode.NRefactory.VB @@ -2261,10 +2233,7 @@ namespace ICSharpCode.NRefactory.VB
WriteKeyword("Using");
WriteCommaSeparatedList(usingStatement.Resources);
NewLine();
Indent();
usingStatement.Body.AcceptVisitor(this, data);
Unindent();
WriteKeyword("End");
WriteKeyword("Using");
@ -2317,10 +2286,7 @@ namespace ICSharpCode.NRefactory.VB @@ -2317,10 +2286,7 @@ namespace ICSharpCode.NRefactory.VB
else
WriteKeyword("Function");
WriteCommaSeparatedListInParenthesis(multiLineLambdaExpression.Parameters, false);
NewLine();
Indent();
multiLineLambdaExpression.Body.AcceptVisitor(this, data);
Unindent();
WriteKeyword("End");
if (multiLineLambdaExpression.IsSub)
WriteKeyword("Sub");

263
NRefactory.VB/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs

@ -22,6 +22,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -22,6 +22,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors
IType ResolveType(AstType type, TypeDeclaration entity = null);
bool IsMethodGroup(CSharp.Expression expression);
bool HasEvent(Expression expression);
CSharp.ParameterDeclaration[] GetParametersForProperty(CSharp.PropertyDeclaration property);
}
/// <summary>
@ -98,13 +99,24 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -98,13 +99,24 @@ namespace ICSharpCode.NRefactory.VB.Visitors
Type = (AstType)arrayCreateExpression.Type.AcceptVisitor(this, data),
Initializer = (ArrayInitializerExpression)arrayCreateExpression.Initializer.AcceptVisitor(this, data)
};
ConvertNodes(arrayCreateExpression.Arguments, expr.Arguments,
n => new BinaryOperatorExpression(n, BinaryOperatorType.Subtract, new PrimitiveExpression(1)));
ConvertNodes(arrayCreateExpression.Arguments, expr.Arguments, ReduceArrayUpperBoundExpression);
ConvertNodes(arrayCreateExpression.AdditionalArraySpecifiers, expr.AdditionalArraySpecifiers);
return EndNode(arrayCreateExpression, expr);
}
Expression ReduceArrayUpperBoundExpression(Expression expression)
{
if (expression is PrimitiveExpression)
{
var numericLiteral = expression as PrimitiveExpression;
int? upperBound = numericLiteral.Value as int?;
if (upperBound.HasValue)
return new PrimitiveExpression(upperBound.Value - 1);
}
return new BinaryOperatorExpression(expression, BinaryOperatorType.Subtract, new PrimitiveExpression(1));
}
public AstNode VisitArrayInitializerExpression(CSharp.ArrayInitializerExpression arrayInitializerExpression, object data)
{
var expr = new ArrayInitializerExpression();
@ -125,10 +137,10 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -125,10 +137,10 @@ namespace ICSharpCode.NRefactory.VB.Visitors
var right = (Expression)assignmentExpression.Right.AcceptVisitor(this, data);
switch (assignmentExpression.Operator) {
case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Assign:
case CSharp.AssignmentOperatorType.Assign:
op = AssignmentOperatorType.Assign;
break;
case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Add:
case CSharp.AssignmentOperatorType.Add:
if (provider.HasEvent(left)) {
var addHandler = new AddRemoveHandlerStatement { IsAddHandler = true };
addHandler.EventExpression = left;
@ -137,7 +149,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -137,7 +149,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors
}
op = AssignmentOperatorType.Add;
break;
case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Subtract:
case CSharp.AssignmentOperatorType.Subtract:
if (provider.HasEvent(left)) {
var addHandler = new AddRemoveHandlerStatement { IsAddHandler = false };
addHandler.EventExpression = left;
@ -146,31 +158,31 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -146,31 +158,31 @@ namespace ICSharpCode.NRefactory.VB.Visitors
}
op = AssignmentOperatorType.Subtract;
break;
case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Multiply:
case CSharp.AssignmentOperatorType.Multiply:
op = AssignmentOperatorType.Multiply;
break;
case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Divide:
case CSharp.AssignmentOperatorType.Divide:
op = AssignmentOperatorType.Divide;
break;
case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Modulus:
case CSharp.AssignmentOperatorType.Modulus:
op = AssignmentOperatorType.Assign;
right = new BinaryOperatorExpression((Expression)left.Clone(), BinaryOperatorType.Modulus, right);
break;
case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.ShiftLeft:
case CSharp.AssignmentOperatorType.ShiftLeft:
op = AssignmentOperatorType.ShiftLeft;
break;
case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.ShiftRight:
case CSharp.AssignmentOperatorType.ShiftRight:
op = AssignmentOperatorType.ShiftRight;
break;
case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.BitwiseAnd:
case CSharp.AssignmentOperatorType.BitwiseAnd:
op = AssignmentOperatorType.Assign;
right = new BinaryOperatorExpression((Expression)left.Clone(), BinaryOperatorType.BitwiseAnd, right);
break;
case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.BitwiseOr:
case CSharp.AssignmentOperatorType.BitwiseOr:
op = AssignmentOperatorType.Assign;
right = new BinaryOperatorExpression((Expression)left.Clone(), BinaryOperatorType.BitwiseOr, right);
break;
case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.ExclusiveOr:
case CSharp.AssignmentOperatorType.ExclusiveOr:
op = AssignmentOperatorType.Assign;
right = new BinaryOperatorExpression((Expression)left.Clone(), BinaryOperatorType.ExclusiveOr, right);
break;
@ -196,68 +208,68 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -196,68 +208,68 @@ namespace ICSharpCode.NRefactory.VB.Visitors
var right = (Expression)binaryOperatorExpression.Right.AcceptVisitor(this, data);
switch (binaryOperatorExpression.Operator) {
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.BitwiseAnd:
case CSharp.BinaryOperatorType.BitwiseAnd:
op = BinaryOperatorType.BitwiseAnd;
break;
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.BitwiseOr:
case CSharp.BinaryOperatorType.BitwiseOr:
op = BinaryOperatorType.BitwiseOr;
break;
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.ConditionalAnd:
case CSharp.BinaryOperatorType.ConditionalAnd:
op = BinaryOperatorType.LogicalAnd;
break;
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.ConditionalOr:
case CSharp.BinaryOperatorType.ConditionalOr:
op = BinaryOperatorType.LogicalOr;
break;
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.ExclusiveOr:
case CSharp.BinaryOperatorType.ExclusiveOr:
op = BinaryOperatorType.ExclusiveOr;
break;
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.GreaterThan:
case CSharp.BinaryOperatorType.GreaterThan:
op = BinaryOperatorType.GreaterThan;
break;
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.GreaterThanOrEqual:
case CSharp.BinaryOperatorType.GreaterThanOrEqual:
op = BinaryOperatorType.GreaterThanOrEqual;
break;
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.Equality:
case CSharp.BinaryOperatorType.Equality:
if (IsReferentialEquality(binaryOperatorExpression))
op = BinaryOperatorType.ReferenceEquality;
else
op = BinaryOperatorType.Equality;
break;
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.InEquality:
case CSharp.BinaryOperatorType.InEquality:
if (IsReferentialEquality(binaryOperatorExpression))
op = BinaryOperatorType.ReferenceInequality;
else
op = BinaryOperatorType.InEquality;
break;
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.LessThan:
case CSharp.BinaryOperatorType.LessThan:
op = BinaryOperatorType.LessThan;
break;
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.LessThanOrEqual:
case CSharp.BinaryOperatorType.LessThanOrEqual:
op = BinaryOperatorType.LessThanOrEqual;
break;
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.Add:
case CSharp.BinaryOperatorType.Add:
// TODO might be string concatenation
op = BinaryOperatorType.Add;
break;
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.Subtract:
case CSharp.BinaryOperatorType.Subtract:
op = BinaryOperatorType.Subtract;
break;
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.Multiply:
case CSharp.BinaryOperatorType.Multiply:
op = BinaryOperatorType.Multiply;
break;
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.Divide:
case CSharp.BinaryOperatorType.Divide:
op = BinaryOperatorType.Divide;
break;
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.Modulus:
case CSharp.BinaryOperatorType.Modulus:
op = BinaryOperatorType.Modulus;
break;
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.ShiftLeft:
case CSharp.BinaryOperatorType.ShiftLeft:
op = BinaryOperatorType.ShiftLeft;
break;
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.ShiftRight:
case CSharp.BinaryOperatorType.ShiftRight:
op = BinaryOperatorType.ShiftRight;
break;
case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.NullCoalescing:
case CSharp.BinaryOperatorType.NullCoalescing:
var nullCoalescing = new ConditionalExpression {
ConditionExpression = left,
FalseExpression = right
@ -502,8 +514,10 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -502,8 +514,10 @@ namespace ICSharpCode.NRefactory.VB.Visitors
{
Expression expr;
if (!string.IsNullOrEmpty(primitiveExpression.Value as string) || primitiveExpression.Value is char)
if (!string.IsNullOrEmpty(primitiveExpression.Value as string))
expr = ConvertToConcat(primitiveExpression.Value.ToString());
else if (primitiveExpression.Value is char)
expr = ConvertToSpecialChar((char)primitiveExpression.Value);
else
expr = new PrimitiveExpression(primitiveExpression.Value);
@ -519,24 +533,15 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -519,24 +533,15 @@ namespace ICSharpCode.NRefactory.VB.Visitors
string part;
switch (literal[i]) {
case '\0':
part = literal.Substring(start, i - start);
if (!string.IsNullOrEmpty(part))
parts.Push(new PrimitiveExpression(part));
parts.Push(new IdentifierExpression("vbNullChar"));
start = i + 1;
break;
case '\b':
part = literal.Substring(start, i - start);
if (!string.IsNullOrEmpty(part))
parts.Push(new PrimitiveExpression(part));
parts.Push(new IdentifierExpression("vbBack"));
start = i + 1;
break;
case '\f':
case '\n':
case '\t':
case '\v':
part = literal.Substring(start, i - start);
if (!string.IsNullOrEmpty(part))
parts.Push(new PrimitiveExpression(part));
parts.Push(new IdentifierExpression("vbFormFeed"));
parts.Push(ConvertToSpecialChar(literal[i]));
start = i + 1;
break;
case '\r':
@ -550,27 +555,6 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -550,27 +555,6 @@ namespace ICSharpCode.NRefactory.VB.Visitors
parts.Push(new IdentifierExpression("vbCr"));
start = i + 1;
break;
case '\n':
part = literal.Substring(start, i - start);
if (!string.IsNullOrEmpty(part))
parts.Push(new PrimitiveExpression(part));
parts.Push(new IdentifierExpression("vbLf"));
start = i + 1;
break;
case '\t':
part = literal.Substring(start, i - start);
if (!string.IsNullOrEmpty(part))
parts.Push(new PrimitiveExpression(part));
parts.Push(new IdentifierExpression("vbTab"));
start = i + 1;
break;
case '\v':
part = literal.Substring(start, i - start);
if (!string.IsNullOrEmpty(part))
parts.Push(new PrimitiveExpression(part));
parts.Push(new IdentifierExpression("vbVerticalTab"));
start = i + 1;
break;
default:
if ((int)literal[i] > 255) {
part = literal.Substring(start, i - start);
@ -598,6 +582,30 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -598,6 +582,30 @@ namespace ICSharpCode.NRefactory.VB.Visitors
return current;
}
Expression ConvertToSpecialChar(char ch)
{
switch (ch) {
case '\0':
return new IdentifierExpression("vbNullChar");
case '\b':
return new IdentifierExpression("vbBack");
case '\f':
return new IdentifierExpression("vbFormFeed");
case '\r':
return new IdentifierExpression("vbCr");
case '\n':
return new IdentifierExpression("vbLf");
case '\t':
return new IdentifierExpression("vbTab");
case '\v':
return new IdentifierExpression("vbVerticalTab");
default:
if (ch > 255)
return new InvocationExpression(new IdentifierExpression("ChrW"), new PrimitiveExpression((int)ch));
return new PrimitiveExpression(ch);
}
}
public AstNode VisitSizeOfExpression(CSharp.SizeOfExpression sizeOfExpression, object data)
{
return EndNode(
@ -645,57 +653,57 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -645,57 +653,57 @@ namespace ICSharpCode.NRefactory.VB.Visitors
Expression expr;
switch (unaryOperatorExpression.Operator) {
case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Not:
case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.BitNot:
case CSharp.UnaryOperatorType.Not:
case CSharp.UnaryOperatorType.BitNot:
expr = new UnaryOperatorExpression() {
Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data),
Operator = UnaryOperatorType.Not
};
break;
case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Minus:
case CSharp.UnaryOperatorType.Minus:
expr = new UnaryOperatorExpression() {
Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data),
Operator = UnaryOperatorType.Minus
};
break;
case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Plus:
case CSharp.UnaryOperatorType.Plus:
expr = new UnaryOperatorExpression() {
Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data),
Operator = UnaryOperatorType.Plus
};
break;
case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Increment:
case CSharp.UnaryOperatorType.Increment:
expr = new InvocationExpression();
((InvocationExpression)expr).Target = new IdentifierExpression() { Identifier = "__Increment" };
((InvocationExpression)expr).Arguments.Add((Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data));
break;
case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.PostIncrement:
case CSharp.UnaryOperatorType.PostIncrement:
expr = new InvocationExpression();
((InvocationExpression)expr).Target = new IdentifierExpression() { Identifier = "__PostIncrement" };
((InvocationExpression)expr).Arguments.Add((Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data));
break;
case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Decrement:
case CSharp.UnaryOperatorType.Decrement:
expr = new InvocationExpression();
((InvocationExpression)expr).Target = new IdentifierExpression() { Identifier = "__Decrement" };
((InvocationExpression)expr).Arguments.Add((Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data));
break;
case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.PostDecrement:
case CSharp.UnaryOperatorType.PostDecrement:
expr = new InvocationExpression();
((InvocationExpression)expr).Target = new IdentifierExpression() { Identifier = "__PostDecrement" };
((InvocationExpression)expr).Arguments.Add((Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data));
break;
case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.AddressOf:
case CSharp.UnaryOperatorType.AddressOf:
expr = new UnaryOperatorExpression() {
Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data),
Operator = UnaryOperatorType.AddressOf
};
break;
case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Dereference:
case CSharp.UnaryOperatorType.Dereference:
expr = new InvocationExpression();
((InvocationExpression)expr).Target = new IdentifierExpression() { Identifier = "__Dereference" };
((InvocationExpression)expr).Arguments.Add((Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data));
break;
case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Await:
case CSharp.UnaryOperatorType.Await:
expr = new UnaryOperatorExpression() {
Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data),
Operator = UnaryOperatorType.Await
@ -840,7 +848,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -840,7 +848,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors
foreach (string id in namespaceDeclaration.Identifiers) {
newNamespace.Identifiers.Add(new Identifier(id, TextLocation.Empty));
}
ConvertNodes(namespaceDeclaration.Members, newNamespace.Members);
ConvertMembers(namespaceDeclaration, newNamespace, CSharp.NamespaceDeclaration.MemberRole, NamespaceDeclaration.MemberRole);
return EndNode(namespaceDeclaration, newNamespace);
}
@ -864,7 +872,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -864,7 +872,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors
type.Name = new Identifier(typeDeclaration.Name, TextLocation.Empty);
ConvertNodes(typeDeclaration.Members, type.Members);
ConvertMembers(typeDeclaration, type, CSharp.Roles.TypeMemberRole, EnumDeclaration.MemberRole);
return EndNode(typeDeclaration, type);
} else {
@ -904,6 +912,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -904,6 +912,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors
ConvertNodes(typeDeclaration.Attributes, type.Attributes);
ConvertNodes(typeDeclaration.ModifierTokens, type.ModifierTokens);
ConvertNodes(typeDeclaration.TypeParameters, type.TypeParameters);
if (typeDeclaration.BaseTypes.Any()) {
var first = typeDeclaration.BaseTypes.First();
@ -918,7 +927,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -918,7 +927,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors
type.Name = typeDeclaration.Name;
types.Push(type);
ConvertNodes(typeDeclaration.Members, type.Members);
ConvertMembers(typeDeclaration, type, CSharp.Roles.TypeMemberRole, TypeDeclaration.MemberRole);
types.Pop();
return EndNode(typeDeclaration, type);
@ -1473,15 +1482,16 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -1473,15 +1482,16 @@ namespace ICSharpCode.NRefactory.VB.Visitors
var result = new EventDeclaration();
ConvertNodes(eventDeclaration.Attributes, result.Attributes);
if (types.Any() && types.Peek().ClassType == ClassType.Module)
eventDeclaration.Modifiers &= ~CSharp.Modifiers.Static;
if (types.Any()) {
if (types.Peek().ClassType == ClassType.Module)
eventDeclaration.Modifiers &= ~CSharp.Modifiers.Static;
types.Peek().Members.Add(result);
}
result.Modifiers = ConvertModifiers(eventDeclaration.Modifiers, eventDeclaration);
result.Name = evt.Name;
result.ReturnType = (AstType)eventDeclaration.ReturnType.AcceptVisitor(this, data);
// CreateImplementsClausesForEvent(result);
types.Peek().Members.Add(result);
}
members.Pop();
@ -1759,76 +1769,76 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -1759,76 +1769,76 @@ namespace ICSharpCode.NRefactory.VB.Visitors
ConvertNodes(operatorDeclaration.Attributes.Where(section => section.AttributeTarget != "return"), op.Attributes);
ConvertNodes(operatorDeclaration.ModifierTokens, op.ModifierTokens);
switch (operatorDeclaration.OperatorType) {
case ICSharpCode.NRefactory.CSharp.OperatorType.LogicalNot:
case ICSharpCode.NRefactory.CSharp.OperatorType.OnesComplement:
case CSharp.OperatorType.LogicalNot:
case CSharp.OperatorType.OnesComplement:
op.Operator = OverloadableOperatorType.Not;
break;
case ICSharpCode.NRefactory.CSharp.OperatorType.True:
case CSharp.OperatorType.True:
op.Operator = OverloadableOperatorType.IsTrue;
break;
case ICSharpCode.NRefactory.CSharp.OperatorType.False:
case CSharp.OperatorType.False:
op.Operator = OverloadableOperatorType.IsFalse;
break;
case ICSharpCode.NRefactory.CSharp.OperatorType.Implicit:
case CSharp.OperatorType.Implicit:
op.Modifiers |= Modifiers.Widening;
op.Operator = OverloadableOperatorType.CType;
break;
case ICSharpCode.NRefactory.CSharp.OperatorType.Explicit:
case CSharp.OperatorType.Explicit:
op.Modifiers |= Modifiers.Narrowing;
op.Operator = OverloadableOperatorType.CType;
break;
case ICSharpCode.NRefactory.CSharp.OperatorType.Addition:
case CSharp.OperatorType.Addition:
op.Operator = OverloadableOperatorType.Add;
break;
case ICSharpCode.NRefactory.CSharp.OperatorType.Subtraction:
case CSharp.OperatorType.Subtraction:
op.Operator = OverloadableOperatorType.Subtract;
break;
case ICSharpCode.NRefactory.CSharp.OperatorType.UnaryPlus:
case CSharp.OperatorType.UnaryPlus:
op.Operator = OverloadableOperatorType.UnaryPlus;
break;
case ICSharpCode.NRefactory.CSharp.OperatorType.UnaryNegation:
case CSharp.OperatorType.UnaryNegation:
op.Operator = OverloadableOperatorType.UnaryMinus;
break;
case ICSharpCode.NRefactory.CSharp.OperatorType.Multiply:
case CSharp.OperatorType.Multiply:
op.Operator = OverloadableOperatorType.Multiply;
break;
case ICSharpCode.NRefactory.CSharp.OperatorType.Division:
case CSharp.OperatorType.Division:
op.Operator = OverloadableOperatorType.Divide;
break;
case ICSharpCode.NRefactory.CSharp.OperatorType.Modulus:
case CSharp.OperatorType.Modulus:
op.Operator = OverloadableOperatorType.Modulus;
break;
case ICSharpCode.NRefactory.CSharp.OperatorType.BitwiseAnd:
case CSharp.OperatorType.BitwiseAnd:
op.Operator = OverloadableOperatorType.BitwiseAnd;
break;
case ICSharpCode.NRefactory.CSharp.OperatorType.BitwiseOr:
case CSharp.OperatorType.BitwiseOr:
op.Operator = OverloadableOperatorType.BitwiseOr;
break;
case ICSharpCode.NRefactory.CSharp.OperatorType.ExclusiveOr:
case CSharp.OperatorType.ExclusiveOr:
op.Operator = OverloadableOperatorType.ExclusiveOr;
break;
case ICSharpCode.NRefactory.CSharp.OperatorType.LeftShift:
case CSharp.OperatorType.LeftShift:
op.Operator = OverloadableOperatorType.ShiftLeft;
break;
case ICSharpCode.NRefactory.CSharp.OperatorType.RightShift:
case CSharp.OperatorType.RightShift:
op.Operator = OverloadableOperatorType.ShiftRight;
break;
case ICSharpCode.NRefactory.CSharp.OperatorType.Equality:
case CSharp.OperatorType.Equality:
op.Operator = OverloadableOperatorType.Equality;
break;
case ICSharpCode.NRefactory.CSharp.OperatorType.Inequality:
case CSharp.OperatorType.Inequality:
op.Operator = OverloadableOperatorType.InEquality;
break;
case ICSharpCode.NRefactory.CSharp.OperatorType.GreaterThan:
case CSharp.OperatorType.GreaterThan:
op.Operator = OverloadableOperatorType.GreaterThan;
break;
case ICSharpCode.NRefactory.CSharp.OperatorType.LessThan:
case CSharp.OperatorType.LessThan:
op.Operator = OverloadableOperatorType.LessThan;
break;
case ICSharpCode.NRefactory.CSharp.OperatorType.GreaterThanOrEqual:
case CSharp.OperatorType.GreaterThanOrEqual:
op.Operator = OverloadableOperatorType.GreaterThanOrEqual;
break;
case ICSharpCode.NRefactory.CSharp.OperatorType.LessThanOrEqual:
case CSharp.OperatorType.LessThanOrEqual:
op.Operator = OverloadableOperatorType.LessThanOrEqual;
break;
default:
@ -1852,7 +1862,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -1852,7 +1862,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors
ConvertNodes(parameterDeclaration.Attributes, param.Attributes);
param.Modifiers = ConvertParamModifiers(parameterDeclaration.ParameterModifier);
if ((parameterDeclaration.ParameterModifier & ICSharpCode.NRefactory.CSharp.ParameterModifier.Out) == ICSharpCode.NRefactory.CSharp.ParameterModifier.Out) {
if ((parameterDeclaration.ParameterModifier & CSharp.ParameterModifier.Out) == CSharp.ParameterModifier.Out) {
AttributeBlock block = new AttributeBlock();
block.Attributes.Add(new Ast.Attribute() { Type = new SimpleType("Out") });
param.Attributes.Add(block);
@ -1869,13 +1879,13 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -1869,13 +1879,13 @@ namespace ICSharpCode.NRefactory.VB.Visitors
Modifiers ConvertParamModifiers(CSharp.ParameterModifier mods)
{
switch (mods) {
case ICSharpCode.NRefactory.CSharp.ParameterModifier.None:
case ICSharpCode.NRefactory.CSharp.ParameterModifier.This:
case CSharp.ParameterModifier.None:
case CSharp.ParameterModifier.This:
return Modifiers.None;
case ICSharpCode.NRefactory.CSharp.ParameterModifier.Ref:
case ICSharpCode.NRefactory.CSharp.ParameterModifier.Out:
case CSharp.ParameterModifier.Ref:
case CSharp.ParameterModifier.Out:
return Modifiers.ByRef;
case ICSharpCode.NRefactory.CSharp.ParameterModifier.Params:
case CSharp.ParameterModifier.Params:
return Modifiers.ParamArray;
default:
throw new Exception("Invalid value for ParameterModifier");
@ -1914,6 +1924,8 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -1914,6 +1924,8 @@ namespace ICSharpCode.NRefactory.VB.Visitors
decl.Modifiers |= Modifiers.Iterator;
}
ConvertNodes(provider.GetParametersForProperty(propertyDeclaration), decl.Parameters);
return EndNode(propertyDeclaration, decl);
}
@ -1923,7 +1935,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -1923,7 +1935,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors
// look for type in parent
decl.Type = (AstType)variableInitializer.Parent
.GetChildByRole(ICSharpCode.NRefactory.CSharp.Roles.Type)
.GetChildByRole(CSharp.Roles.Type)
.AcceptVisitor(this, data);
decl.Identifiers.Add(new VariableIdentifier() { Name = variableInitializer.Name });
decl.Initializer = (Expression)variableInitializer.Initializer.AcceptVisitor(this, data);
@ -2091,7 +2103,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -2091,7 +2103,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors
};
var constraint = typeParameterDeclaration.Parent
.GetChildrenByRole(ICSharpCode.NRefactory.CSharp.Roles.Constraint)
.GetChildrenByRole(CSharp.Roles.Constraint)
.SingleOrDefault(c => c.TypeParameter.Identifier == typeParameterDeclaration.Name);
if (constraint != null)
@ -2222,6 +2234,23 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -2222,6 +2234,23 @@ namespace ICSharpCode.NRefactory.VB.Visitors
}
}
void ConvertMembers<T, S, M>(CSharp.AstNode parent, T result, Role<S> sourceRole, Role<M> targetRole) where T : VB.AstNode where S : CSharp.AstNode where M : VB.AstNode
{
foreach (var node in parent.Children) {
if (node.Role == CSharp.Roles.Comment) {
var n = (Comment)node.AcceptVisitor(this, null);
if (n != null)
result.AddChild(n, AstNode.Roles.Comment);
}
if (node.Role == sourceRole) {
var n = (M)node.AcceptVisitor(this, null);
if (n != null)
result.AddChild(n, targetRole);
}
}
}
T EndNode<T>(CSharp.AstNode node, T result) where T : VB.AstNode
{
if (result != null) {

28
README.md

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
# ILSpy
[![Join the chat at https://gitter.im/icsharpcode/ILSpy](https://badges.gitter.im/icsharpcode/ILSpy.svg)](https://gitter.im/icsharpcode/ILSpy?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[@ilspy](https://twitter.com/ilspy) | [ilspy.net](http://ilspy.net/)
Downloads
-------
Xcopy-deployable binaries via [ilspy.net](http://ilspy.net/)
Visual Studio extension via [VS Gallery](https://visualstudiogallery.msdn.microsoft.com/8ef1d688-f80c-4380-8004-2ec7f814e7de)
Decompiler NuGet package via [NuGet](https://www.nuget.org/packages/ICSharpCode.Decompiler/)
Get a recent nightly build from [here](http://build.sharpdevelop.net/BuildArtefacts/#ILSpyMaster)
License
-------
ILSpy is distributed under the MIT License.
Included open-source libraries:
* Mono.Cecil: MIT License (thanks to Jb Evain)
* AvalonEdit: LGPL
* SharpTreeView: LGPL
* ICSharpCode.Decompiler: MIT License (developed as part of ILSpy)
* Ricciolo.StylesExplorer: MS-PL (part of ILSpy.BamlDecompiler.Plugin)

2
README.txt

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
ILSpy is the open-source .NET assembly browser and decompiler.
Website: http://www.ilspy.net/
Copyright 2011-2014 AlphaSierraPapa for the SharpDevelop team
Copyright 2011-2016 AlphaSierraPapa for the SharpDevelop team
License: ILSpy is distributed under the MIT License.
Included open-source libraries:

22
Rebracer.xml

@ -10,13 +10,13 @@ @@ -10,13 +10,13 @@
<ToolsOptionsCategory name="Environment">
<ToolsOptionsSubCategory name="TaskList">
<PropertyValue name="CommentTokens" ArrayType="VT_VARIANT" ArrayElementCount="4">
<PropertyValue name="0">TODO:2</PropertyValue>
<PropertyValue name="1">HACK:2</PropertyValue>
<PropertyValue name="0">HACK:2</PropertyValue>
<PropertyValue name="1">TODO:2</PropertyValue>
<PropertyValue name="2">UNDONE:2</PropertyValue>
<PropertyValue name="3">UnresolvedMergeConflict:3</PropertyValue>
</PropertyValue>
<PropertyValue name="ConfirmTaskDeletion">true</PropertyValue>
<PropertyValue name="DontShowFilePaths">true</PropertyValue>
<PropertyValue name="ConfirmTaskDeletion">false</PropertyValue>
<PropertyValue name="DontShowFilePaths">false</PropertyValue>
<PropertyValue name="WarnOnAddingHiddenItem">false</PropertyValue>
</ToolsOptionsSubCategory>
</ToolsOptionsCategory>
@ -24,9 +24,14 @@ @@ -24,9 +24,14 @@
<ToolsOptionsSubCategory name="CSharp-Specific">
<PropertyValue name="AutoComment">1</PropertyValue>
<PropertyValue name="BringUpOnIdentifier">1</PropertyValue>
<PropertyValue name="ClosedFileDiagnostics">1</PropertyValue>
<PropertyValue name="CodeDefinitionWindow_DocumentationComment_IndentBase">1</PropertyValue>
<PropertyValue name="CodeDefinitionWindow_DocumentationComment_IndentOffset">2</PropertyValue>
<PropertyValue name="CodeDefinitionWindow_DocumentationComment_WrapLength">80</PropertyValue>
<PropertyValue name="DisplayLineSeparators">0</PropertyValue>
<PropertyValue name="EnableHighlightRelatedKeywords">1</PropertyValue>
<PropertyValue name="ExtractMethod_AllowMovingDeclaration">0</PropertyValue>
<PropertyValue name="ExtractMethod_DoNotPutOutOrRefOnStruct">1</PropertyValue>
<PropertyValue name="Formatting_TriggerOnBlockCompletion">1</PropertyValue>
<PropertyValue name="Formatting_TriggerOnPaste">1</PropertyValue>
<PropertyValue name="Formatting_TriggerOnStatementCompletion">1</PropertyValue>
@ -34,11 +39,12 @@ @@ -34,11 +39,12 @@
<PropertyValue name="Indent_BlockContents">1</PropertyValue>
<PropertyValue name="Indent_Braces">0</PropertyValue>
<PropertyValue name="Indent_CaseContents">1</PropertyValue>
<PropertyValue name="Indent_CaseLabels">0</PropertyValue>
<PropertyValue name="Indent_CaseLabels">1</PropertyValue>
<PropertyValue name="Indent_FlushLabelsLeft">0</PropertyValue>
<PropertyValue name="Indent_UnindentLabels">2</PropertyValue>
<PropertyValue name="InsertNewlineOnEnterWithWholeWord">0</PropertyValue>
<PropertyValue name="NewLines_AnonymousTypeInitializer_EachMember">1</PropertyValue>
<PropertyValue name="NewLines_Braces_Accessor">0</PropertyValue>
<PropertyValue name="NewLines_Braces_AnonymousMethod">0</PropertyValue>
<PropertyValue name="NewLines_Braces_AnonymousTypeInitializer">0</PropertyValue>
<PropertyValue name="NewLines_Braces_ArrayInitializer">0</PropertyValue>
@ -47,6 +53,7 @@ @@ -47,6 +53,7 @@
<PropertyValue name="NewLines_Braces_LambdaExpressionBody">0</PropertyValue>
<PropertyValue name="NewLines_Braces_Method">1</PropertyValue>
<PropertyValue name="NewLines_Braces_ObjectInitializer">1</PropertyValue>
<PropertyValue name="NewLines_Braces_Property">1</PropertyValue>
<PropertyValue name="NewLines_Braces_Type">1</PropertyValue>
<PropertyValue name="NewLines_Keywords_Catch">0</PropertyValue>
<PropertyValue name="NewLines_Keywords_Else">0</PropertyValue>
@ -54,6 +61,7 @@ @@ -54,6 +61,7 @@
<PropertyValue name="NewLines_ObjectInitializer_EachMember">1</PropertyValue>
<PropertyValue name="NewLines_QueryExpression_EachClause">1</PropertyValue>
<PropertyValue name="RemoveUnusedUsings">1</PropertyValue>
<PropertyValue name="RenameTrackingPreview">1</PropertyValue>
<PropertyValue name="ShowKeywords">1</PropertyValue>
<PropertyValue name="ShowSnippets">1</PropertyValue>
<PropertyValue name="SortUsings">1</PropertyValue>
@ -84,6 +92,10 @@ @@ -84,6 +92,10 @@
<PropertyValue name="Space_WithinMethodDeclarationParentheses">0</PropertyValue>
<PropertyValue name="Space_WithinOtherParentheses">0</PropertyValue>
<PropertyValue name="Space_WithinSquares">0</PropertyValue>
<PropertyValue name="Style_PreferIntrinsicPredefinedTypeKeywordInDeclaration">1</PropertyValue>
<PropertyValue name="Style_PreferIntrinsicPredefinedTypeKeywordInMemberAccess">1</PropertyValue>
<PropertyValue name="Style_QualifyMemberAccessWithThisOrMe">0</PropertyValue>
<PropertyValue name="Style_UseVarWhenDeclaringLocals">1</PropertyValue>
<PropertyValue name="WarnOnBuildErrors">1</PropertyValue>
<PropertyValue name="WarnWhenMembersCauseCompilerGeneratedReferences">1</PropertyValue>
<PropertyValue name="Wrapping_IgnoreSpacesAroundBinaryOperators">0</PropertyValue>

21
SharpTreeView/SharpTreeView.cs

@ -122,6 +122,27 @@ namespace ICSharpCode.TreeView @@ -122,6 +122,27 @@ namespace ICSharpCode.TreeView
TreeFlattener flattener;
bool updatesLocked;
public IDisposable LockUpdates()
{
return new UpdateLock(this);
}
class UpdateLock : IDisposable
{
SharpTreeView instance;
public UpdateLock(SharpTreeView instance)
{
this.instance = instance;
this.instance.updatesLocked = true;
}
public void Dispose()
{
this.instance.updatesLocked = false;
}
}
void Reload()
{
if (flattener != null) {

12
TestPlugin/TestPlugin.csproj

@ -83,27 +83,27 @@ @@ -83,27 +83,27 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.csproj">
<Project>{984CC812-9470-4A13-AFF9-CC44068D666C}</Project>
<Project>{984cc812-9470-4a13-aff9-cc44068d666c}</Project>
<Name>ICSharpCode.Decompiler</Name>
</ProjectReference>
<ProjectReference Include="..\ILSpy\ILSpy.csproj">
<Project>{1E85EFF9-E370-4683-83E4-8A3D063FF791}</Project>
<Project>{1e85eff9-e370-4683-83e4-8a3d063ff791}</Project>
<Name>ILSpy</Name>
</ProjectReference>
<ProjectReference Include="..\cecil\Mono.Cecil.csproj">
<Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
<Project>{d68133bd-1e63-496e-9ede-4fbdbf77b486}</Project>
<Name>Mono.Cecil</Name>
</ProjectReference>
<ProjectReference Include="..\NRefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj">
<Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project>
<Project>{53dca265-3c3c-42f9-b647-f72ba678122b}</Project>
<Name>ICSharpCode.NRefactory.CSharp</Name>
</ProjectReference>
<ProjectReference Include="..\NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
<Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project>
<Project>{3b2a5653-ec97-4001-bb9b-d90f1af2c371}</Project>
<Name>ICSharpCode.NRefactory</Name>
</ProjectReference>
<ProjectReference Include="..\SharpTreeView\ICSharpCode.TreeView.csproj">
<Project>{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}</Project>
<Project>{dde2a481-8271-4eac-a330-8fa6a38d13d1}</Project>
<Name>ICSharpCode.TreeView</Name>
</ProjectReference>
</ItemGroup>

2
appveyor.yml

@ -10,4 +10,4 @@ build: @@ -10,4 +10,4 @@ build:
parallel: true
verbosity: minimal
after_test:
- python ICSharpCode.AvalonEdit.Tests\tidy.py
- python BuildTools\tidy.py

2
debugbuild.bat

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
@if not exist "AvalonEdit\ICSharpCode.AvalonEdit.sln" (
git submodule update --init || exit /b 1
)
%windir%\microsoft.net\framework\v4.0.30319\msbuild /m ILSpy.sln /p:Configuration=Debug "/p:Platform=Any CPU"
"%ProgramFiles(x86)%\MSBuild\14.0\Bin\msbuild.exe" /m ILSpy.sln /p:Configuration=Debug "/p:Platform=Any CPU"
@IF %ERRORLEVEL% NEQ 0 GOTO err
@exit /B 0
:err

2
releasebuild.bat

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
@if not exist "AvalonEdit\ICSharpCode.AvalonEdit.sln" (
git submodule update --init || exit /b 1
)
%windir%\microsoft.net\framework\v4.0.30319\msbuild /m ILSpy.sln /p:Configuration=Release "/p:Platform=Any CPU"
"%ProgramFiles(x86)%\MSBuild\14.0\Bin\msbuild.exe" /m ILSpy.sln /p:Configuration=Release "/p:Platform=Any CPU"
@IF %ERRORLEVEL% NEQ 0 GOTO err
@exit /B 0
:err

Loading…
Cancel
Save