[mcs] Use same result bucket for extension method lookup in all types of using expression
[mono.git] / mcs / mcs / namespace.cs
index 7103f8df2cb8eb6b50ac9e6b86526121985846ee..f5ca0a818a4480e5080a67945f414dca21fd4a2e 100644 (file)
@@ -22,9 +22,10 @@ namespace Mono.CSharp {
                readonly Dictionary<string, Namespace> all_namespaces;
 
                public RootNamespace (string alias_name)
-                       : base (null, String.Empty)
+                       : base ()
                {
                        this.alias_name = alias_name;
+                       RegisterNamespace (this);
 
                        all_namespaces = new Dictionary<string, Namespace> ();
                        all_namespaces.Add ("", this);
@@ -64,12 +65,12 @@ namespace Mono.CSharp {
                //
                // For better error reporting where compiler tries to guess missing using directive
                //
-               public List<string> FindExtensionMethodNamespaces (IMemberContext ctx, TypeSpec extensionType, string name, int arity)
+               public List<string> FindExtensionMethodNamespaces (IMemberContext ctx, string name, int arity)
                {
                        List<string> res = null;
 
                        foreach (var ns in all_namespaces) {
-                               var methods = ns.Value.LookupExtensionMethod (ctx, extensionType, name, arity);
+                               var methods = ns.Value.LookupExtensionMethod (ctx, name, arity);
                                if (methods != null) {
                                        if (res == null)
                                                res = new List<string> ();
@@ -87,24 +88,13 @@ namespace Mono.CSharp {
                                all_namespaces.Add (child.Name, child);
                }
 
-               public bool IsNamespace (string name)
-               {
-                       return all_namespaces.ContainsKey (name);
-               }
-
-               protected void RegisterNamespace (string dotted_name)
-               {
-                       if (dotted_name != null && dotted_name.Length != 0 && ! IsNamespace (dotted_name))
-                               GetNamespace (dotted_name, true);
-               }
-
                public override string GetSignatureForError ()
                {
                        return alias_name + "::";
                }
        }
 
-       public class GlobalRootNamespace : RootNamespace
+       public sealed class GlobalRootNamespace : RootNamespace
        {
                public GlobalRootNamespace ()
                        : base ("global")
@@ -115,67 +105,52 @@ namespace Mono.CSharp {
        //
        // Namespace cache for imported and compiled namespaces
        //
-       // This is an Expression to allow it to be referenced in the
-       // compiler parse/intermediate tree during name resolution.
-       //
-       public class Namespace : FullNamedExpression
+       public class Namespace
        {
-               Namespace parent;
+               readonly Namespace parent;
                string fullname;
                protected Dictionary<string, Namespace> namespaces;
                protected Dictionary<string, IList<TypeSpec>> types;
                List<TypeSpec> extension_method_types;
-               Dictionary<string, TypeExpr> cached_types;
-               RootNamespace root;
+               Dictionary<string, TypeSpec> cached_types;
                bool cls_checked;
 
-               public readonly MemberName MemberName;
-
                /// <summary>
                ///   Constructor Takes the current namespace and the
                ///   name.  This is bootstrapped with parent == null
                ///   and name = ""
                /// </summary>
                public Namespace (Namespace parent, string name)
+                       : this ()
                {
-                       // Expression members.
-                       this.eclass = ExprClass.Namespace;
-                       this.Type = InternalType.Namespace;
-                       this.loc = Location.Null;
+                       if (name == null)
+                               throw new ArgumentNullException ("name");
 
                        this.parent = parent;
 
-                       if (parent != null)
-                               this.root = parent.root;
-                       else
-                               this.root = this as RootNamespace;
-
-                       if (this.root == null)
-                               throw new InternalErrorException ("Root namespaces must be created using RootNamespace");
-                       
-                       string pname = parent != null ? parent.fullname : "";
+                       string pname = parent != null ? parent.fullname : null;
                                
-                       if (pname == "")
+                       if (pname == null)
                                fullname = name;
                        else
-                               fullname = parent.fullname + "." + name;
+                               fullname = pname + "." + name;
 
-                       if (fullname == null)
-                               throw new InternalErrorException ("Namespace has a null fullname");
-
-                       if (parent != null && parent.MemberName != MemberName.Null)
-                               MemberName = new MemberName (parent.MemberName, name, Location.Null);
-                       else if (name.Length == 0)
-                               MemberName = MemberName.Null;
-                       else
-                               MemberName = new MemberName (name, Location.Null);
+                       while (parent.parent != null)
+                               parent = parent.parent;
 
-                       namespaces = new Dictionary<string, Namespace> ();
-                       cached_types = new Dictionary<string, TypeExpr> ();
+                       var root = parent as RootNamespace;
+                       if (root == null)
+                               throw new InternalErrorException ("Root namespaces must be created using RootNamespace");
 
                        root.RegisterNamespace (this);
                }
 
+               protected Namespace ()
+               {
+                       namespaces = new Dictionary<string, Namespace> ();
+                       cached_types = new Dictionary<string, TypeSpec> ();
+               }
+
                #region Properties
 
                /// <summary>
@@ -195,85 +170,6 @@ namespace Mono.CSharp {
 
                #endregion
 
-               protected override Expression DoResolve (ResolveContext ec)
-               {
-                       return this;
-               }
-
-               public void Error_NamespaceDoesNotExist (IMemberContext ctx, string name, int arity, Location loc)
-               {
-                       var retval = LookupType (ctx, name, arity, LookupMode.IgnoreAccessibility, loc);
-                       if (retval != null) {
-                               ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (retval.Type);
-                               ErrorIsInaccesible (ctx, retval.GetSignatureForError (), loc);
-                               return;
-                       }
-
-                       retval = LookupType (ctx, name, -System.Math.Max (1, arity), LookupMode.Probing, loc);
-                       if (retval != null) {
-                               Error_TypeArgumentsCannotBeUsed (ctx, retval.Type, arity, loc);
-                               return;
-                       }
-
-                       Namespace ns;
-                       if (arity > 0 && namespaces.TryGetValue (name, out ns)) {
-                               ns.Error_TypeArgumentsCannotBeUsed (ctx, null, arity, loc);
-                               return;
-                       }
-
-                       string assembly = null;
-                       string possible_name = fullname + "." + name;
-
-                       // Only assembly unique name should be added
-                       switch (possible_name) {
-                       case "System.Drawing":
-                       case "System.Web.Services":
-                       case "System.Web":
-                       case "System.Data":
-                       case "System.Configuration":
-                       case "System.Data.Services":
-                       case "System.DirectoryServices":
-                       case "System.Json":
-                       case "System.Net.Http":
-                       case "System.Numerics":
-                       case "System.Runtime.Caching":
-                       case "System.ServiceModel":
-                       case "System.Transactions":
-                       case "System.Web.Routing":
-                       case "System.Xml.Linq":
-                       case "System.Xml":
-                               assembly = possible_name;
-                               break;
-
-                       case "System.Linq":
-                       case "System.Linq.Expressions":
-                               assembly = "System.Core";
-                               break;
-
-                       case "System.Windows.Forms":
-                       case "System.Windows.Forms.Layout":
-                               assembly = "System.Windows.Forms";
-                               break;
-                       }
-
-                       assembly = assembly == null ? "an" : "`" + assembly + "'";
-
-                       if (this is GlobalRootNamespace) {
-                               ctx.Module.Compiler.Report.Error (400, loc,
-                                       "The type or namespace name `{0}' could not be found in the global namespace. Are you missing {1} assembly reference?",
-                                       name, assembly);
-                       } else {
-                               ctx.Module.Compiler.Report.Error (234, loc,
-                                       "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing {2} assembly reference?",
-                                       name, GetSignatureForError (), assembly);
-                       }
-               }
-
-               public override string GetSignatureForError ()
-               {
-                       return fullname;
-               }
-
                public Namespace AddNamespace (MemberName name)
                {
                        var ns_parent = name.Left == null ? this : AddNamespace (name.Left);
@@ -292,6 +188,11 @@ namespace Mono.CSharp {
                        return ns;
                }
 
+               public bool TryGetNamespace (string name, out Namespace ns)
+               {
+                       return namespaces.TryGetValue (name, out ns);
+               }
+
                // TODO: Replace with CreateNamespace where MemberName is created for the method call
                public Namespace GetNamespace (string name, bool create)
                {
@@ -327,22 +228,28 @@ namespace Mono.CSharp {
                        return found;
                }
 
-               public TypeExpr LookupType (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)
+               public virtual string GetSignatureForError ()
+               {
+                       return fullname;
+               }
+
+               public TypeSpec LookupType (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)
                {
                        if (types == null)
                                return null;
 
-                       TypeExpr te;
-                       if (arity == 0 && cached_types.TryGetValue (name, out te))
-                               return te;
+                       TypeSpec best = null;
+                       if (arity == 0 && cached_types.TryGetValue (name, out best)) {
+                               if (best != null || mode != LookupMode.IgnoreAccessibility)
+                                       return best;
+                       }
 
                        IList<TypeSpec> found;
                        if (!types.TryGetValue (name, out found))
                                return null;
 
-                       TypeSpec best = 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;
@@ -352,11 +259,20 @@ namespace Mono.CSharp {
                                        }
 
                                        if (best.MemberDefinition.IsImported && ts.MemberDefinition.IsImported) {
+                                               if (ts.Kind == MemberKind.MissingType)
+                                                       continue;
+
+                                               if (best.Kind == MemberKind.MissingType) {
+                                                       best = ts;
+                                                       continue;
+                                               }
+
                                                if (mode == LookupMode.Normal) {
                                                        ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (best);
                                                        ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts);
                                                        ctx.Module.Compiler.Report.Error (433, loc, "The imported type `{0}' is defined multiple times", ts.GetSignatureForError ());
                                                }
+
                                                break;
                                        }
 
@@ -391,16 +307,17 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (best == null)
-                               return null;
-
-                       te = new TypeExpression (best, Location.Null);
-
                        // TODO MemberCache: Cache more
                        if (arity == 0 && mode == LookupMode.Normal)
-                               cached_types.Add (name, te);
+                               cached_types.Add (name, best);
+
+                       if (best != null) {
+                               var dep = best.GetMissingDependencies ();
+                               if (dep != null)
+                                       ImportedTypeDefinition.Error_MissingDependency (ctx, dep, loc);
+                       }
 
-                       return te;
+                       return best;
                }
 
                public FullNamedExpression LookupTypeOrNamespace (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)
@@ -410,21 +327,24 @@ namespace Mono.CSharp {
                        Namespace ns;
                        if (arity == 0 && namespaces.TryGetValue (name, out ns)) {
                                if (texpr == null)
-                                       return ns;
+                                       return new NamespaceExpression (ns, loc);
 
                                if (mode != LookupMode.Probing) {
-                                       ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (texpr.Type);
+                                       //ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (texpr.Type);
                                        // ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ns.loc, "");
                                        ctx.Module.Compiler.Report.Warning (437, 2, loc,
                                                "The type `{0}' conflicts with the imported namespace `{1}'. Using the definition found in the source file",
                                                texpr.GetSignatureForError (), ns.GetSignatureForError ());
                                }
 
-                               if (texpr.Type.MemberDefinition.IsImported)
-                                       return ns;
+                               if (texpr.MemberDefinition.IsImported)
+                                       return new NamespaceExpression (ns, loc);
                        }
 
-                       return texpr;
+                       if (texpr == null)
+                               return null;
+
+                       return new TypeExpression (texpr, loc);
                }
 
                //
@@ -448,7 +368,7 @@ namespace Mono.CSharp {
                // 
                // Looks for extension method in this namespace
                //
-               public List<MethodSpec> LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity)
+               public List<MethodSpec> LookupExtensionMethod (IMemberContext invocationContext, string name, int arity)
                {
                        if (extension_method_types == null)
                                return null;
@@ -471,7 +391,7 @@ namespace Mono.CSharp {
                                        continue;
                                }
 
-                               var res = ts.MemberCache.FindExtensionMethods (invocationContext, extensionType, name, arity);
+                               var res = ts.MemberCache.FindExtensionMethods (invocationContext, name, arity);
                                if (res == null)
                                        continue;
 
@@ -568,13 +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;
 
-               public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext mc)
-               {
-                       return this;
+                                       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)
@@ -643,11 +572,6 @@ namespace Mono.CSharp {
                                        "Identifier `{0}' differing only in case is not CLS-compliant", compiled.GetSignatureForError ());
                        }
                }
-
-               public override string ToString ()
-               {
-                       return Name;
-               }
        }
 
        public class CompilationSourceFile : NamespaceContainer
@@ -730,7 +654,7 @@ namespace Mono.CSharp {
                void CreateUnitSymbolInfo (MonoSymbolFile symwriter)
                {
                        var si = file.CreateSymbolInfo (symwriter);
-                       comp_unit = new CompileUnitEntry (symwriter, si);;
+                       comp_unit = new CompileUnitEntry (symwriter, si);
 
                        if (include_files != null) {
                                foreach (SourceFile include in include_files.Values) {
@@ -754,6 +678,11 @@ namespace Mono.CSharp {
 
                        return Compiler.Settings.IsConditionalSymbolDefined (value);
                }
+
+               public override void Accept (StructuralVisitor visitor)
+               {
+                       visitor.Visit (this);
+               }
        }
 
 
@@ -774,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)
@@ -868,15 +798,14 @@ namespace Mono.CSharp {
                public override void AddPartial (TypeDefinition next_part)
                {
                        var existing = ns.LookupType (this, next_part.MemberName.Name, next_part.MemberName.Arity, LookupMode.Probing, Location.Null);
-                       var td = existing != null ? existing.Type.MemberDefinition as TypeDefinition : null;
+                       var td = existing != null ? existing.MemberDefinition as TypeDefinition : null;
                        AddPartial (next_part, td);
                }
 
                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;
@@ -887,7 +816,7 @@ namespace Mono.CSharp {
                        MemberCore mc;
                        if (names_container.DefinedNames.TryGetValue (name, out mc)) {
                                if (tc is NamespaceContainer && mc is NamespaceContainer) {
-                                       containers.Add (tc);
+                                       AddTypeContainerMember (tc);
                                        return;
                                }
 
@@ -964,7 +893,7 @@ namespace Mono.CSharp {
                        ExtensionMethodCandidates candidates;
                        var container = this;
                        do {
-                               candidates = container.LookupExtensionMethodCandidates (invocationContext, extensionType, name, arity, ref position);
+                               candidates = container.LookupExtensionMethodCandidates (invocationContext, name, arity, ref position);
                                if (candidates != null || container.MemberName == null)
                                        return candidates;
 
@@ -979,7 +908,7 @@ namespace Mono.CSharp {
                                while (mn != null) {
                                        ++position;
 
-                                       var methods = container_ns.LookupExtensionMethod (invocationContext, extensionType, name, arity);
+                                       var methods = container_ns.LookupExtensionMethod (invocationContext, name, arity);
                                        if (methods != null) {
                                                return new ExtensionMethodCandidates (invocationContext, methods, container, position);
                                        }
@@ -995,14 +924,14 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               ExtensionMethodCandidates LookupExtensionMethodCandidates (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity, ref int position)
+               ExtensionMethodCandidates LookupExtensionMethodCandidates (IMemberContext invocationContext, string name, int arity, ref int position)
                {
                        List<MethodSpec> candidates = null;
 
                        if (position == 0) {
                                ++position;
 
-                               candidates = ns.LookupExtensionMethod (invocationContext, extensionType, name, arity);
+                               candidates = ns.LookupExtensionMethod (invocationContext, name, arity);
                                if (candidates != null) {
                                        return new ExtensionMethodCandidates (invocationContext, candidates, this, position);
                                }
@@ -1012,7 +941,7 @@ namespace Mono.CSharp {
                                ++position;
 
                                foreach (Namespace n in namespace_using_table) {
-                                       var a = n.LookupExtensionMethod (invocationContext, extensionType, name, arity);
+                                       var a = n.LookupExtensionMethod (invocationContext, name, arity);
                                        if (a == null)
                                                continue;
 
@@ -1022,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);
                        }
@@ -1057,6 +1000,9 @@ namespace Mono.CSharp {
 
                public override void GetCompletionStartingWith (string prefix, List<string> results)
                {
+                       if (Usings == null)
+                               return;
+
                        foreach (var un in Usings) {
                                if (un.Alias != null)
                                        continue;
@@ -1132,7 +1078,7 @@ namespace Mono.CSharp {
                        if (aliases != null && arity == 0) {
                                UsingAliasNamespace uan;
                                if (aliases.TryGetValue (name, out uan)) {
-                                       if (fne != null) {
+                                       if (fne != null && mode != LookupMode.Probing) {
                                                // TODO: Namespace has broken location
                                                //Report.SymbolRelatedToPreviousError (fne.Location, null);
                                                Compiler.Report.SymbolRelatedToPreviousError (uan.Location, null);
@@ -1164,10 +1110,11 @@ namespace Mono.CSharp {
                                // A using directive imports only types contained in the namespace, it
                                // does not import any nested namespaces
                                //
-                               fne = using_ns.LookupType (this, name, arity, mode, loc);
-                               if (fne == null)
+                               var t = using_ns.LookupType (this, name, arity, mode, loc);
+                               if (t == null)
                                        continue;
 
+                               fne = new TypeExpression (t, loc);
                                if (match == null) {
                                        match = fne;
                                        continue;
@@ -1203,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)
@@ -1216,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) {
@@ -1254,22 +1239,37 @@ namespace Mono.CSharp {
                                                continue;
                                        }
 
-                                       Namespace using_ns = entry.ResolvedExpression as Namespace;
-                                       if (using_ns == null)
-                                               continue;
+                                       var using_ns = entry.ResolvedExpression as NamespaceExpression;
+                                       if (using_ns == null) {
 
-                                       if (list.Contains (using_ns)) {
-                                               // Ensure we don't report the warning multiple times in repl
-                                               clauses.RemoveAt (i--);
+                                               var type = ((TypeExpr)entry.ResolvedExpression).Type;
 
-                                               Compiler.Report.Warning (105, 3, entry.Location,
-                                                       "The using directive for `{0}' appeared previously in this namespace", using_ns.GetSignatureForError ());
+                                               if (types == null)
+                                                       types = new List<TypeSpec> ();
+
+                                               if (types.Contains (type)) {
+                                                       Warning_DuplicateEntry (entry);
+                                               } else {
+                                                       types.Add (type);
+                                               }
                                        } else {
-                                               list.Add (using_ns);
+                                               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) {
@@ -1325,6 +1325,18 @@ 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);
+               }
        }
 
        public class UsingNamespace
@@ -1374,15 +1386,29 @@ namespace Mono.CSharp {
 
                public virtual void Define (NamespaceContainer ctx)
                {
-                       resolved = expr.ResolveAsTypeOrNamespace (ctx);
-                       var ns = resolved as Namespace;
-                       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 ());
+                       resolved = expr.ResolveAsTypeOrNamespace (ctx, false);
+                       var ns = resolved as NamespaceExpression;
+                       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 ());
                        }
                }
 
@@ -1401,12 +1427,15 @@ namespace Mono.CSharp {
 
                public override void Define (NamespaceContainer ctx)
                {
-                       resolved = ctx.Module.GetRootNamespace (Alias.Value);
-                       if (resolved == null) {
+                       var ns = ctx.Module.GetRootNamespace (Alias.Value);
+                       if (ns == null) {
                                ctx.Module.Compiler.Report.Error (430, Location,
                                        "The extern alias `{0}' was not specified in -reference option",
                                        Alias.Value);
+                               return;
                        }
+
+                       resolved = new NamespaceExpression (ns, Location);
                }
        }
 
@@ -1535,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);
                }
        }
 }