diff --git a/BuildTools/Automated.proj b/BuildTools/Automated.proj
index 3cce65247..d0b3a5c2f 100644
--- a/BuildTools/Automated.proj
+++ b/BuildTools/Automated.proj
@@ -9,6 +9,7 @@
$(MSBuildProjectDirectory)\..
$(ProjectDir)\ILSpy\bin\Release
+ $(ProjectDir)\ILSpy.AddIn\bin\Release
$(ProjectDir)\BuildTools\MSBuildCommunityTasks
ILSpy_
@@ -17,7 +18,7 @@
properties available for the projects inside the solution
(but this works using the command line) -->
- "$(MSBuildBinPath)\..\v4.0.30319\msbuild.exe"
+ "$(MSBuildBinPath)\msbuild.exe"
/p:Configuration=Release "/p:Platform=Any CPU"
$(BuildProperties) "/p:BranchName=$(BranchName)"
$(BuildProperties) $(AdditionalBuildProperties)
@@ -92,6 +93,8 @@
ZipLevel="9"
WorkingDirectory="$(ILSpyBin)"
ZipFileName="$(ArtefactsOutputDir)\$(ArtefactPrefix)$(BuildNumber)_Binaries.zip"/>
+
diff --git a/BuildTools/buildAndCreatePackage.bat b/BuildTools/buildAndCreatePackage.bat
index 3624a6f0c..e5974726b 100644
--- a/BuildTools/buildAndCreatePackage.bat
+++ b/BuildTools/buildAndCreatePackage.bat
@@ -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
diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs
index aa97dc9bf..8dbf82cd3 100644
--- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs
+++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs
@@ -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 {
diff --git a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
index b5b7d57ff..a0bb65095 100644
--- a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
+++ b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
@@ -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);
}
diff --git a/ICSharpCode.Decompiler/Ast/DecompilerContext.cs b/ICSharpCode.Decompiler/Ast/DecompilerContext.cs
index 624b1b33f..b8cc2e149 100644
--- a/ICSharpCode.Decompiler/Ast/DecompilerContext.cs
+++ b/ICSharpCode.Decompiler/Ast/DecompilerContext.cs
@@ -34,26 +34,12 @@ namespace ICSharpCode.Decompiler
public MethodDefinition CurrentMethod;
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 resolveContexts = new List();
-// 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);
}
///
diff --git a/ICSharpCode.Decompiler/Ast/NameVariables.cs b/ICSharpCode.Decompiler/Ast/NameVariables.cs
index 3da808cbe..3dc30e2dc 100644
--- a/ICSharpCode.Decompiler/Ast/NameVariables.cs
+++ b/ICSharpCode.Decompiler/Ast/NameVariables.cs
@@ -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)
diff --git a/ICSharpCode.Decompiler/Ast/TextTokenWriter.cs b/ICSharpCode.Decompiler/Ast/TextTokenWriter.cs
index 2cfff7d96..d7e8fcfb9 100644
--- a/ICSharpCode.Decompiler/Ast/TextTokenWriter.cs
+++ b/ICSharpCode.Decompiler/Ast/TextTokenWriter.cs
@@ -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);
}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs b/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
index 0741466f9..d76e029a7 100644
--- a/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
+++ b/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
@@ -194,7 +194,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
ame.Body = body;
replacement = ame;
}
- var expectedType = objectCreateExpression.Annotation().ExpectedType.Resolve();
+ var expectedType = objectCreateExpression.Annotation()?.ExpectedType?.Resolve();
if (expectedType != null && !expectedType.IsDelegate()) {
var simplifiedDelegateCreation = (ObjectCreateExpression)objectCreateExpression.Clone();
simplifiedDelegateCreation.Arguments.Clear();
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs b/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs
index bff2cc6b9..d38116f11 100644
--- a/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs
+++ b/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs
@@ -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
};
}
- 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
}
}.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)
@@ -213,9 +243,20 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
// Validate that the variable is not used after the using statement:
if (!IsVariableValueUnused(varDecl, tryCatch))
return null;
-
+
+ if (m2.Has("f#")) {
+ string variableNameDisposable = m2.Get("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();
usingStatement.EmbeddedStatement = tryCatch.TryBlock.Detach();
tryCatch.ReplaceWith(usingStatement);
@@ -378,6 +419,13 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
// We just care that we can move it in front of the loop:
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")) {
+ if (stmt.Descendants.OfType().Any(id => enumeratorId.IsMatch(id)))
+ return null;
+ }
BlockStatement newBody = new BlockStatement();
foreach (Statement stmt in m.Get("variablesInsideLoop"))
diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
index 2d8cb71d4..99b6693f0 100644
--- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
+++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
@@ -139,16 +139,16 @@
-
- {D68133BD-1E63-496E-9EDE-4FBDBF77B486}
+
+ {d68133bd-1e63-496e-9ede-4fbdbf77b486}
Mono.Cecil
-
- {53DCA265-3C3C-42F9-B647-F72BA678122B}
+
+ {53dca265-3c3c-42f9-b647-f72ba678122b}
ICSharpCode.NRefactory.CSharp
- {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}
+ {3b2a5653-ec97-4001-bb9b-d90f1af2c371}
ICSharpCode.NRefactory
diff --git a/ICSharpCode.Decompiler/ILAst/StateRange.cs b/ICSharpCode.Decompiler/ILAst/StateRange.cs
index 3a3dfc2f3..a25af05ce 100644
--- a/ICSharpCode.Decompiler/ILAst/StateRange.cs
+++ b/ICSharpCode.Decompiler/ILAst/StateRange.cs
@@ -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 body, int pos, int bodyLength)
diff --git a/ICSharpCode.Decompiler/Tests/Async.cs b/ICSharpCode.Decompiler/Tests/Async.cs
index 7629dd5e6..910da5aeb 100644
--- a/ICSharpCode.Decompiler/Tests/Async.cs
+++ b/ICSharpCode.Decompiler/Tests/Async.cs
@@ -37,6 +37,10 @@ public class Async
Console.WriteLine("No Await");
}
+ public async void EmptyVoidMethod()
+ {
+ }
+
public async void AwaitYield()
{
await Task.Yield();
diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs
index 37c1c0d71..67052909a 100644
--- a/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs
+++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs
@@ -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)]
diff --git a/ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpPatternTests.cs b/ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpPatternTests.cs
new file mode 100644
index 000000000..7980d6579
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpPatternTests.cs
@@ -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);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs b/ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs
new file mode 100644
index 000000000..5db5939da
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs
@@ -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)
diff --git a/ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Debug.cs b/ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Debug.cs
new file mode 100644
index 000000000..3c62c0cac
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Debug.cs
@@ -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);
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Debug.il b/ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Debug.il
new file mode 100644
index 000000000..3661238ac
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Debug.il
@@ -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
diff --git a/ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Release.cs b/ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Release.cs
new file mode 100644
index 000000000..c9d091847
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Release.cs
@@ -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);
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Release.il b/ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Release.il
new file mode 100644
index 000000000..6299c9687
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Release.il
@@ -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
diff --git a/ICSharpCode.Decompiler/Tests/FSharpPatterns/TestHelpers.cs b/ICSharpCode.Decompiler/Tests/FSharpPatterns/TestHelpers.cs
new file mode 100644
index 000000000..dc6cd0bc4
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/FSharpPatterns/TestHelpers.cs
@@ -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 ilasm = new Lazy(() => ToolLocator.FindTool("ilasm.exe"));
+ static Lazy ildasm = new Lazy(() => 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 `` where the part after tmp is randomly generated.
+ // remove this from the ast to simplify the diff
+ var startupCodeNode = decompiler.SyntaxTree.Children.OfType().SingleOrDefault(d => d.Name.StartsWith(" Path.Combine(dir, fileName)).FirstOrDefault(File.Exists);
+ }
+
+ private static IEnumerable 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 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;
+ }
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
index adf4d5607..4212a76b6 100644
--- a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
+++ b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
@@ -49,10 +49,26 @@
..\..\packages\DiffLib.1.0.0.55\lib\net35-Client\DiffLib.dll
+
+ ..\..\packages\NUnitTestAdapter.2.0.0\lib\nunit.core.dll
+ False
+
+
+ ..\..\packages\NUnitTestAdapter.2.0.0\lib\nunit.core.interfaces.dll
+ False
+
False
.\nunit.framework.dll
+
+ ..\..\packages\NUnitTestAdapter.2.0.0\lib\nunit.util.dll
+ False
+
+
+ ..\..\packages\NUnitTestAdapter.2.0.0\lib\NUnit.VisualStudio.TestAdapter.dll
+ False
+
3.5
@@ -69,13 +85,19 @@
+
+
+
+
+
+
@@ -112,28 +134,40 @@
- {D68133BD-1E63-496E-9EDE-4FBDBF77B486}
+ {d68133bd-1e63-496e-9ede-4fbdbf77b486}
Mono.Cecil
+
+ {63e6915c-7ea4-4d76-ab28-0d7191eea626}
+ Mono.Cecil.Pdb
+
- {53DCA265-3C3C-42F9-B647-F72BA678122B}
+ {53dca265-3c3c-42f9-b647-f72ba678122b}
ICSharpCode.NRefactory.CSharp
- {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}
+ {3b2a5653-ec97-4001-bb9b-d90f1af2c371}
ICSharpCode.NRefactory
- {984CC812-9470-4A13-AFF9-CC44068D666C}
+ {984cc812-9470-4a13-aff9-cc44068d666c}
ICSharpCode.Decompiler
-
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ICSharpCode.Decompiler/Tests/NotUsingBlock.cs b/ICSharpCode.Decompiler/Tests/NotUsingBlock.cs
new file mode 100644
index 000000000..b20750ac8
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/NotUsingBlock.cs
@@ -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);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/TestRunner.cs b/ICSharpCode.Decompiler/Tests/TestRunner.cs
index 215725b0a..1af5bec0c 100644
--- a/ICSharpCode.Decompiler/Tests/TestRunner.cs
+++ b/ICSharpCode.Decompiler/Tests/TestRunner.cs
@@ -180,13 +180,20 @@ namespace ICSharpCode.Decompiler.Tests
{
TestFile(@"..\..\Tests\YieldReturn.cs");
}
-
+
[Test]
public void TypeAnalysis()
{
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);
diff --git a/ICSharpCode.Decompiler/Tests/packages.config b/ICSharpCode.Decompiler/Tests/packages.config
index 4d992b424..44cab4495 100644
--- a/ICSharpCode.Decompiler/Tests/packages.config
+++ b/ICSharpCode.Decompiler/Tests/packages.config
@@ -1,4 +1,5 @@
+
\ No newline at end of file
diff --git a/ILSpy.AddIn/CodeElementXmlDocKeyProvider.cs b/ILSpy.AddIn/CodeElementXmlDocKeyProvider.cs
new file mode 100644
index 000000000..b7210e918
--- /dev/null
+++ b/ILSpy.AddIn/CodeElementXmlDocKeyProvider.cs
@@ -0,0 +1,269 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ICSharpCode.ILSpy.AddIn
+{
+ ///
+ /// Provides XML documentation tags for Visual Studio CodeElements.
+ ///
+ ///
+ /// 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.
+ ///
+ 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 allGenericParameters = new List();
+ 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
+ }
+}
\ No newline at end of file
diff --git a/ILSpy.AddIn/ILSpy.AddIn.csproj b/ILSpy.AddIn/ILSpy.AddIn.csproj
index b2cc7f4d6..b56546a98 100644
--- a/ILSpy.AddIn/ILSpy.AddIn.csproj
+++ b/ILSpy.AddIn/ILSpy.AddIn.csproj
@@ -138,6 +138,7 @@
+
True
True
@@ -147,6 +148,7 @@
+
diff --git a/ILSpy.AddIn/ILSpyAddIn.vsct b/ILSpy.AddIn/ILSpyAddIn.vsct
index 69af34274..0105c1a53 100644
--- a/ILSpy.AddIn/ILSpyAddIn.vsct
+++ b/ILSpy.AddIn/ILSpyAddIn.vsct
@@ -47,6 +47,10 @@
+
+
+
+
@@ -77,6 +81,14 @@
+
+
- {984CC812-9470-4A13-AFF9-CC44068D666C}
+ {984cc812-9470-4a13-aff9-cc44068d666c}
ICSharpCode.Decompiler
- {D68133BD-1E63-496E-9EDE-4FBDBF77B486}
+ {d68133bd-1e63-496e-9ede-4fbdbf77b486}
Mono.Cecil
- {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}
+ {6c55b776-26d4-4db3-a6ab-87e783b2f3d1}
ICSharpCode.AvalonEdit
- {63E6915C-7EA4-4D76-AB28-0D7191EEA626}
+ {63e6915c-7ea4-4d76-ab28-0d7191eea626}
Mono.Cecil.Pdb
- {7B82B671-419F-45F4-B778-D9286F996EFA}
+ {7b82b671-419f-45f4-b778-d9286f996efa}
ICSharpCode.NRefactory.VB
- {53DCA265-3C3C-42F9-B647-F72BA678122B}
+ {53dca265-3c3c-42f9-b647-f72ba678122b}
ICSharpCode.NRefactory.CSharp
- {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}
+ {3b2a5653-ec97-4001-bb9b-d90f1af2c371}
ICSharpCode.NRefactory
- {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}
+ {dde2a481-8271-4eac-a330-8fa6a38d13d1}
ICSharpCode.TreeView
@@ -404,6 +407,11 @@
-
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ILSpy/Images/Library.png b/ILSpy/Images/Library.png
index d366971ff..7524cadf5 100644
Binary files a/ILSpy/Images/Library.png and b/ILSpy/Images/Library.png differ
diff --git a/ILSpy/Images/OverlayStatic.png b/ILSpy/Images/OverlayStatic.png
index d079a1107..1a0e5e9d4 100644
Binary files a/ILSpy/Images/OverlayStatic.png and b/ILSpy/Images/OverlayStatic.png differ
diff --git a/ILSpy/Images/SearchMsdn.png b/ILSpy/Images/SearchMsdn.png
new file mode 100644
index 000000000..42cefecdf
Binary files /dev/null and b/ILSpy/Images/SearchMsdn.png differ
diff --git a/ILSpy/Images/Sort.png b/ILSpy/Images/Sort.png
new file mode 100644
index 000000000..b508e9a49
Binary files /dev/null and b/ILSpy/Images/Sort.png differ
diff --git a/ILSpy/Languages/CSharpLanguage.cs b/ILSpy/Languages/CSharpLanguage.cs
index 031fa4247..15e0daaba 100644
--- a/ILSpy/Languages/CSharpLanguage.cs
+++ b/ILSpy/Languages/CSharpLanguage.cs
@@ -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
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
}
#endregion
- #region WriteResourceFilesInProject
- IEnumerable> WriteResourceFilesInProject(LoadedAssembly assembly, DecompilationOptions options, HashSet directories)
- {
- //AppDomain bamlDecompilerAppDomain = null;
- //try {
- foreach (EmbeddedResource r in assembly.ModuleDefinition.Resources.OfType()) {
- string fileName;
- Stream s = r.GetResourceStream();
- s.Position = 0;
- if (r.Name.EndsWith(".g.resources", StringComparison.OrdinalIgnoreCase)) {
- IEnumerable rs = null;
- try {
- rs = new ResourceSet(s).Cast();
- }
- 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 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
((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)
@@ -662,7 +585,15 @@ namespace ICSharpCode.ILSpy
} else
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)
diff --git a/ILSpy/Languages/IResourceFileHandler.cs b/ILSpy/Languages/IResourceFileHandler.cs
new file mode 100644
index 000000000..9d0849df2
--- /dev/null
+++ b/ILSpy/Languages/IResourceFileHandler.cs
@@ -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);
+ }
+}
diff --git a/ILSpy/Languages/Language.cs b/ILSpy/Languages/Language.cs
index 750dd8186..467bc8bec 100644
--- a/ILSpy/Languages/Language.cs
+++ b/ILSpy/Languages/Language.cs
@@ -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;
@@ -134,7 +138,14 @@ namespace ICSharpCode.ILSpy
throw new ArgumentNullException("property");
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
{
return member;
}
+
+ #region WriteResourceFilesInProject
+ protected virtual IEnumerable> WriteResourceFilesInProject(LoadedAssembly assembly, DecompilationOptions options, HashSet directories)
+ {
+ foreach (EmbeddedResource r in assembly.ModuleDefinition.Resources.OfType()) {
+ Stream stream = r.GetResourceStream();
+ stream.Position = 0;
+
+ IEnumerable 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()) {
+ 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 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 entries)
+ {
+ try {
+ entries = new ResourceSet(stream).Cast();
+ return true;
+ } catch (ArgumentException) {
+ entries = null;
+ return false;
+ }
+ }
+ #endregion
+
}
}
diff --git a/ILSpy/LoadedAssembly.cs b/ILSpy/LoadedAssembly.cs
index f9cc50ad1..e83e96b72 100644
--- a/ILSpy/LoadedAssembly.cs
+++ b/ILSpy/LoadedAssembly.cs
@@ -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)) {
diff --git a/ILSpy/MainWindow.xaml b/ILSpy/MainWindow.xaml
index 9aec1acde..2c12afc6c 100644
--- a/ILSpy/MainWindow.xaml
+++ b/ILSpy/MainWindow.xaml
@@ -141,12 +141,12 @@
-
+
-
+
- A new ILSpy version is available.
-
+ A new ILSpy version is available.
+
diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs
index 493a55d70..1cdfe40ed 100644
--- a/ILSpy/MainWindow.xaml.cs
+++ b/ILSpy/MainWindow.xaml.cs
@@ -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 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
SearchPane.Instance.SearchTerm = args.Search;
SearchPane.Instance.Show();
}
- if (!string.IsNullOrEmpty(args.SaveDirectory)) {
- foreach (var x in commandLineLoadedAssemblies) {
- x.ContinueWhenLoaded( (Task 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
#region Update Check
string updateAvailableDownloadUrl;
- void ShowMessageIfUpdatesAvailableAsync(ILSpySettings spySettings)
+ public void ShowMessageIfUpdatesAvailableAsync(ILSpySettings spySettings, bool forceCheck = false)
{
- AboutPage.CheckForUpdatesIfEnabledAsync(spySettings).ContinueWith(
- delegate (Task task) {
- if (task.Result != null) {
- updateAvailableDownloadUrl = task.Result;
- updateAvailablePanel.Visibility = Visibility.Visible;
- }
- },
- TaskScheduler.FromCurrentSynchronizationContext()
- );
+ Task 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 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
@@ -531,6 +549,14 @@ namespace ICSharpCode.ILSpy
}
}
}
+
+ public void SelectNodes(IEnumerable nodes)
+ {
+ if (nodes.Any() && nodes.All(n => !n.AncestorsAndSelf().Any(a => a.IsHidden))) {
+ treeView.FocusNode(nodes.First());
+ treeView.SetSelectedNodes(nodes);
+ }
+ }
///
/// Retrieves a node using the .ToString() representations of its ancestors.
@@ -557,7 +583,7 @@ namespace ICSharpCode.ILSpy
///
/// Gets the .ToString() representation of the node's ancestors.
///
- public string[] GetPathForNode(SharpTreeNode node)
+ public static string[] GetPathForNode(SharpTreeNode node)
{
if (node == null)
return null;
diff --git a/ILSpy/Options/OptionsDialog.xaml.cs b/ILSpy/Options/OptionsDialog.xaml.cs
index 40043fac5..8bd96661f 100644
--- a/ILSpy/Options/OptionsDialog.xaml.cs
+++ b/ILSpy/Options/OptionsDialog.xaml.cs
@@ -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)
diff --git a/ILSpy/Properties/AssemblyInfo.template.cs b/ILSpy/Properties/AssemblyInfo.template.cs
index c4be7cef5..821a569e7 100644
--- a/ILSpy/Properties/AssemblyInfo.template.cs
+++ b/ILSpy/Properties/AssemblyInfo.template.cs
@@ -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;
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;
diff --git a/ILSpy/SearchPane.cs b/ILSpy/SearchPane.cs
index 27177f7e7..20ebec022 100644
--- a/ILSpy/SearchPane.cs
+++ b/ILSpy/SearchPane.cs
@@ -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
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
}
}
- [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
public enum SearchMode
{
+ TypeAndMember,
Type,
Member,
+ Method,
+ Field,
+ Property,
+ Event,
Literal
}
}
\ No newline at end of file
diff --git a/ILSpy/SearchPane.xaml b/ILSpy/SearchPane.xaml
index 37a6ff210..756ee5e92 100644
--- a/ILSpy/SearchPane.xaml
+++ b/ILSpy/SearchPane.xaml
@@ -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)?/..." />
-
+
diff --git a/ILSpy/SearchStrategies.cs b/ILSpy/SearchStrategies.cs
index 302f261db..7d0912a0b 100644
--- a/ILSpy/SearchStrategies.cs
+++ b/ILSpy/SearchStrategies.cs
@@ -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
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
}
}
+ 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
}
}
+ class TypeAndMemberSearchStrategy : AbstractSearchStrategy
+ {
+ public TypeAndMemberSearchStrategy(params string[] terms)
+ : base(terms)
+ {
+ }
+
+ public override void Search(TypeDefinition type, Language language, Action 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);
+ }
+ }
}
diff --git a/ILSpy/TextView/DecompilerTextView.cs b/ILSpy/TextView/DecompilerTextView.cs
index e7a502094..b4a57b0c1 100644
--- a/ILSpy/TextView/DecompilerTextView.cs
+++ b/ILSpy/TextView/DecompilerTextView.cs
@@ -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
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;
diff --git a/ILSpy/TextView/DecompilerTextView.xaml b/ILSpy/TextView/DecompilerTextView.xaml
index 022ab422d..722784b87 100644
--- a/ILSpy/TextView/DecompilerTextView.xaml
+++ b/ILSpy/TextView/DecompilerTextView.xaml
@@ -19,7 +19,7 @@
Decompiling...
-
+
diff --git a/ILSpy/TextView/EditorCommands.cs b/ILSpy/TextView/EditorCommands.cs
index 8615ee896..2907453d2 100644
--- a/ILSpy/TextView/EditorCommands.cs
+++ b/ILSpy/TextView/EditorCommands.cs
@@ -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
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();
+ }
+ }
}
diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs b/ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs
index b9154ead7..23e5dceb2 100644
--- a/ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs
+++ b/ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs
@@ -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)
diff --git a/ILSpy/TreeNodes/Analyzer/RemoveAnalyzeContextMenuEntry.cs b/ILSpy/TreeNodes/Analyzer/RemoveAnalyzeContextMenuEntry.cs
index 3bcbe782f..908c95888 100644
--- a/ILSpy/TreeNodes/Analyzer/RemoveAnalyzeContextMenuEntry.cs
+++ b/ILSpy/TreeNodes/Analyzer/RemoveAnalyzeContextMenuEntry.cs
@@ -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)
diff --git a/ILSpy/TreeNodes/AssemblyTreeNode.cs b/ILSpy/TreeNodes/AssemblyTreeNode.cs
index 89a17eae6..b7c256507 100644
--- a/ILSpy/TreeNodes/AssemblyTreeNode.cs
+++ b/ILSpy/TreeNodes/AssemblyTreeNode.cs
@@ -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
}
}
- [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();
+ 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
}
}
- [ExportContextMenuEntryAttribute(Header = "_Add To Main List")]
+ [ExportContextMenuEntry(Header = "_Add To Main List", Category = "Dependencies")]
sealed class AddToMainList : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)
diff --git a/ILSpy/TreeNodes/MethodTreeNode.cs b/ILSpy/TreeNodes/MethodTreeNode.cs
index d6b33bcb5..19cdb6586 100644
--- a/ILSpy/TreeNodes/MethodTreeNode.cs
+++ b/ILSpy/TreeNodes/MethodTreeNode.cs
@@ -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
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)
diff --git a/ILSpy/TreeNodes/PropertyTreeNode.cs b/ILSpy/TreeNodes/PropertyTreeNode.cs
index 76cd12dd5..f33efc206 100644
--- a/ILSpy/TreeNodes/PropertyTreeNode.cs
+++ b/ILSpy/TreeNodes/PropertyTreeNode.cs
@@ -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
diff --git a/ILSpy/TreeNodes/SearchMsdnContextMenuEntry.cs b/ILSpy/TreeNodes/SearchMsdnContextMenuEntry.cs
index 924c90d09..8632ee213 100644
--- a/ILSpy/TreeNodes/SearchMsdnContextMenuEntry.cs
+++ b/ILSpy/TreeNodes/SearchMsdnContextMenuEntry.cs
@@ -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}";
diff --git a/ILSpy/VB/ILSpyEnvironmentProvider.cs b/ILSpy/VB/ILSpyEnvironmentProvider.cs
index 78c46da12..725a26d9b 100644
--- a/ILSpy/VB/ILSpyEnvironmentProvider.cs
+++ b/ILSpy/VB/ILSpyEnvironmentProvider.cs
@@ -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()
@@ -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();
if (annotation == null)
@@ -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().FirstOrDefault();
@@ -106,9 +106,9 @@ namespace ICSharpCode.ILSpy.VB
return TypeCode.Object;
}
- public Nullable 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().FirstOrDefault();
@@ -129,7 +129,7 @@ namespace ICSharpCode.ILSpy.VB
foreach (var type in interfaces) {
var def = type.Annotation().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
return expression.Annotation() != null;
}
- public bool IsMethodGroup(ICSharpCode.NRefactory.CSharp.Expression expression)
+ public bool IsMethodGroup(NRefactory.CSharp.Expression expression)
{
- var annotation = expression.Annotation();
- if (annotation != null) {
- return true;
+ var methodInfo = expression.Annotation()?.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();
+
+ 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;
+ }
}
}
diff --git a/ILSpy/VB/VBLanguage.cs b/ILSpy/VB/VBLanguage.cs
index 4aad4a870..246dbd375 100644
--- a/ILSpy/VB/VBLanguage.cs
+++ b/ILSpy/VB/VBLanguage.cs
@@ -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;
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
}
#endregion
- #region WriteResourceFilesInProject
- IEnumerable> WriteResourceFilesInProject(LoadedAssembly assembly, DecompilationOptions options, HashSet directories)
- {
- //AppDomain bamlDecompilerAppDomain = null;
- //try {
- foreach (EmbeddedResource r in assembly.ModuleDefinition.Resources.OfType()) {
- string fileName;
- Stream s = r.GetResourceStream();
- s.Position = 0;
- if (r.Name.EndsWith(".g.resources", StringComparison.OrdinalIgnoreCase)) {
- IEnumerable rs = null;
- try {
- rs = new ResourceSet(s).Cast();
- }
- 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 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
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);
}
@@ -483,7 +401,15 @@ namespace ICSharpCode.ILSpy.VB
Settings = settings
});
}
-
+
+ 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)
diff --git a/ILSpy/VB/VBTextOutputFormatter.cs b/ILSpy/VB/VBTextOutputFormatter.cs
index 38f89d7ef..ef43e1247 100644
--- a/ILSpy/VB/VBTextOutputFormatter.cs
+++ b/ILSpy/VB/VBTextOutputFormatter.cs
@@ -33,6 +33,8 @@ namespace ICSharpCode.ILSpy.VB
{
readonly ITextOutput output;
readonly Stack nodeStack = new Stack();
+
+ bool firstImport, lastImport;
public VBTextOutputFormatter(ITextOutput output)
{
@@ -43,28 +45,36 @@ namespace ICSharpCode.ILSpy.VB
public void StartNode(AstNode node)
{
-// var ranges = node.Annotation>();
-// 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() != null);
-// if (n != null) {
-// MemberMapping mapping = n.Annotation();
-//
-// // add all ranges
-// foreach (var range in ranges) {
-// mapping.MemberCodeMappings.Add(new SourceCodeMapping {
-// ILInstructionOffset = range,
-// SourceCodeLine = output.CurrentLine,
-// MemberMapping = mapping
-// });
-// }
-// }
-// }
-// }
-
+ // var ranges = node.Annotation>();
+ // 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() != null);
+ // if (n != null) {
+ // MemberMapping mapping = n.Annotation();
+ //
+ // // 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
return;
}
+ if (firstImport) {
+ output.MarkFoldStart(defaultCollapsed: true);
+ firstImport = false;
+ }
+
output.Write(identifier);
}
@@ -198,6 +213,10 @@ namespace ICSharpCode.ILSpy.VB
public void NewLine()
{
+ if (lastImport) {
+ output.MarkFoldEnd();
+ lastImport = false;
+ }
output.WriteLine();
}
diff --git a/NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/ICSharpCode.NRefactory.VB.Tests.csproj b/NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/ICSharpCode.NRefactory.VB.Tests.csproj
index 583a8acae..ee1d38229 100644
--- a/NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/ICSharpCode.NRefactory.VB.Tests.csproj
+++ b/NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/ICSharpCode.NRefactory.VB.Tests.csproj
@@ -94,13 +94,16 @@
- {7B82B671-419F-45F4-B778-D9286F996EFA}
+ {7b82b671-419f-45f4-b778-d9286f996efa}
ICSharpCode.NRefactory.VB
- {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}
+ {3b2a5653-ec97-4001-bb9b-d90f1af2c371}
ICSharpCode.NRefactory
+
+
+
\ No newline at end of file
diff --git a/NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerContextTests.cs b/NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerContextTests.cs
index f04ab8469..770584a0b 100644
--- a/NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerContextTests.cs
+++ b/NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerContextTests.cs
@@ -568,7 +568,8 @@ exit Global
Assert.IsEmpty(p.Errors);
- Assert.AreEqual(expectedOutput, p.Output);
+ Assert.AreEqual(expectedOutput.Replace("\r", ""),
+ p.Output.Replace("\r", ""));
}
}
}
diff --git a/NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/ImportsStatementTests.cs b/NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/ImportsStatementTests.cs
index 971805090..1067561e3 100644
--- a/NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/ImportsStatementTests.cs
+++ b/NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/ImportsStatementTests.cs
@@ -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
}
[Test]
+ [Ignore("Collection pattern matching is not implemented")]
public void QualifiedTypeImportsStatement()
{
string program = "Imports My.Name.Space\n";
diff --git a/NRefactory.VB/ICSharpCode.NRefactory.VB/Ast/AstNodeCollection.cs b/NRefactory.VB/ICSharpCode.NRefactory.VB/Ast/AstNodeCollection.cs
index aa91bb5c9..fd1265220 100644
--- a/NRefactory.VB/ICSharpCode.NRefactory.VB/Ast/AstNodeCollection.cs
+++ b/NRefactory.VB/ICSharpCode.NRefactory.VB/Ast/AstNodeCollection.cs
@@ -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)
diff --git a/NRefactory.VB/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj b/NRefactory.VB/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj
index 5c75126ba..44e599d12 100644
--- a/NRefactory.VB/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj
+++ b/NRefactory.VB/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj
@@ -211,11 +211,11 @@
- {53DCA265-3C3C-42F9-B647-F72BA678122B}
+ {53dca265-3c3c-42f9-b647-f72ba678122b}
ICSharpCode.NRefactory.CSharp
- {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}
+ {3b2a5653-ec97-4001-bb9b-d90f1af2c371}
ICSharpCode.NRefactory
diff --git a/NRefactory.VB/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs b/NRefactory.VB/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs
index 12e2d5dcf..495768131 100644
--- a/NRefactory.VB/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs
+++ b/NRefactory.VB/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs
@@ -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
WriteModifiers(typeDeclaration.ModifierTokens);
WriteClassTypeKeyword(typeDeclaration);
WriteIdentifier(typeDeclaration.Name.Name);
+ WriteTypeParameters(typeDeclaration.TypeParameters);
MarkFoldStart();
NewLine();
@@ -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
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
void WriteIdentifier(string identifier, Role 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
"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
///
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
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
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
}
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
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
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
{
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
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
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
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
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
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
}
if (!operatorDeclaration.Body.IsNull) {
MarkFoldStart();
- NewLine();
- Indent();
WriteBlock(operatorDeclaration.Body);
- Unindent();
WriteKeyword("End");
WriteKeyword("Operator");
MarkFoldEnd();
@@ -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
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
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
else
WriteKeyword("Function");
WriteCommaSeparatedListInParenthesis(multiLineLambdaExpression.Parameters, false);
- NewLine();
- Indent();
multiLineLambdaExpression.Body.AcceptVisitor(this, data);
- Unindent();
WriteKeyword("End");
if (multiLineLambdaExpression.IsSub)
WriteKeyword("Sub");
diff --git a/NRefactory.VB/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs b/NRefactory.VB/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs
index f9230402a..a38d17e23 100644
--- a/NRefactory.VB/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs
+++ b/NRefactory.VB/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs
@@ -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);
}
///
@@ -98,12 +99,23 @@ 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)
{
@@ -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
}
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
}
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
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
{
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
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
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);
@@ -597,6 +581,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)
{
@@ -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
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
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
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
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
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
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
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
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");
@@ -1913,6 +1923,8 @@ namespace ICSharpCode.NRefactory.VB.Visitors
if (members.Pop().inIterator) {
decl.Modifiers |= Modifiers.Iterator;
}
+
+ ConvertNodes(provider.GetParametersForProperty(propertyDeclaration), decl.Parameters);
return EndNode(propertyDeclaration, decl);
}
@@ -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
};
var constraint = typeParameterDeclaration.Parent
- .GetChildrenByRole(ICSharpCode.NRefactory.CSharp.Roles.Constraint)
+ .GetChildrenByRole(CSharp.Roles.Constraint)
.SingleOrDefault(c => c.TypeParameter.Identifier == typeParameterDeclaration.Name);
if (constraint != null)
@@ -2221,7 +2233,24 @@ namespace ICSharpCode.NRefactory.VB.Visitors
result.Add(n);
}
}
-
+
+ void ConvertMembers(CSharp.AstNode parent, T result, Role sourceRole, Role 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(CSharp.AstNode node, T result) where T : VB.AstNode
{
if (result != null) {
diff --git a/README.md b/README.md
new file mode 100644
index 000000000..3f839dac1
--- /dev/null
+++ b/README.md
@@ -0,0 +1,28 @@
+# ILSpy
+
+[](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)
diff --git a/README.txt b/README.txt
index 56ef9c3bb..76cdfb52f 100644
--- a/README.txt
+++ b/README.txt
@@ -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:
diff --git a/Rebracer.xml b/Rebracer.xml
index bd0a77e01..f0cfda200 100644
--- a/Rebracer.xml
+++ b/Rebracer.xml
@@ -10,13 +10,13 @@
- TODO:2
- HACK:2
+ HACK:2
+ TODO:2
UNDONE:2
UnresolvedMergeConflict:3
- true
- true
+ false
+ false
false
@@ -24,9 +24,14 @@
1
1
+ 1
1
2
80
+ 0
+ 1
+ 0
+ 1
1
1
1
@@ -34,11 +39,12 @@
1
0
1
- 0
+ 1
0
2
0
1
+ 0
0
0
0
@@ -47,6 +53,7 @@
0
1
1
+ 1
1
0
0
@@ -54,6 +61,7 @@
1
1
1
+ 1
1
1
1
@@ -84,6 +92,10 @@
0
0
0
+ 1
+ 1
+ 0
+ 1
1
1
0
diff --git a/SharpTreeView/SharpTreeView.cs b/SharpTreeView/SharpTreeView.cs
index 83b82cc12..093e942ba 100644
--- a/SharpTreeView/SharpTreeView.cs
+++ b/SharpTreeView/SharpTreeView.cs
@@ -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) {
diff --git a/TestPlugin/TestPlugin.csproj b/TestPlugin/TestPlugin.csproj
index dc2e78f56..38230e7a8 100644
--- a/TestPlugin/TestPlugin.csproj
+++ b/TestPlugin/TestPlugin.csproj
@@ -83,27 +83,27 @@
- {984CC812-9470-4A13-AFF9-CC44068D666C}
+ {984cc812-9470-4a13-aff9-cc44068d666c}
ICSharpCode.Decompiler
- {1E85EFF9-E370-4683-83E4-8A3D063FF791}
+ {1e85eff9-e370-4683-83e4-8a3d063ff791}
ILSpy
- {D68133BD-1E63-496E-9EDE-4FBDBF77B486}
+ {d68133bd-1e63-496e-9ede-4fbdbf77b486}
Mono.Cecil
- {53DCA265-3C3C-42F9-B647-F72BA678122B}
+ {53dca265-3c3c-42f9-b647-f72ba678122b}
ICSharpCode.NRefactory.CSharp
- {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}
+ {3b2a5653-ec97-4001-bb9b-d90f1af2c371}
ICSharpCode.NRefactory
- {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}
+ {dde2a481-8271-4eac-a330-8fa6a38d13d1}
ICSharpCode.TreeView
diff --git a/appveyor.yml b/appveyor.yml
index 4a1154b81..310fc2803 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -10,4 +10,4 @@ build:
parallel: true
verbosity: minimal
after_test:
-- python ICSharpCode.AvalonEdit.Tests\tidy.py
+- python BuildTools\tidy.py
diff --git a/debugbuild.bat b/debugbuild.bat
index 1dfe9ceca..9227bc776 100644
--- a/debugbuild.bat
+++ b/debugbuild.bat
@@ -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
diff --git a/releasebuild.bat b/releasebuild.bat
index 11f863dab..57d174305 100644
--- a/releasebuild.bat
+++ b/releasebuild.bat
@@ -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