diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index 0c249b6c6..aaeb49d84 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -153,6 +153,7 @@ namespace ICSharpCode.Decompiler.Ast TypeDefinition oldCurrentType = context.CurrentType; context.CurrentType = typeDef; TypeDeclaration astType = new TypeDeclaration(); + ConvertAttributes(astType, typeDef); astType.AddAnnotation(typeDef); astType.Modifiers = ConvertModifiers(typeDef); astType.Name = CleanName(typeDef.Name); @@ -216,7 +217,6 @@ namespace ICSharpCode.Decompiler.Ast AddTypeMembers(astType, typeDef); } - ConvertAttributes(astType, typeDef); context.CurrentType = oldCurrentType; return astType; } @@ -506,7 +506,25 @@ namespace ICSharpCode.Decompiler.Ast // Add properties foreach(PropertyDefinition propDef in typeDef.Properties) { - astType.AddChild(CreateProperty(propDef), TypeDeclaration.MemberRole); + MemberDeclaration astProp = CreateProperty(propDef); + + if (astProp.Name == "Item" && propDef.HasParameters) + { + var defaultMember = GetDefaultMember(astType.Annotation()); + if (defaultMember.Item1 == "Item") + { + astProp = ConvertPropertyToIndexer((PropertyDeclaration)astProp, propDef); + + var astAttr = astType.Attributes.SelectMany(sec => sec.Attributes).First(attr => attr.Annotation() == defaultMember.Item2); + var attrSection = (AttributeSection)astAttr.Parent; + if (attrSection.Attributes.Count == 1) + attrSection.Remove(); + else + astAttr.Remove(); + } + } + + astType.AddChild(astProp, TypeDeclaration.MemberRole); } // Add constructors @@ -595,6 +613,19 @@ namespace ICSharpCode.Decompiler.Ast return astMethod; } + IndexerDeclaration ConvertPropertyToIndexer(PropertyDeclaration astProp, PropertyDefinition propDef) + { + var astIndexer = new IndexerDeclaration(); + astIndexer.Name = astProp.Name; + astIndexer.CopyAnnotationsFrom(astProp); + astIndexer.Modifiers = astProp.Modifiers; + astIndexer.ReturnType = astProp.ReturnType.Detach(); + astIndexer.Getter = astProp.Getter.Detach(); + astIndexer.Setter = astProp.Setter.Detach(); + astIndexer.Parameters.AddRange(MakeParameters(propDef.Parameters)); + return astIndexer; + } + PropertyDeclaration CreateProperty(PropertyDefinition propDef) { PropertyDeclaration astProp = new PropertyDeclaration(); @@ -894,6 +925,7 @@ namespace ICSharpCode.Decompiler.Ast var attributes = new List(); foreach (var customAttribute in customAttributeProvider.CustomAttributes) { var attribute = new ICSharpCode.NRefactory.CSharp.Attribute(); + attribute.AddAnnotation(customAttribute); attribute.Type = ConvertType(customAttribute.AttributeType); attributes.Add(attribute); @@ -1024,5 +1056,23 @@ namespace ICSharpCode.Decompiler.Ast return type.CustomAttributes.Any(attr => attr.AttributeType.FullName == "System.FlagsAttribute"); } + + /// + /// Gets the name of the default member of the type pointed by the attribute. + /// + /// The type definition. + /// The name of the default member or null if no attribute has been found. + private static Tuple GetDefaultMember(TypeDefinition type) + { + foreach (CustomAttribute ca in type.CustomAttributes) + { + if (ca.Constructor.FullName == "System.Void System.Reflection.DefaultMemberAttribute::.ctor(System.String)") + { + return Tuple.Create(ca.ConstructorArguments.Single().Value as string, ca); + } + } + return new Tuple(null, null); + } + } } diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs index 8c54c97d7..d219bfee0 100644 --- a/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs +++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs @@ -138,6 +138,21 @@ namespace AppliedToPropertySet } } } +//$$ AppliedToIndexer +namespace AppliedToIndexer +{ + public class TestClass + { + [Obsolete("reason")] + public int this[int i] + { + get + { + return 0; + } + } + } +} //$$ AppliedToDelegate [Obsolete("reason")] public delegate int AppliedToDelegate(); @@ -361,7 +376,6 @@ namespace TargetPropertyIndexSetParam [param: MyAttribute] set { - return; } } } @@ -385,7 +399,6 @@ namespace TargetPropertyIndexSetMultiParam [param: MyAttribute] set { - return; } } } diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/Accessor.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/Accessor.cs index c487032eb..cc5651d87 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/Accessor.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/Accessor.cs @@ -56,8 +56,12 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.Body); } set { SetChildByRole (Roles.Body, value); } } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public AstNodeCollection Parameters { + get { return GetChildrenByRole(Roles.Parameter); } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitAccessor (this, data); } diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs index da02c47d5..5a5d01d09 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs @@ -202,8 +202,21 @@ namespace ICSharpCode.NRefactory.CSharp { WriteCommaSeparatedListInParenthesis(list.SafeCast(), spaceWithin); } + #endif - + + void WriteCommaSeparatedListInBrackets(IEnumerable list, bool spaceWithin) + { + WriteToken("[", AstNode.Roles.LBracket); + if (list.Any()) + { + Space(spaceWithin); + WriteCommaSeparatedList(list.SafeCast()); + Space(spaceWithin); + } + WriteToken("]", AstNode.Roles.RBracket); + } + void WriteCommaSeparatedListInBrackets(IEnumerable list) { WriteToken("[", AstNode.Roles.LBracket); @@ -1815,7 +1828,7 @@ namespace ICSharpCode.NRefactory.CSharp WritePrivateImplementationType(indexerDeclaration.PrivateImplementationType); WriteKeyword("this"); Space(policy.BeforeMethodDeclarationParentheses); - WriteCommaSeparatedListInParenthesis(indexerDeclaration.Parameters, policy.WithinMethodDeclarationParentheses); + WriteCommaSeparatedListInBrackets(indexerDeclaration.Parameters, policy.WithinMethodDeclarationParentheses); OpenBrace(policy.PropertyBraceStyle); // output get/set in their original order foreach (AstNode node in indexerDeclaration.Children) {