Browse Source

Merge pull request #1 from icsharpcode/master

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

5
BuildTools/Automated.proj

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

2
BuildTools/buildAndCreatePackage.bat

@ -1,6 +1,6 @@
@echo This script simulates what the build server is doing @echo This script simulates what the build server is doing
@rem /p:AdditionalBuildProperties="/v:d /p:MSBuildTargetsVerbose=true" @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 @IF %ERRORLEVEL% NEQ 0 GOTO err
@exit /B 0 @exit /B 0
:err :err

3
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -1521,7 +1521,8 @@ namespace ICSharpCode.Decompiler.Ast
} }
var type = argument.Type.Resolve(); var type = argument.Type.Resolve();
if (type != null && type.IsEnum) { 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) { } else if (argument.Value is TypeReference) {
return CreateTypeOfExpression((TypeReference)argument.Value); return CreateTypeOfExpression((TypeReference)argument.Value);
} else { } else {

8
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -754,9 +754,8 @@ namespace ICSharpCode.Decompiler.Ast
return ace; return ace;
} }
} }
if (declaringType.IsAnonymousType()) {
MethodDefinition ctor = ((MethodReference)operand).Resolve(); MethodDefinition ctor = ((MethodReference)operand).Resolve();
if (methodDef != null) { if (declaringType.IsAnonymousType() && methodDef != null) {
AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression(); AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression();
if (CanInferAnonymousTypePropertyNamesFromArguments(args, ctor.Parameters)) { if (CanInferAnonymousTypePropertyNamesFromArguments(args, ctor.Parameters)) {
atce.Initializers.AddRange(args); atce.Initializers.AddRange(args);
@ -771,9 +770,12 @@ namespace ICSharpCode.Decompiler.Ast
} }
return atce; return atce;
} }
}
var oce = new Ast.ObjectCreateExpression(); var oce = new Ast.ObjectCreateExpression();
oce.Type = AstBuilder.ConvertType(declaringType); 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); oce.Arguments.AddRange(args);
return oce.WithAnnotation(operand); return oce.WithAnnotation(operand);
} }

16
ICSharpCode.Decompiler/Ast/DecompilerContext.cs

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

2
ICSharpCode.Decompiler/Ast/NameVariables.cs

@ -335,7 +335,7 @@ namespace ICSharpCode.Decompiler.Ast
// remove field prefix: // remove field prefix:
if (name.Length > 2 && name.StartsWith("m_", StringComparison.Ordinal)) if (name.Length > 2 && name.StartsWith("m_", StringComparison.Ordinal))
name = name.Substring(2); 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); name = name.Substring(1);
if (name.Length == 0) if (name.Length == 0)

9
ICSharpCode.Decompiler/Ast/TextTokenWriter.cs

@ -188,6 +188,15 @@ namespace ICSharpCode.Decompiler.Ast
public override void WriteKeyword(Role role, string keyword) 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); output.Write(keyword);
} }

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

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

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

