Files
2018-10-10 14:40:52 +01:00

101 lines
3.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A CIL attribute.
/// </summary>
interface IAttribute : IExtractedEntity
{
}
/// <summary>
/// Entity representing a CIL attribute.
/// </summary>
class Attribute : UnlabelledEntity, IAttribute
{
readonly CustomAttribute attrib;
readonly IEntity @object;
public Attribute(Context cx, IEntity @object, CustomAttributeHandle handle) : base(cx)
{
attrib = cx.mdReader.GetCustomAttribute(handle);
this.@object = @object;
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
var constructor = (Method)cx.Create(attrib.Constructor);
yield return constructor;
yield return Tuples.cil_attribute(this, @object, constructor);
CustomAttributeValue<Type> decoded;
try
{
decoded = attrib.DecodeValue(new CustomAttributeDecoder(cx));
}
catch (NotImplementedException)
{
// Attribute decoding is only partial at this stage.
yield break;
}
for (int index = 0; index < decoded.FixedArguments.Length; ++index)
{
object value = decoded.FixedArguments[index].Value;
yield return Tuples.cil_attribute_positional_argument(this, index, value == null ? "null" : value.ToString());
}
foreach (var p in decoded.NamedArguments)
{
object value = p.Value;
yield return Tuples.cil_attribute_named_argument(this, p.Name, value == null ? "null" : value.ToString());
}
}
}
public static IEnumerable<IExtractionProduct> Populate(Context cx, IEntity @object, CustomAttributeHandleCollection attributes)
{
foreach (var attrib in attributes)
{
yield return new Attribute(cx, @object, attrib);
}
}
}
/// <summary>
/// Helper class to decode the attribute structure.
/// Note that there are some unhandled cases that should be fixed in due course.
/// </summary>
class CustomAttributeDecoder : ICustomAttributeTypeProvider<Type>
{
readonly Context cx;
public CustomAttributeDecoder(Context cx) { this.cx = cx; }
public Type GetPrimitiveType(PrimitiveTypeCode typeCode) => cx.Populate(new PrimitiveType(cx, typeCode));
public Type GetSystemType() => throw new NotImplementedException();
public Type GetSZArrayType(Type elementType) =>
cx.Populate(new ArrayType(cx, elementType));
public Type GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) =>
(Type)cx.Create(handle);
public Type GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) =>
(Type)cx.Create(handle);
public Type GetTypeFromSerializedName(string name) => throw new NotImplementedException();
public PrimitiveTypeCode GetUnderlyingEnumType(Type type) => throw new NotImplementedException();
public bool IsSystemType(Type type) => type is PrimitiveType; // ??
}
}