diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index 9f4ef22f1..634d98a3a 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -287,6 +287,8 @@ namespace ICSharpCode.Decompiler.CSharp var typeDefinition = def as TypeDefinition; var methodDefinition = def as MethodDefinition; var fieldDefinition = def as FieldDefinition; + var propertyDefinition = def as PropertyDefinition; + var eventDefinition = def as EventDefinition; if (typeDefinition != null) { ITypeDefinition typeDef = typeSystem.Resolve(typeDefinition).GetDefinition(); if (typeDef == null) @@ -302,8 +304,18 @@ namespace ICSharpCode.Decompiler.CSharp if (field == null) throw new InvalidOperationException("Could not find field definition in NR type system"); syntaxTree.Members.Add(DoDecompile(fieldDefinition, field, new SimpleTypeResolveContext(field))); + } else if (propertyDefinition != null) { + IProperty property = typeSystem.Resolve(propertyDefinition); + if (property == null) + throw new InvalidOperationException("Could not find field definition in NR type system"); + syntaxTree.Members.Add(DoDecompile(propertyDefinition, property, new SimpleTypeResolveContext(property))); + } else if (eventDefinition != null) { + IEvent ev = typeSystem.Resolve(eventDefinition); + if (ev == null) + throw new InvalidOperationException("Could not find field definition in NR type system"); + syntaxTree.Members.Add(DoDecompile(eventDefinition, ev, new SimpleTypeResolveContext(ev))); } else { - throw new NotImplementedException(); + throw new NotSupportedException(def.GetType().Name); } } RunTransforms(syntaxTree, new SimpleTypeResolveContext(typeSystem.MainAssembly)); diff --git a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs index 359896ff0..0a86c0cca 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs @@ -72,6 +72,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (inst.Arguments.Count != inst.Method.Parameters.Count + 1) return; var newObj = new NewObj(inst.Method); + newObj.ILRange = inst.ILRange; newObj.Arguments.AddRange(inst.Arguments.Skip(1)); var expr = new StObj(inst.Arguments[0], newObj, inst.Method.DeclaringType); inst.ReplaceWith(expr); diff --git a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs index b7ac3e39b..95725f360 100644 --- a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs +++ b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs @@ -37,7 +37,9 @@ namespace ICSharpCode.Decompiler Dictionary entityDict = new Dictionary(); Dictionary fieldLookupCache = new Dictionary(); + Dictionary propertyLookupCache = new Dictionary(); Dictionary methodLookupCache = new Dictionary(); + Dictionary eventLookupCache = new Dictionary(); public DecompilerTypeSystem(ModuleDefinition moduleDefinition) { @@ -299,5 +301,76 @@ namespace ICSharpCode.Decompiler } } #endregion + + #region Resolve Property + public IProperty Resolve(PropertyReference propertyReference) + { + if (propertyReference == null) + throw new ArgumentNullException("propertyReference"); + lock (propertyLookupCache) { + IProperty property; + if (!propertyLookupCache.TryGetValue(propertyReference, out property)) { + property = FindNonGenericProperty(propertyReference); + if (propertyReference.DeclaringType.IsGenericInstance) { + var git = (GenericInstanceType)propertyReference.DeclaringType; + var typeArguments = git.GenericArguments.SelectArray(Resolve); + property = (IProperty)property.Specialize(new TypeParameterSubstitution(typeArguments, null)); + } + propertyLookupCache.Add(propertyReference, property); + } + return property; + } + } + + IProperty FindNonGenericProperty(PropertyReference propertyReference) + { + ITypeDefinition typeDef = Resolve(propertyReference.DeclaringType).GetDefinition(); + if (typeDef == null) + return null; + var parameterTypes = propertyReference.Parameters.SelectArray(p => Resolve(p.ParameterType)); + var returnType = Resolve(propertyReference.PropertyType); + foreach (IProperty property in typeDef.Properties) { + if (property.Name == propertyReference.Name + && CompareTypes(property.ReturnType, returnType) + && CompareSignatures(property.Parameters, parameterTypes)) + return property; + } + return null; + } + #endregion + + #region Resolve Event + public IEvent Resolve(EventReference eventReference) + { + if (eventReference == null) + throw new ArgumentNullException("propertyReference"); + lock (eventLookupCache) { + IEvent ev; + if (!eventLookupCache.TryGetValue(eventReference, out ev)) { + ev = FindNonGenericEvent(eventReference); + if (eventReference.DeclaringType.IsGenericInstance) { + var git = (GenericInstanceType)eventReference.DeclaringType; + var typeArguments = git.GenericArguments.SelectArray(Resolve); + ev = (IEvent)ev.Specialize(new TypeParameterSubstitution(typeArguments, null)); + } + eventLookupCache.Add(eventReference, ev); + } + return ev; + } + } + + IEvent FindNonGenericEvent(EventReference eventReference) + { + ITypeDefinition typeDef = Resolve(eventReference.DeclaringType).GetDefinition(); + if (typeDef == null) + return null; + var returnType = Resolve(eventReference.EventType); + foreach (IEvent ev in typeDef.Events) { + if (ev.Name == eventReference.Name && CompareTypes(ev.ReturnType, returnType)) + return ev; + } + return null; + } + #endregion } } diff --git a/ILSpy/Languages/CSharpLanguage.cs b/ILSpy/Languages/CSharpLanguage.cs index b022cfd00..735ee627d 100644 --- a/ILSpy/Languages/CSharpLanguage.cs +++ b/ILSpy/Languages/CSharpLanguage.cs @@ -90,13 +90,24 @@ namespace ICSharpCode.ILSpy get { return ".csproj"; } } - public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options) + CSharpDecompiler CreateDecompiler(ModuleDefinition module, DecompilationOptions options) { - WriteCommentLine(output, TypeToString(method.DeclaringType, includeNamespace: true)); - CSharpDecompiler decompiler = new CSharpDecompiler(method.Module, options.DecompilerSettings); + CSharpDecompiler decompiler = new CSharpDecompiler(module, options.DecompilerSettings); while (decompiler.AstTransforms.Count > transformCount) decompiler.AstTransforms.RemoveAt(decompiler.AstTransforms.Count - 1); - output.WriteLine(decompiler.Decompile(method).ToString()); + return decompiler; + } + + void WriteCode(ITextOutput output, SyntaxTree syntaxTree) + { + output.WriteLine(syntaxTree.ToString()); + } + + public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options) + { + WriteCommentLine(output, TypeToString(method.DeclaringType, includeNamespace: true)); + CSharpDecompiler decompiler = CreateDecompiler(method.Module, options); + WriteCode(output, decompiler.Decompile(method)); /* AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: method.DeclaringType, isSingleMember: true); if (method.IsConstructor && !method.IsStatic && !method.DeclaringType.IsValueType) { @@ -147,15 +158,13 @@ namespace ICSharpCode.ILSpy } */ - /* public override void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilationOptions options) { WriteCommentLine(output, TypeToString(property.DeclaringType, includeNamespace: true)); - AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: property.DeclaringType, isSingleMember: true); - codeDomBuilder.AddProperty(property); - RunTransformsAndGenerateCode(codeDomBuilder, output, options); + CSharpDecompiler decompiler = CreateDecompiler(property.Module, options); + WriteCode(output, decompiler.Decompile(property)); } - +/* public override void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options) { WriteCommentLine(output, TypeToString(field.DeclaringType, includeNamespace: true)); @@ -203,22 +212,19 @@ namespace ICSharpCode.ILSpy codeDomBuilder.AddMethod(ctor); } } - +*/ public override void DecompileEvent(EventDefinition ev, ITextOutput output, DecompilationOptions options) { WriteCommentLine(output, TypeToString(ev.DeclaringType, includeNamespace: true)); - AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: ev.DeclaringType, isSingleMember: true); - codeDomBuilder.AddEvent(ev); - RunTransformsAndGenerateCode(codeDomBuilder, output, options); + CSharpDecompiler decompiler = CreateDecompiler(ev.Module, options); + WriteCode(output, decompiler.Decompile(ev)); } -*/ + public override void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options) { - CSharpDecompiler decompiler = new CSharpDecompiler(type.Module, options.DecompilerSettings); - output.WriteLine(decompiler.Decompile(type).ToString()); -// AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: type); -// codeDomBuilder.AddType(type); -// RunTransformsAndGenerateCode(codeDomBuilder, output, options); + WriteCommentLine(output, TypeToString(type, includeNamespace: true)); + CSharpDecompiler decompiler = CreateDecompiler(type.Module, options); + WriteCode(output, decompiler.Decompile(type)); } /*