@ -58,11 +58,12 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
public override AstNode VisitExpressionStatement(ExpressionStatement expressionStatement, object data) public override AstNode VisitExpressionStatement(ExpressionStatement expressionStatement, object data)
{ {
AstNode result; AstNode result;
if (context.Settings.UsingStatement) { if (context.Settings.UsingStatement)
result = TransformUsings(expressionStatement); {
result = TransformNonGenericForEach(expressionStatement);
if (result != null) if (result != null)
return result; return result;
result = TransformNonGenericForEach(expressionStatement); result = TransformUsings(expressionStatement);
if (result != null) if (result != null)
return result; 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(), TryBlock = new AnyNode(),
FinallyBlock = new BlockStatement { FinallyBlock = new BlockStatement {
new Choice { new Choice {
@ -177,6 +180,33 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
} }
}.ToStatement() }.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) public UsingStatement TransformUsings(ExpressionStatement node)
@ -214,6 +244,17 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
if (!IsVariableValueUnused(varDecl, tryCatch)) if (!IsVariableValueUnused(varDecl, tryCatch))
return null; return null;
if (m2.Has("f#")) {
string variableNameDisposable = m2.Get<IdentifierExpression>("disposable").Single().Identifier;
VariableDeclarationStatement varDeclDisposable = FindVariableDeclaration(node, variableNameDisposable);
if (varDeclDisposable == null || !(varDeclDisposable.Parent is BlockStatement))
return null;
// Validate that the variable is not used after the using statement:
if (!IsVariableValueUnused(varDeclDisposable, tryCatch))
return null;
}
node.Remove(); node.Remove();
UsingStatement usingStatement = new UsingStatement(); UsingStatement usingStatement = new UsingStatement();
@ -379,6 +420,13 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
if (declarationPoint != loop) if (declarationPoint != loop)
return null; return null;
// Make sure that the enumerator variable is not used inside the body
var enumeratorId = Identifier.Create(enumeratorVar.Name);
foreach (Statement stmt in m.Get<Statement>("statement")) {
if (stmt.Descendants.OfType<Identifier>().Any(id => enumeratorId.IsMatch(id)))
return null;
}
BlockStatement newBody = new BlockStatement(); BlockStatement newBody = new BlockStatement();
foreach (Statement stmt in m.Get<Statement>("variablesInsideLoop")) foreach (Statement stmt in m.Get<Statement>("variablesInsideLoop"))
newBody.Add(stmt.Detach()); newBody.Add(stmt.Detach());

6
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

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

13
ICSharpCode.Decompiler/ILAst/StateRange.cs

@ -273,15 +273,24 @@ namespace ICSharpCode.Decompiler.ILAst
{ {
if (pos > 0 && body[pos - 1] is ILLabel) { if (pos > 0 && body[pos - 1] is ILLabel) {
pos--; pos--;
} else { return; // label found
}
// ensure that the first element at body[pos] is a label: // ensure that the first element at body[pos] is a label:
ILLabel newLabel = new ILLabel(); ILLabel newLabel = new ILLabel();
newLabel.Name = "YieldReturnEntryPoint"; 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 {
ranges[newLabel] = ranges[body[pos]]; // give the label the range of the instruction at body[pos] ranges[newLabel] = ranges[body[pos]]; // give the label the range of the instruction at body[pos]
}
body.Insert(pos, newLabel); body.Insert(pos, newLabel);
bodyLength++; bodyLength++;
} }
}
public LabelRangeMapping CreateLabelRangeMapping(List<ILNode> body, int pos, int bodyLength) public LabelRangeMapping CreateLabelRangeMapping(List<ILNode> body, int pos, int bodyLength)
{ {

4
ICSharpCode.Decompiler/Tests/Async.cs

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

5
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)] [CustomAttributes.MyAttribute(CustomAttributes.EnumWithFlag.Item1 | CustomAttributes.EnumWithFlag.Item2)]
private static int field; private static int field;
[CustomAttributes.MyAttribute(CustomAttributes.EnumWithFlag.All)] [CustomAttributes.MyAttribute(CustomAttributes.EnumWithFlag.All)]

30
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);
}
}
}

38
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)

64
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);
}
}

344
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

64
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);
}
}

311
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

87
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<string> ilasm = new Lazy<string>(() => ToolLocator.FindTool("ilasm.exe"));
static Lazy<string> ildasm = new Lazy<string>(() => ToolLocator.FindTool("ildasm.exe"));
public static string CompileIL(string source)
{
if (ilasm.Value == null)
Assert.NotNull(ilasm.Value, "Could not find ILASM.exe");
var tmp = Path.GetTempFileName();
File.Delete(tmp);
var sourceFile = Path.ChangeExtension(tmp, ".il");
File.WriteAllText(sourceFile, source);
var asmFile = Path.ChangeExtension(sourceFile, ".dll");
var args = string.Format("{0} /dll /debug /output:{1}", sourceFile, asmFile);
using (var proc = Process.Start(new ProcessStartInfo(ilasm.Value, args) { UseShellExecute = false, }))
{
proc.WaitForExit();
Assert.AreEqual(0, proc.ExitCode);
}
File.Delete(sourceFile);
Assert.True(File.Exists(asmFile), "Assembly File does not exist");
return asmFile;
}
public static void RunIL(string ilCode, string expectedCSharpCode)
{
var asmFilePath = CompileIL(ilCode);
CompareAssemblyAgainstCSharp(expectedCSharpCode, asmFilePath);
}
private static void CompareAssemblyAgainstCSharp(string expectedCSharpCode, string asmFilePath)
{
var module = ModuleDefinition.ReadModule(asmFilePath);
try
{
try { module.ReadSymbols(); } catch { }
AstBuilder decompiler = new AstBuilder(new DecompilerContext(module));
decompiler.AddAssembly(module);
new Helpers.RemoveCompilerAttribute().Run(decompiler.SyntaxTree);
StringWriter output = new StringWriter();
// the F# assembly contains a namespace `<StartupCode$tmp6D55>` where the part after tmp is randomly generated.
// remove this from the ast to simplify the diff
var startupCodeNode = decompiler.SyntaxTree.Children.OfType<NamespaceDeclaration>().SingleOrDefault(d => d.Name.StartsWith("<StartupCode$", StringComparison.Ordinal));
if (startupCodeNode != null)
startupCodeNode.Remove();
decompiler.GenerateCode(new PlainTextOutput(output));
var fullCSharpCode = output.ToString();
CodeAssert.AreEqual(expectedCSharpCode, output.ToString());
}
finally
{
File.Delete(asmFilePath);
File.Delete(Path.ChangeExtension(asmFilePath, ".pdb"));
}
}
}
}

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

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

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

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

