public abstract class MetadataImporter
{
//
- // Dynamic types reader with additional logic to reconstruct a dynamic
- // type using DynamicAttribute values
+ // Types reader with additional logic to reconstruct extra
+ // type information encoded in custom attributes values
//
- protected struct DynamicTypeReader
+ protected struct AttributesTypeInfoReader
{
static readonly bool[] single_attribute = { true };
- public int Position;
- bool[] flags;
+ public int DynamicPosition;
+ bool[] dynamicFlags;
+
+ public int TuplePosition;
+ string[] tupleNames;
// There is no common type for CustomAttributeData and we cannot
// use ICustomAttributeProvider
//
// A member provider which can be used to get CustomAttributeData
//
- public DynamicTypeReader (object provider)
+ public AttributesTypeInfoReader (object provider)
{
- Position = 0;
- flags = null;
+ DynamicPosition = 0;
+ TuplePosition = 0;
+ dynamicFlags = null;
+ tupleNames = null;
this.provider = provider;
}
if (provider != null)
ReadAttribute ();
- return flags != null && Position < flags.Length && flags[Position];
+ return dynamicFlags != null && DynamicPosition < dynamicFlags.Length && dynamicFlags [DynamicPosition];
}
//
if (provider != null)
ReadAttribute ();
- return flags != null;
+ return dynamicFlags != null;
+ }
+
+ public bool HasNamedTupleAttribute ()
+ {
+ if (provider != null)
+ ReadAttribute ();
+
+ return tupleNames != null;
+ }
+
+ public IList<string> GetNamedTupleElements (int length)
+ {
+ if (TuplePosition == 0 && length == tupleNames.Length)
+ return tupleNames;
+
+ for (int i = TuplePosition; i < length + TuplePosition; ++i) {
+ if (tupleNames [i] != null) {
+ var res = new string [length];
+ Array.Copy (tupleNames, TuplePosition, res, 0, length);
+ return res;
+ }
+ }
+
+ //
+ // Current range can be just padding
+ //
+ return null;
}
IList<CustomAttributeData> GetCustomAttributes ()
if (cad.Count > 0) {
foreach (var ca in cad) {
var dt = ca.Constructor.DeclaringType;
- if (dt.Name != "DynamicAttribute" || dt.Namespace != CompilerServicesNamespace)
+ if (dt.Namespace != CompilerServicesNamespace)
continue;
- if (ca.ConstructorArguments.Count == 0) {
- flags = single_attribute;
- break;
- }
+ switch (dt.Name) {
+ case "DynamicAttribute":
+ if (ca.ConstructorArguments.Count == 0) {
+ dynamicFlags = single_attribute;
+ break;
+ }
- var arg_type = ca.ConstructorArguments[0].ArgumentType;
+ var arg_type = ca.ConstructorArguments [0].ArgumentType;
- if (arg_type.IsArray && MetaType.GetTypeCode (arg_type.GetElementType ()) == TypeCode.Boolean) {
- var carg = (IList<CustomAttributeTypedArgument>) ca.ConstructorArguments[0].Value;
- flags = new bool[carg.Count];
- for (int i = 0; i < flags.Length; ++i) {
- if (MetaType.GetTypeCode (carg[i].ArgumentType) == TypeCode.Boolean)
- flags[i] = (bool) carg[i].Value;
+ if (arg_type.IsArray && MetaType.GetTypeCode (arg_type.GetElementType ()) == TypeCode.Boolean) {
+ var carg = (IList<CustomAttributeTypedArgument>)ca.ConstructorArguments [0].Value;
+ dynamicFlags = new bool [carg.Count];
+ for (int i = 0; i < dynamicFlags.Length; ++i) {
+ if (MetaType.GetTypeCode (carg [i].ArgumentType) == TypeCode.Boolean)
+ dynamicFlags [i] = (bool)carg [i].Value;
+ }
+ }
+
+ break;
+ case "TupleElementNamesAttribute":
+ if (ca.ConstructorArguments.Count != 1)
+ break;
+
+ var tuple_arg_type = ca.ConstructorArguments [0].ArgumentType;
+ if (tuple_arg_type.IsArray && MetaType.GetTypeCode (tuple_arg_type.GetElementType ()) == TypeCode.String) {
+ var carg = (IList<CustomAttributeTypedArgument>)ca.ConstructorArguments [0].Value;
+ tupleNames = new string [carg.Count];
+ for (int i = 0; i < tupleNames.Length; ++i) {
+ if (MetaType.GetTypeCode (carg [i].ArgumentType) == TypeCode.String)
+ tupleNames [i] = (string)carg [i].Value;
+ }
}
break;
TypeSpec field_type;
try {
- field_type = ImportType (fi.FieldType, new DynamicTypeReader (fi), declaringType);
+ field_type = ImportType (fi.FieldType, new AttributesTypeInfoReader (fi), declaringType);
//
// Private field has private type which is not fixed buffer
if (add.Modifiers != remove.Modifiers)
throw new NotImplementedException ("Different accessor modifiers " + ei.Name);
- var event_type = ImportType (ei.EventHandlerType, new DynamicTypeReader (ei), declaringType);
+ var event_type = ImportType (ei.EventHandlerType, new AttributesTypeInfoReader (ei), declaringType);
var definition = new ImportedMemberDefinition (ei, event_type, this);
return new EventSpec (declaringType, definition, event_type, add.Modifiers, add, remove);
}
var type = tparams[pos];
int index = pos - first;
- tspec[index] = (TypeParameterSpec) CreateType (type, new DynamicTypeReader (), false);
+ tspec[index] = (TypeParameterSpec) CreateType (type, new AttributesTypeInfoReader (), false);
}
return tspec;
}
- TypeSpec[] CreateGenericArguments (int first, MetaType[] tparams, DynamicTypeReader dtype)
+ TypeSpec[] CreateGenericArguments (int first, MetaType[] tparams, AttributesTypeInfoReader dtype)
{
- ++dtype.Position;
+ ++dtype.DynamicPosition;
var tspec = new TypeSpec [tparams.Length - first];
for (int pos = first; pos < tparams.Length; ++pos) {
TypeSpec spec;
if (type.HasElementType) {
var element = type.GetElementType ();
- ++dtype.Position;
+ ++dtype.DynamicPosition;
spec = ImportType (element, dtype, null);
if (!type.IsArray) {
if (spec == null)
return null;
- ++dtype.Position;
+ ++dtype.DynamicPosition;
tspec[index] = spec;
}
returnType = module.Compiler.BuiltinTypes.Void;
} else {
var mi = (MethodInfo)mb;
- returnType = ImportType (mi.ReturnType, new DynamicTypeReader (mi.ReturnParameter), declaringType);
+ returnType = ImportType (mi.ReturnType, new AttributesTypeInfoReader (mi.ReturnParameter), declaringType);
//
// Detect operators and destructors
// Strip reference wrapping
//
var el = p.ParameterType.GetElementType ();
- types[i] = ImportType (el, new DynamicTypeReader (p), parent); // TODO: 1-based positio to be csc compatible
+ types[i] = ImportType (el, new AttributesTypeInfoReader (p), parent); // TODO: 1-based positio to be csc compatible
} else if (i == 0 && method.IsStatic && (parent.Modifiers & Modifiers.METHOD_EXTENSION) != 0 &&
HasAttribute (CustomAttributeData.GetCustomAttributes (method), "ExtensionAttribute", CompilerServicesNamespace)) {
mod = Parameter.Modifier.This;
- types[i] = ImportType (p.ParameterType, new DynamicTypeReader (p), parent);
+ types[i] = ImportType (p.ParameterType, new AttributesTypeInfoReader (p), parent);
} else {
- types[i] = ImportType (p.ParameterType, new DynamicTypeReader (p), parent);
+ types[i] = ImportType (p.ParameterType, new AttributesTypeInfoReader (p), parent);
if (i >= pi.Length - 2 && types[i] is ArrayContainer) {
if (HasAttribute (CustomAttributeData.GetCustomAttributes (p), "ParamArrayAttribute", "System")) {
public TypeSpec CreateType (MetaType type)
{
- return CreateType (type, new DynamicTypeReader (), true);
+ return CreateType (type, new AttributesTypeInfoReader (), true);
}
public TypeSpec CreateNestedType (MetaType type, TypeSpec declaringType)
{
- return CreateType (type, declaringType, new DynamicTypeReader (type), false);
+ return CreateType (type, declaringType, new AttributesTypeInfoReader (type), false);
}
- TypeSpec CreateType (MetaType type, DynamicTypeReader dtype, bool canImportBaseType)
+ TypeSpec CreateType (MetaType type, AttributesTypeInfoReader dtype, bool canImportBaseType)
{
TypeSpec declaring_type;
if (type.IsNested && !type.IsGenericParameter)
- declaring_type = CreateType (type.DeclaringType, new DynamicTypeReader (type.DeclaringType), true);
+ declaring_type = CreateType (type.DeclaringType, new AttributesTypeInfoReader (type.DeclaringType), true);
else
declaring_type = null;
return CreateType (type, declaring_type, dtype, canImportBaseType);
}
- protected TypeSpec CreateType (MetaType type, TypeSpec declaringType, DynamicTypeReader dtype, bool canImportBaseType)
+ protected TypeSpec CreateType (MetaType type, TypeSpec declaringType, AttributesTypeInfoReader dtype, bool canImportBaseType)
{
TypeSpec spec;
if (import_cache.TryGetValue (type, out spec)) {
return null;
if (declaringType == null) {
// Simple case, no nesting
- spec = CreateType (type_def, null, new DynamicTypeReader (), canImportBaseType);
+ spec = CreateType (type_def, null, new AttributesTypeInfoReader (), canImportBaseType);
spec = spec.MakeGenericType (module, targs);
} else {
//
}
}
+ if (spec.IsTupleType && dtype.HasNamedTupleAttribute ()) {
+ var names = dtype.GetNamedTupleElements (spec.Arity);
+ if (names != null)
+ return NamedTupleSpec.MakeType (module, (InflatedTypeSpec) spec, names);
+
+ dtype.TuplePosition += spec.Arity;
+ }
+
// Don't add generic type with dynamic arguments, they can interfere with same type
// using object type arguments
if (!spec.HasDynamicElement) {
}
}
- if (kind == MemberKind.Class) {
+ switch (kind) {
+ case MemberKind.Class:
if ((ma & TypeAttributes.Sealed) != 0) {
if ((ma & TypeAttributes.Abstract) != 0)
mod |= Modifiers.STATIC;
} else if ((ma & TypeAttributes.Abstract) != 0) {
mod |= Modifiers.ABSTRACT;
}
+ break;
+ case MemberKind.Struct:
+ if (HasAttribute (CustomAttributeData.GetCustomAttributes (type), "IsReadOnlyAttribute", CompilerServicesNamespace)) {
+ mod |= Modifiers.READONLY;
+ }
+
+ break;
}
}
else if (type.BaseType != null) {
TypeSpec base_type;
if (!IsMissingType (type.BaseType) && type.BaseType.IsGenericType)
- base_type = CreateType (type.BaseType, new DynamicTypeReader (type), true);
+ base_type = CreateType (type.BaseType, new AttributesTypeInfoReader (type), true);
else
base_type = CreateType (type.BaseType);
if (t.Name[0] == '<')
continue;
- var it = CreateType (t, null, new DynamicTypeReader (t), true);
+ var it = CreateType (t, null, new AttributesTypeInfoReader (t), true);
if (it == null)
continue;
public TypeSpec ImportType (MetaType type)
{
- return ImportType (type, new DynamicTypeReader (type), null);
+ return ImportType (type, new AttributesTypeInfoReader (type), null);
}
- TypeSpec ImportType (MetaType type, DynamicTypeReader dtype, TypeSpec currentType)
+ TypeSpec ImportType (MetaType type, AttributesTypeInfoReader dtype, TypeSpec currentType)
{
if (type.HasElementType) {
var element = type.GetElementType ();
- ++dtype.Position;
+ ++dtype.DynamicPosition;
var spec = ImportType (element, dtype, currentType);
if (type.IsArray)