Browse Source

#1080: Add ILTransformContext.RequiredNamespacesSuperset

pull/1087/head
Siegfried Pammer 8 years ago
parent
commit
a06a04d48b
  1. 298
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 2
      ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs
  3. 9
      ICSharpCode.Decompiler/CSharp/Transforms/TransformContext.cs
  4. 2
      ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs
  5. 2
      ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs
  6. 6
      ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs
  7. 2
      ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs
  8. 3
      ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs
  9. 5
      ILSpy/Languages/ILAstLanguage.cs

298
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -34,6 +34,8 @@ using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.Util;
using System.IO;
using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching;
using System.Collections.Immutable;
using System.Runtime.InteropServices;
namespace ICSharpCode.Decompiler.CSharp
{
@ -49,6 +51,7 @@ namespace ICSharpCode.Decompiler.CSharp
readonly DecompilerTypeSystem typeSystem;
readonly DecompilerSettings settings;
SyntaxTree syntaxTree;
HashSet<string> namespaces;
List<IILTransform> ilTransforms = GetILTransforms();
@ -291,7 +294,7 @@ namespace ICSharpCode.Decompiler.CSharp
void RunTransforms(AstNode rootNode, ITypeResolveContext decompilationContext)
{
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
var context = new TransformContext(typeSystem, decompilationContext, typeSystemAstBuilder, settings, CancellationToken);
var context = new TransformContext(typeSystem, decompilationContext, namespaces.ToImmutableHashSet(), typeSystemAstBuilder, settings, CancellationToken);
foreach (var transform in astTransforms) {
CancellationToken.ThrowIfCancellationRequested();
transform.Run(rootNode, context);
@ -314,6 +317,7 @@ namespace ICSharpCode.Decompiler.CSharp
var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainAssembly);
syntaxTree = new SyntaxTree();
definedSymbols = new HashSet<string>();
namespaces = new HashSet<string>();
DoDecompileModuleAndAssemblyAttributes(decompilationContext, syntaxTree);
RunTransforms(syntaxTree, decompilationContext);
return syntaxTree;
@ -330,6 +334,9 @@ namespace ICSharpCode.Decompiler.CSharp
void DoDecompileModuleAndAssemblyAttributes(ITypeResolveContext decompilationContext, SyntaxTree syntaxTree)
{
foreach (var a in typeSystem.Compilation.MainAssembly.AssemblyAttributes) {
namespaces.Add(a.AttributeType.Namespace);
namespaces.AddRange(a.PositionalArguments.Select(pa => pa.Type.Namespace));
namespaces.AddRange(a.NamedArguments.Select(na => na.Value.Type.Namespace));
var astBuilder = CreateAstBuilder(decompilationContext);
var attrSection = new AttributeSection(astBuilder.ConvertAttribute(a));
attrSection.AttributeTarget = "assembly";
@ -369,12 +376,290 @@ namespace ICSharpCode.Decompiler.CSharp
var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainAssembly);
syntaxTree = new SyntaxTree();
definedSymbols = new HashSet<string>();
namespaces = CollectNamespacesForAllTypes();
DoDecompileModuleAndAssemblyAttributes(decompilationContext, syntaxTree);
DoDecompileTypes(typeSystem.ModuleDefinition.Types, decompilationContext, syntaxTree);
RunTransforms(syntaxTree, decompilationContext);
return syntaxTree;
}
HashSet<string> CollectNamespacesForAllTypes()
{
var namespaces = new HashSet<string>();
foreach (var type in typeSystem.ModuleDefinition.Types) {
CollectNamespacesForDecompilation(new[] { type }, namespaces);
}
foreach (var typeRef in typeSystem.ModuleDefinition.GetTypeReferences()) {
namespaces.Add(typeRef.Namespace);
}
return namespaces;
}
static void CollectNamespacesForDecompilation(MemberReference memberReference, HashSet<string> namespaces, bool decodeDetails = false)
{
void CollectAttributes(ICustomAttributeProvider provider)
{
if (!provider.HasCustomAttributes || !decodeDetails) return;
foreach (var ca in provider.CustomAttributes) {
CollectNamespacesForDecompilation(ca.AttributeType, namespaces);
CollectNamespacesForDecompilation(ca.Constructor, namespaces);
foreach (var val in ca.ConstructorArguments) {
if (val.Value is TypeReference tr)
namespaces.Add(tr.Namespace);
}
}
}
if (memberReference == null)
return;
if (memberReference is IGenericParameterProvider genericParamProvider && genericParamProvider.HasGenericParameters) {
foreach (var gp in genericParamProvider.GenericParameters) {
if (gp.HasConstraints) {
foreach (var constraint in gp.Constraints) {
// Avoid infinite recursion
if (!(constraint is GenericInstanceType git && git.ElementType == gp.Owner))
CollectNamespacesForDecompilation(constraint, namespaces);
}
}
}
}
if (memberReference is ICustomAttributeProvider cap) {
CollectAttributes(cap);
}
switch (memberReference) {
case TypeDefinition typeDef:
if (typeDef.IsNested) {
var tr = typeDef.DeclaringType;
while (tr.DeclaringType != null)
tr = tr.DeclaringType;
namespaces.Add(tr.Namespace);
} else {
namespaces.Add(typeDef.Namespace);
}
if (!decodeDetails) break;
CollectNamespacesForDecompilation(typeDef.BaseType, namespaces);
if (typeDef.HasInterfaces) {
foreach (var inter in typeDef.Interfaces)
CollectNamespacesForDecompilation(inter.InterfaceType, namespaces);
}
LayoutKind layoutKind = LayoutKind.Auto;
switch (typeDef.Attributes & TypeAttributes.LayoutMask) {
case TypeAttributes.SequentialLayout:
layoutKind = LayoutKind.Sequential;
break;
case TypeAttributes.ExplicitLayout:
layoutKind = LayoutKind.Explicit;
break;
}
CharSet charSet = CharSet.None;
switch (typeDef.Attributes & TypeAttributes.StringFormatMask) {
case TypeAttributes.AnsiClass:
charSet = CharSet.Ansi;
break;
case TypeAttributes.AutoClass:
charSet = CharSet.Auto;
break;
case TypeAttributes.UnicodeClass:
charSet = CharSet.Unicode;
break;
}
LayoutKind defaultLayoutKind = (typeDef.IsValueType && !typeDef.IsEnum) ? LayoutKind.Sequential : LayoutKind.Auto;
if (layoutKind != defaultLayoutKind || charSet != CharSet.Ansi || typeDef.PackingSize > 0 || typeDef.ClassSize > 0)
namespaces.Add("System.Runtime.InteropServices");
if (typeDef.HasNestedTypes)
CollectNamespacesForDecompilation(typeDef.NestedTypes, namespaces);
if (typeDef.HasFields)
CollectNamespacesForDecompilation(typeDef.Fields, namespaces);
if (typeDef.HasProperties)
CollectNamespacesForDecompilation(typeDef.Properties, namespaces);
if (typeDef.HasMethods)
CollectNamespacesForDecompilation(typeDef.Methods, namespaces);
if (typeDef.HasEvents)
CollectNamespacesForDecompilation(typeDef.Events, namespaces);
break;
case Mono.Cecil.ArrayType arrayType:
CollectNamespacesForDecompilation(arrayType.ElementType, namespaces);
break;
case Mono.Cecil.FunctionPointerType fp:
CollectAttributes(fp.MethodReturnType);
CollectNamespacesForDecompilation(fp.ReturnType, namespaces);
if (fp.HasParameters) {
foreach (var p in fp.Parameters) {
CollectAttributes(p);
CollectNamespacesForDecompilation(p.ParameterType, namespaces);
}
}
break;
case Mono.Cecil.GenericInstanceType git:
CollectNamespacesForDecompilation(git.ElementType, namespaces);
if (git.HasGenericArguments) {
foreach (var ga in git.GenericArguments) {
CollectNamespacesForDecompilation(ga, namespaces);
}
}
break;
case Mono.Cecil.OptionalModifierType modopt:
CollectNamespacesForDecompilation(modopt.ElementType, namespaces);
break;
case Mono.Cecil.RequiredModifierType modreq:
CollectNamespacesForDecompilation(modreq.ElementType, namespaces);
break;
case Mono.Cecil.PinnedType pinned:
CollectNamespacesForDecompilation(pinned.ElementType, namespaces);
break;
case Mono.Cecil.PointerType pointer:
CollectNamespacesForDecompilation(pointer.ElementType, namespaces);
break;
case Mono.Cecil.ByReferenceType byRef:
CollectNamespacesForDecompilation(byRef.ElementType, namespaces);
break;
case SentinelType sentinel:
CollectNamespacesForDecompilation(sentinel.ElementType, namespaces);
break;
case TypeReference typeRef:
if (typeRef.IsNested) {
var tr = typeRef.DeclaringType;
while (tr.DeclaringType != null)
tr = tr.DeclaringType;
namespaces.Add(tr.Namespace);
} else {
namespaces.Add(typeRef.Namespace);
}
break;
case FieldReference fieldRef:
CollectNamespacesForDecompilation(fieldRef.DeclaringType, namespaces);
CollectNamespacesForDecompilation(fieldRef.FieldType, namespaces);
break;
case PropertyDefinition propertyDef:
CollectNamespacesForDecompilation(propertyDef.DeclaringType, namespaces);
CollectNamespacesForDecompilation(propertyDef.PropertyType, namespaces);
if (!decodeDetails) break;
if (propertyDef.HasParameters) {
foreach (var p in propertyDef.Parameters) {
if (p.IsOut || p.IsIn || p.HasMarshalInfo) // these manifest as attributes in C#
namespaces.Add("System.Runtime.InteropServices");
CollectAttributes(p);
CollectNamespacesForDecompilation(p.ParameterType, namespaces);
}
}
if (propertyDef.GetMethod != null) {
CollectNamespacesForDecompilation(propertyDef.GetMethod, namespaces, true);
}
if (propertyDef.SetMethod != null) {
CollectNamespacesForDecompilation(propertyDef.SetMethod, namespaces, true);
}
break;
case PropertyReference propertyRef:
CollectNamespacesForDecompilation(propertyRef.DeclaringType, namespaces);
CollectNamespacesForDecompilation(propertyRef.PropertyType, namespaces);
break;
case EventDefinition eventDef:
CollectNamespacesForDecompilation(eventDef.DeclaringType, namespaces);
CollectNamespacesForDecompilation(eventDef.EventType, namespaces);
if (!decodeDetails) break;
if (eventDef.AddMethod != null) {
CollectNamespacesForDecompilation(eventDef.AddMethod, namespaces, true);
}
if (eventDef.RemoveMethod != null) {
CollectNamespacesForDecompilation(eventDef.RemoveMethod, namespaces, true);
}
if (eventDef.InvokeMethod != null) {
CollectNamespacesForDecompilation(eventDef.InvokeMethod, namespaces, true);
}
break;
case EventReference eventRef:
CollectNamespacesForDecompilation(eventRef.DeclaringType, namespaces);
CollectNamespacesForDecompilation(eventRef.EventType, namespaces);
break;
case MethodDefinition methodDef:
CollectNamespacesForDecompilation(methodDef.DeclaringType, namespaces);
CollectAttributes(methodDef.MethodReturnType);
if (methodDef.HasPInvokeInfo || methodDef.MethodReturnType.HasMarshalInfo || methodDef.IsPreserveSig) // these manifest as attributes in C#
namespaces.Add("System.Runtime.InteropServices");
if (methodDef.ImplAttributes != 0)
namespaces.Add("System.Runtime.CompilerServices");
CollectNamespacesForDecompilation(methodDef.ReturnType, namespaces);
if (methodDef.HasParameters) {
foreach (var p in methodDef.Parameters) {
if (p.IsOut || p.IsIn || p.HasMarshalInfo) // these manifest as attributes in C#
namespaces.Add("System.Runtime.InteropServices");
CollectAttributes(p);
CollectNamespacesForDecompilation(p.ParameterType, namespaces);
}
}
if (methodDef.HasBody && decodeDetails) {
CollectNamespacesForDecompilation(methodDef.Body, namespaces);
}
break;
case GenericInstanceMethod methodSpec:
CollectNamespacesForDecompilation(methodSpec.DeclaringType, namespaces);
CollectNamespacesForDecompilation(methodSpec.ReturnType, namespaces);
if (methodSpec.HasParameters) {
foreach (var p in methodSpec.Parameters) {
CollectNamespacesForDecompilation(p.ParameterType, namespaces);
}
}
if (methodSpec.HasGenericArguments) {
foreach (var ga in methodSpec.GenericArguments) {
CollectNamespacesForDecompilation(ga, namespaces);
}
}
break;
case MethodReference methodRef:
CollectNamespacesForDecompilation(methodRef.DeclaringType, namespaces);
CollectNamespacesForDecompilation(methodRef.ReturnType, namespaces);
if (methodRef.HasParameters) {
foreach (var p in methodRef.Parameters) {
CollectNamespacesForDecompilation(p.ParameterType, namespaces);
}
}
break;
}
}
static void CollectNamespacesForDecompilation(Mono.Cecil.Cil.MethodBody body, HashSet<string> namespaces)
{
if (body.HasVariables) {
foreach (var v in body.Variables)
CollectNamespacesForDecompilation(v.VariableType, namespaces);
}
if (body.HasExceptionHandlers) {
foreach (var eh in body.ExceptionHandlers)
CollectNamespacesForDecompilation(eh.CatchType, namespaces);
}
foreach (var inst in body.Instructions) {
if (inst.Operand is MemberReference mr)
CollectNamespacesForDecompilation(mr, namespaces);
}
}
public static void CollectNamespacesForDecompilation(IEnumerable<IMemberDefinition> memberDefinitions, HashSet<string> namespaces)
{
var visitedItems = new HashSet<MemberReference>();
foreach (var def in memberDefinitions) {
switch (def) {
case TypeDefinition typeDef:
CollectNamespacesForDecompilation(typeDef, namespaces, true);
break;
case FieldDefinition fieldDef:
CollectNamespacesForDecompilation(fieldDef, namespaces, true);
break;
case PropertyDefinition propertyDef:
CollectNamespacesForDecompilation(propertyDef, namespaces, true);
break;
case EventDefinition eventDef:
CollectNamespacesForDecompilation(eventDef, namespaces, true);
break;
case MethodDefinition methodDef:
CollectNamespacesForDecompilation(methodDef, namespaces, true);
break;
}
}
}
/// <summary>
/// Decompiles the whole module into a single string.
/// </summary>
@ -396,6 +681,8 @@ namespace ICSharpCode.Decompiler.CSharp
var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainAssembly);
syntaxTree = new SyntaxTree();
definedSymbols = new HashSet<string>();
namespaces = new HashSet<string>();
CollectNamespacesForDecompilation(types, namespaces);
DoDecompileTypes(types, decompilationContext, syntaxTree);
RunTransforms(syntaxTree, decompilationContext);
return syntaxTree;
@ -426,7 +713,10 @@ namespace ICSharpCode.Decompiler.CSharp
var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainAssembly);
syntaxTree = new SyntaxTree();
definedSymbols = new HashSet<string>();
DoDecompileTypes(new[] { typeSystem.GetCecil(type) }, decompilationContext, syntaxTree);
namespaces = new HashSet<string>();
var cecilType = typeSystem.GetCecil(type);
CollectNamespacesForDecompilation(cecilType, namespaces, true);
DoDecompileTypes(new[] { cecilType }, decompilationContext, syntaxTree);
RunTransforms(syntaxTree, decompilationContext);
return syntaxTree;
}
@ -460,6 +750,8 @@ namespace ICSharpCode.Decompiler.CSharp
ITypeDefinition parentTypeDef = null;
syntaxTree = new SyntaxTree();
definedSymbols = new HashSet<string>();
namespaces = new HashSet<string>();
CollectNamespacesForDecompilation(definitions, namespaces);
foreach (var def in definitions) {
if (def == null)
throw new ArgumentException("definitions contains null element");
@ -773,7 +1065,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
var context = new ILTransformContext(function, specializingTypeSystem, settings) {
var context = new ILTransformContext(function, specializingTypeSystem, namespaces.ToImmutableHashSet(), settings) {
CancellationToken = CancellationToken
};
foreach (var transform in ilTransforms) {

2
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs

@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.CSharp.Syntax;
@ -46,6 +47,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
// Now add using declarations for those namespaces:
foreach (string ns in requiredImports.ImportedNamespaces.OrderByDescending(n => n)) {
Debug.Assert(context.RequiredNamespacesSuperset.Contains(ns), $"Should not insert using declaration for namespace that is missing from the superset: {ns}");
// we go backwards (OrderByDescending) through the list of namespaces because we insert them backwards
// (always inserting at the start of the list)
string[] parts = ns.Split('.');

9
ICSharpCode.Decompiler/CSharp/Transforms/TransformContext.cs

@ -16,6 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Collections.Immutable;
using System.Threading;
using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.TypeSystem;
@ -55,10 +56,16 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
get { return decompilationContext.CurrentAssembly; }
}
internal TransformContext(DecompilerTypeSystem typeSystem, ITypeResolveContext decompilationContext, TypeSystemAstBuilder typeSystemAstBuilder, DecompilerSettings settings, CancellationToken cancellationToken)
/// <summary>
/// Returns the max possible set of namespaces that will be used during decompilation.
/// </summary>
public IImmutableSet<string> RequiredNamespacesSuperset { get; }
internal TransformContext(DecompilerTypeSystem typeSystem, ITypeResolveContext decompilationContext, IImmutableSet<string> namespaces, TypeSystemAstBuilder typeSystemAstBuilder, DecompilerSettings settings, CancellationToken cancellationToken)
{
this.TypeSystem = typeSystem;
this.decompilationContext = decompilationContext;
this.RequiredNamespacesSuperset = namespaces;
this.TypeSystemAstBuilder = typeSystemAstBuilder;
this.Settings = settings;
this.CancellationToken = cancellationToken;

2
ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs

@ -378,7 +378,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
}
var il = new ILReader(typeSystem).ReadIL(method.Body, context.CancellationToken);
il.RunTransforms(CSharpDecompiler.EarlyILTransforms(true),
new ILTransformContext(il, typeSystem, context.Settings) {
new ILTransformContext(il, typeSystem, context.RequiredNamespacesSuperset, context.Settings) {
CancellationToken = context.CancellationToken
});
return il;

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

@ -149,7 +149,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
v.Name = contextPrefix + v.Name;
}
var nestedContext = new ILTransformContext(function, localTypeSystem, context.Settings) {
var nestedContext = new ILTransformContext(function, localTypeSystem, context.RequiredNamespacesSuperset, context.Settings) {
CancellationToken = context.CancellationToken
};
function.RunTransforms(CSharpDecompiler.GetILTransforms().TakeWhile(t => !(t is DelegateConstruction)), nestedContext);

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

@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Threading;
using ICSharpCode.Decompiler.TypeSystem;
@ -39,13 +40,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms
public ILFunction Function { get; }
public IDecompilerTypeSystem TypeSystem { get; }
public DecompilerSettings Settings { get; }
public IImmutableSet<string> RequiredNamespacesSuperset { get; }
public CancellationToken CancellationToken { get; set; }
public Stepper Stepper { get; set; }
public ILTransformContext(ILFunction function, IDecompilerTypeSystem typeSystem, DecompilerSettings settings = null)
public ILTransformContext(ILFunction function, IDecompilerTypeSystem typeSystem, IImmutableSet<string> requiredNamespaces, DecompilerSettings settings = null)
{
this.Function = function ?? throw new ArgumentNullException(nameof(function));
this.TypeSystem = typeSystem ?? throw new ArgumentNullException(nameof(typeSystem));
this.RequiredNamespacesSuperset = requiredNamespaces ?? throw new ArgumentNullException(nameof(requiredNamespaces));
this.Settings = settings ?? new DecompilerSettings();
Stepper = new Stepper();
}
@ -55,6 +58,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
this.Function = context.Function;
this.TypeSystem = context.TypeSystem;
this.Settings = context.Settings;
this.RequiredNamespacesSuperset = context.RequiredNamespacesSuperset;
this.CancellationToken = context.CancellationToken;
this.Stepper = context.Stepper;
}

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

@ -21,7 +21,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var ilReader = new ILReader(specializingTypeSystem);
System.Threading.CancellationToken cancellationToken = new System.Threading.CancellationToken();
var proxyFunction = ilReader.ReadIL(methodDef.Body, cancellationToken);
var transformContext = new ILTransformContext(proxyFunction, specializingTypeSystem, this.context.Settings) {
var transformContext = new ILTransformContext(proxyFunction, specializingTypeSystem, context.RequiredNamespacesSuperset, this.context.Settings) {
CancellationToken = cancellationToken
};
foreach (var transform in CSharp.CSharpDecompiler.GetILTransforms()) {

3
ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using ICSharpCode.Decompiler;
@ -60,7 +61,7 @@ namespace ILSpy.BamlDecompiler
var ilReader = new ILReader(typeSystem);
var function = ilReader.ReadIL(method.Body, cancellationToken);
var context = new ILTransformContext(function, typeSystem) {
var context = new ILTransformContext(function, typeSystem, ImmutableHashSet<string>.Empty) {
CancellationToken = cancellationToken
};
function.RunTransforms(CSharpDecompiler.GetILTransforms(), context);

5
ILSpy/Languages/ILAstLanguage.cs

@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using ICSharpCode.Decompiler;
@ -116,7 +117,9 @@ namespace ICSharpCode.ILSpy
var reader = new ILReader(specializingTypeSystem);
reader.UseDebugSymbols = options.DecompilerSettings.UseDebugSymbols;
ILFunction il = reader.ReadIL(method.Body, options.CancellationToken);
ILTransformContext context = new ILTransformContext(il, typeSystem, options.DecompilerSettings) {
var namespaces = new HashSet<string>();
CSharpDecompiler.CollectNamespacesForDecompilation(new[] { method }, namespaces);
ILTransformContext context = new ILTransformContext(il, typeSystem, namespaces.ToImmutableHashSet(), options.DecompilerSettings) {
CancellationToken = options.CancellationToken
};
context.Stepper.StepLimit = options.StepLimit;

Loading…
Cancel
Save