28
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);
}
}
}

7
ICSharpCode.Decompiler/Tests/TestRunner.cs

@ -187,6 +187,13 @@ namespace ICSharpCode.Decompiler.Tests
TestFile(@"..\..\Tests\TypeAnalysisTests.cs"); 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) static void TestFile(string fileName, bool useDebug = false, int compilerVersion = 4)
{ {
AssertRoundtripCode(fileName, optimize: false, useDebug: useDebug, compilerVersion: compilerVersion); AssertRoundtripCode(fileName, optimize: false, useDebug: useDebug, compilerVersion: compilerVersion);

1
ICSharpCode.Decompiler/Tests/packages.config

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

269
ILSpy.AddIn/CodeElementXmlDocKeyProvider.cs

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

2
ILSpy.AddIn/ILSpy.AddIn.csproj

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

14
ILSpy.AddIn/ILSpyAddIn.vsct

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

139
ILSpy.AddIn/ILSpyAddInPackage.cs

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

1
ILSpy.AddIn/PkgCmdID.cs

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

4
ILSpy.AddIn/Properties/AssemblyInfo.cs

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

414
ILSpy.AddIn/Samples/ILSpyAddInSamples.cs

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

6
ILSpy.AddIn/Utils.cs

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

2
ILSpy.AddIn/license.txt

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

6
ILSpy.AddIn/source.extension.vsixmanifest

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

19
ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs

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

10
ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj

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

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

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

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

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

1
ILSpy.BamlDecompiler/Tests/TestRunner.cs

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

3
ILSpy.sln

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

27
ILSpy/AboutPage.cs

@ -288,6 +288,26 @@ namespace ICSharpCode.ILSpy
if (s.LastSuccessfulUpdateCheck == null if (s.LastSuccessfulUpdateCheck == null
|| s.LastSuccessfulUpdateCheck < DateTime.UtcNow.AddDays(-7) || s.LastSuccessfulUpdateCheck < DateTime.UtcNow.AddDays(-7)
|| s.LastSuccessfulUpdateCheck > DateTime.UtcNow) || s.LastSuccessfulUpdateCheck > DateTime.UtcNow)
{
CheckForUpdateInternal(tcs, s);
} else {
tcs.SetResult(null);
}
} else {
tcs.SetResult(null);
}
return tcs.Task;
}
public static Task<string> CheckForUpdatesAsync(ILSpySettings spySettings)
{
var tcs = new TaskCompletionSource<string>();
UpdateSettings s = new UpdateSettings(spySettings);
CheckForUpdateInternal(tcs, s);
return tcs.Task;
}
static void CheckForUpdateInternal(TaskCompletionSource<string> tcs, UpdateSettings s)
{ {
GetLatestVersionAsync().ContinueWith( GetLatestVersionAsync().ContinueWith(
delegate (Task<AvailableVersionInfo> task) { delegate (Task<AvailableVersionInfo> task) {
@ -303,13 +323,6 @@ namespace ICSharpCode.ILSpy
tcs.SetResult(null); tcs.SetResult(null);
} }
}); });
} else {
tcs.SetResult(null);
}
} else {
tcs.SetResult(null);
}
return tcs.Task;
} }
} }

20
ILSpy/AssemblyList.cs

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

31
ILSpy/Commands/CheckForUpdatesCommand.cs

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

2
ILSpy/Commands/OpenCommand.cs

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

