Enum = 1 << 14,
Interface = 1 << 15,
TypeParameter = 1 << 16,
+ ByRef = 1 << 17,
ArrayType = 1 << 19,
PointerType = 1 << 20,
//
static bool AddInterfaceMember (MemberSpec member, ref IList<MemberSpec> existing)
{
- var member_param = member is IParametersMember ? ((IParametersMember) member).Parameters : ParametersCompiled.EmptyReadOnlyParameters;
+ var member_param = member is IParametersMember ? ((IParametersMember) member).Parameters : null;
//
// interface IA : IB { int Prop { set; } }
if (entry.Arity != member.Arity)
continue;
- if (entry is IParametersMember) {
- var entry_param = ((IParametersMember) entry).Parameters;
- if (!TypeSpecComparer.Override.IsEqual (entry_param, member_param))
- continue;
+ AParametersCollection entry_param = null;
+ if (member_param != null) {
+ var entry_pm = entry as IParametersMember;
+ if (entry_pm != null) {
+ entry_param = entry_pm.Parameters;
+ if (entry.DeclaringType != member.DeclaringType) {
+ if (!TypeSpecComparer.Override.IsEqual (entry_param, member_param))
+ continue;
+ } else {
+ if (!TypeSpecComparer.Equals (entry_param.Types, member_param.Types))
+ continue;
+ }
+ }
}
if (member.DeclaringType.ImplementsInterface (entry.DeclaringType, false)) {
continue;
}
- if ((entry.DeclaringType == member.DeclaringType && entry.IsAccessor == member.IsAccessor) ||
- entry.DeclaringType.ImplementsInterface (member.DeclaringType, false))
+ if ((entry.DeclaringType == member.DeclaringType && entry.IsAccessor == member.IsAccessor))
+ return false;
+
+ if (entry.DeclaringType.ImplementsInterface (member.DeclaringType, false) && AParametersCollection.HasSameParameterDefaults (entry_param, member_param))
return false;
}
public static MemberSpec FindMember (TypeSpec container, MemberFilter filter, BindingRestriction restrictions)
{
+ if (filter.Kind == MemberKind.Method && container.Kind == MemberKind.TypeParameter && filter.Parameters == null)
+ throw new NotSupportedException ("type parameters methods cannot be lookup up due to two stage setup");
+
+ IList<MemberSpec> applicable;
+ var top_container = container;
+
do {
- IList<MemberSpec> applicable;
if (container.MemberCache.member_hash.TryGetValue (filter.Name, out applicable)) {
// Start from the end because interface members are in reverse order
for (int i = applicable.Count - 1; i >= 0; i--) {
container = container.BaseType;
} while (container != null);
+ var tps = top_container as TypeParameterSpec;
+ if (tps != null && tps.InterfaceCache != null) {
+ if (tps.InterfaceCache.member_hash.TryGetValue (filter.Name, out applicable)) {
+ for (int i = applicable.Count - 1; i >= 0; i--) {
+ var entry = applicable [i];
+
+ if ((restrictions & BindingRestriction.NoAccessors) != 0 && entry.IsAccessor)
+ continue;
+
+ if ((restrictions & BindingRestriction.OverrideOnly) != 0 && (entry.Modifiers & Modifiers.OVERRIDE) == 0)
+ continue;
+
+ if (!filter.Equals (entry))
+ continue;
+
+ return entry;
+ }
+ }
+ }
+
return null;
}
//
public static IList<MemberSpec> FindMembers (TypeSpec container, string name, bool declaredOnlyClass)
{
- IList<MemberSpec> applicable;
-
do {
+ IList<MemberSpec> applicable;
+
if (container.MemberCache.member_hash.TryGetValue (name, out applicable) || declaredOnlyClass)
return applicable;
return null;
}
+ public static IList<MemberSpec> FindInterfaceMembers (TypeParameterSpec typeParameter, string name)
+ {
+ if (typeParameter.InterfaceCache != null) {
+ IList<MemberSpec> applicable;
+ typeParameter.InterfaceCache.member_hash.TryGetValue (name, out applicable);
+ return applicable;
+ }
+
+ return null;
+ }
+
//
// Finds the nested type in container
//
- public static TypeSpec FindNestedType (TypeSpec container, string name, int arity)
+ public static TypeSpec FindNestedType (TypeSpec container, string name, int arity, bool declaredOnlyClass)
{
IList<MemberSpec> applicable;
TypeSpec best_match = null;
if (arity < 0) {
if (best_match == null) {
best_match = ts;
- } else if (System.Math.Abs (ts.Arity + arity) < System.Math.Abs (ts.Arity + arity)) {
+ } else if (System.Math.Abs (ts.Arity + arity) < System.Math.Abs (best_match.Arity + arity)) {
best_match = ts;
}
}
}
container = container.BaseType;
- } while (container != null);
+ } while (container != null && !declaredOnlyClass);
return best_match;
}
return ambig_candidate;
}
+ public static List<TypeSpec> GetDeclaredNestedTypes (TypeSpec container)
+ {
+ List<TypeSpec> found = null;
+ foreach (var entry in container.MemberCache.member_hash) {
+ foreach (var member in entry.Value) {
+ if ((member.Kind & MemberKind.NestedMask) == 0)
+ continue;
+
+ if (found == null)
+ found = new List<TypeSpec> ();
+
+ found.Add ((TypeSpec)member);
+ }
+ }
+
+ return found;
+ }
+
//
// Returns inflated version of MemberSpec, it works similarly to
// SRE TypeBuilder.GetMethod
throw new NotImplementedException (member.GetType ().ToString ());
}
- public static List<FieldSpec> GetAllFieldsForDefiniteAssignment (TypeSpec container)
+ public static List<FieldSpec> GetAllFieldsForDefiniteAssignment (TypeSpec container, IMemberContext context)
{
List<FieldSpec> fields = null;
+ bool imported = container.MemberDefinition.IsImported;
foreach (var entry in container.MemberCache.member_hash) {
foreach (var name_entry in entry.Value) {
if (name_entry.Kind != MemberKind.Field)
continue;
var fs = (FieldSpec) name_entry;
-
- //
- // LAMESPEC: Very bizzare hack, definitive assignment is not done
- // for imported non-public reference fields except array. No idea what the
- // actual csc rule is
- //
- if (!fs.IsPublic && container.MemberDefinition.IsImported && (!fs.MemberType.IsArray && TypeSpec.IsReferenceType (fs.MemberType)))
+ if (imported && ShouldIgnoreFieldForDefiniteAssignment (fs, context))
continue;
//if ((fs.Modifiers & (Modifiers.BACKING_FIELD) != 0)
return fields ?? new List<FieldSpec> (0);
}
+ static bool ShouldIgnoreFieldForDefiniteAssignment (FieldSpec fs, IMemberContext context)
+ {
+ //
+ // LAMESPEC: This mimics csc quirk where definitive assignment is not done
+ // for all kinds of imported non-public struct fields
+ //
+ var mod = fs.Modifiers;
+ if ((mod & Modifiers.PRIVATE) == 0 && ((mod & Modifiers.INTERNAL) != 0 && fs.DeclaringType.MemberDefinition.IsInternalAsPublic (context.Module.DeclaringAssembly)))
+ return false;
+
+ //
+ // Ignore reference type fields except when type is an array or type parameter
+ //
+ var type = fs.MemberType;
+ switch (type.Kind) {
+ case MemberKind.ArrayType:
+ case MemberKind.TypeParameter:
+ return false;
+ default:
+ return TypeSpec.IsReferenceType (type);
+ }
+ }
+
public static IList<MemberSpec> GetCompletitionMembers (IMemberContext ctx, TypeSpec container, string name)
{
var matches = new List<MemberSpec> ();
shared_list = false;
prev = new List<MemberSpec> (found.Count + 1);
prev.AddRange (found);
+ found = prev;
} else {
prev = (List<MemberSpec>) found;
}
if (a.DeclaringType.MemberDefinition != b.DeclaringType.MemberDefinition)
return mc_b;
- if (mc_a.Location.File != mc_a.Location.File)
+ if (mc_a.Location.File != mc_b.Location.File)
return mc_b;
return mc_b.Location.Row > mc_a.Location.Row ? mc_b : mc_a;
}
return false;
}
+
+ var pm_member = (MethodCore)member;
+ if (!NamedTupleSpec.CheckOverrideName (pm, pm_member) || !NamedTupleSpec.CheckOverrideName (pm.MemberType, pm_member.MemberType)) {
+ Report.Error (8142, member.Location,
+ "A partial method declaration and partial method implementation must both use the same tuple element names");
+ }
}
}