[mcs] Initial by ref returns and variables support
[mono.git] / mcs / mcs / membercache.cs
index 57e2e11e19c8dc221a3933ce666ccba0de57a08f..eebf71b844b8e2a51337bf35a1560c7b13d7134f 100644 (file)
@@ -35,6 +35,7 @@ namespace Mono.CSharp {
                Enum            = 1 << 14,
                Interface       = 1 << 15,
                TypeParameter = 1 << 16,
+               ByRef           = 1 << 17,
 
                ArrayType = 1 << 19,
                PointerType = 1 << 20,
@@ -373,8 +374,13 @@ namespace Mono.CSharp {
                                        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 (entry.DeclaringType != member.DeclaringType) {
+                                                       if (!TypeSpecComparer.Override.IsEqual (entry_param, member_param))
+                                                               continue;
+                                               } else {
+                                                       if (!TypeSpecComparer.Equals (entry_param.Types, member_param.Types))
+                                                               continue;
+                                               }
                                        }
                                }
 
@@ -406,8 +412,13 @@ namespace Mono.CSharp {
 
                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--) {
@@ -438,6 +449,26 @@ namespace Mono.CSharp {
                                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;
                }
 
@@ -450,9 +481,9 @@ namespace Mono.CSharp {
                //
                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;
 
@@ -462,10 +493,21 @@ namespace Mono.CSharp {
                        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;
@@ -494,7 +536,7 @@ namespace Mono.CSharp {
                                                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;
                                                        }
                                                }
@@ -502,7 +544,7 @@ namespace Mono.CSharp {
                                }
 
                                container = container.BaseType;
-                       } while (container != null);
+                       } while (container != null && !declaredOnlyClass);
 
                        return best_match;
                }
@@ -643,6 +685,24 @@ namespace Mono.CSharp {
                        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
@@ -970,6 +1030,7 @@ namespace Mono.CSharp {
                                                                                shared_list = false;
                                                                                prev = new List<MemberSpec> (found.Count + 1);
                                                                                prev.AddRange (found);
+                                                                               found = prev;
                                                                        } else {
                                                                                prev = (List<MemberSpec>) found;
                                                                        }
@@ -1322,7 +1383,7 @@ namespace Mono.CSharp {
                        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;
@@ -1441,6 +1502,12 @@ namespace Mono.CSharp {
                                                        }
                                                        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");
+                                               }
                                        }
                                }