2
ILSpy/Commands/OpenFromGacCommand.cs

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

2
ILSpy/Commands/OpenListCommand.cs

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

2
ILSpy/Commands/RefreshCommand.cs

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

39
ILSpy/Commands/SortAssemblyListCommand.cs

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

2
ILSpy/ContextMenuEntry.cs

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

26
ILSpy/ILSpy.csproj

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

BIN
ILSpy/Images/Library.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 B

After

Width:  |  Height:  |  Size: 417 B

BIN
ILSpy/Images/OverlayStatic.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 315 B

After

Width:  |  Height:  |  Size: 347 B

BIN
ILSpy/Images/SearchMsdn.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 710 B

BIN
ILSpy/Images/Sort.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 B

95
ILSpy/Languages/CSharpLanguage.cs

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

30
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);
}
}

96
ILSpy/Languages/Language.cs

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

14
ILSpy/LoadedAssembly.cs

@ -139,6 +139,20 @@ namespace ICSharpCode.ILSpy
private void LoadSymbols(ModuleDefinition module) 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 // search for pdb in same directory as dll
string pdbName = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName) + ".pdb"); string pdbName = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName) + ".pdb");
if (File.Exists(pdbName)) { if (File.Exists(pdbName)) {

8
ILSpy/MainWindow.xaml

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

68
ILSpy/MainWindow.xaml.cs

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

2
ILSpy/Options/OptionsDialog.xaml.cs

@ -89,7 +89,7 @@ namespace ICSharpCode.ILSpy.Options
public int Order { get; set; } 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 sealed class ShowOptionsCommand : SimpleCommand
{ {
public override void Execute(object parameter) public override void Execute(object parameter)

6
ILSpy/Properties/AssemblyInfo.template.cs

@ -15,7 +15,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyDescription(".NET assembly inspector and decompiler")] [assembly: AssemblyDescription(".NET assembly inspector and decompiler")]
[assembly: AssemblyCompany("ic#code")] [assembly: AssemblyCompany("ic#code")]
[assembly: AssemblyProduct("ILSpy")] [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: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
@ -35,8 +35,8 @@ using System.Runtime.InteropServices;
internal static class RevisionClass internal static class RevisionClass
{ {
public const string Major = "2"; public const string Major = "2";
public const string Minor = "3"; public const string Minor = "4";
public const string Build = "1"; public const string Build = "0";
public const string Revision = "$INSERTREVISION$"; public const string Revision = "$INSERTREVISION$";
public const string VersionName = null; public const string VersionName = null;

48
ILSpy/SearchPane.cs

@ -58,10 +58,15 @@ namespace ICSharpCode.ILSpy
private SearchPane() private SearchPane()
{ {
InitializeComponent(); 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.Class, Name = "Type" });
searchModeComboBox.Items.Add(new { Image = Images.Property, Name = "Member" }); 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.Items.Add(new { Image = Images.Literal, Name = "Constant" });
searchModeComboBox.SelectedIndex = (int)SearchMode.Type; searchModeComboBox.SelectedIndex = (int)SearchMode.TypeAndMember;
ContextMenuProvider.Add(listBox); ContextMenuProvider.Add(listBox);
MainWindow.Instance.CurrentAssemblyListChanged += MainWindow_Instance_CurrentAssemblyListChanged; MainWindow.Instance.CurrentAssemblyListChanged += MainWindow_Instance_CurrentAssemblyListChanged;
@ -249,23 +254,49 @@ namespace ICSharpCode.ILSpy
AbstractSearchStrategy GetSearchStrategy(SearchMode mode, string[] terms) AbstractSearchStrategy GetSearchStrategy(SearchMode mode, string[] terms)
{ {
if (terms.Length == 1) { 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)); 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)); 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)); return new LiteralSearchStrategy(terms[0].Substring(2));
} }
switch (mode) { switch (mode)
{
case SearchMode.TypeAndMember:
return new TypeAndMemberSearchStrategy(terms);
case SearchMode.Type: case SearchMode.Type:
return new TypeSearchStrategy(terms); return new TypeSearchStrategy(terms);
case SearchMode.Member: case SearchMode.Member:
return new MemberSearchStrategy(terms); return new MemberSearchStrategy(terms);
case SearchMode.Literal: case SearchMode.Literal:
return new LiteralSearchStrategy(terms); 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; 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)] [ExportToolbarCommand(ToolTip = "Search (Ctrl+Shift+F or Ctrl+E)", ToolbarIcon = "Images/Find.png", ToolbarCategory = "View", ToolbarOrder = 100)]
sealed class ShowSearchCommand : CommandWrapper sealed class ShowSearchCommand : CommandWrapper
{ {
@ -308,8 +339,13 @@ namespace ICSharpCode.ILSpy
public enum SearchMode public enum SearchMode
{ {
TypeAndMember,
Type, Type,
Member, Member,
Method,
Field,
Property,
Event,
Literal Literal
} }
} }

2
ILSpy/SearchPane.xaml

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

79
ILSpy/SearchStrategies.cs

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

4
ILSpy/TextView/DecompilerTextView.cs

@ -233,6 +233,9 @@ namespace ICSharpCode.ILSpy.TextView
{ {
if (waitAdorner.Visibility != Visibility.Visible) { if (waitAdorner.Visibility != Visibility.Visible) {
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)); waitAdorner.BeginAnimation(OpacityProperty, new DoubleAnimation(0, 1, new Duration(TimeSpan.FromSeconds(0.5)), FillBehavior.Stop));
var taskBar = MainWindow.Instance.TaskbarItemInfo; var taskBar = MainWindow.Instance.TaskbarItemInfo;
if (taskBar != null) { if (taskBar != null) {
@ -260,6 +263,7 @@ namespace ICSharpCode.ILSpy.TextView
if (currentCancellationTokenSource == myCancellationTokenSource) { if (currentCancellationTokenSource == myCancellationTokenSource) {
currentCancellationTokenSource = null; currentCancellationTokenSource = null;
waitAdorner.Visibility = Visibility.Collapsed; waitAdorner.Visibility = Visibility.Collapsed;
progressBar.IsIndeterminate = false;
var taskBar = MainWindow.Instance.TaskbarItemInfo; var taskBar = MainWindow.Instance.TaskbarItemInfo;
if (taskBar != null) { if (taskBar != null) {
taskBar.ProgressState = System.Windows.Shell.TaskbarItemProgressState.None; taskBar.ProgressState = System.Windows.Shell.TaskbarItemProgressState.None;

2
ILSpy/TextView/DecompilerTextView.xaml

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

28
ILSpy/TextView/EditorCommands.cs

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

2
ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs

@ -24,7 +24,7 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer 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 internal sealed class AnalyzeContextMenuEntry : IContextMenuEntry
{ {
public bool IsVisible(TextViewContext context) public bool IsVisible(TextViewContext context)

2
ILSpy/TreeNodes/Analyzer/RemoveAnalyzeContextMenuEntry.cs

@ -20,7 +20,7 @@ using System.Linq;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer 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 internal sealed class RemoveAnalyzeContextMenuEntry : IContextMenuEntry
{ {
public bool IsVisible(TextViewContext context) public bool IsVisible(TextViewContext context)

38
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 sealed class RemoveAssembly : IContextMenuEntry
{ {
public bool IsVisible(TextViewContext context) 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<string[]>();
using (context.TreeView.LockUpdates()) {
foreach (var node in context.SelectedTreeNodes) {
paths.Add(MainWindow.GetPathForNode(node));
var la = ((AssemblyTreeNode)node).LoadedAssembly;
la.AssemblyList.ReloadAssembly(la.FileName);
}
}
MainWindow.Instance.SelectNodes(paths.Select(p => MainWindow.Instance.FindNodeByPath(p, true)).ToArray());
MainWindow.Instance.RefreshDecompiledView();
}
}
[ExportContextMenuEntry(Header = "_Load Dependencies", Category = "Dependencies")]
sealed class LoadDependencies : IContextMenuEntry sealed class LoadDependencies : IContextMenuEntry
{ {
public bool IsVisible(TextViewContext context) 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 sealed class AddToMainList : IContextMenuEntry
{ {
public bool IsVisible(TextViewContext context) public bool IsVisible(TextViewContext context)

4
ILSpy/TreeNodes/MethodTreeNode.cs

@ -69,7 +69,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
b.Append(") : "); b.Append(") : ");
b.Append(language.TypeToString(method.ReturnType, false, method.MethodReturnType)); b.Append(language.TypeToString(method.ReturnType, false, method.MethodReturnType));
b.Append(method.MetadataToken.ToSuffixString()); b.Append(method.MetadataToken.ToSuffixString());
return HighlightSearchMatch(method.Name, b.ToString()); return HighlightSearchMatch(language.FormatMethodName(method), b.ToString());
} }
public override object Icon public override object Icon
@ -93,7 +93,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
if (method.IsSpecialName && if (method.IsSpecialName &&
(method.Name == ".ctor" || method.Name == ".cctor")) { (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) if (method.HasPInvokeInfo)

30
ILSpy/TreeNodes/PropertyTreeNode.cs

@ -62,7 +62,35 @@ namespace ICSharpCode.ILSpy.TreeNodes
public static object GetText(PropertyDefinition property, Language language, bool? isIndexer = null) 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 public override object Icon

2
ILSpy/TreeNodes/SearchMsdnContextMenuEntry.cs

@ -26,7 +26,7 @@ using ICSharpCode.ILSpy.TreeNodes.Analyzer;
namespace ICSharpCode.ILSpy.TreeNodes 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 internal sealed class SearchMsdnContextMenuEntry : IContextMenuEntry
{ {
private static string msdnAddress = "http://msdn.microsoft.com/en-us/library/{0}"; private static string msdnAddress = "http://msdn.microsoft.com/en-us/library/{0}";

40
ILSpy/VB/ILSpyEnvironmentProvider.cs

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

94
ILSpy/VB/VBLanguage.cs

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

21
ILSpy/VB/VBTextOutputFormatter.cs

@ -34,6 +34,8 @@ namespace ICSharpCode.ILSpy.VB
readonly ITextOutput output; readonly ITextOutput output;
readonly Stack<AstNode> nodeStack = new Stack<AstNode>(); readonly Stack<AstNode> nodeStack = new Stack<AstNode>();
bool firstImport, lastImport;
public VBTextOutputFormatter(ITextOutput output) public VBTextOutputFormatter(ITextOutput output)
{ {
if (output == null) if (output == null)
@ -64,7 +66,15 @@ namespace ICSharpCode.ILSpy.VB
// } // }
// } // }
// } // }
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); nodeStack.Push(node);
} }
@ -100,6 +110,11 @@ namespace ICSharpCode.ILSpy.VB
return; return;
} }
if (firstImport) {
output.MarkFoldStart(defaultCollapsed: true);
firstImport = false;
}
output.Write(identifier); output.Write(identifier);
} }
@ -198,6 +213,10 @@ namespace ICSharpCode.ILSpy.VB
public void NewLine() public void NewLine()
{ {
if (lastImport) {
output.MarkFoldEnd();
lastImport = false;
}
output.WriteLine(); output.WriteLine();
} }

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

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

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

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

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

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

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

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

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

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

104
NRefactory.VB/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs

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

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

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

28
README.md

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

2
README.txt

@ -1,7 +1,7 @@
ILSpy is the open-source .NET assembly browser and decompiler. ILSpy is the open-source .NET assembly browser and decompiler.
Website: http://www.ilspy.net/ 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. License: ILSpy is distributed under the MIT License.
Included open-source libraries: Included open-source libraries:

22
Rebracer.xml

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

21
SharpTreeView/SharpTreeView.cs

@ -122,6 +122,27 @@ namespace ICSharpCode.TreeView
TreeFlattener flattener; TreeFlattener flattener;
bool updatesLocked; 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() void Reload()
{ {
if (flattener != null) { if (flattener != null) {

12
TestPlugin/TestPlugin.csproj

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

2
appveyor.yml

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

2
debugbuild.bat

@ -1,7 +1,7 @@
@if not exist "AvalonEdit\ICSharpCode.AvalonEdit.sln" ( @if not exist "AvalonEdit\ICSharpCode.AvalonEdit.sln" (
git submodule update --init || exit /b 1 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 @IF %ERRORLEVEL% NEQ 0 GOTO err
@exit /B 0 @exit /B 0
:err :err

2
releasebuild.bat

@ -1,7 +1,7 @@
@if not exist "AvalonEdit\ICSharpCode.AvalonEdit.sln" ( @if not exist "AvalonEdit\ICSharpCode.AvalonEdit.sln" (
git submodule update --init || exit /b 1 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 @IF %ERRORLEVEL% NEQ 0 GOTO err
@exit /B 0 @exit /B 0
:err :err

Loading…
Cancel
Save