//
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 (!TypeSpecComparer.Override.IsEqual (entry_param, member_param))
+ 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;
}
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)
if ((name_entry.Modifiers & Modifiers.STATIC) != 0)
continue;
- //
- // Ignore user private fields for definite assignment. This is sort of unexpected but
- // rationale is to have consistent results when using reference assemblies which don't
- // include any private fields and full assemblies
- //
- if ((name_entry.Modifiers & (Modifiers.PRIVATE | Modifiers.BACKING_FIELD)) == Modifiers.PRIVATE)
- continue;
-
//
// Fixed size buffers are not subject to definite assignment checking
//
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)
+ // continue;
+
if (fields == null)
fields = new List<FieldSpec> ();
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> ();
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;