Browse Source

Add BlockTransform concept and apply a bunch of refactoring essentials suggestions.

pull/728/merge
Daniel Grunwald 9 years ago
parent
commit
7273fe58fd
  1. 14
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 4
      ICSharpCode.Decompiler/CecilExtensions.cs
  3. 2
      ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs
  4. 2
      ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs
  5. 2
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  6. 2
      ICSharpCode.Decompiler/FlowAnalysis/DataFlowVisitor.cs
  7. 6
      ICSharpCode.Decompiler/FlowAnalysis/ReachingDefinitionsVisitor.cs
  8. 2
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  9. 84
      ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs
  10. 4
      ICSharpCode.Decompiler/IL/ILReader.cs
  11. 2
      ICSharpCode.Decompiler/IL/ILVariable.cs
  12. 15
      ICSharpCode.Decompiler/IL/Instructions/Block.cs
  13. 2
      ICSharpCode.Decompiler/IL/Instructions/Branch.cs
  14. 1
      ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs
  15. 2
      ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs
  16. 2
      ICSharpCode.Decompiler/IL/Instructions/InstructionCollection.cs
  17. 109
      ICSharpCode.Decompiler/IL/Transforms/BlockTransform.cs
  18. 70
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs
  19. 63
      ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs
  20. 50
      ICSharpCode.Decompiler/IL/Transforms/LoopingTransform.cs
  21. 64
      ICSharpCode.Decompiler/IL/Transforms/Stepper.cs
  22. 2
      ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs
  23. 2
      ICSharpCode.Decompiler/Output/PlainTextOutput.cs
  24. 2
      ICSharpCode.Decompiler/Output/TextOutputWriter.cs
  25. 11
      ICSharpCode.Decompiler/Properties/AssemblyInfo.template.cs
  26. 8
      ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
  27. 4
      ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs
  28. 22
      ICSharpCode.Decompiler/TypeSystem/TypesHierarchyHelpers.cs
  29. 4
      ICSharpCode.Decompiler/Util/Interval.cs
  30. 16
      ILSpy/AvalonEdit/TextMarkerService.cs
  31. 6
      ILSpy/Controls/ExtensionMethods.cs
  32. 2
      ILSpy/Controls/MarkupExtensions.cs
  33. 6
      ILSpy/ExtensionMethods.cs
  34. 2
      ILSpy/Languages/CSharpLanguage.cs
  35. 47
      ILSpy/Languages/ILAstLanguage.cs
  36. 4
      ILSpy/Languages/Language.cs
  37. 4
      ILSpy/Languages/TextTokenWriter.cs
  38. 6
      ILSpy/LoadedAssembly.cs
  39. 41
      ILSpy/MainWindow.xaml.cs
  40. 10
      ILSpy/Properties/AssemblyInfo.template.cs
  41. 18
      ILSpy/TaskHelper.cs
  42. 4
      ILSpy/TextView/ReferenceElementGenerator.cs
  43. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedAssemblyTreeNode.cs
  44. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedAttributeAppliedToTreeNode.cs
  45. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedEventFiredByTreeNode.cs
  46. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs
  47. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs
  48. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs
  49. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedFieldTreeNode.cs
  50. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs
  51. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs
  52. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs
  53. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs
  54. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs
  55. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs
  56. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs
  57. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs
  58. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs
  59. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs
  60. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs
  61. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs
  62. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs
  63. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeUsedByTreeNode.cs
  64. 2
      ILSpy/TreeNodes/Analyzer/AnalyzedVirtualMethodUsedByTreeNode.cs
  65. 4
      ILSpy/TreeNodes/Analyzer/Helpers.cs
  66. 2
      ILSpy/TreeNodes/AssemblyListTreeNode.cs
  67. 4
      ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs
  68. 2
      ILSpy/TreeNodes/AssemblyTreeNode.cs
  69. 2
      ILSpy/TreeNodes/BaseTypesEntryNode.cs
  70. 2
      ILSpy/TreeNodes/EventTreeNode.cs
  71. 2
      ILSpy/TreeNodes/FieldTreeNode.cs
  72. 2
      ILSpy/TreeNodes/MethodTreeNode.cs
  73. 2
      ILSpy/TreeNodes/ModuleReferenceTreeNode.cs
  74. 2
      ILSpy/TreeNodes/NamespaceTreeNode.cs
  75. 2
      ILSpy/TreeNodes/PropertyTreeNode.cs
  76. 4
      ILSpy/TreeNodes/ResourceNodes/ResourceEntryNode.cs
  77. 2
      ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs
  78. 4
      ILSpy/TreeNodes/TypeTreeNode.cs
  79. 2
      ILSpy/XmlDoc/XmlDocKeyProvider.cs
  80. 2
      ILSpy/XmlDoc/XmlDocLoader.cs

