[mcs] Use same result bucket for extension method lookup in all types of using expression
[mono.git] / mcs / mcs / namespace.cs
index f6031a534d39c5b1a48b228a1b71ca625ce5c881..f5ca0a818a4480e5080a67945f414dca21fd4a2e 100644 (file)
@@ -249,7 +249,7 @@ namespace Mono.CSharp {
                                return null;
 
                        foreach (var ts in found) {
-                               if (ts.Arity == arity) {
+                               if (ts.Arity == arity || mode == LookupMode.NameOf) {
                                        if (best == null) {
                                                if ((ts.Modifiers & Modifiers.INTERNAL) != 0 && !ts.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly) && mode != LookupMode.IgnoreAccessibility)
                                                        continue;
@@ -311,6 +311,12 @@ namespace Mono.CSharp {
                        if (arity == 0 && mode == LookupMode.Normal)
                                cached_types.Add (name, best);
 
+                       if (best != null) {
+                               var dep = best.GetMissingDependencies ();
+                               if (dep != null)
+                                       ImportedTypeDefinition.Error_MissingDependency (ctx, dep, loc);
+                       }
+
                        return best;
                }
 
@@ -482,8 +488,22 @@ namespace Mono.CSharp {
 
                public void RemoveContainer (TypeContainer tc)
                {
-                       types.Remove (tc.Basename);
-                       cached_types.Remove (tc.Basename);
+                       IList<TypeSpec> found;
+                       if (types.TryGetValue (tc.MemberName.Name, out found)) {
+                               for (int i = 0; i < found.Count; ++i) {
+                                       if (tc.MemberName.Arity != found [i].Arity)
+                                               continue;
+
+                                       if (found.Count == 1)
+                                               types.Remove (tc.MemberName.Name);
+                                       else
+                                               found.RemoveAt (i);
+
+                                       break;
+                               }
+                       }
+
+                       cached_types.Remove (tc.MemberName.Basename);
                }
 
                public void SetBuiltinType (BuiltinTypeSpec pts)
@@ -683,6 +703,7 @@ namespace Mono.CSharp {
                public bool DeclarationFound;
 
                Namespace[] namespace_using_table;
+               TypeSpec[] types_using_table;
                Dictionary<string, UsingAliasNamespace> aliases;
 
                public NamespaceContainer (MemberName name, NamespaceContainer parent)
@@ -783,9 +804,8 @@ namespace Mono.CSharp {
 
                public override void AddTypeContainer (TypeContainer tc)
                {
-                       string name = tc.Basename;
-
                        var mn = tc.MemberName;
+                       var name = mn.Basename;
                        while (mn.Left != null) {
                                mn = mn.Left;
                                name = mn.Name;
@@ -931,6 +951,20 @@ namespace Mono.CSharp {
                                                candidates.AddRange (a);
                                }
 
+                               if (types_using_table != null) {
+                                       foreach (var t in types_using_table) {
+
+                                               var res = t.MemberCache.FindExtensionMethods (invocationContext, name, arity);
+                                               if (res == null)
+                                                       continue;
+
+                                               if (candidates == null)
+                                                       candidates = res;
+                                               else
+                                                       candidates.AddRange (res);
+                                       }
+                               }
+
                                if (candidates != null)
                                        return new ExtensionMethodCandidates (invocationContext, candidates, this, position);
                        }
@@ -1116,6 +1150,42 @@ namespace Mono.CSharp {
                        return match;
                }
 
+               public static MethodGroupExpr LookupStaticUsings (IMemberContext mc, string name, int arity, Location loc)
+               {
+                       for (var m = mc.CurrentMemberDefinition; m != null; m = m.Parent) {
+
+                               var nc = m as NamespaceContainer;
+                               if (nc == null)
+                                       continue;
+
+                               List<MemberSpec> candidates = null;
+                               if (nc.types_using_table != null) {
+                                       foreach (var using_type in nc.types_using_table) {
+                                               var members = MemberCache.FindMembers (using_type, name, true);
+                                               if (members != null) {
+                                                       foreach (var member in members) {
+                                                               if ((member.Modifiers & Modifiers.METHOD_EXTENSION) != 0)
+                                                                       continue;
+
+                                                               if (arity > 0 && member.Arity != arity)
+                                                                       continue;
+
+                                                               if (candidates == null)
+                                                                       candidates = new List<MemberSpec> ();
+
+                                                               candidates.Add (member);
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               if (candidates != null)
+                                       return new MethodGroupExpr (candidates, null, loc);
+                       }
+
+                       return null;
+               }
+
                protected override void DefineNamespace ()
                {
                        if (namespace_using_table == null)
@@ -1129,7 +1199,9 @@ namespace Mono.CSharp {
                        namespace_using_table = empty_namespaces;
 
                        if (clauses != null) {
-                               var list = new List<Namespace> (clauses.Count);
+                               List<Namespace> namespaces = null;
+                               List<TypeSpec> types = null;
+
                                bool post_process_using_aliases = false;
 
                                for (int i = 0; i < clauses.Count; ++i) {
@@ -1168,21 +1240,36 @@ namespace Mono.CSharp {
                                        }
 
                                        var using_ns = entry.ResolvedExpression as NamespaceExpression;
-                                       if (using_ns == null)
-                                               continue;
+                                       if (using_ns == null) {
 
-                                       if (list.Contains (using_ns.Namespace)) {
-                                               // Ensure we don't report the warning multiple times in repl
-                                               clauses.RemoveAt (i--);
+                                               var type = ((TypeExpr)entry.ResolvedExpression).Type;
+
+                                               if (types == null)
+                                                       types = new List<TypeSpec> ();
 
-                                               Compiler.Report.Warning (105, 3, entry.Location,
-                                                       "The using directive for `{0}' appeared previously in this namespace", using_ns.GetSignatureForError ());
+                                               if (types.Contains (type)) {
+                                                       Warning_DuplicateEntry (entry);
+                                               } else {
+                                                       types.Add (type);
+                                               }
                                        } else {
-                                               list.Add (using_ns.Namespace);
+                                               if (namespaces == null)
+                                                       namespaces = new List<Namespace> ();
+
+                                               if (namespaces.Contains (using_ns.Namespace)) {
+                                                       // Ensure we don't report the warning multiple times in repl
+                                                       clauses.RemoveAt (i--);
+
+                                                       Warning_DuplicateEntry (entry);
+                                               } else {
+                                                       namespaces.Add (using_ns.Namespace);
+                                               }
                                        }
                                }
 
-                               namespace_using_table = list.ToArray ();
+                               namespace_using_table = namespaces == null ? new Namespace [0] : namespaces.ToArray ();
+                               if (types != null)
+                                       types_using_table = types.ToArray ();
 
                                if (post_process_using_aliases) {
                                        for (int i = 0; i < clauses.Count; ++i) {
@@ -1239,6 +1326,13 @@ namespace Mono.CSharp {
                        return false;
                }
 
+               void Warning_DuplicateEntry (UsingNamespace entry)
+               {
+                       Compiler.Report.Warning (105, 3, entry.Location,
+                               "The using directive for `{0}' appeared previously in this namespace",
+                               entry.ResolvedExpression.GetSignatureForError ());
+               }
+
                public override void Accept (StructuralVisitor visitor)
                {
                        visitor.Visit (this);
@@ -1292,15 +1386,29 @@ namespace Mono.CSharp {
 
                public virtual void Define (NamespaceContainer ctx)
                {
-                       resolved = expr.ResolveAsTypeOrNamespace (ctx);
+                       resolved = expr.ResolveAsTypeOrNamespace (ctx, false);
                        var ns = resolved as NamespaceExpression;
-                       if (ns == null) {
-                               if (resolved != null) {
-                                       ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (resolved.Type);
-                                       ctx.Module.Compiler.Report.Error (138, Location,
-                                               "`{0}' is a type not a namespace. A using namespace directive can only be applied to namespaces",
-                                               GetSignatureForError ());
+                       if (ns != null)
+                               return;
+
+                       if (resolved != null) {
+                               var compiler = ctx.Module.Compiler;
+                               var type = resolved.Type;
+                               if (compiler.Settings.Version >= LanguageVersion.V_6) {
+                                       if (!type.IsClass || !type.IsStatic) {
+                                               compiler.Report.SymbolRelatedToPreviousError (type);
+                                               compiler.Report.Error (7007, Location,
+                                                       "`{0}' is not a static class. A using namespace directive can only be applied to static classes or namespace",
+                                                       GetSignatureForError ());
+                                       }
+
+                                       return;
                                }
+
+                               compiler.Report.SymbolRelatedToPreviousError (type);
+                               compiler.Report.Error (138, Location,
+                                       "`{0}' is a type not a namespace. A using namespace directive can only be applied to namespaces",
+                                       GetSignatureForError ());
                        }
                }
 
@@ -1456,7 +1564,7 @@ namespace Mono.CSharp {
                        // We achieve that by introducing alias-context which redirect any local
                        // namespace or type resolve calls to parent namespace
                        //
-                       resolved = NamespaceExpression.ResolveAsTypeOrNamespace (new AliasContext (ctx));
+                       resolved = NamespaceExpression.ResolveAsTypeOrNamespace (new AliasContext (ctx), false);
                }
        }
 }