|
|
|
@ -771,5 +771,206 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -771,5 +771,206 @@ namespace ICSharpCode.Decompiler.CSharp
|
|
|
|
|
} |
|
|
|
|
return eventDecl; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#region Convert Type Reference
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Converts a type reference.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="type">The Cecil type reference that should be converted into
|
|
|
|
|
/// a type system type reference.</param>
|
|
|
|
|
/// <param name="typeAttributes">Attributes associated with the Cecil type reference.
|
|
|
|
|
/// This is used to support the 'dynamic' type.</param>
|
|
|
|
|
public static AstType ConvertType(TypeReference type, ICustomAttributeProvider typeAttributes = null, ConvertTypeOptions options = ConvertTypeOptions.None) |
|
|
|
|
{ |
|
|
|
|
int typeIndex = 0; |
|
|
|
|
return ConvertType(type, typeAttributes, ref typeIndex, options); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static AstType ConvertType(TypeReference type, ICustomAttributeProvider typeAttributes, ref int typeIndex, ConvertTypeOptions options) |
|
|
|
|
{ |
|
|
|
|
while (type is OptionalModifierType || type is RequiredModifierType) { |
|
|
|
|
type = ((TypeSpecification)type).ElementType; |
|
|
|
|
} |
|
|
|
|
if (type == null) { |
|
|
|
|
return AstType.Null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (type is Mono.Cecil.ByReferenceType) { |
|
|
|
|
typeIndex++; |
|
|
|
|
// by reference type cannot be represented in C#; so we'll represent it as a pointer instead
|
|
|
|
|
return ConvertType((type as Mono.Cecil.ByReferenceType).ElementType, typeAttributes, ref typeIndex, options) |
|
|
|
|
.MakePointerType(); |
|
|
|
|
} else if (type is Mono.Cecil.PointerType) { |
|
|
|
|
typeIndex++; |
|
|
|
|
return ConvertType((type as Mono.Cecil.PointerType).ElementType, typeAttributes, ref typeIndex, options) |
|
|
|
|
.MakePointerType(); |
|
|
|
|
} else if (type is Mono.Cecil.ArrayType) { |
|
|
|
|
typeIndex++; |
|
|
|
|
return ConvertType((type as Mono.Cecil.ArrayType).ElementType, typeAttributes, ref typeIndex, options) |
|
|
|
|
.MakeArrayType((type as Mono.Cecil.ArrayType).Rank); |
|
|
|
|
} else if (type is GenericInstanceType) { |
|
|
|
|
GenericInstanceType gType = (GenericInstanceType)type; |
|
|
|
|
if (gType.ElementType.Namespace == "System" && gType.ElementType.Name == "Nullable`1" && gType.GenericArguments.Count == 1) { |
|
|
|
|
typeIndex++; |
|
|
|
|
return new ComposedType { |
|
|
|
|
BaseType = ConvertType(gType.GenericArguments[0], typeAttributes, ref typeIndex, options), |
|
|
|
|
HasNullableSpecifier = true |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
AstType baseType = ConvertType(gType.ElementType, typeAttributes, ref typeIndex, options & ~ConvertTypeOptions.IncludeTypeParameterDefinitions); |
|
|
|
|
List<AstType> typeArguments = new List<AstType>(); |
|
|
|
|
foreach (var typeArgument in gType.GenericArguments) { |
|
|
|
|
typeIndex++; |
|
|
|
|
typeArguments.Add(ConvertType(typeArgument, typeAttributes, ref typeIndex, options)); |
|
|
|
|
} |
|
|
|
|
ApplyTypeArgumentsTo(baseType, typeArguments); |
|
|
|
|
return baseType; |
|
|
|
|
} else if (type is GenericParameter) { |
|
|
|
|
return new SimpleType(type.Name); |
|
|
|
|
} else if (type.IsNested) { |
|
|
|
|
AstType typeRef = ConvertType(type.DeclaringType, typeAttributes, ref typeIndex, options & ~ConvertTypeOptions.IncludeTypeParameterDefinitions); |
|
|
|
|
string namepart = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name); |
|
|
|
|
MemberType memberType = new MemberType { Target = typeRef, MemberName = namepart }; |
|
|
|
|
memberType.AddAnnotation(type); |
|
|
|
|
if ((options & ConvertTypeOptions.IncludeTypeParameterDefinitions) == ConvertTypeOptions.IncludeTypeParameterDefinitions) { |
|
|
|
|
AddTypeParameterDefininitionsTo(type, memberType); |
|
|
|
|
} |
|
|
|
|
return memberType; |
|
|
|
|
} else { |
|
|
|
|
string ns = type.Namespace ?? string.Empty; |
|
|
|
|
string name = type.Name; |
|
|
|
|
if (name == null) |
|
|
|
|
throw new InvalidOperationException("type.Name returned null. Type: " + type.ToString()); |
|
|
|
|
|
|
|
|
|
if (name == "Object" && ns == "System" && HasDynamicAttribute(typeAttributes, typeIndex)) { |
|
|
|
|
return new Syntax.PrimitiveType("dynamic"); |
|
|
|
|
} else { |
|
|
|
|
if (ns == "System") { |
|
|
|
|
if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) |
|
|
|
|
!= ConvertTypeOptions.DoNotUsePrimitiveTypeNames) { |
|
|
|
|
switch (name) { |
|
|
|
|
case "SByte": |
|
|
|
|
return new Syntax.PrimitiveType("sbyte"); |
|
|
|
|
case "Int16": |
|
|
|
|
return new Syntax.PrimitiveType("short"); |
|
|
|
|
case "Int32": |
|
|
|
|
return new Syntax.PrimitiveType("int"); |
|
|
|
|
case "Int64": |
|
|
|
|
return new Syntax.PrimitiveType("long"); |
|
|
|
|
case "Byte": |
|
|
|
|
return new Syntax.PrimitiveType("byte"); |
|
|
|
|
case "UInt16": |
|
|
|
|
return new Syntax.PrimitiveType("ushort"); |
|
|
|
|
case "UInt32": |
|
|
|
|
return new Syntax.PrimitiveType("uint"); |
|
|
|
|
case "UInt64": |
|
|
|
|
return new Syntax.PrimitiveType("ulong"); |
|
|
|
|
case "String": |
|
|
|
|
return new Syntax.PrimitiveType("string"); |
|
|
|
|
case "Single": |
|
|
|
|
return new Syntax.PrimitiveType("float"); |
|
|
|
|
case "Double": |
|
|
|
|
return new Syntax.PrimitiveType("double"); |
|
|
|
|
case "Decimal": |
|
|
|
|
return new Syntax.PrimitiveType("decimal"); |
|
|
|
|
case "Char": |
|
|
|
|
return new Syntax.PrimitiveType("char"); |
|
|
|
|
case "Boolean": |
|
|
|
|
return new Syntax.PrimitiveType("bool"); |
|
|
|
|
case "Void": |
|
|
|
|
return new Syntax.PrimitiveType("void"); |
|
|
|
|
case "Object": |
|
|
|
|
return new Syntax.PrimitiveType("object"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name); |
|
|
|
|
|
|
|
|
|
AstType astType; |
|
|
|
|
if ((options & ConvertTypeOptions.IncludeNamespace) == ConvertTypeOptions.IncludeNamespace && ns.Length > 0) { |
|
|
|
|
string[] parts = ns.Split('.'); |
|
|
|
|
AstType nsType = new SimpleType(parts[0]); |
|
|
|
|
for (int i = 1; i < parts.Length; i++) { |
|
|
|
|
nsType = new MemberType { Target = nsType, MemberName = parts[i] }; |
|
|
|
|
} |
|
|
|
|
astType = new MemberType { Target = nsType, MemberName = name }; |
|
|
|
|
} else { |
|
|
|
|
astType = new SimpleType(name); |
|
|
|
|
} |
|
|
|
|
astType.AddAnnotation(type); |
|
|
|
|
|
|
|
|
|
if ((options & ConvertTypeOptions.IncludeTypeParameterDefinitions) == ConvertTypeOptions.IncludeTypeParameterDefinitions) { |
|
|
|
|
AddTypeParameterDefininitionsTo(type, astType); |
|
|
|
|
} |
|
|
|
|
return astType; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void AddTypeParameterDefininitionsTo(TypeReference type, AstType astType) |
|
|
|
|
{ |
|
|
|
|
if (type.HasGenericParameters) { |
|
|
|
|
List<AstType> typeArguments = new List<AstType>(); |
|
|
|
|
foreach (GenericParameter gp in type.GenericParameters) { |
|
|
|
|
typeArguments.Add(new SimpleType(gp.Name)); |
|
|
|
|
} |
|
|
|
|
ApplyTypeArgumentsTo(astType, typeArguments); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void ApplyTypeArgumentsTo(AstType baseType, List<AstType> typeArguments) |
|
|
|
|
{ |
|
|
|
|
SimpleType st = baseType as SimpleType; |
|
|
|
|
if (st != null) { |
|
|
|
|
st.TypeArguments.AddRange(typeArguments); |
|
|
|
|
} |
|
|
|
|
MemberType mt = baseType as MemberType; |
|
|
|
|
if (mt != null) { |
|
|
|
|
TypeReference type = mt.Annotation<TypeReference>(); |
|
|
|
|
if (type != null) { |
|
|
|
|
int typeParameterCount; |
|
|
|
|
ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount); |
|
|
|
|
if (typeParameterCount > typeArguments.Count) |
|
|
|
|
typeParameterCount = typeArguments.Count; |
|
|
|
|
mt.TypeArguments.AddRange(typeArguments.GetRange(typeArguments.Count - typeParameterCount, typeParameterCount)); |
|
|
|
|
typeArguments.RemoveRange(typeArguments.Count - typeParameterCount, typeParameterCount); |
|
|
|
|
if (typeArguments.Count > 0) |
|
|
|
|
ApplyTypeArgumentsTo(mt.Target, typeArguments); |
|
|
|
|
} else { |
|
|
|
|
mt.TypeArguments.AddRange(typeArguments); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const string DynamicAttributeFullName = "System.Runtime.CompilerServices.DynamicAttribute"; |
|
|
|
|
|
|
|
|
|
static bool HasDynamicAttribute(ICustomAttributeProvider attributeProvider, int typeIndex) |
|
|
|
|
{ |
|
|
|
|
if (attributeProvider == null || !attributeProvider.HasCustomAttributes) |
|
|
|
|
return false; |
|
|
|
|
foreach (CustomAttribute a in attributeProvider.CustomAttributes) { |
|
|
|
|
if (a.Constructor.DeclaringType.FullName == DynamicAttributeFullName) { |
|
|
|
|
if (a.ConstructorArguments.Count == 1) { |
|
|
|
|
CustomAttributeArgument[] values = a.ConstructorArguments[0].Value as CustomAttributeArgument[]; |
|
|
|
|
if (values != null && typeIndex < values.Length && values[typeIndex].Value is bool) |
|
|
|
|
return (bool)values[typeIndex].Value; |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
[Flags] |
|
|
|
|
public enum ConvertTypeOptions |
|
|
|
|
{ |
|
|
|
|
None = 0, |
|
|
|
|
IncludeNamespace = 1, |
|
|
|
|
IncludeTypeParameterDefinitions = 2, |
|
|
|
|
DoNotUsePrimitiveTypeNames = 4 |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|