Browse Source

Indexers support. Explicit implementation of methods and parameters.

Conflicts:

	ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
	ICSharpCode.Decompiler/Tests/Types/TypeTests.cs
pull/70/head
Artur Zgodziski 15 years ago
parent
commit
16fd9d07e3
  1. 72
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 60
      ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs
  3. 6
      ICSharpCode.Decompiler/Tests/DelegateConstruction.cs
  4. 1
      ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
  5. 305
      ICSharpCode.Decompiler/Tests/Types/S_TypeMemberDeclarations.cs
  6. 5
      ICSharpCode.Decompiler/Tests/Types/TypeTests.cs

72
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -231,9 +231,12 @@ namespace ICSharpCode.Decompiler.Ast
int pos = name.LastIndexOf('`'); int pos = name.LastIndexOf('`');
if (pos >= 0) if (pos >= 0)
name = name.Substring(0, pos); name = name.Substring(0, pos);
pos = name.LastIndexOf('.');
if (pos >= 0)
name = name.Substring(pos + 1);
return name; return name;
} }
#region Convert Type Reference #region Convert Type Reference
/// <summary> /// <summary>
/// Converts a type reference. /// Converts a type reference.
@ -489,6 +492,7 @@ namespace ICSharpCode.Decompiler.Ast
return modifiers; return modifiers;
} }
#endregion #endregion
void AddTypeMembers(TypeDeclaration astType, TypeDefinition typeDef) void AddTypeMembers(TypeDeclaration astType, TypeDefinition typeDef)
@ -503,29 +507,9 @@ namespace ICSharpCode.Decompiler.Ast
foreach(EventDefinition eventDef in typeDef.Events) { foreach(EventDefinition eventDef in typeDef.Events) {
astType.AddChild(CreateEvent(eventDef), TypeDeclaration.MemberRole); astType.AddChild(CreateEvent(eventDef), TypeDeclaration.MemberRole);
} }
// Add properties
foreach(PropertyDefinition propDef in typeDef.Properties) {
MemberDeclaration astProp = CreateProperty(propDef);
if (astProp.Name == "Item" && propDef.HasParameters)
{
var defaultMember = GetDefaultMember(astType.Annotation<TypeDefinition>());
if (defaultMember.Item1 == "Item")
{
astProp = ConvertPropertyToIndexer((PropertyDeclaration)astProp, propDef);
var astAttr = astType.Attributes.SelectMany(sec => sec.Attributes).First(attr => attr.Annotation<CustomAttribute>() == defaultMember.Item2); // Add properties
var attrSection = (AttributeSection)astAttr.Parent; CreateProperties(astType, typeDef);
if (attrSection.Attributes.Count == 1)
attrSection.Remove();
else
astAttr.Remove();
}
}
astType.AddChild(astProp, TypeDeclaration.MemberRole);
}
// Add constructors // Add constructors
foreach(MethodDefinition methodDef in typeDef.Methods) { foreach(MethodDefinition methodDef in typeDef.Methods) {
@ -542,6 +526,35 @@ namespace ICSharpCode.Decompiler.Ast
} }
} }
private void CreateProperties(TypeDeclaration astType, TypeDefinition typeDef)
{
CustomAttribute attributeToRemove = null;
foreach (PropertyDefinition propDef in typeDef.Properties) {
MemberDeclaration astProp = CreateProperty(propDef);
if (astProp.Name == "Item" && propDef.HasParameters) {
var defaultMember = GetDefaultMember(astType.Annotation<TypeDefinition>());
if (defaultMember.Item1 == "Item") {
astProp = ConvertPropertyToIndexer((PropertyDeclaration)astProp, propDef);
attributeToRemove = defaultMember.Item2;
} else if ((propDef.GetMethod ?? propDef.SetMethod).HasOverrides) {
astProp = ConvertPropertyToIndexer((PropertyDeclaration)astProp, propDef);
}
}
astType.AddChild(astProp, TypeDeclaration.MemberRole);
}
if (attributeToRemove != null) {
var astAttr = astType.Attributes.SelectMany(sec => sec.Attributes).First(attr => attr.Annotation<CustomAttribute>() == attributeToRemove);
var attrSection = (AttributeSection)astAttr.Parent;
if (attrSection.Attributes.Count == 1)
attrSection.Remove();
else
astAttr.Remove();
}
}
MethodDeclaration CreateMethod(MethodDefinition methodDef) MethodDeclaration CreateMethod(MethodDefinition methodDef)
{ {
MethodDeclaration astMethod = new MethodDeclaration(); MethodDeclaration astMethod = new MethodDeclaration();
@ -552,7 +565,10 @@ namespace ICSharpCode.Decompiler.Ast
astMethod.Parameters.AddRange(MakeParameters(methodDef.Parameters)); astMethod.Parameters.AddRange(MakeParameters(methodDef.Parameters));
astMethod.Constraints.AddRange(MakeConstraints(methodDef.GenericParameters)); astMethod.Constraints.AddRange(MakeConstraints(methodDef.GenericParameters));
if (!methodDef.DeclaringType.IsInterface) { if (!methodDef.DeclaringType.IsInterface) {
astMethod.Modifiers = ConvertModifiers(methodDef); if (!methodDef.HasOverrides)
astMethod.Modifiers = ConvertModifiers(methodDef);
else
astMethod.PrivateImplementationType = ConvertType(methodDef.Overrides.First().DeclaringType);
astMethod.Body = AstMethodBodyBuilder.CreateMethodBody(methodDef, context); astMethod.Body = AstMethodBodyBuilder.CreateMethodBody(methodDef, context);
} }
ConvertAttributes(astMethod, methodDef); ConvertAttributes(astMethod, methodDef);
@ -618,7 +634,9 @@ namespace ICSharpCode.Decompiler.Ast
var astIndexer = new IndexerDeclaration(); var astIndexer = new IndexerDeclaration();
astIndexer.Name = astProp.Name; astIndexer.Name = astProp.Name;
astIndexer.CopyAnnotationsFrom(astProp); astIndexer.CopyAnnotationsFrom(astProp);
astProp.Attributes.MoveTo(astIndexer.Attributes);
astIndexer.Modifiers = astProp.Modifiers; astIndexer.Modifiers = astProp.Modifiers;
astIndexer.PrivateImplementationType = astProp.PrivateImplementationType.Detach();
astIndexer.ReturnType = astProp.ReturnType.Detach(); astIndexer.ReturnType = astProp.ReturnType.Detach();
astIndexer.Getter = astProp.Getter.Detach(); astIndexer.Getter = astProp.Getter.Detach();
astIndexer.Setter = astProp.Setter.Detach(); astIndexer.Setter = astProp.Setter.Detach();
@ -630,7 +648,11 @@ namespace ICSharpCode.Decompiler.Ast
{ {
PropertyDeclaration astProp = new PropertyDeclaration(); PropertyDeclaration astProp = new PropertyDeclaration();
astProp.AddAnnotation(propDef); astProp.AddAnnotation(propDef);
astProp.Modifiers = ConvertModifiers(propDef.GetMethod ?? propDef.SetMethod); var accessor = propDef.SetMethod ?? propDef.GetMethod;
if (!propDef.DeclaringType.IsInterface && !accessor.HasOverrides) {
astProp.Modifiers = ConvertModifiers(accessor);
} else if (accessor.HasOverrides)
astProp.PrivateImplementationType = ConvertType(accessor.Overrides.First().DeclaringType);
astProp.Name = CleanName(propDef.Name); astProp.Name = CleanName(propDef.Name);
astProp.ReturnType = ConvertType(propDef.PropertyType, propDef); astProp.ReturnType = ConvertType(propDef.PropertyType, propDef);
if (propDef.GetMethod != null) { if (propDef.GetMethod != null) {

60
ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs

@ -358,8 +358,62 @@ namespace TargetPropertySetReturn
} }
} }
} }
//$$ TargetPropertyIndexSetParam //$$ TargetPropertyIndexGetReturn
namespace TargetPropertyIndexSetParam namespace TargetPropertyIndexGetReturn
{
[AttributeUsage(AttributeTargets.All)]
public class MyAttributeAttribute : Attribute
{
}
public class MyClass
{
public int this[string s]
{
[return: MyAttribute]
get
{
return 3;
}
}
}
}
//$$ TargetPropertyIndexParamOnlySet
namespace TargetPropertyIndexParamOnlySet
{
[AttributeUsage(AttributeTargets.All)]
public class MyAttributeAttribute : Attribute
{
}
public class MyClass
{
public int this[[MyAttribute] string s]
{
set
{
}
}
}
}
//$$ TargetPropertyIndexParamOnlyGet
namespace TargetPropertyIndexParamOnlyGet
{
[AttributeUsage(AttributeTargets.All)]
public class MyAttributeAttribute : Attribute
{
}
public class MyClass
{
public int this[[MyAttribute] string s]
{
get
{
return 3;
}
}
}
}
//$$ TargetPropertyIndexSetReturn
namespace TargetPropertyIndexSetReturn
{ {
[AttributeUsage(AttributeTargets.All)] [AttributeUsage(AttributeTargets.All)]
public class MyAttributeAttribute : Attribute public class MyAttributeAttribute : Attribute
@ -373,7 +427,7 @@ namespace TargetPropertyIndexSetParam
{ {
return ""; return "";
} }
[param: MyAttribute] [return: MyAttribute]
set set
{ {
} }

6
ICSharpCode.Decompiler/Tests/DelegateConstruction.cs

@ -43,7 +43,8 @@ public static class DelegateConstruction
public static List<Action<int>> AnonymousMethodStoreWithinLoop() public static List<Action<int>> AnonymousMethodStoreWithinLoop()
{ {
List<Action<int>> list = new List<Action<int>>(); List<Action<int>> list = new List<Action<int>>();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++)
{
int counter; int counter;
list.Add(x => counter = x); list.Add(x => counter = x);
} }
@ -54,7 +55,8 @@ public static class DelegateConstruction
{ {
List<Action<int>> list = new List<Action<int>>(); List<Action<int>> list = new List<Action<int>>();
int counter; int counter;
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++)
{
list.Add(x => counter = x); list.Add(x => counter = x);
} }
return list; return list;

1
ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj

@ -57,6 +57,7 @@
<None Include="Types\S_EnumSamples.cs" /> <None Include="Types\S_EnumSamples.cs" />
<None Include="CustomAttributes\S_AssemblyCustomAttribute.cs" /> <None Include="CustomAttributes\S_AssemblyCustomAttribute.cs" />
<Compile Include="Helpers\RemoveCompilerAttribute.cs" /> <Compile Include="Helpers\RemoveCompilerAttribute.cs" />
<None Include="Types\S_TypeMemberDeclarations.cs" />
<Compile Include="Types\EnumTests.cs" /> <Compile Include="Types\EnumTests.cs" />
<Compile Include="Types\TypeTests.cs" /> <Compile Include="Types\TypeTests.cs" />
<Compile Include="DelegateConstruction.cs" /> <Compile Include="DelegateConstruction.cs" />

305
ICSharpCode.Decompiler/Tests/Types/S_TypeMemberDeclarations.cs

@ -0,0 +1,305 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
//$CS
using System;
//$CE
//$$ IndexerWithGetOnly
namespace IndexerWithGetOnly
{
public class MyClass
{
public int this[int i]
{
get
{
return i;
}
}
}
}
//$$ IndexerWithSetOnly
namespace IndexerWithSetOnly
{
public class MyClass
{
public int this[int i]
{
set
{
}
}
}
}
//$$ IndexerWithMoreParameters
namespace IndexerWithMoreParameters
{
public class MyClass
{
public int this[int i, string s, Type t]
{
get
{
return 0;
}
}
}
}
//$$ IndexerInGenericClass
namespace IndexerInGenericClass
{
public class MyClass<T>
{
public int this[T t]
{
get
{
return 0;
}
}
}
}
//$$ OverloadedIndexer
namespace OverloadedIndexer
{
public class MyClass
{
public int this[int t]
{
get
{
return 0;
}
}
public int this[string s]
{
get
{
return 0;
}
set
{
Console.WriteLine(value + " " + s);
}
}
}
}
//$$ IndexerInInterface
namespace IndexerInInterface
{
public interface IInterface
{
int this[string s, string s2]
{
set;
}
}
}
//$$ IndexerInterfaceExplicitImplementation
namespace IndexerInterfaceExplicitImplementation
{
public interface IMyInterface
{
int this[string s]
{
get;
}
}
public class MyClass : IMyInterface
{
int IMyInterface.this[string s]
{
get
{
return 3;
}
}
}
}
//$$ IndexerInterfaceImplementation
namespace IndexerInterfaceImplementation
{
public interface IMyInterface
{
int this[string s]
{
get;
}
}
public class MyClass : IMyInterface
{
public int this[string s]
{
get
{
return 3;
}
}
}
}
//$$ IndexerAbstract
namespace IndexerAbstract
{
public abstract class MyClass
{
public abstract int this[string s, string s2]
{
set;
}
protected abstract string this[int index]
{
get;
}
}
}
//$$ MethodExplicit
namespace MethodExplicit
{
public interface IMyInterface
{
void MyMethod();
}
public class MyClass : IMyInterface
{
void IMyInterface.MyMethod()
{
}
}
}
//$$ MethodFromInterfaceVirtual
namespace MethodFromInterfaceVirtual
{
public interface IMyInterface
{
void MyMethod();
}
public class MyClass : IMyInterface
{
public virtual void MyMethod()
{
}
}
}
//$$ MethodFromInterface
namespace MethodFromInterface
{
public interface IMyInterface
{
void MyMethod();
}
public class MyClass : IMyInterface
{
public void MyMethod()
{
}
}
}
//$$ MethodFromInterfaceAbstract
namespace MethodFromInterfaceAbstract
{
public interface IMyInterface
{
void MyMethod();
}
public abstract class MyClass : IMyInterface
{
public abstract void MyMethod();
}
}
//$$ PropertyInterface
namespace PropertyInterface
{
public interface IMyInterface
{
int MyProperty
{
get;
set;
}
}
}
//$$ PropertyInterfaceExplicitImplementation
namespace PropertyInterfaceExplicitImplementation
{
public interface IMyInterface
{
int MyProperty
{
get;
set;
}
}
public class MyClass : IMyInterface
{
int IMyInterface.MyProperty
{
get
{
return 0;
}
set
{
}
}
}
}
//$$ PropertyInterfaceImplementation
namespace PropertyInterfaceImplementation
{
public interface IMyInterface
{
int MyProperty
{
get;
set;
}
}
public class MyClass : IMyInterface
{
public int MyProperty
{
get
{
return 0;
}
set
{
}
}
}
}
//$$ PropertyPrivateGetPublicSet
namespace PropertyPrivateGetPublicSet
{
public class MyClass
{
public int MyProperty
{
private get
{
return 3;
}
set
{
}
}
}
}
//$$ PropertyPublicGetProtectedSet
namespace PropertyPublicGetProtectedSet
{
public class MyClass
{
public int MyProperty
{
get
{
return 3;
}
protected set
{
}
}
}
}

5
ICSharpCode.Decompiler/Tests/Types/TypeTests.cs

@ -8,5 +8,10 @@ namespace ICSharpCode.Decompiler.Tests.Types
{ {
public class TypeTests : DecompilerTestBase public class TypeTests : DecompilerTestBase
{ {
[Test]
public void TypeMemberDeclarations()
{
ValidateFileRoundtrip(@"Types\S_TypeMemberDeclarations.cs");
}
} }
} }

Loading…
Cancel
Save