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. 68
      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

68
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -231,6 +231,9 @@ namespace ICSharpCode.Decompiler.Ast @@ -231,6 +231,9 @@ namespace ICSharpCode.Decompiler.Ast
int pos = name.LastIndexOf('`');
if (pos >= 0)
name = name.Substring(0, pos);
pos = name.LastIndexOf('.');
if (pos >= 0)
name = name.Substring(pos + 1);
return name;
}
@ -489,6 +492,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -489,6 +492,7 @@ namespace ICSharpCode.Decompiler.Ast
return modifiers;
}
#endregion
void AddTypeMembers(TypeDeclaration astType, TypeDefinition typeDef)
@ -505,27 +509,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -505,27 +509,7 @@ namespace ICSharpCode.Decompiler.Ast
}
// 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);
var attrSection = (AttributeSection)astAttr.Parent;
if (attrSection.Attributes.Count == 1)
attrSection.Remove();
else
astAttr.Remove();
}
}
astType.AddChild(astProp, TypeDeclaration.MemberRole);
}
CreateProperties(astType, typeDef);
// Add constructors
foreach(MethodDefinition methodDef in typeDef.Methods) {
@ -542,6 +526,35 @@ namespace ICSharpCode.Decompiler.Ast @@ -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 astMethod = new MethodDeclaration();
@ -552,7 +565,10 @@ namespace ICSharpCode.Decompiler.Ast @@ -552,7 +565,10 @@ namespace ICSharpCode.Decompiler.Ast
astMethod.Parameters.AddRange(MakeParameters(methodDef.Parameters));
astMethod.Constraints.AddRange(MakeConstraints(methodDef.GenericParameters));
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);
}
ConvertAttributes(astMethod, methodDef);
@ -618,7 +634,9 @@ namespace ICSharpCode.Decompiler.Ast @@ -618,7 +634,9 @@ namespace ICSharpCode.Decompiler.Ast
var astIndexer = new IndexerDeclaration();
astIndexer.Name = astProp.Name;
astIndexer.CopyAnnotationsFrom(astProp);
astProp.Attributes.MoveTo(astIndexer.Attributes);
astIndexer.Modifiers = astProp.Modifiers;
astIndexer.PrivateImplementationType = astProp.PrivateImplementationType.Detach();
astIndexer.ReturnType = astProp.ReturnType.Detach();
astIndexer.Getter = astProp.Getter.Detach();
astIndexer.Setter = astProp.Setter.Detach();
@ -630,7 +648,11 @@ namespace ICSharpCode.Decompiler.Ast @@ -630,7 +648,11 @@ namespace ICSharpCode.Decompiler.Ast
{
PropertyDeclaration astProp = new PropertyDeclaration();
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.ReturnType = ConvertType(propDef.PropertyType, propDef);
if (propDef.GetMethod != null) {

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

@ -358,8 +358,62 @@ namespace TargetPropertySetReturn @@ -358,8 +358,62 @@ namespace TargetPropertySetReturn
}
}
}
//$$ TargetPropertyIndexSetParam
namespace TargetPropertyIndexSetParam
//$$ TargetPropertyIndexGetReturn
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)]
public class MyAttributeAttribute : Attribute
@ -373,7 +427,7 @@ namespace TargetPropertyIndexSetParam @@ -373,7 +427,7 @@ namespace TargetPropertyIndexSetParam
{
return "";
}
[param: MyAttribute]
[return: MyAttribute]
set
{
}

6
ICSharpCode.Decompiler/Tests/DelegateConstruction.cs

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

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

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

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

@ -0,0 +1,305 @@ @@ -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 @@ -8,5 +8,10 @@ namespace ICSharpCode.Decompiler.Tests.Types
{
public class TypeTests : DecompilerTestBase
{
[Test]
public void TypeMemberDeclarations()
{
ValidateFileRoundtrip(@"Types\S_TypeMemberDeclarations.cs");
}
}
}

Loading…
Cancel
Save