14
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -61,7 +61,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -61,7 +61,11 @@ namespace ICSharpCode.Decompiler.CSharp
new SwitchDetection(),
new LoopDetection(),
new IntroduceExitPoints(),
new ConditionDetection(),
new BlockILTransform( // per-block transforms
new ConditionDetection(),
new LoopingBlockTransform( // per-block transforms that depend on each other, and thus need to loop
)
),
new ILInlining(),
new TransformAssignment(),
new CopyPropagation(),
@ -117,7 +121,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -117,7 +121,7 @@ namespace ICSharpCode.Decompiler.CSharp
public CSharpDecompiler(DecompilerTypeSystem typeSystem, DecompilerSettings settings)
{
if (typeSystem == null)
throw new ArgumentNullException("typeSystem");
throw new ArgumentNullException(nameof(typeSystem));
this.typeSystem = typeSystem;
this.settings = settings;
}
@ -288,7 +292,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -288,7 +292,7 @@ namespace ICSharpCode.Decompiler.CSharp
public SyntaxTree DecompileTypes(IEnumerable<TypeDefinition> types)
{
if (types == null)
throw new ArgumentNullException("types");
throw new ArgumentNullException(nameof(types));
var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainAssembly);
SyntaxTree syntaxTree = new SyntaxTree();
DoDecompileTypes(types, decompilationContext, syntaxTree);
@ -302,7 +306,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -302,7 +306,7 @@ namespace ICSharpCode.Decompiler.CSharp
public SyntaxTree Decompile(params IMemberDefinition[] definitions)
{
if (definitions == null)
throw new ArgumentNullException("definitions");
throw new ArgumentNullException(nameof(definitions));
ITypeDefinition parentTypeDef = null;
var syntaxTree = new SyntaxTree();
foreach (var def in definitions) {
@ -601,7 +605,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -601,7 +605,7 @@ namespace ICSharpCode.Decompiler.CSharp
Debug.Assert(decompilationContext.CurrentMember == field);
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
if (decompilationContext.CurrentTypeDefinition.Kind == TypeKind.Enum) {
var enumDec = new EnumMemberDeclaration() {
var enumDec = new EnumMemberDeclaration {
Name = field.Name,
Initializer = typeSystemAstBuilder.ConvertConstantValue(decompilationContext.CurrentTypeDefinition.EnumUnderlyingType, field.ConstantValue),
};

4
ICSharpCode.Decompiler/CecilExtensions.cs

@ -148,7 +148,7 @@ namespace ICSharpCode.Decompiler @@ -148,7 +148,7 @@ namespace ICSharpCode.Decompiler
public static int GetEndOffset(this Instruction inst)
{
if (inst == null)
throw new ArgumentNullException("inst");
throw new ArgumentNullException(nameof(inst));
return inst.Offset + inst.GetSize();
}
@ -241,7 +241,7 @@ namespace ICSharpCode.Decompiler @@ -241,7 +241,7 @@ namespace ICSharpCode.Decompiler
public static TypeReference GetEnumUnderlyingType(this TypeDefinition type)
{
if (!type.IsEnum)
throw new ArgumentException("Type must be an enum", "type");
throw new ArgumentException("Type must be an enum", nameof(type));
var fields = type.Fields;

2
ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs

@ -321,7 +321,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -321,7 +321,7 @@ namespace ICSharpCode.Decompiler.Disassembler
public static void WriteOperand(ITextOutput writer, object operand)
{
if (operand == null)
throw new ArgumentNullException("operand");
throw new ArgumentNullException(nameof(operand));
Instruction targetInstruction = operand as Instruction;
if (targetInstruction != null) {

2
ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs

@ -39,7 +39,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -39,7 +39,7 @@ namespace ICSharpCode.Decompiler.Disassembler
public MethodBodyDisassembler(ITextOutput output, bool detectControlStructure, CancellationToken cancellationToken)
{
if (output == null)
throw new ArgumentNullException("output");
throw new ArgumentNullException(nameof(output));
this.output = output;
this.detectControlStructure = detectControlStructure;
this.cancellationToken = cancellationToken;

2
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -41,7 +41,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -41,7 +41,7 @@ namespace ICSharpCode.Decompiler.Disassembler
public ReflectionDisassembler(ITextOutput output, bool detectControlStructure, CancellationToken cancellationToken)
{
if (output == null)
throw new ArgumentNullException("output");
throw new ArgumentNullException(nameof(output));
this.output = output;
this.cancellationToken = cancellationToken;
this.methodBodyDisassembler = new MethodBodyDisassembler(output, detectControlStructure, cancellationToken);

2
ICSharpCode.Decompiler/FlowAnalysis/DataFlowVisitor.cs

@ -517,7 +517,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -517,7 +517,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
/// </summary>
protected internal override sealed void VisitTryCatchHandler(TryCatchHandler inst)
{
throw new NotImplementedException();
throw new NotSupportedException();
}
protected internal override void VisitTryFinally(TryFinally inst)

6
ICSharpCode.Decompiler/FlowAnalysis/ReachingDefinitionsVisitor.cs

@ -243,7 +243,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -243,7 +243,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
static BitSet GetActiveVariableBitSet(ILVariableScope scope, Predicate<ILVariable> pred)
{
if (scope == null)
throw new ArgumentNullException("scope");
throw new ArgumentNullException(nameof(scope));
BitSet activeVariables = new BitSet(scope.Variables.Count);
for (int vi = 0; vi < scope.Variables.Count; vi++) {
activeVariables[vi] = pred(scope.Variables[vi]);
@ -259,9 +259,9 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -259,9 +259,9 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
public ReachingDefinitionsVisitor(ILVariableScope scope, BitSet analyzedVariables)
{
if (scope == null)
throw new ArgumentNullException("scope");
throw new ArgumentNullException(nameof(scope));
if (analyzedVariables == null)
throw new ArgumentNullException("analyzedVariables");
throw new ArgumentNullException(nameof(analyzedVariables));
this.scope = scope;
this.analyzedVariables = analyzedVariables;
base.flagsRequiringManualImpl |= InstructionFlags.MayWriteLocals;

2
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -129,6 +129,7 @@ @@ -129,6 +129,7 @@
<Compile Include="IL\Patterns\ListMatch.cs" />
<Compile Include="IL\Patterns\Match.cs" />
<Compile Include="IL\SlotInfo.cs" />
<Compile Include="IL\Transforms\BlockTransform.cs" />
<Compile Include="IL\Transforms\CopyPropagation.cs" />
<Compile Include="IL\Transforms\IILTransform.cs" />
<Compile Include="IL\Transforms\ILInlining.cs" />
@ -138,6 +139,7 @@ @@ -138,6 +139,7 @@
<Compile Include="IL\Transforms\DelegateConstruction.cs" />
<Compile Include="IL\Transforms\RemoveDeadVariableInit.cs" />
<Compile Include="IL\Transforms\SplitVariables.cs" />
<Compile Include="IL\Transforms\Stepper.cs" />
<Compile Include="IL\Transforms\TransformArrayInitializers.cs" />
<Compile Include="CecilExtensions.cs" />
<Compile Include="Disassembler\DisassemblerHelpers.cs" />

84
ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs

@ -33,35 +33,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -33,35 +33,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
/// Blocks should be basic blocks prior to this transform.
/// After this transform, they will be extended basic blocks.
/// </remarks>
public class ConditionDetection : IILTransform, ISingleStep
public class ConditionDetection : IBlockTransform
{
public void Run(ILFunction function, ILTransformContext context)
{
foreach (var container in function.Descendants.OfType<BlockContainer>()) {
Run(container, context);
}
}
public int MaxStepCount { get; set; } = int.MaxValue;
Stepper stepper;
BlockTransformContext context;
BlockContainer currentContainer;
ControlFlowNode[] controlFlowGraph;
void Run(BlockContainer container, ILTransformContext context)
{
stepper = new Stepper(MaxStepCount);
currentContainer = container;
controlFlowGraph = LoopDetection.BuildCFG(container);
Dominance.ComputeDominance(controlFlowGraph[0], context.CancellationToken);
BuildConditionStructure(controlFlowGraph[0]);
// If there are multiple blocks remaining, keep them sorted.
// (otherwise we end up with a more-or-less random order due to the SwapRemove() calls).
container.SortBlocks();
controlFlowGraph = null;
currentContainer = null;
}
/// <summary>
/// Builds structured control flow for the block associated with the control flow node.
/// </summary>
@ -69,13 +44,21 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -69,13 +44,21 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
/// After a block was processed, it should use structured control flow
/// and have just a single 'regular' exit point (last branch instruction in the block)
/// </remarks>
void BuildConditionStructure(ControlFlowNode cfgNode)
public void Run(Block block, BlockTransformContext context)
{
Block block = (Block)cfgNode.UserData;
// First, process the children in the dominator tree.
// This ensures that blocks being embedded into this block are already fully processed.
foreach (var child in cfgNode.DominatorTreeChildren)
BuildConditionStructure(child);
this.context = context;
// We only embed blocks into this block if they aren't referenced anywhere else,
// so those blocks are dominated by this block.
// BlockILTransform thus guarantees that the blocks being embedded are already
// fully processed.
var cfgNode = context.ControlFlowNode;
Debug.Assert(cfgNode.UserData == block);
// Because this transform runs at the beginning of the block transforms,
// we know that `block` is still a (non-extended) basic block.
// Last instruction is one with unreachable endpoint
// (guaranteed by combination of BlockContainer and Block invariants)
Debug.Assert(block.Instructions.Last().HasFlag(InstructionFlags.EndPointUnreachable));
@ -99,38 +82,31 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -99,38 +82,31 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
Debug.Assert(exitInst == block.Instructions.Last());
block.Instructions.RemoveAt(block.Instructions.Count - 1);
block.Instructions.AddRange(targetBlock.Instructions);
DeleteBlockFromContainer(targetBlock);
stepper.Stepped();
targetBlock.Remove();
}
}
void DeleteBlockFromContainer(Block block)
{
Debug.Assert(block.Parent == currentContainer);
Debug.Assert(currentContainer.Blocks[block.ChildIndex] == block);
currentContainer.Blocks.SwapRemoveAt(block.ChildIndex);
}
private void HandleIfInstruction(ControlFlowNode cfgNode, Block block, IfInstruction ifInst, ref ILInstruction exitInst)
{
if (IsBranchToLaterTarget(ifInst.TrueInst, exitInst)) {
// "if (c) goto lateBlock; goto earlierBlock;"
// -> "if (!c)" goto earlierBlock; goto lateBlock;
// This reordering should make the if structure correspond more closely to the original C# source code
context.Step("Negate if", ifInst);
block.Instructions[block.Instructions.Count - 1] = ifInst.TrueInst;
ifInst.TrueInst = exitInst;
exitInst = block.Instructions.Last();
ifInst.Condition = new LogicNot(ifInst.Condition);
stepper.Stepped();
}
ILInstruction trueExitInst;
if (IsUsableBranchToChild(cfgNode, ifInst.TrueInst)) {
// "if (...) goto targetBlock; exitInst;"
// -> "if (...) { targetBlock } exitInst;"
context.Step("Inline block as then-branch", ifInst);
var targetBlock = ((Branch)ifInst.TrueInst).TargetBlock;
// The targetBlock was already processed, we can embed it into the if statement:
DeleteBlockFromContainer(targetBlock);
targetBlock.Remove();
ifInst.TrueInst = targetBlock;
ILInstruction nestedCondition, nestedTrueInst;
while (targetBlock.Instructions.Count > 0
@ -140,6 +116,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -140,6 +116,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (CompatibleExitInstruction(exitInst, nestedTrueInst)) {
// "if (...) { if (nestedCondition) goto exitPoint; ... } goto exitPoint;"
// -> "if (... && !nestedCondition) { ... } goto exitPoint;"
context.Step("Combine 'if (cond1 && !cond2)' in then-branch", ifInst);
ifInst.Condition = IfInstruction.LogicAnd(ifInst.Condition, new LogicNot(nestedCondition));
targetBlock.Instructions.RemoveAt(0);
// Update targetBlock label now that we've removed the first instruction
@ -157,17 +134,18 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -157,17 +134,18 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (CompatibleExitInstruction(exitInst, trueExitInst)) {
// "if (...) { ...; goto exitPoint } goto exitPoint;"
// -> "if (...) { ... } goto exitPoint;"
context.Step("Remove redundant 'goto exitPoint;' in then-branch", ifInst);
targetBlock.Instructions.RemoveAt(targetBlock.Instructions.Count - 1);
trueExitInst = null;
if (targetBlock.Instructions.Count == 1 && targetBlock.Instructions[0].MatchIfInstruction(out nestedCondition, out nestedTrueInst)) {
// "if (...) { if (nestedCondition) nestedTrueInst; } exitInst;"
// --> "if (... && nestedCondition) nestedTrueInst; } exitInst"
context.Step("Combine if conditions into logic.and (in then-branch)", ifInst);
ifInst.Condition = IfInstruction.LogicAnd(ifInst.Condition, nestedCondition);
ifInst.TrueInst = nestedTrueInst;
trueExitInst = (nestedTrueInst as Block)?.Instructions.LastOrDefault();
}
}
stepper.Stepped();
} else {
trueExitInst = ifInst.TrueInst;
}
@ -177,8 +155,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -177,8 +155,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (CompatibleExitInstruction(trueExitInst, falseExitInst)) {
// if (...) { ...; goto exitPoint; } goto nextBlock; nextBlock: ...; goto exitPoint;
// -> if (...) { ... } else { ... } goto exitPoint;
context.Step("Inline block as else-branch", ifInst);
targetBlock.Instructions.RemoveAt(targetBlock.Instructions.Count - 1);
DeleteBlockFromContainer(targetBlock);
targetBlock.Remove();
ifInst.FalseInst = targetBlock;
exitInst = block.Instructions[block.Instructions.Count - 1] = falseExitInst;
Block trueBlock = ifInst.TrueInst as Block;
@ -189,16 +168,15 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -189,16 +168,15 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
Debug.Assert(trueExitInst == ifInst.TrueInst);
ifInst.TrueInst = new Nop { ILRange = ifInst.TrueInst.ILRange };
}
stepper.Stepped();
}
}
if (IsEmpty(ifInst.TrueInst)) {
// prefer empty true-branch to empty-else branch
context.Step("Swap empty then-branch with else-branch", ifInst);
var oldTrue = ifInst.TrueInst;
ifInst.TrueInst = ifInst.FalseInst;
ifInst.FalseInst = new Nop { ILRange = oldTrue.ILRange };
ifInst.Condition = new LogicNot(ifInst.Condition);
stepper.Stepped();
// After swapping, it's possible that we can introduce a short-circuit operator:
Block trueBlock = ifInst.TrueInst as Block;
@ -208,18 +186,18 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -208,18 +186,18 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
&& trueBlock.Instructions[0].MatchIfInstruction(out nestedCondition, out nestedTrueInst)) {
// if (cond) if (nestedCond) nestedTrueInst
// ==> if (cond && nestedCond) nestedTrueInst
context.Step("Combine if conditions into logic.and (after branch swapping)", ifInst);
ifInst.Condition = IfInstruction.LogicAnd(ifInst.Condition, nestedCondition);
ifInst.TrueInst = nestedTrueInst;
stepper.Stepped();
}
} else if (ifInst.FalseInst.OpCode != OpCode.Nop && ifInst.FalseInst.ILRange.Start < ifInst.TrueInst.ILRange.Start) {
// swap true and false branches of if/else construct,
// to bring them in the same order as the IL code
context.Step("Swap then-branch with else-branch", ifInst);
var oldTrue = ifInst.TrueInst;
ifInst.TrueInst = ifInst.FalseInst;
ifInst.FalseInst = oldTrue;
ifInst.Condition = new LogicNot(ifInst.Condition);
stepper.Stepped();
}
}
@ -265,7 +243,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -265,7 +243,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (br == null)
return false;
var targetBlock = br.TargetBlock;
return targetBlock.Parent == currentContainer && cfgNode.Dominates(controlFlowGraph[targetBlock.ChildIndex])
return targetBlock.Parent == context.Container && cfgNode.Dominates(context.GetNode(targetBlock))
&& targetBlock.IncomingEdgeCount == 1 && targetBlock.FinalInstruction.OpCode == OpCode.Nop;
}
@ -299,7 +277,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -299,7 +277,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (IsUsableBranchToChild(cfgNode, section.Body)) {
// case ...: goto targetBlock;
var targetBlock = ((Branch)section.Body).TargetBlock;
DeleteBlockFromContainer(targetBlock);
targetBlock.Remove();
section.Body = targetBlock;
}
}
@ -308,7 +286,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -308,7 +286,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
// switch(...){} goto targetBlock;
// ---> switch(..) { default: { targetBlock } }
var targetBlock = ((Branch)exitInst).TargetBlock;
DeleteBlockFromContainer(targetBlock);
targetBlock.Remove();
sw.DefaultBody = targetBlock;
if (IsBranchOrLeave(targetBlock.Instructions.Last())) {
exitInst = block.Instructions[block.Instructions.Count - 1] = targetBlock.Instructions.Last();

4
ICSharpCode.Decompiler/IL/ILReader.cs

@ -39,7 +39,7 @@ namespace ICSharpCode.Decompiler.IL @@ -39,7 +39,7 @@ namespace ICSharpCode.Decompiler.IL
public ILReader(IDecompilerTypeSystem typeSystem)
{
if (typeSystem == null)
throw new ArgumentNullException("typeSystem");
throw new ArgumentNullException(nameof(typeSystem));
this.typeSystem = typeSystem;
this.compilation = typeSystem.Compilation;
}
@ -63,7 +63,7 @@ namespace ICSharpCode.Decompiler.IL @@ -63,7 +63,7 @@ namespace ICSharpCode.Decompiler.IL
void Init(Cil.MethodBody body)
{
if (body == null)
throw new ArgumentNullException("body");
throw new ArgumentNullException(nameof(body));
this.body = body;
this.currentInstruction = null;
this.nextInstructionIndex = 0;

2
ICSharpCode.Decompiler/IL/ILVariable.cs

@ -155,7 +155,7 @@ namespace ICSharpCode.Decompiler.IL @@ -155,7 +155,7 @@ namespace ICSharpCode.Decompiler.IL
public ILVariable(VariableKind kind, IType type, int index)
{
if (type == null)
throw new ArgumentNullException("type");
throw new ArgumentNullException(nameof(type));
this.Kind = kind;
this.type = type;
this.StackType = type.GetStackType();

15
ICSharpCode.Decompiler/IL/Instructions/Block.cs

@ -196,6 +196,21 @@ namespace ICSharpCode.Decompiler.IL @@ -196,6 +196,21 @@ namespace ICSharpCode.Decompiler.IL
return InstructionFlags.None;
}
}
/// <summary>
/// Deletes this block from its parent container.
/// This may cause the indices of other blocks in that container to change.
///
/// It is an error to call this method on blocks that are not directly within a container.
/// It is also an error to call this method on the entry-point block.
/// </summary>
public void Remove()
{
Debug.Assert(ChildIndex > 0);
var container = (BlockContainer)Parent;
Debug.Assert(container.Blocks[ChildIndex] == this);
container.Blocks.SwapRemoveAt(ChildIndex);
}
}
public enum BlockType {

2
ICSharpCode.Decompiler/IL/Instructions/Branch.cs

@ -45,7 +45,7 @@ namespace ICSharpCode.Decompiler.IL @@ -45,7 +45,7 @@ namespace ICSharpCode.Decompiler.IL
public Branch(Block targetBlock) : base(OpCode.Branch)
{
if (targetBlock == null)
throw new ArgumentNullException("targetBlock");
throw new ArgumentNullException(nameof(targetBlock));
this.targetBlock = targetBlock;
this.targetILOffset = targetBlock.ILRange.Start;
}

1
ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs

@ -79,6 +79,7 @@ namespace ICSharpCode.Decompiler.IL @@ -79,6 +79,7 @@ namespace ICSharpCode.Decompiler.IL
/// </summary>
public void RunTransforms(IEnumerable<IILTransform> transforms, ILTransformContext context)
{
this.CheckInvariant(ILPhase.Normal);
foreach (var transform in transforms) {
context.CancellationToken.ThrowIfCancellationRequested();
transform.Run(this, context);

2
ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs

@ -52,7 +52,7 @@ namespace ICSharpCode.Decompiler.IL @@ -52,7 +52,7 @@ namespace ICSharpCode.Decompiler.IL
protected void ValidateChild(ILInstruction inst)
{
if (inst == null)
throw new ArgumentNullException("inst");
throw new ArgumentNullException(nameof(inst));
Debug.Assert(!this.IsDescendantOf(inst), "ILAst must form a tree");
}

2
ICSharpCode.Decompiler/IL/Instructions/InstructionCollection.cs

@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.IL @@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.IL
public InstructionCollection(ILInstruction parentInstruction, int firstChildIndex)
{
if (parentInstruction == null)
throw new ArgumentNullException("parentInstruction");
throw new ArgumentNullException(nameof(parentInstruction));
this.parentInstruction = parentInstruction;
this.firstChildIndex = firstChildIndex;
}

109
ICSharpCode.Decompiler/IL/Transforms/BlockTransform.cs

@ -0,0 +1,109 @@ @@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.FlowAnalysis;
using ICSharpCode.Decompiler.IL.ControlFlow;
namespace ICSharpCode.Decompiler.IL.Transforms
{
/// <summary>
/// Per-block IL transform.
/// </summary>
public interface IBlockTransform
{
void Run(Block block, BlockTransformContext context);
}
/// <summary>
/// Parameter class holding various arguments for <see cref="IBlockTransform.Run(ILFunction, BlockTransformContext)"/>.
/// </summary>
public class BlockTransformContext : ILTransformContext
{
/// <summary>
/// The container currently being processed.
/// </summary>
public BlockContainer Container { get; set; }
/// <summary>
/// The block to process.
/// </summary>
/// <remarks>
/// Should be identical to the <c>block</c> parameter to <c>IBlockTransform.Run</c>.
/// </remarks>
public Block Block { get; set; }
/// <summary>
/// The control flow node corresponding to the block being processed.
/// </summary>
public ControlFlowNode ControlFlowNode { get; set; }
internal readonly Dictionary<Block, ControlFlowNode> cfg = new Dictionary<Block, ControlFlowNode>();
public BlockTransformContext(ILTransformContext context) : base(context)
{
}
/// <summary>
/// Gets the ControlFlowNode for the block.
/// Precondition: the block belonged to the <c>Container</c> at the start of the block transforms
/// (when the control flow graph was created).
/// </summary>
public ControlFlowNode GetNode(Block block)
{
return cfg[block];
}
}
/// <summary>
/// IL transform that runs a list of per-block transforms.
/// </summary>
public class BlockILTransform : IILTransform
{
readonly IBlockTransform[] blockTransforms;
public BlockILTransform(params IBlockTransform[] blockTransforms)
{
this.blockTransforms = blockTransforms;
}
public void Run(ILFunction function, ILTransformContext context)
{
var blockContext = new BlockTransformContext(context);
foreach (var container in function.Descendants.OfType<BlockContainer>()) {
context.CancellationToken.ThrowIfCancellationRequested();
var cfg = LoopDetection.BuildCFG(container);
Dominance.ComputeDominance(cfg[0], context.CancellationToken);
blockContext.Container = container;
blockContext.cfg.Clear();
for (int i = 0; i < cfg.Length; i++) {
blockContext.cfg.Add(container.Blocks[i], cfg[i]);
}
VisitBlock(cfg[0], blockContext);
// TODO: handle unreachable code?
}
}
void VisitBlock(ControlFlowNode cfgNode, BlockTransformContext context)
{
// First, process the children in the dominator tree.
// The ConditionDetection transform requires dominated blocks to
// be already processed.
foreach (var child in cfgNode.DominatorTreeChildren) {
VisitBlock(child, context);
}
context.ControlFlowNode = cfgNode;
context.Block = (Block)cfgNode.UserData;
context.Block.CheckInvariant(ILPhase.Normal);
foreach (var transform in blockTransforms) {
context.CancellationToken.ThrowIfCancellationRequested();
transform.Run(context.Block, context);
context.Block.CheckInvariant(ILPhase.Normal);
}
}
}
}

70
ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs

@ -30,14 +30,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -30,14 +30,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// <remarks>
/// Should run after inlining so that the expression patterns can be detected.
/// </remarks>
public class ExpressionTransforms : ILVisitor, IILTransform, ISingleStep
public class ExpressionTransforms : ILVisitor, IILTransform
{
public int MaxStepCount { get; set; } = int.MaxValue;
Stepper stepper;
ILTransformContext context;
void IILTransform.Run(ILFunction function, ILTransformContext context)
{
stepper = new Stepper(MaxStepCount);
this.context = context;
function.AcceptVisitor(this);
}
@ -52,19 +51,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -52,19 +51,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
base.VisitComp(inst);
if (inst.Right.MatchLdNull()) {
// comp(left > ldnull) => comp(left != ldnull)
// comp(left <= ldnull) => comp(left == ldnull)
if (inst.Kind == ComparisonKind.GreaterThan)
if (inst.Kind == ComparisonKind.GreaterThan) {
context.Step("comp(left > ldnull) => comp(left != ldnull)", inst);
inst.Kind = ComparisonKind.Inequality;
else if (inst.Kind == ComparisonKind.LessThanOrEqual)
} else if (inst.Kind == ComparisonKind.LessThanOrEqual) {
context.Step("comp(left <= ldnull) => comp(left == ldnull)", inst);
inst.Kind = ComparisonKind.Equality;
}
} else if (inst.Left.MatchLdNull()) {
// comp(ldnull < right) => comp(ldnull != right)
// comp(ldnull >= right) => comp(ldnull == right)
if (inst.Kind == ComparisonKind.LessThan)
if (inst.Kind == ComparisonKind.LessThan) {
context.Step("comp(ldnull < right) => comp(ldnull != right)", inst);
inst.Kind = ComparisonKind.Inequality;
else if (inst.Kind == ComparisonKind.GreaterThanOrEqual)
} else if (inst.Kind == ComparisonKind.GreaterThanOrEqual) {
context.Step("comp(ldnull >= right) => comp(ldnull == right)", inst);
inst.Kind = ComparisonKind.Equality;
}
}
var rightWithoutConv = inst.Right.UnwrapConv(ConversionKind.SignExtend).UnwrapConv(ConversionKind.ZeroExtend);
@ -77,16 +78,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -77,16 +78,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// comp.unsigned(ldlen array > conv i4->i(ldc.i4 0))
// => comp(ldlen.i4 array > ldc.i4 0)
// This is a special case where the C# compiler doesn't generate conv.i4 after ldlen.
context.Step("comp(ldlen.i4 array > ldc.i4 0)", inst);
inst.Left.ReplaceWith(new LdLen(StackType.I4, array) { ILRange = inst.Left.ILRange });
inst.Right = rightWithoutConv;
}
// comp.unsigned(left > ldc.i4 0) => comp(left != ldc.i4 0)
// comp.unsigned(left <= ldc.i4 0) => comp(left == ldc.i4 0)
if (inst.Kind == ComparisonKind.GreaterThan)
if (inst.Kind == ComparisonKind.GreaterThan) {
context.Step("comp.unsigned(left > ldc.i4 0) => comp(left != ldc.i4 0)", inst);
inst.Kind = ComparisonKind.Inequality;
else if (inst.Kind == ComparisonKind.LessThanOrEqual)
} else if (inst.Kind == ComparisonKind.LessThanOrEqual) {
context.Step("comp.unsigned(left <= ldc.i4 0) => comp(left == ldc.i4 0)", inst);
inst.Kind = ComparisonKind.Equality;
stepper.Stepped();
}
}
}
@ -95,10 +97,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -95,10 +97,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
inst.Argument.AcceptVisitor(this);
ILInstruction array;
if (inst.Argument.MatchLdLen(StackType.I, out array) && inst.TargetType.IsIntegerType() && !inst.CheckForOverflow) {
// conv.i4(ldlen array) => ldlen.i4(array)
context.Step("conv.i4(ldlen array) => ldlen.i4(array)", inst);
inst.AddILRange(inst.Argument.ILRange);
inst.ReplaceWith(new LdLen(inst.TargetType.GetStackType(), array) { ILRange = inst.ILRange });
stepper.Stepped();
}
}
@ -106,27 +107,25 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -106,27 +107,25 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
ILInstruction arg, lhs, rhs;
if (inst.Argument.MatchLogicNot(out arg)) {
// logic.not(logic.not(arg))
// ==> arg
context.Step("logic.not(logic.not(arg)) => arg", inst);
Debug.Assert(arg.ResultType == StackType.I4);
arg.AddILRange(inst.ILRange);
arg.AddILRange(inst.Argument.ILRange);
inst.ReplaceWith(arg);
stepper.Stepped();
arg.AcceptVisitor(this);
} else if (inst.Argument is Comp) {
Comp comp = (Comp)inst.Argument;
if (comp.InputType != StackType.F || comp.Kind.IsEqualityOrInequality()) {
// push negation into comparison:
context.Step("push negation into comparison", inst);
comp.Kind = comp.Kind.Negate();
comp.AddILRange(inst.ILRange);
inst.ReplaceWith(comp);
stepper.Stepped();
}
comp.AcceptVisitor(this);
} else if (inst.Argument.MatchLogicAnd(out lhs, out rhs)) {
// logic.not(if (lhs) rhs else ldc.i4 0)
// ==> if (logic.not(lhs)) ldc.i4 1 else logic.not(rhs)
context.Step("push negation into logic.and", inst);
IfInstruction ifInst = (IfInstruction)inst.Argument;
var ldc0 = ifInst.FalseInst;
Debug.Assert(ldc0.MatchLdcI4(0));
@ -134,11 +133,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -134,11 +133,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
ifInst.TrueInst = new LdcI4(1) { ILRange = ldc0.ILRange };
ifInst.FalseInst = new LogicNot(rhs) { ILRange = inst.ILRange };
inst.ReplaceWith(ifInst);
stepper.Stepped();
ifInst.AcceptVisitor(this);
} else if (inst.Argument.MatchLogicOr(out lhs, out rhs)) {
// logic.not(if (lhs) ldc.i4 1 else rhs)
// ==> if (logic.not(lhs)) logic.not(rhs) else ldc.i4 0)
context.Step("push negation into logic.or", inst);
IfInstruction ifInst = (IfInstruction)inst.Argument;
var ldc1 = ifInst.TrueInst;
Debug.Assert(ldc1.MatchLdcI4(1));
@ -146,7 +145,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -146,7 +145,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms
ifInst.TrueInst = new LogicNot(rhs) { ILRange = inst.ILRange };
ifInst.FalseInst = new LdcI4(0) { ILRange = ldc1.ILRange };
inst.ReplaceWith(ifInst);
stepper.Stepped();
ifInst.AcceptVisitor(this);
} else {
inst.Argument.AcceptVisitor(this);
@ -157,7 +155,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -157,7 +155,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
if (inst.Method.IsConstructor && !inst.Method.IsStatic && inst.Method.DeclaringType.Kind == TypeKind.Struct) {
Debug.Assert(inst.Arguments.Count == inst.Method.Parameters.Count + 1);
// Transform call to struct constructor:
context.Step("Transform call to struct constructor", inst);
// call(ref, ...)
// => stobj(ref, newobj(...))
var newObj = new NewObj(inst.Method);
@ -165,7 +163,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -165,7 +163,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms
newObj.Arguments.AddRange(inst.Arguments.Skip(1));
var expr = new StObj(inst.Arguments[0], newObj, inst.Method.DeclaringType);
inst.ReplaceWith(expr);
stepper.Stepped();
// Both the StObj and the NewObj may trigger further rules, so continue visiting the replacement:
VisitStObj(expr);
} else {
@ -177,8 +174,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -177,8 +174,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
LdcDecimal decimalConstant;
if (TransformDecimalCtorToConstant(inst, out decimalConstant)) {
context.Step("TransformDecimalCtorToConstant", inst);
inst.ReplaceWith(decimalConstant);
stepper.Stepped();
return;
}
base.VisitNewObj(inst);
@ -220,20 +217,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -220,20 +217,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms
&& inst.UnalignedPrefix == 0
&& !inst.IsVolatile)
{
// stobj(ldloca(v), ...)
// => stloc(v, ...)
context.Step("stobj(ldloca(v), ...) => stloc(v, ...)", inst);
inst.ReplaceWith(new StLoc(v, inst.Value));
stepper.Stepped();
}
ILInstruction target;
IType t;
BinaryNumericInstruction binary = inst.Value as BinaryNumericInstruction;
if (binary != null && binary.Left.MatchLdObj(out target, out t) && inst.Target.Match(target).Success) {
context.Step("compound assignment", inst);
// stobj(target, binary.op(ldobj(target), ...))
// => compound.op(target, ...)
inst.ReplaceWith(new CompoundAssignmentInstruction(binary.Operator, binary.Left, binary.Right, t, binary.CheckForOverflow, binary.Sign, CompoundAssignmentType.EvaluatesToNewValue));
stepper.Stepped();
}
}
@ -243,6 +238,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -243,6 +238,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// if (cond) ldc.i4 0 else RHS --> if (!cond) RHS else ldc.i4 0
// if (cond) RHS else ldc.i4 1 --> if (!cond) ldc.i4 1 else RHS
if (inst.TrueInst.MatchLdcI4(0) || inst.FalseInst.MatchLdcI4(1)) {
context.Step("canonicalize logic and/or", inst);
var t = inst.TrueInst;
inst.TrueInst = inst.FalseInst;
inst.FalseInst = t;
@ -258,11 +254,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -258,11 +254,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
Block falseInst = inst.FalseInst as Block;
if (falseInst == null || falseInst.Instructions.Count != 1)
return;
ILVariable v1, v2;
ILVariable v;
ILInstruction value1, value2;
if (trueInst.Instructions[0].MatchStLoc(out v1, out value1) && falseInst.Instructions[0].MatchStLoc(out v2, out value2) && v1 == v2) {
inst.ReplaceWith(new StLoc(v1, new IfInstruction(new LogicNot(inst.Condition), value2, value1)));
stepper.Stepped();
if (trueInst.Instructions[0].MatchStLoc(out v, out value1) && falseInst.Instructions[0].MatchStLoc(v, out value2)) {
context.Step("conditional operator", inst);
inst.ReplaceWith(new StLoc(v, new IfInstruction(new LogicNot(inst.Condition), value2, value1)));
}
}
}

63
ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs

@ -17,71 +17,48 @@ @@ -17,71 +17,48 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Diagnostics;
using System.Threading;
namespace ICSharpCode.Decompiler.IL.Transforms
{
/// <summary>
/// Parameter class holding various arguments for <see cref="IILTransform.Run(ILFunction, ILTransformContext)"/>.
/// Per-function IL transform.
/// </summary>
public class ILTransformContext
{
public IDecompilerTypeSystem TypeSystem { get; set; }
public DecompilerSettings Settings { get; set; }
public CancellationToken CancellationToken { get; set; }
}
public interface IILTransform
{
void Run(ILFunction function, ILTransformContext context);
}
/// <summary>
/// Interface for transforms that can be "single-stepped" for debug purposes.
///
/// After the transform has performed MaxStepCount steps, it throws a
/// <see cref="StepLimitReachedException"/>.
/// </summary>
public interface ISingleStep
{
/// <summary>
/// Limits the number of steps performed by the transform.
///
/// The default is int.MaxValue = unlimited.
/// </summary>
int MaxStepCount { get; set; }
}
/// <summary>
/// Exception thrown when an IL transform runs into the <see cref="ISingleStep.MaxStepCount"/> limit.
/// Parameter class holding various arguments for <see cref="IILTransform.Run(ILFunction, ILTransformContext)"/>.
/// </summary>
public class StepLimitReachedException : Exception
public class ILTransformContext
{
}
public IDecompilerTypeSystem TypeSystem { get; set; }
public DecompilerSettings Settings { get; set; }
public CancellationToken CancellationToken { get; set; }
public Stepper Stepper { get; set; }
/// <summary>
/// Helper struct for use in transforms that implement ISingleStep.
/// </summary>
internal struct Stepper
{
public readonly int MaxStepCount;
public int StepCount;
public ILTransformContext()
{
}
public Stepper(int maxStepCount)
public ILTransformContext(ILTransformContext context)
{
this.StepCount = 0;
this.MaxStepCount = maxStepCount;
if (maxStepCount == 0)
throw new StepLimitReachedException();
this.TypeSystem = context.TypeSystem;
this.Settings = context.Settings;
this.CancellationToken = context.CancellationToken;
}
/// <summary>
/// Called immediately after a transform step was taken.
/// Call this method immediately before performing a transform step.
/// Unlike <c>context.Stepper.Step()</c>, calls to this method are only compiled in debug builds.
/// </summary>
public void Stepped()
[Conditional("STEP")]
internal void Step(string description, ILInstruction near)
{
if (++StepCount == MaxStepCount)
throw new StepLimitReachedException();
Stepper.Step(description, near);
}
}
}

50
ICSharpCode.Decompiler/IL/Transforms/LoopingTransform.cs

@ -19,33 +19,67 @@ @@ -19,33 +19,67 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.Immutable;
namespace ICSharpCode.Decompiler.IL.Transforms
{
/// <summary>
/// Repeats the child transforms until the ILAst no longer changes.
/// </summary>
public class LoopingTransform : IILTransform, ISingleStep
public class LoopingTransform : IILTransform
{
public int MaxStepCount { get; set; } = int.MaxValue;
readonly IReadOnlyCollection<IILTransform> children;
readonly IILTransform[] children;
public LoopingTransform(params IILTransform[] children)
{
this.children = children;
}
public void Run(ILFunction function, ILTransformContext context)
{
var stepper = new Stepper(MaxStepCount);
do {
function.ResetDirty();
function.RunTransforms(children, context);
stepper.Stepped();
function.CheckInvariant(ILPhase.Normal);
foreach (var transform in children) {
context.CancellationToken.ThrowIfCancellationRequested();
transform.Run(function, context);
function.CheckInvariant(ILPhase.Normal);
}
} while (function.IsDirty);
}
public IReadOnlyCollection<IILTransform> Transforms {
public IReadOnlyCollection<IILTransform> Transforms
{
get { return children; }
}
}
/// <summary>
/// Repeats the child transforms until the ILAst no longer changes.
/// </summary>
public class LoopingBlockTransform : IBlockTransform
{
readonly IBlockTransform[] children;
public LoopingBlockTransform(params IBlockTransform[] children)
{
this.children = children;
}
public void Run(Block block, BlockTransformContext context)
{
do {
block.ResetDirty();
block.CheckInvariant(ILPhase.Normal);
foreach (var transform in children) {
context.CancellationToken.ThrowIfCancellationRequested();
transform.Run(block, context);
block.CheckInvariant(ILPhase.Normal);
}
} while (block.IsDirty);
}
public IReadOnlyCollection<IBlockTransform> Transforms {
get { return children; }
}
}

64
ICSharpCode.Decompiler/IL/Transforms/Stepper.cs

@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
// Copyright (c) 2016 Daniel Grunwald
//
// 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;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL.Transforms
{
/// <summary>
/// Exception thrown when an IL transform runs into the <see cref="Stepper.MaxStepCount"/> limit.
/// </summary>
public class StepLimitReachedException : Exception
{
}
/// <summary>
/// Helper class that manages recording transform steps.
/// </summary>
public class Stepper
{
/// <summary>
/// Gets whether stepping of built-in transforms is supported in this build of ICSharpCode.Decompiler.
/// Usually only debug builds support transform stepping.
/// </summary>
public static bool SteppingAvailable {
get {
#if STEP
return true;
#else
return false;
#endif
}
}
/// <summary>
/// Call this method immediately before performing a transform step.
/// Used for debugging the IL transforms. Has no effect in release mode.
///
/// May throw <see cref="StepLimitReachedException"/> in debug mode.
/// </summary>
public void Step(string description, ILInstruction near)
{
// TODO: implement stepping
}
}
}

2
ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs

@ -454,7 +454,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -454,7 +454,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
case TypeCode.Double:
return 8;
default:
throw new ArgumentOutOfRangeException("elementType");
throw new ArgumentOutOfRangeException(nameof(elementType));
}
}
}

2
ICSharpCode.Decompiler/Output/PlainTextOutput.cs

@ -34,7 +34,7 @@ namespace ICSharpCode.Decompiler @@ -34,7 +34,7 @@ namespace ICSharpCode.Decompiler
public PlainTextOutput(TextWriter writer)
{
if (writer == null)
throw new ArgumentNullException("writer");
throw new ArgumentNullException(nameof(writer));
this.writer = writer;
}

2
ICSharpCode.Decompiler/Output/TextOutputWriter.cs

@ -29,7 +29,7 @@ namespace ICSharpCode.Decompiler @@ -29,7 +29,7 @@ namespace ICSharpCode.Decompiler
public TextOutputWriter(ITextOutput output)
{
if (output == null)
throw new ArgumentNullException("output");
throw new ArgumentNullException(nameof(output));
this.output = output;
}

11
ICSharpCode.Decompiler/Properties/AssemblyInfo.template.cs

@ -5,6 +5,7 @@ using System.Resources; @@ -5,6 +5,7 @@ using System.Resources;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Diagnostics.CodeAnalysis;
#endregion
@ -12,7 +13,7 @@ using System.Runtime.InteropServices; @@ -12,7 +13,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyDescription("IL decompiler engine")]
[assembly: AssemblyCompany("ic#code")]
[assembly: AssemblyProduct("ILSpy")]
[assembly: AssemblyCopyright("Copyright 2011-2015 AlphaSierraPapa for the SharpDevelop Team")]
[assembly: AssemblyCopyright("Copyright 2011-2016 AlphaSierraPapa for the SharpDevelop Team")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@ -24,7 +25,11 @@ using System.Runtime.InteropServices; @@ -24,7 +25,11 @@ using System.Runtime.InteropServices;
[assembly: AssemblyInformationalVersion("$INSERTVERSION$$INSERTBRANCHPOSTFIX$$INSERTVERSIONNAMEPOSTFIX$-$INSERTSHORTCOMMITHASH$")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly",
[assembly: InternalsVisibleTo("ICSharpCode.Decompiler.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001004dcf3979c4e902efa4dd2163a039701ed5822e6f1134d77737296abbb97bf0803083cfb2117b4f5446a217782f5c7c634f9fe1fc60b4c11d62c5b3d33545036706296d31903ddcf750875db38a8ac379512f51620bb948c94d0831125fbc5fe63707cbb93f48c1459c4d1749eb7ac5e681a2f0d6d7c60fa527a3c0b8f92b02bf")]
[assembly: SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly",
Justification = "AssemblyInformationalVersion does not need to be a parsable version")]
[assembly: InternalsVisibleTo("ICSharpCode.Decompiler.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001004dcf3979c4e902efa4dd2163a039701ed5822e6f1134d77737296abbb97bf0803083cfb2117b4f5446a217782f5c7c634f9fe1fc60b4c11d62c5b3d33545036706296d31903ddcf750875db38a8ac379512f51620bb948c94d0831125fbc5fe63707cbb93f48c1459c4d1749eb7ac5e681a2f0d6d7c60fa527a3c0b8f92b02bf")]
[assembly: SuppressMessage("Language Usage Opportunities", "RECS0091:Use 'var' keyword when possible")]
[assembly: SuppressMessage("Redundancies in Code", "RECS0113:Redundant comma in array initializer")]

8
ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

@ -44,7 +44,7 @@ namespace ICSharpCode.Decompiler @@ -44,7 +44,7 @@ namespace ICSharpCode.Decompiler
public DecompilerTypeSystem(ModuleDefinition moduleDefinition)
{
if (moduleDefinition == null)
throw new ArgumentNullException("moduleDefinition");
throw new ArgumentNullException(nameof(moduleDefinition));
this.moduleDefinition = moduleDefinition;
CecilLoader mainAssemblyCecilLoader = new CecilLoader { IncludeInternalMembers = true, LazyLoad = true, OnEntityLoaded = StoreMemberReference, ShortenInterfaceImplNames = false };
CecilLoader referencedAssemblyCecilLoader = new CecilLoader { IncludeInternalMembers = true, LazyLoad = true, ShortenInterfaceImplNames = false };
@ -134,7 +134,7 @@ namespace ICSharpCode.Decompiler @@ -134,7 +134,7 @@ namespace ICSharpCode.Decompiler
public IField Resolve(FieldReference fieldReference)
{
if (fieldReference == null)
throw new ArgumentNullException("fieldReference");
throw new ArgumentNullException(nameof(fieldReference));
lock (fieldLookupCache) {
IField field;
if (!fieldLookupCache.TryGetValue(fieldReference, out field)) {
@ -191,7 +191,7 @@ namespace ICSharpCode.Decompiler @@ -191,7 +191,7 @@ namespace ICSharpCode.Decompiler
public IMethod Resolve(MethodReference methodReference)
{
if (methodReference == null)
throw new ArgumentNullException("methodReference");
throw new ArgumentNullException(nameof(methodReference));
lock (methodLookupCache) {
IMethod method;
if (!methodLookupCache.TryGetValue(methodReference, out method)) {
@ -325,7 +325,7 @@ namespace ICSharpCode.Decompiler @@ -325,7 +325,7 @@ namespace ICSharpCode.Decompiler
public IProperty Resolve(PropertyReference propertyReference)
{
if (propertyReference == null)
throw new ArgumentNullException("propertyReference");
throw new ArgumentNullException(nameof(propertyReference));
lock (propertyLookupCache) {
IProperty property;
if (!propertyLookupCache.TryGetValue(propertyReference, out property)) {

4
ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs

@ -32,9 +32,9 @@ namespace ICSharpCode.Decompiler @@ -32,9 +32,9 @@ namespace ICSharpCode.Decompiler
public SpecializingDecompilerTypeSystem(IDecompilerTypeSystem context, TypeParameterSubstitution substitution)
{
if (context == null)
throw new ArgumentNullException("context");
throw new ArgumentNullException(nameof(context));
if (substitution == null)
throw new ArgumentNullException("substitution");
throw new ArgumentNullException(nameof(substitution));
this.context = context;
this.substitution = substitution;
}

22
ICSharpCode.Decompiler/TypeSystem/TypesHierarchyHelpers.cs

@ -57,9 +57,9 @@ namespace ICSharpCode.Decompiler.Ast @@ -57,9 +57,9 @@ namespace ICSharpCode.Decompiler.Ast
public static bool IsBaseMethod(MethodDefinition parentMethod, MethodDefinition childMethod)
{
if (parentMethod == null)
throw new ArgumentNullException("parentMethod");
throw new ArgumentNullException(nameof(parentMethod));
if (childMethod == null)
throw new ArgumentNullException("childMethod");
throw new ArgumentNullException(nameof(childMethod));
if (parentMethod.Name != childMethod.Name)
return false;
@ -81,9 +81,9 @@ namespace ICSharpCode.Decompiler.Ast @@ -81,9 +81,9 @@ namespace ICSharpCode.Decompiler.Ast
public static bool IsBaseProperty(PropertyDefinition parentProperty, PropertyDefinition childProperty)
{
if (parentProperty == null)
throw new ArgumentNullException("parentProperty");
throw new ArgumentNullException(nameof(parentProperty));
if (childProperty == null)
throw new ArgumentNullException("childProperty");
throw new ArgumentNullException(nameof(childProperty));
if (parentProperty.Name != childProperty.Name)
return false;
@ -111,7 +111,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -111,7 +111,7 @@ namespace ICSharpCode.Decompiler.Ast
public static IEnumerable<MethodDefinition> FindBaseMethods(MethodDefinition method)
{
if (method == null)
throw new ArgumentNullException("method");
throw new ArgumentNullException(nameof(method));
var typeContext = CreateGenericContext(method.DeclaringType);
var gMethod = typeContext.ApplyTo(method);
@ -133,7 +133,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -133,7 +133,7 @@ namespace ICSharpCode.Decompiler.Ast
public static IEnumerable<PropertyDefinition> FindBaseProperties(PropertyDefinition property)
{
if (property == null)
throw new ArgumentNullException("property");
throw new ArgumentNullException(nameof(property));
if ((property.GetMethod ?? property.SetMethod).HasOverrides)
yield break;
@ -158,7 +158,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -158,7 +158,7 @@ namespace ICSharpCode.Decompiler.Ast
public static IEnumerable<EventDefinition> FindBaseEvents(EventDefinition eventDef)
{
if (eventDef == null)
throw new ArgumentNullException("eventDef");
throw new ArgumentNullException(nameof(eventDef));
var typeContext = CreateGenericContext(eventDef.DeclaringType);
var gEvent = typeContext.ApplyTo(eventDef);
@ -183,9 +183,9 @@ namespace ICSharpCode.Decompiler.Ast @@ -183,9 +183,9 @@ namespace ICSharpCode.Decompiler.Ast
public static bool IsVisibleFromDerived(IMemberDefinition baseMember, TypeDefinition derivedType)
{
if (baseMember == null)
throw new ArgumentNullException("baseMember");
throw new ArgumentNullException(nameof(baseMember));
if (derivedType == null)
throw new ArgumentNullException("derivedType");
throw new ArgumentNullException(nameof(derivedType));
MethodAttributes attrs = GetAccessAttributes(baseMember) & MethodAttributes.MemberAccessMask;
if (attrs == MethodAttributes.Private)
@ -399,7 +399,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -399,7 +399,7 @@ namespace ICSharpCode.Decompiler.Ast
public GenericContext(T item)
{
if (item == null)
throw new ArgumentNullException("item");
throw new ArgumentNullException(nameof(item));
Item = item;
TypeArguments = Empty;
@ -408,7 +408,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -408,7 +408,7 @@ namespace ICSharpCode.Decompiler.Ast
public GenericContext(T item, IEnumerable<TypeReference> typeArguments)
{
if (item == null)
throw new ArgumentNullException("item");
throw new ArgumentNullException(nameof(item));
Item = item;
var list = new List<TypeReference>();

4
ICSharpCode.Decompiler/Util/Interval.cs

@ -57,7 +57,7 @@ namespace ICSharpCode.Decompiler @@ -57,7 +57,7 @@ namespace ICSharpCode.Decompiler
public Interval(int start, int end)
{
if (!(start <= unchecked(end - 1) || start == end))
throw new ArgumentException("The end must be after the start", "end");
throw new ArgumentException("The end must be after the start", nameof(end));
this.Start = start;
this.End = end;
}
@ -179,7 +179,7 @@ namespace ICSharpCode.Decompiler @@ -179,7 +179,7 @@ namespace ICSharpCode.Decompiler
public LongInterval(long start, long end)
{
if (!(start <= unchecked(end - 1) || start == end))
throw new ArgumentException("The end must be after the start", "end");
throw new ArgumentException("The end must be after the start", nameof(end));
this.Start = start;
this.End = end;
}

16
ILSpy/AvalonEdit/TextMarkerService.cs

@ -40,7 +40,7 @@ namespace ICSharpCode.ILSpy.AvalonEdit @@ -40,7 +40,7 @@ namespace ICSharpCode.ILSpy.AvalonEdit
public TextMarkerService(TextView textView)
{
if (textView == null)
throw new ArgumentNullException("textView");
throw new ArgumentNullException(nameof(textView));
this.textView = textView;
textView.DocumentChanged += OnDocumentChanged;
OnDocumentChanged(null, null);
@ -62,9 +62,9 @@ namespace ICSharpCode.ILSpy.AvalonEdit @@ -62,9 +62,9 @@ namespace ICSharpCode.ILSpy.AvalonEdit
int textLength = textView.Document.TextLength;
if (startOffset < 0 || startOffset > textLength)
throw new ArgumentOutOfRangeException("startOffset", startOffset, "Value must be between 0 and " + textLength);
throw new ArgumentOutOfRangeException(nameof(startOffset), startOffset, "Value must be between 0 and " + textLength);
if (length < 0 || startOffset + length > textLength)
throw new ArgumentOutOfRangeException("length", length, "length must not be negative and startOffset+length must not be after the end of the document");
throw new ArgumentOutOfRangeException(nameof(length), length, "length must not be negative and startOffset+length must not be after the end of the document");
TextMarker m = new TextMarker(this, startOffset, length);
markers.Add(m);
@ -87,7 +87,7 @@ namespace ICSharpCode.ILSpy.AvalonEdit @@ -87,7 +87,7 @@ namespace ICSharpCode.ILSpy.AvalonEdit
public void RemoveAll(Predicate<ITextMarker> predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
throw new ArgumentNullException(nameof(predicate));
if (markers != null) {
foreach (TextMarker m in markers.ToArray()) {
if (predicate(m))
@ -99,7 +99,7 @@ namespace ICSharpCode.ILSpy.AvalonEdit @@ -99,7 +99,7 @@ namespace ICSharpCode.ILSpy.AvalonEdit
public void Remove(ITextMarker marker)
{
if (marker == null)
throw new ArgumentNullException("marker");
throw new ArgumentNullException(nameof(marker));
TextMarker m = marker as TextMarker;
if (markers != null && markers.Remove(m)) {
Redraw(m);
@ -164,9 +164,9 @@ namespace ICSharpCode.ILSpy.AvalonEdit @@ -164,9 +164,9 @@ namespace ICSharpCode.ILSpy.AvalonEdit
public void Draw(ICSharpCode.AvalonEdit.Rendering.TextView textView, DrawingContext drawingContext)
{
if (textView == null)
throw new ArgumentNullException("textView");
throw new ArgumentNullException(nameof(textView));
if (drawingContext == null)
throw new ArgumentNullException("drawingContext");
throw new ArgumentNullException(nameof(drawingContext));
if (markers == null || !textView.VisualLinesValid)
return;
var visualLines = textView.VisualLines;
@ -245,7 +245,7 @@ namespace ICSharpCode.ILSpy.AvalonEdit @@ -245,7 +245,7 @@ namespace ICSharpCode.ILSpy.AvalonEdit
public TextMarker(TextMarkerService service, int startOffset, int length)
{
if (service == null)
throw new ArgumentNullException("service");
throw new ArgumentNullException(nameof(service));
this.service = service;
this.StartOffset = startOffset;
this.Length = length;

6
ILSpy/Controls/ExtensionMethods.cs

@ -37,11 +37,11 @@ namespace ICSharpCode.ILSpy.Controls @@ -37,11 +37,11 @@ namespace ICSharpCode.ILSpy.Controls
// This method was copied from ICSharpCode.Core.Presentation (with permission to switch license to X11)
if (targetObject == null)
throw new ArgumentNullException("targetObject");
throw new ArgumentNullException(nameof(targetObject));
if (property == null)
throw new ArgumentNullException("property");
throw new ArgumentNullException(nameof(property));
if (markupExtension == null)
throw new ArgumentNullException("markupExtension");
throw new ArgumentNullException(nameof(markupExtension));
var serviceProvider = new SetValueToExtensionServiceProvider(targetObject, property);
targetObject.SetValue(property, markupExtension.ProvideValue(serviceProvider));

2
ILSpy/Controls/MarkupExtensions.cs

@ -39,7 +39,7 @@ namespace ICSharpCode.ILSpy.Controls @@ -39,7 +39,7 @@ namespace ICSharpCode.ILSpy.Controls
public ControlColor(float val)
{
if (!(val >= 105 && val <= 255))
throw new ArgumentOutOfRangeException("val");
throw new ArgumentOutOfRangeException(nameof(val));
this.val = val;
}

6
ILSpy/ExtensionMethods.cs

@ -38,11 +38,11 @@ namespace ICSharpCode.ILSpy @@ -38,11 +38,11 @@ namespace ICSharpCode.ILSpy
public static int BinarySearch<T>(this IList<T> list, T item, int start, int count, IComparer<T> comparer)
{
if (list == null)
throw new ArgumentNullException("list");
throw new ArgumentNullException(nameof(list));
if (start < 0 || start >= list.Count)
throw new ArgumentOutOfRangeException("start", start, "Value must be between 0 and " + (list.Count - 1));
throw new ArgumentOutOfRangeException(nameof(start), start, "Value must be between 0 and " + (list.Count - 1));
if (count < 0 || count > list.Count - start)
throw new ArgumentOutOfRangeException("count", count, "Value must be between 0 and " + (list.Count - start));
throw new ArgumentOutOfRangeException(nameof(count), count, "Value must be between 0 and " + (list.Count - start));
int end = start + count - 1;
while (start <= end) {
int pivot = (start + end) / 2;

2
ILSpy/Languages/CSharpLanguage.cs

@ -410,7 +410,7 @@ namespace ICSharpCode.ILSpy @@ -410,7 +410,7 @@ namespace ICSharpCode.ILSpy
public override string FormatPropertyName(PropertyDefinition property, bool? isIndexer)
{
if (property == null)
throw new ArgumentNullException("property");
throw new ArgumentNullException(nameof(property));
if (!isIndexer.HasValue) {
isIndexer = property.IsIndexer();

47
ILSpy/Languages/ILAstLanguage.cs

@ -105,11 +105,7 @@ namespace ICSharpCode.ILSpy @@ -105,11 +105,7 @@ namespace ICSharpCode.ILSpy
static ILAstLanguage MakeDebugLanguage(IEnumerable<IILTransform> transforms)
{
var list = transforms.ToList();
if (list.LastOrDefault() is ISingleStep)
return new SingleSteppableIL(list);
else
return new BlockIL(list);
return new BlockIL(transforms.ToList());
}
public override string FileExtension {
@ -118,10 +114,10 @@ namespace ICSharpCode.ILSpy @@ -118,10 +114,10 @@ namespace ICSharpCode.ILSpy
}
}
public override string TypeToString(TypeReference t, bool includeNamespace, ICustomAttributeProvider attributeProvider = null)
public override string TypeToString(TypeReference type, bool includeNamespace, ICustomAttributeProvider typeAttributes = null)
{
PlainTextOutput output = new PlainTextOutput();
t.WriteTo(output, includeNamespace ? ILNameSyntax.TypeName : ILNameSyntax.ShortTypeName);
type.WriteTo(output, includeNamespace ? ILNameSyntax.TypeName : ILNameSyntax.ShortTypeName);
return output.ToString();
}
@ -169,43 +165,6 @@ namespace ICSharpCode.ILSpy @@ -169,43 +165,6 @@ namespace ICSharpCode.ILSpy
il.WriteTo(output);
}
}
class SingleSteppableIL : ILAstLanguage, ISingleStep
{
readonly IReadOnlyList<IILTransform> transforms;
readonly ISingleStep steppingTransform;
public SingleSteppableIL(IReadOnlyList<IILTransform> transforms) : base("ILAst (" + transforms.Last().GetType().Name + ")")
{
this.transforms = transforms;
this.steppingTransform = (ISingleStep)transforms.Last();
}
public int MaxStepCount { get; set; } = int.MaxValue;
public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options)
{
base.DecompileMethod(method, output, options);
output.WriteLine("// This transform support single-stepping. Press '+' or '-' to change the step limit.");
output.WriteLine("// Current step limit: " + MaxStepCount);
if (!method.HasBody)
return;
var typeSystem = new DecompilerTypeSystem(method.Module);
ILReader reader = new ILReader(typeSystem);
ILFunction il = reader.ReadIL(method.Body, options.CancellationToken);
steppingTransform.MaxStepCount = this.MaxStepCount;
try {
il.RunTransforms(transforms, new ILTransformContext { Settings = options.DecompilerSettings, TypeSystem = typeSystem });
output.WriteLine("// The transform ran to completion.");
} catch (StepLimitReachedException) {
output.WriteLine("// The transform was aborted after reaching the step limit.");
} finally {
steppingTransform.MaxStepCount = int.MaxValue; // unlimit again so that other languages can use the transform
}
output.WriteLine();
il.WriteTo(output);
}
}
}
#endif
}

4
ILSpy/Languages/Language.cs

@ -135,14 +135,14 @@ namespace ICSharpCode.ILSpy @@ -135,14 +135,14 @@ namespace ICSharpCode.ILSpy
public virtual string FormatPropertyName(PropertyDefinition property, bool? isIndexer = null)
{
if (property == null)
throw new ArgumentNullException("property");
throw new ArgumentNullException(nameof(property));
return property.Name;
}
public virtual string FormatTypeName(TypeDefinition type)
{
if (type == null)
throw new ArgumentNullException("type");
throw new ArgumentNullException(nameof(type));
return type.Name;
}

4
ILSpy/Languages/TextTokenWriter.cs

@ -45,9 +45,9 @@ namespace ICSharpCode.ILSpy @@ -45,9 +45,9 @@ namespace ICSharpCode.ILSpy
public TextTokenWriter(ITextOutput output, DecompilerSettings settings)
{
if (output == null)
throw new ArgumentNullException("output");
throw new ArgumentNullException(nameof(output));
if (settings == null)
throw new ArgumentNullException("settings");
throw new ArgumentNullException(nameof(settings));
this.output = output;
this.settings = settings;
}

6
ILSpy/LoadedAssembly.cs

@ -38,9 +38,9 @@ namespace ICSharpCode.ILSpy @@ -38,9 +38,9 @@ namespace ICSharpCode.ILSpy
public LoadedAssembly(AssemblyList assemblyList, string fileName, Stream stream = null)
{
if (assemblyList == null)
throw new ArgumentNullException("assemblyList");
throw new ArgumentNullException(nameof(assemblyList));
if (fileName == null)
throw new ArgumentNullException("fileName");
throw new ArgumentNullException(nameof(fileName));
this.assemblyList = assemblyList;
this.fileName = fileName;
@ -217,7 +217,7 @@ namespace ICSharpCode.ILSpy @@ -217,7 +217,7 @@ namespace ICSharpCode.ILSpy
public LoadedAssembly LookupReferencedAssembly(AssemblyNameReference name)
{
if (name == null)
throw new ArgumentNullException("name");
throw new ArgumentNullException(nameof(name));
if (name.IsWindowsRuntime) {
return assemblyList.winRTMetadataLookupCache.GetOrAdd(name.Name, LookupWinRTMetadata);
} else {

41
ILSpy/MainWindow.xaml.cs

@ -92,7 +92,7 @@ namespace ICSharpCode.ILSpy @@ -92,7 +92,7 @@ namespace ICSharpCode.ILSpy
InitToolbar();
ContextMenuProvider.Add(treeView, decompilerTextView);
this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
this.Loaded += MainWindow_Loaded;
}
void SetWindowBounds(Rect bounds)
@ -656,8 +656,11 @@ namespace ICSharpCode.ILSpy @@ -656,8 +656,11 @@ namespace ICSharpCode.ILSpy
string link = "http://msdn.microsoft.com/library/system.reflection.emit.opcodes." + ((Mono.Cecil.Cil.OpCode)reference).Code.ToString().ToLowerInvariant() + ".aspx";
try {
Process.Start(link);
} catch {
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
} catch (Exception) {
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
// Process.Start can throw several errors (not all of them documented),
// just ignore all of them.
}
}
return decompilationTask;
@ -680,7 +683,7 @@ namespace ICSharpCode.ILSpy @@ -680,7 +683,7 @@ namespace ICSharpCode.ILSpy
public void OpenFiles(string[] fileNames, bool focusNode = true)
{
if (fileNames == null)
throw new ArgumentNullException("fileNames");
throw new ArgumentNullException(nameof(fileNames));
if (focusNode)
treeView.UnselectAll();
@ -742,7 +745,7 @@ namespace ICSharpCode.ILSpy @@ -742,7 +745,7 @@ namespace ICSharpCode.ILSpy
if (node != null && node.View(decompilerTextView))
return;
}
decompilationTask = decompilerTextView.DecompileAsync(this.CurrentLanguage, this.SelectedNodes, new DecompilationOptions() { TextViewState = state });
decompilationTask = decompilerTextView.DecompileAsync(this.CurrentLanguage, this.SelectedNodes, new DecompilationOptions { TextViewState = state });
}
void SaveCommandExecuted(object sender, ExecutedRoutedEventArgs e)
@ -753,7 +756,7 @@ namespace ICSharpCode.ILSpy @@ -753,7 +756,7 @@ namespace ICSharpCode.ILSpy
}
this.TextView.SaveToDisk(this.CurrentLanguage,
this.SelectedNodes,
new DecompilationOptions() { FullDecompilation = true });
new DecompilationOptions { FullDecompilation = true });
}
public void RefreshDecompiledView()
@ -778,32 +781,6 @@ namespace ICSharpCode.ILSpy @@ -778,32 +781,6 @@ namespace ICSharpCode.ILSpy
return treeView.GetTopLevelSelection().OfType<ILSpyTreeNode>();
}
}
protected override void OnPreviewKeyDown(KeyEventArgs e)
{
if (CurrentLanguage is Decompiler.IL.Transforms.ISingleStep) {
var step = (Decompiler.IL.Transforms.ISingleStep)CurrentLanguage;
if (e.Key == Key.OemPlus || e.Key == Key.Add) {
if (step.MaxStepCount == int.MaxValue) {
step.MaxStepCount = 0;
} else {
step.MaxStepCount++;
}
DecompileSelectedNodes(recordHistory: false);
e.Handled = true;
} else if (e.Key == Key.OemMinus || e.Key == Key.Subtract) {
if (step.MaxStepCount == 0) {
step.MaxStepCount = int.MaxValue;
} else {
step.MaxStepCount--;
}
DecompileSelectedNodes(recordHistory: false);
e.Handled = true;
}
} else {
base.OnPreviewKeyDown(e);
}
}
#endregion
#region Back/Forward navigation

10
ILSpy/Properties/AssemblyInfo.template.cs

@ -5,6 +5,7 @@ using System.Resources; @@ -5,6 +5,7 @@ using System.Resources;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Diagnostics.CodeAnalysis;
#endregion
@ -27,10 +28,15 @@ using System.Runtime.InteropServices; @@ -27,10 +28,15 @@ using System.Runtime.InteropServices;
[assembly: AssemblyInformationalVersion(RevisionClass.FullVersion + "-$INSERTSHORTCOMMITHASH$")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly",
[assembly: InternalsVisibleTo("ILSpy.AddIn, PublicKey=0024000004800000940000000602000000240000525341310004000001000100653c4a319be4f524972c3c5bba5fd243330f8e900287d9022d7821a63fd0086fd3801e3683dbe9897f2ecc44727023e9b40adcf180730af70c81c54476b3e5ba8b0f07f5132b2c3cc54347a2c1a9d64ebaaaf3cbffc1a18c427981e2a51d53d5ab02536b7550e732f795121c38a0abfdb38596353525d034baf9e6f1fd8ac4ac")]
[assembly: SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly",
Justification = "AssemblyInformationalVersion does not need to be a parsable version")]
[assembly: InternalsVisibleTo("ILSpy.AddIn, PublicKey=0024000004800000940000000602000000240000525341310004000001000100653c4a319be4f524972c3c5bba5fd243330f8e900287d9022d7821a63fd0086fd3801e3683dbe9897f2ecc44727023e9b40adcf180730af70c81c54476b3e5ba8b0f07f5132b2c3cc54347a2c1a9d64ebaaaf3cbffc1a18c427981e2a51d53d5ab02536b7550e732f795121c38a0abfdb38596353525d034baf9e6f1fd8ac4ac")]
[assembly: SuppressMessage("Language Usage Opportunities", "RECS0091:Use 'var' keyword when possible")]
[assembly: SuppressMessage("Redundancies in Code", "RECS0113:Redundant comma in array initializer")]
[assembly: SuppressMessage("Redundancies in Symbol Declarations", "RECS0122:Initializing field with default value is redundant",
Justification = "Explicit default initialization is necessary to avoid compiler warning with MEF")]
internal static class RevisionClass
{

18
ILSpy/TaskHelper.cs

@ -91,35 +91,35 @@ namespace ICSharpCode.ILSpy @@ -91,35 +91,35 @@ namespace ICSharpCode.ILSpy
public static Task Then<T>(this Task<T> task, Action<T> action)
{
if (action == null)
throw new ArgumentNullException("action");
throw new ArgumentNullException(nameof(action));
return task.ContinueWith(t => action(t.Result), CancellationToken.None, TaskContinuationOptions.NotOnCanceled, TaskScheduler.FromCurrentSynchronizationContext());
}
public static Task<U> Then<T, U>(this Task<T> task, Func<T, U> func)
{
if (func == null)
throw new ArgumentNullException("func");
throw new ArgumentNullException(nameof(func));
return task.ContinueWith(t => func(t.Result), CancellationToken.None, TaskContinuationOptions.NotOnCanceled, TaskScheduler.FromCurrentSynchronizationContext());
}
public static Task Then<T>(this Task<T> task, Func<T, Task> asyncFunc)
{
if (asyncFunc == null)
throw new ArgumentNullException("asyncFunc");
throw new ArgumentNullException(nameof(asyncFunc));
return task.ContinueWith(t => asyncFunc(t.Result), CancellationToken.None, TaskContinuationOptions.NotOnCanceled, TaskScheduler.FromCurrentSynchronizationContext()).Unwrap();
}
public static Task<U> Then<T, U>(this Task<T> task, Func<T, Task<U>> asyncFunc)
{
if (asyncFunc == null)
throw new ArgumentNullException("asyncFunc");
throw new ArgumentNullException(nameof(asyncFunc));
return task.ContinueWith(t => asyncFunc(t.Result), CancellationToken.None, TaskContinuationOptions.NotOnCanceled, TaskScheduler.FromCurrentSynchronizationContext()).Unwrap();
}
public static Task Then(this Task task, Action action)
{
if (action == null)
throw new ArgumentNullException("action");
throw new ArgumentNullException(nameof(action));
return task.ContinueWith(t => {
t.Wait();
action();
@ -129,7 +129,7 @@ namespace ICSharpCode.ILSpy @@ -129,7 +129,7 @@ namespace ICSharpCode.ILSpy
public static Task<U> Then<U>(this Task task, Func<U> func)
{
if (func == null)
throw new ArgumentNullException("func");
throw new ArgumentNullException(nameof(func));
return task.ContinueWith(t => {
t.Wait();
return func();
@ -139,7 +139,7 @@ namespace ICSharpCode.ILSpy @@ -139,7 +139,7 @@ namespace ICSharpCode.ILSpy
public static Task Then(this Task task, Func<Task> asyncAction)
{
if (asyncAction == null)
throw new ArgumentNullException("asyncAction");
throw new ArgumentNullException(nameof(asyncAction));
return task.ContinueWith(t => {
t.Wait();
return asyncAction();
@ -149,7 +149,7 @@ namespace ICSharpCode.ILSpy @@ -149,7 +149,7 @@ namespace ICSharpCode.ILSpy
public static Task<U> Then<U>(this Task task, Func<Task<U>> asyncFunc)
{
if (asyncFunc == null)
throw new ArgumentNullException("asyncFunc");
throw new ArgumentNullException(nameof(asyncFunc));
return task.ContinueWith(t => {
t.Wait();
return asyncFunc();
@ -167,7 +167,7 @@ namespace ICSharpCode.ILSpy @@ -167,7 +167,7 @@ namespace ICSharpCode.ILSpy
public static Task Catch<TException>(this Task task, Action<TException> action) where TException : Exception
{
if (action == null)
throw new ArgumentNullException("action");
throw new ArgumentNullException(nameof(action));
return task.ContinueWith(t => {
if (t.IsFaulted) {
Exception ex = t.Exception;

4
ILSpy/TextView/ReferenceElementGenerator.cs

@ -39,9 +39,9 @@ namespace ICSharpCode.ILSpy.TextView @@ -39,9 +39,9 @@ namespace ICSharpCode.ILSpy.TextView
public ReferenceElementGenerator(Action<ReferenceSegment> referenceClicked, Predicate<ReferenceSegment> isLink)
{
if (referenceClicked == null)
throw new ArgumentNullException("referenceClicked");
throw new ArgumentNullException(nameof(referenceClicked));
if (isLink == null)
throw new ArgumentNullException("isLink");
throw new ArgumentNullException(nameof(isLink));
this.referenceClicked = referenceClicked;
this.isLink = isLink;
}

2
ILSpy/TreeNodes/Analyzer/AnalyzedAssemblyTreeNode.cs

@ -28,7 +28,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -28,7 +28,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedAssemblyTreeNode(ModuleDefinition analyzedAssembly)
{
if (analyzedAssembly == null)
throw new ArgumentNullException("analyzedAssembly");
throw new ArgumentNullException(nameof(analyzedAssembly));
this.analyzedAssembly = analyzedAssembly;
//this.LazyLoading = true;
}

2
ILSpy/TreeNodes/Analyzer/AnalyzedAttributeAppliedToTreeNode.cs

@ -45,7 +45,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -45,7 +45,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedAttributeAppliedToTreeNode(TypeDefinition analyzedType)
{
if (analyzedType == null)
throw new ArgumentNullException("analyzedType");
throw new ArgumentNullException(nameof(analyzedType));
this.analyzedType = analyzedType;
attributeName = this.analyzedType.FullName;

2
ILSpy/TreeNodes/Analyzer/AnalyzedEventFiredByTreeNode.cs

@ -37,7 +37,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -37,7 +37,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedEventFiredByTreeNode(EventDefinition analyzedEvent)
{
if (analyzedEvent == null)
throw new ArgumentNullException("analyzedEvent");
throw new ArgumentNullException(nameof(analyzedEvent));
this.analyzedEvent = analyzedEvent;

2
ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs

@ -32,7 +32,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -32,7 +32,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedEventOverridesTreeNode(EventDefinition analyzedEvent)
{
if (analyzedEvent == null)
throw new ArgumentNullException("analyzedEvent");
throw new ArgumentNullException(nameof(analyzedEvent));
this.analyzedEvent = analyzedEvent;
}

2
ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs

@ -29,7 +29,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -29,7 +29,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedEventTreeNode(EventDefinition analyzedEvent, string prefix = "")
{
if (analyzedEvent == null)
throw new ArgumentNullException("analyzedEvent");
throw new ArgumentNullException(nameof(analyzedEvent));
this.analyzedEvent = analyzedEvent;
this.prefix = prefix;
this.LazyLoading = true;

2
ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs

@ -36,7 +36,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -36,7 +36,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedFieldAccessTreeNode(FieldDefinition analyzedField, bool showWrites)
{
if (analyzedField == null)
throw new ArgumentNullException("analyzedField");
throw new ArgumentNullException(nameof(analyzedField));
this.analyzedField = analyzedField;
this.showWrites = showWrites;

2
ILSpy/TreeNodes/Analyzer/AnalyzedFieldTreeNode.cs

@ -28,7 +28,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -28,7 +28,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedFieldTreeNode(FieldDefinition analyzedField)
{
if (analyzedField == null)
throw new ArgumentNullException("analyzedField");
throw new ArgumentNullException(nameof(analyzedField));
this.analyzedField = analyzedField;
this.LazyLoading = true;
}

2
ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs

@ -33,7 +33,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -33,7 +33,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedInterfaceEventImplementedByTreeNode(EventDefinition analyzedEvent)
{
if (analyzedEvent == null)
throw new ArgumentNullException("analyzedEvent");
throw new ArgumentNullException(nameof(analyzedEvent));
this.analyzedEvent = analyzedEvent;
this.analyzedMethod = this.analyzedEvent.AddMethod ?? this.analyzedEvent.RemoveMethod;

2
ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs

@ -32,7 +32,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -32,7 +32,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedInterfaceMethodImplementedByTreeNode(MethodDefinition analyzedMethod)
{
if (analyzedMethod == null)
throw new ArgumentNullException("analyzedMethod");
throw new ArgumentNullException(nameof(analyzedMethod));
this.analyzedMethod = analyzedMethod;
}

2
ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs

@ -33,7 +33,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -33,7 +33,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedInterfacePropertyImplementedByTreeNode(PropertyDefinition analyzedProperty)
{
if (analyzedProperty == null)
throw new ArgumentNullException("analyzedProperty");
throw new ArgumentNullException(nameof(analyzedProperty));
this.analyzedProperty = analyzedProperty;
this.analyzedMethod = this.analyzedProperty.GetMethod ?? this.analyzedProperty.SetMethod;

2
ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs

@ -36,7 +36,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -36,7 +36,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedMethodOverridesTreeNode(MethodDefinition analyzedMethod)
{
if (analyzedMethod == null)
throw new ArgumentNullException("analyzedMethod");
throw new ArgumentNullException(nameof(analyzedMethod));
this.analyzedMethod = analyzedMethod;
}

2
ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs

@ -29,7 +29,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -29,7 +29,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedMethodTreeNode(MethodDefinition analyzedMethod, string prefix = "")
{
if (analyzedMethod == null)
throw new ArgumentNullException("analyzedMethod");
throw new ArgumentNullException(nameof(analyzedMethod));
this.analyzedMethod = analyzedMethod;
this.prefix = prefix;
this.LazyLoading = true;

2
ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs

@ -34,7 +34,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -34,7 +34,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedMethodUsedByTreeNode(MethodDefinition analyzedMethod)
{
if (analyzedMethod == null)
throw new ArgumentNullException("analyzedMethod");
throw new ArgumentNullException(nameof(analyzedMethod));
this.analyzedMethod = analyzedMethod;
}

2
ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs

@ -35,7 +35,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -35,7 +35,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedMethodUsesTreeNode(MethodDefinition analyzedMethod)
{
if (analyzedMethod == null)
throw new ArgumentNullException("analyzedMethod");
throw new ArgumentNullException(nameof(analyzedMethod));
this.analyzedMethod = analyzedMethod;
}

2
ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs

@ -32,7 +32,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -32,7 +32,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedPropertyOverridesTreeNode(PropertyDefinition analyzedProperty)
{
if (analyzedProperty == null)
throw new ArgumentNullException("analyzedProperty");
throw new ArgumentNullException(nameof(analyzedProperty));
this.analyzedProperty = analyzedProperty;
}

2
ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs

@ -31,7 +31,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -31,7 +31,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedPropertyTreeNode(PropertyDefinition analyzedProperty, string prefix = "")
{
if (analyzedProperty == null)
throw new ArgumentNullException("analyzedProperty");
throw new ArgumentNullException(nameof(analyzedProperty));
this.isIndexer = analyzedProperty.IsIndexer();
this.analyzedProperty = analyzedProperty;
this.prefix = prefix;

2
ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs

@ -31,7 +31,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -31,7 +31,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedTypeExposedByTreeNode(TypeDefinition analyzedType)
{
if (analyzedType == null)
throw new ArgumentNullException("analyzedType");
throw new ArgumentNullException(nameof(analyzedType));
this.analyzedType = analyzedType;
}

2
ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs

@ -31,7 +31,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -31,7 +31,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedTypeExtensionMethodsTreeNode(TypeDefinition analyzedType)
{
if (analyzedType == null)
throw new ArgumentNullException("analyzedType");
throw new ArgumentNullException(nameof(analyzedType));
this.analyzedType = analyzedType;
}

2
ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs

@ -34,7 +34,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -34,7 +34,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedTypeInstantiationsTreeNode(TypeDefinition analyzedType)
{
if (analyzedType == null)
throw new ArgumentNullException("analyzedType");
throw new ArgumentNullException(nameof(analyzedType));
this.analyzedType = analyzedType;

2
ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs

@ -28,7 +28,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -28,7 +28,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedTypeTreeNode(TypeDefinition analyzedType)
{
if (analyzedType == null)
throw new ArgumentNullException("analyzedType");
throw new ArgumentNullException(nameof(analyzedType));
this.analyzedType = analyzedType;
this.LazyLoading = true;
}

2
ILSpy/TreeNodes/Analyzer/AnalyzedTypeUsedByTreeNode.cs

@ -32,7 +32,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -32,7 +32,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedTypeUsedByTreeNode(TypeDefinition analyzedType)
{
if (analyzedType == null)
throw new ArgumentNullException("analyzedType");
throw new ArgumentNullException(nameof(analyzedType));
this.analyzedType = analyzedType;
}

2
ILSpy/TreeNodes/Analyzer/AnalyzedVirtualMethodUsedByTreeNode.cs

@ -37,7 +37,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -37,7 +37,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public AnalyzedVirtualMethodUsedByTreeNode(MethodDefinition analyzedMethod)
{
if (analyzedMethod == null)
throw new ArgumentNullException("analyzedMethod");
throw new ArgumentNullException(nameof(analyzedMethod));
this.analyzedMethod = analyzedMethod;
}

4
ILSpy/TreeNodes/Analyzer/Helpers.cs

@ -30,9 +30,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -30,9 +30,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
// TODO: move it to a better place after adding support for more cases.
if (type == null)
throw new ArgumentNullException("type");
throw new ArgumentNullException(nameof(type));
if (typeRef == null)
throw new ArgumentNullException("typeRef");
throw new ArgumentNullException(nameof(typeRef));
if (type == typeRef)
return true;

2
ILSpy/TreeNodes/AssemblyListTreeNode.cs

@ -43,7 +43,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -43,7 +43,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public AssemblyListTreeNode(AssemblyList assemblyList)
{
if (assemblyList == null)
throw new ArgumentNullException("assemblyList");
throw new ArgumentNullException(nameof(assemblyList));
this.assemblyList = assemblyList;
BindToObservableCollection(assemblyList.assemblies);
}

4
ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs

@ -33,9 +33,9 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -33,9 +33,9 @@ namespace ICSharpCode.ILSpy.TreeNodes
public AssemblyReferenceTreeNode(AssemblyNameReference r, AssemblyTreeNode parentAssembly)
{
if (parentAssembly == null)
throw new ArgumentNullException("parentAssembly");
throw new ArgumentNullException(nameof(parentAssembly));
if (r == null)
throw new ArgumentNullException("r");
throw new ArgumentNullException(nameof(r));
this.r = r;
this.parentAssembly = parentAssembly;
this.LazyLoading = true;

2
ILSpy/TreeNodes/AssemblyTreeNode.cs

@ -44,7 +44,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -44,7 +44,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public AssemblyTreeNode(LoadedAssembly assembly)
{
if (assembly == null)
throw new ArgumentNullException("assembly");
throw new ArgumentNullException(nameof(assembly));
this.assembly = assembly;

2
ILSpy/TreeNodes/BaseTypesEntryNode.cs

@ -33,7 +33,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -33,7 +33,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public BaseTypesEntryNode(TypeReference tr, bool isInterface)
{
if (tr == null)
throw new ArgumentNullException("tr");
throw new ArgumentNullException(nameof(tr));
this.tr = tr;
this.def = tr.Resolve();
this.isInterface = isInterface;

2
ILSpy/TreeNodes/EventTreeNode.cs

@ -33,7 +33,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -33,7 +33,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public EventTreeNode(EventDefinition ev)
{
if (ev == null)
throw new ArgumentNullException("ev");
throw new ArgumentNullException(nameof(ev));
this.ev = ev;
if (ev.AddMethod != null)

2
ILSpy/TreeNodes/FieldTreeNode.cs

@ -38,7 +38,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -38,7 +38,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public FieldTreeNode(FieldDefinition field)
{
if (field == null)
throw new ArgumentNullException("field");
throw new ArgumentNullException(nameof(field));
this.field = field;
}

2
ILSpy/TreeNodes/MethodTreeNode.cs

@ -40,7 +40,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -40,7 +40,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public MethodTreeNode(MethodDefinition method)
{
if (method == null)
throw new ArgumentNullException("method");
throw new ArgumentNullException(nameof(method));
this.method = method;
}

2
ILSpy/TreeNodes/ModuleReferenceTreeNode.cs

@ -32,7 +32,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -32,7 +32,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public ModuleReferenceTreeNode(ModuleReference r)
{
if (r == null)
throw new ArgumentNullException("r");
throw new ArgumentNullException(nameof(r));
this.r = r;
}

2
ILSpy/TreeNodes/NamespaceTreeNode.cs

@ -36,7 +36,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -36,7 +36,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public NamespaceTreeNode(string name)
{
if (name == null)
throw new ArgumentNullException("name");
throw new ArgumentNullException(nameof(name));
this.name = name;
}

2
ILSpy/TreeNodes/PropertyTreeNode.cs

@ -34,7 +34,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -34,7 +34,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public PropertyTreeNode(PropertyDefinition property)
{
if (property == null)
throw new ArgumentNullException("property");
throw new ArgumentNullException(nameof(property));
this.property = property;
using (LoadedAssembly.DisableAssemblyLoad()) {
this.isIndexer = property.IsIndexer();

4
ILSpy/TreeNodes/ResourceNodes/ResourceEntryNode.cs

@ -51,9 +51,9 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -51,9 +51,9 @@ namespace ICSharpCode.ILSpy.TreeNodes
public ResourceEntryNode(string key, Stream data)
{
if (key == null)
throw new ArgumentNullException("key");
throw new ArgumentNullException(nameof(key));
if (data == null)
throw new ArgumentNullException("data");
throw new ArgumentNullException(nameof(data));
this.key = key;
this.data = data;
}

2
ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs

@ -39,7 +39,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -39,7 +39,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public ResourceTreeNode(Resource r)
{
if (r == null)
throw new ArgumentNullException("r");
throw new ArgumentNullException(nameof(r));
this.r = r;
}

4
ILSpy/TreeNodes/TypeTreeNode.cs

@ -34,9 +34,9 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -34,9 +34,9 @@ namespace ICSharpCode.ILSpy.TreeNodes
public TypeTreeNode(TypeDefinition type, AssemblyTreeNode parentAssemblyNode)
{
if (parentAssemblyNode == null)
throw new ArgumentNullException("parentAssemblyNode");
throw new ArgumentNullException(nameof(parentAssemblyNode));
if (type == null)
throw new ArgumentNullException("type");
throw new ArgumentNullException(nameof(type));
this.type = type;
this.parentAssemblyNode = parentAssemblyNode;
this.LazyLoading = true;

2
ILSpy/XmlDoc/XmlDocKeyProvider.cs

@ -165,7 +165,7 @@ namespace ICSharpCode.ILSpy.XmlDoc @@ -165,7 +165,7 @@ namespace ICSharpCode.ILSpy.XmlDoc
public static MemberReference FindMemberByKey(ModuleDefinition module, string key)
{
if (module == null)
throw new ArgumentNullException("module");
throw new ArgumentNullException(nameof(module));
if (key == null || key.Length < 2 || key[1] != ':')
return null;
switch (key[0]) {

2
ILSpy/XmlDoc/XmlDocLoader.cs

@ -50,7 +50,7 @@ namespace ICSharpCode.ILSpy.XmlDoc @@ -50,7 +50,7 @@ namespace ICSharpCode.ILSpy.XmlDoc
public static XmlDocumentationProvider LoadDocumentation(ModuleDefinition module)
{
if (module == null)
throw new ArgumentNullException("module");
throw new ArgumentNullException(nameof(module));
lock (cache) {
XmlDocumentationProvider xmlDoc;
if (!cache.TryGetValue(module, out xmlDoc)) {

Loading…
Cancel
Save