Merge pull request #498 from Unroll-Me/master
[mono.git] / mcs / mcs / namespace.cs
index a19f5938a784baa4eccbcf7faffd5e8a04aa3a80..7dd44807f6810e358d40b258aed1bbce65ddb369 100644 (file)
@@ -7,10 +7,12 @@
 //
 // Copyright 2001 Ximian, Inc.
 // Copyright 2003-2008 Novell, Inc.
+// Copyright 2011 Xamarin Inc
 //
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using Mono.CompilerServices.SymbolWriter;
 
 namespace Mono.CSharp {
 
@@ -34,6 +36,51 @@ namespace Mono.CSharp {
                        }
                }
 
+               public static void Error_GlobalNamespaceRedefined (Report report, Location loc)
+               {
+                       report.Error (1681, loc, "The global extern alias cannot be redefined");
+               }
+
+               //
+               // For better error reporting where we try to guess missing using directive
+               //
+               public List<string> FindTypeNamespaces (IMemberContext ctx, string name, int arity)
+               {
+                       List<string> res = null;
+
+                       foreach (var ns in all_namespaces) {
+                               var type = ns.Value.LookupType (ctx, name, arity, LookupMode.Normal, Location.Null);
+                               if (type != null) {
+                                       if (res == null)
+                                               res = new List<string> ();
+
+                                       res.Add (ns.Key);
+                               }
+                       }
+
+                       return res;
+               }
+
+               //
+               // For better error reporting where compiler tries to guess missing using directive
+               //
+               public List<string> FindExtensionMethodNamespaces (IMemberContext ctx, TypeSpec extensionType, string name, int arity)
+               {
+                       List<string> res = null;
+
+                       foreach (var ns in all_namespaces) {
+                               var methods = ns.Value.LookupExtensionMethod (ctx, extensionType, name, arity);
+                               if (methods != null) {
+                                       if (res == null)
+                                               res = new List<string> ();
+
+                                       res.Add (ns.Key);
+                               }
+                       }
+
+                       return res;
+               }
+
                public void RegisterNamespace (Namespace child)
                {
                        if (child != this)
@@ -63,13 +110,6 @@ namespace Mono.CSharp {
                        : base ("global")
                {
                }
-
-               public override void Error_NamespaceDoesNotExist (Location loc, string name, int arity, IMemberContext ctx)
-               {
-                       ctx.Module.Compiler.Report.Error (400, loc,
-                               "The type or namespace name `{0}' could not be found in the global namespace (are you missing an assembly reference?)",
-                               name);
-               }
        }
 
        //
@@ -84,6 +124,7 @@ namespace Mono.CSharp {
                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;
                bool cls_checked;
@@ -123,11 +164,11 @@ namespace Mono.CSharp {
                                throw new InternalErrorException ("Namespace has a null fullname");
 
                        if (parent != null && parent.MemberName != MemberName.Null)
-                               MemberName = new MemberName (parent.MemberName, name);
+                               MemberName = new MemberName (parent.MemberName, name, Location.Null);
                        else if (name.Length == 0)
                                MemberName = MemberName.Null;
                        else
-                               MemberName = new MemberName (name);
+                               MemberName = new MemberName (name, Location.Null);
 
                        namespaces = new Dictionary<string, Namespace> ();
                        cached_types = new Dictionary<string, TypeExpr> ();
@@ -159,9 +200,16 @@ namespace Mono.CSharp {
                        return this;
                }
 
-               public virtual void Error_NamespaceDoesNotExist (Location loc, string name, int arity, IMemberContext ctx)
+               public void Error_NamespaceDoesNotExist (IMemberContext ctx, string name, int arity, Location loc)
                {
-                       var retval = LookupType (ctx, name, -System.Math.Max (1, arity), 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;
@@ -173,16 +221,87 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       ctx.Module.Compiler.Report.Error (234, loc,
-                               "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing an assembly reference?",
-                               name, GetSignatureForError ());
+                       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.Name";
+                               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)
+               {
+                       Namespace ns_parent;
+                       if (name.Left != null) {
+                               if (parent != null)
+                                       ns_parent = parent.AddNamespace (name.Left);
+                               else
+                                       ns_parent = AddNamespace (name.Left);
+                       } else {
+                               ns_parent = this;
+                       }
+
+                       return ns_parent.TryAddNamespace (name.Basename);
+               }
+
+               Namespace TryAddNamespace (string name)
+               {
+                       Namespace ns;
+
+                       if (!namespaces.TryGetValue (name, out ns)) {
+                               ns = new Namespace (this, name);
+                               namespaces.Add (name, ns);
+                       }
+
+                       return ns;
+               }
+
+               // TODO: Replace with CreateNamespace where MemberName is created for the method call
                public Namespace GetNamespace (string name, bool create)
                {
                        int pos = name.IndexOf ('.');
@@ -217,7 +336,7 @@ namespace Mono.CSharp {
                        return found;
                }
 
-               public TypeExpr LookupType (IMemberContext ctx, string name, int arity, Location loc)
+               public TypeExpr LookupType (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)
                {
                        if (types == null)
                                return null;
@@ -234,14 +353,19 @@ namespace Mono.CSharp {
                        foreach (var ts in found) {
                                if (ts.Arity == arity) {
                                        if (best == null) {
+                                               if ((ts.Modifiers & Modifiers.INTERNAL) != 0 && !ts.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly) && mode != LookupMode.IgnoreAccessibility)
+                                                       continue;
+
                                                best = ts;
                                                continue;
                                        }
 
                                        if (best.MemberDefinition.IsImported && ts.MemberDefinition.IsImported) {
-                                               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 ());
+                                               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;
                                        }
 
@@ -251,6 +375,9 @@ namespace Mono.CSharp {
                                        if ((best.Modifiers & Modifiers.INTERNAL) != 0 && !best.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly))
                                                continue;
 
+                                       if (mode != LookupMode.Normal)
+                                               continue;
+
                                        if (ts.MemberDefinition.IsImported)
                                                ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts);
 
@@ -260,7 +387,7 @@ namespace Mono.CSharp {
                                }
 
                                //
-                               // Lookup for the best candidate with closest arity match
+                               // Lookup for the best candidate with the closest arity match
                                //
                                if (arity < 0) {
                                        if (best == null) {
@@ -274,63 +401,31 @@ namespace Mono.CSharp {
                        if (best == null)
                                return null;
 
-                       if ((best.Modifiers & Modifiers.INTERNAL) != 0 && !best.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly))
-                               return null;
-
                        te = new TypeExpression (best, Location.Null);
 
                        // TODO MemberCache: Cache more
-                       if (arity == 0)
+                       if (arity == 0 && mode == LookupMode.Normal)
                                cached_types.Add (name, te);
 
                        return te;
                }
 
-               TypeSpec LookupType (string name, int arity)
+               public FullNamedExpression LookupTypeOrNamespace (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)
                {
-                       if (types == null)
-                               return null;
-
-                       IList<TypeSpec> found;
-                       if (types.TryGetValue (name, out found)) {
-                               TypeSpec best = null;
-
-                               foreach (var ts in found) {
-                                       if (ts.Arity == arity)
-                                               return ts;
-
-                                       //
-                                       // Lookup for the best candidate with closest arity match
-                                       //
-                                       if (arity < 0) {
-                                               if (best == null) {
-                                                       best = ts;
-                                               } else if (System.Math.Abs (ts.Arity + arity) < System.Math.Abs (best.Arity + arity)) {
-                                                       best = ts;
-                                               }
-                                       }
-                               }
-                               
-                               return best;
-                       }
-
-                       return null;
-               }
-
-               public FullNamedExpression LookupTypeOrNamespace (IMemberContext ctx, string name, int arity, Location loc)
-               {
-                       var texpr = LookupType (ctx, name, arity, loc);
+                       var texpr = LookupType (ctx, name, arity, mode, loc);
 
                        Namespace ns;
                        if (arity == 0 && namespaces.TryGetValue (name, out ns)) {
                                if (texpr == null)
                                        return ns;
 
-                               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 (mode != LookupMode.Probing) {
+                                       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;
@@ -357,32 +452,40 @@ namespace Mono.CSharp {
                        return res;
                }
 
-               /// 
-               /// Looks for extension method in this namespace
-               //
+               // 
+               // Looks for extension method in this namespace
+               //
                public List<MethodSpec> LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity)
                {
-                       if (types == null)
+                       if (extension_method_types == null)
                                return null;
 
                        List<MethodSpec> found = null;
+                       for (int i = 0; i < extension_method_types.Count; ++i) {
+                               var ts = extension_method_types[i];
 
-                       // TODO: Add per namespace flag when at least 1 type has extension
+                               //
+                               // When the list was built we didn't know what members the type
+                               // contains
+                               //
+                               if ((ts.Modifiers & Modifiers.METHOD_EXTENSION) == 0) {
+                                       if (extension_method_types.Count == 1) {
+                                               extension_method_types = null;
+                                               return found;
+                                       }
 
-                       foreach (var tgroup in types.Values) {
-                               foreach (var ts in tgroup) {
-                                       if ((ts.Modifiers & Modifiers.METHOD_EXTENSION) == 0)
-                                               continue;
+                                       extension_method_types.RemoveAt (i--);
+                                       continue;
+                               }
 
-                                       var res = ts.MemberCache.FindExtensionMethods (invocationContext, extensionType, name, arity);
-                                       if (res == null)
-                                               continue;
+                               var res = ts.MemberCache.FindExtensionMethods (invocationContext, extensionType, name, arity);
+                               if (res == null)
+                                       continue;
 
-                                       if (found == null) {
-                                               found = res;
-                                       } else {
-                                               found.AddRange (res);
-                                       }
+                               if (found == null) {
+                                       found = res;
+                               } else {
+                                       found.AddRange (res);
                                }
                        }
 
@@ -395,6 +498,16 @@ namespace Mono.CSharp {
                                types = new Dictionary<string, IList<TypeSpec>> (64);
                        }
 
+                       if (ts.IsClass && ts.Arity == 0) {
+                               var extension_method_allowed = ts.MemberDefinition.IsImported ? (ts.Modifiers & Modifiers.METHOD_EXTENSION) != 0 : (ts.IsStatic || ts.MemberDefinition.IsPartial);
+                               if (extension_method_allowed) {
+                                       if (extension_method_types == null)
+                                               extension_method_types = new List<TypeSpec> ();
+
+                                       extension_method_types.Add (ts);
+                               }
+                       }
+
                        var name = ts.Name;
                        IList<TypeSpec> existing;
                        if (types.TryGetValue (name, out existing)) {
@@ -460,10 +573,10 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               public void RemoveDeclSpace (string name)
+               public void RemoveContainer (TypeContainer tc)
                {
-                       types.Remove (name);
-                       cached_types.Remove (name);
+                       types.Remove (tc.Basename);
+                       cached_types.Remove (tc.Basename);
                }
 
                public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext mc)
@@ -537,388 +650,528 @@ namespace Mono.CSharp {
                                        "Identifier `{0}' differing only in case is not CLS-compliant", compiled.GetSignatureForError ());
                        }
                }
+
+               public override string ToString ()
+               {
+                       return Name;
+               }
        }
 
-       //
-       // Namespace block as created by the parser
-       //
-       public class NamespaceContainer : IMemberContext, ITypesContainer
+       public class CompilationSourceFile : NamespaceContainer
        {
-               Namespace ns;
-
-               readonly ModuleContainer module;
-               readonly NamespaceContainer parent;
-               readonly CompilationSourceFile file;
-               readonly Location loc;
-
-               NamespaceContainer implicit_parent;
-               int symfile_id;
-
-               // Namespace using import block
-               List<NamespaceUsingAlias> using_aliases;
-               List<NamespaceUsing> using_clauses;
-               public bool DeclarationFound;
-               // End
-
-               bool resolved;
-
-               public readonly bool IsImplicit;
-               public readonly TypeContainer SlaveDeclSpace;
-               static readonly Namespace [] empty_namespaces = new Namespace [0];
-               static readonly string[] empty_using_list = new string[0];
+               readonly SourceFile file;
+               CompileUnitEntry comp_unit;
+               Dictionary<string, SourceFile> include_files;
+               Dictionary<string, bool> conditionals;
 
-               Namespace [] namespace_using_table;
-
-               public NamespaceContainer (MemberName name, ModuleContainer module, NamespaceContainer parent, CompilationSourceFile sourceFile)
+               public CompilationSourceFile (ModuleContainer parent, SourceFile sourceFile)
+                       : this (parent)
                {
-                       this.module = module;
-                       this.parent = parent;
                        this.file = sourceFile;
-                       this.loc = name == null ? Location.Null : name.Location;
-
-                       if (parent != null)
-                               ns = parent.NS.GetNamespace (name.GetName (), true);
-                       else if (name != null)
-                               ns = module.GlobalRootNamespace.GetNamespace (name.GetName (), true);
-                       else
-                               ns = module.GlobalRootNamespace;
-
-                       SlaveDeclSpace = new RootDeclSpace (module, this);
                }
 
-               private NamespaceContainer (ModuleContainer module, NamespaceContainer parent, CompilationSourceFile file, Namespace ns, bool slave)
+               public CompilationSourceFile (ModuleContainer parent)
+                       : base (parent)
                {
-                       this.module = module;
-                       this.parent = parent;
-                       this.file = file;
-                       this.IsImplicit = true;
-                       this.ns = ns;
-                       this.SlaveDeclSpace = slave ? new RootDeclSpace (module, this) : null;
                }
 
-               #region Properties
-
-               public Location Location {
+               public CompileUnitEntry SymbolUnitEntry {
                        get {
-                               return loc;
+                               return comp_unit;
                        }
                }
 
-               public MemberName MemberName {
+               public string FileName {
                        get {
-                               return ns.MemberName;
+                               return file.Name;
                        }
                }
 
-               public CompilationSourceFile SourceFile {
+               public SourceFile SourceFile {
                        get {
                                return file;
                        }
                }
 
-               public List<NamespaceUsing> Usings {
-                       get {
-                               return using_clauses;
-                       }
+               public void AddIncludeFile (SourceFile file)
+               {
+                       if (file == this.file)
+                               return;
+
+                       if (include_files == null)
+                               include_files = new Dictionary<string, SourceFile> ();
+
+                       if (!include_files.ContainsKey (file.FullPathName))
+                               include_files.Add (file.FullPathName, file);
                }
 
-               #endregion
+               public void AddDefine (string value)
+               {
+                       if (conditionals == null)
+                               conditionals = new Dictionary<string, bool> (2);
+
+                       conditionals[value] = true;
+               }
+
+               public void AddUndefine (string value)
+               {
+                       if (conditionals == null)
+                               conditionals = new Dictionary<string, bool> (2);
+
+                       conditionals[value] = false;
+               }
+
+               public override void PrepareEmit ()
+               {
+                       var sw = Module.DeclaringAssembly.SymbolWriter;
+                       if (sw != null) {
+                               CreateUnitSymbolInfo (sw);
+                       }
+
+                       base.PrepareEmit ();
+               }
 
                //
-               // Extracts the using alises and using clauses into a couple of
-               // arrays that might already have the same information;  Used by the
-               // C# Eval mode.
+               // Creates symbol file index in debug symbol file
                //
-               public void Extract (List<NamespaceUsingAlias> out_using_aliases, List<NamespaceUsing> out_using_clauses)
-               {
-                       if (using_aliases != null){
-                               foreach (NamespaceUsingAlias uae in using_aliases){
-                                       bool replaced = false;
-                                       
-                                       for (int i = 0; i < out_using_aliases.Count; i++){
-                                               NamespaceUsingAlias out_uea = (NamespaceUsingAlias) out_using_aliases [i];
-                                               
-                                               if (out_uea.Alias == uae.Alias){
-                                                       out_using_aliases [i] = uae;
-                                                       replaced = true;
-                                                       break;
-                                               }
-                                       }
-                                       if (!replaced)
-                                               out_using_aliases.Add (uae);
+               void CreateUnitSymbolInfo (MonoSymbolFile symwriter)
+               {
+                       var si = file.CreateSymbolInfo (symwriter);
+                       comp_unit = new CompileUnitEntry (symwriter, si);;
+
+                       if (include_files != null) {
+                               foreach (SourceFile include in include_files.Values) {
+                                       si = include.CreateSymbolInfo (symwriter);
+                                       comp_unit.AddFile (si);
                                }
                        }
+               }
 
-                       if (using_clauses != null){
-                               foreach (NamespaceUsing ue in using_clauses){
-                                       bool found = false;
-                                       
-                                       foreach (NamespaceUsing out_ue in out_using_clauses)
-                                               if (out_ue.Name == ue.Name){
-                                                       found = true;
-                                                       break;
-                                               }
-                                       if (!found)
-                                               out_using_clauses.Add (ue);
-                               }
+               public bool IsConditionalDefined (string value)
+               {
+                       if (conditionals != null) {
+                               bool res;
+                               if (conditionals.TryGetValue (value, out res))
+                                       return res;
+
+                               // When conditional was undefined
+                               if (conditionals.ContainsKey (value))
+                                       return false;
                        }
+
+                       return Compiler.Settings.IsConditionalSymbolDefined (value);
                }
-               
-               //
-               // According to section 16.3.1 (using-alias-directive), the namespace-or-type-name is
-               // resolved as if the immediately containing namespace body has no using-directives.
-               //
-               // Section 16.3.2 says that the same rule is applied when resolving the namespace-name
-               // in the using-namespace-directive.
-               //
-               // To implement these rules, the expressions in the using directives are resolved using 
-               // the "doppelganger" (ghostly bodiless duplicate).
-               //
-               NamespaceContainer doppelganger;
-               NamespaceContainer Doppelganger {
+       }
+
+
+       //
+       // Namespace block as created by the parser
+       //
+       public class NamespaceContainer : TypeContainer, IMemberContext
+       {
+               static readonly Namespace[] empty_namespaces = new Namespace[0];
+
+               readonly Namespace ns;
+
+               public new readonly NamespaceContainer Parent;
+
+               List<UsingNamespace> clauses;
+
+               // Used by parsed to check for parser errors
+               public bool DeclarationFound;
+
+               Namespace[] namespace_using_table;
+               Dictionary<string, UsingAliasNamespace> aliases;
+
+               public NamespaceContainer (MemberName name, NamespaceContainer parent)
+                       : base (parent, name, null, MemberKind.Namespace)
+               {
+                       this.Parent = parent;
+                       this.ns = parent.NS.AddNamespace (name);
+
+                       containers = new List<TypeContainer> ();
+               }
+
+               protected NamespaceContainer (ModuleContainer parent)
+                       : base (parent, null, null, MemberKind.Namespace)
+               {
+                       ns = parent.GlobalRootNamespace;
+                       containers = new List<TypeContainer> (2);
+               }
+
+               #region Properties
+
+               public override AttributeTargets AttributeTargets {
                        get {
-                               if (!IsImplicit && doppelganger == null) {
-                                       doppelganger = new NamespaceContainer (module, ImplicitParent, file, ns, true);
-                                       doppelganger.using_aliases = using_aliases;
-                               }
-                               return doppelganger;
+                               throw new NotSupportedException ();
+                       }
+               }
+
+               public override string DocCommentHeader {
+                       get {
+                               throw new NotSupportedException ();
                        }
                }
 
                public Namespace NS {
-                       get { return ns; }
+                       get {
+                               return ns;
+                       }
                }
 
-               public NamespaceContainer Parent {
-                       get { return parent; }
+               public List<UsingNamespace> Usings {
+                       get {
+                               return clauses;
+                       }
                }
 
-               public NamespaceContainer ImplicitParent {
+               public override string[] ValidAttributeTargets {
                        get {
-                               if (parent == null)
-                                       return null;
-                               if (implicit_parent == null) {
-                                       implicit_parent = (parent.NS == ns.Parent)
-                                               ? parent
-                                               : new NamespaceContainer (module, parent, file, ns.Parent, false);
-                               }
-                               return implicit_parent;
+                               throw new NotSupportedException ();
                        }
                }
 
-               /// <summary>
-               ///   Records a new namespace for resolving name references
-               /// </summary>
-               public void AddUsing (MemberName name, Location loc)
+               #endregion
+
+               public void AddUsing (UsingNamespace un)
                {
                        if (DeclarationFound){
-                               Compiler.Report.Error (1529, loc, "A using clause must precede all other namespace elements except extern alias declarations");
+                               Compiler.Report.Error (1529, un.Location, "A using clause must precede all other namespace elements except extern alias declarations");
                        }
 
-                       if (using_clauses == null) {
-                               using_clauses = new List<NamespaceUsing> ();
-                       } else {
-                               foreach (NamespaceUsing old_entry in using_clauses) {
-                                       if (name.Equals (old_entry.MemberName)) {
-                                               Compiler.Report.SymbolRelatedToPreviousError (old_entry.Location, old_entry.GetSignatureForError ());
-                                               Compiler.Report.Warning (105, 3, loc, "The using directive for `{0}' appeared previously in this namespace", name.GetSignatureForError ());
-                                               return;
-                                       }
-                               }
-                       }
+                       if (clauses == null)
+                               clauses = new List<UsingNamespace> ();
 
-                       using_clauses.Add (new NamespaceUsing (name));
+                       clauses.Add (un);
                }
 
-               public void AddUsingAlias (string alias, MemberName name, Location loc)
+               public void AddUsing (UsingAliasNamespace un)
                {
                        if (DeclarationFound){
-                               Compiler.Report.Error (1529, loc, "A using clause must precede all other namespace elements except extern alias declarations");
+                               Compiler.Report.Error (1529, un.Location, "A using clause must precede all other namespace elements except extern alias declarations");
                        }
 
-                       AddUsingAlias (new LocalUsingAliasEntry (alias, name, loc));
+                       AddAlias (un);
                }
 
-               public void AddUsingExternalAlias (string alias, Location loc, Report Report)
+               void AddAlias (UsingAliasNamespace un)
                {
-                       bool not_first = using_clauses != null || DeclarationFound;
-                       if (using_aliases != null && !not_first) {
-                               foreach (NamespaceUsingAlias uae in using_aliases) {
-                                       if (uae is LocalUsingAliasEntry) {
-                                               not_first = true;
-                                               break;
+                       if (clauses == null) {
+                               clauses = new List<UsingNamespace> ();
+                       } else {
+                               foreach (var entry in clauses) {
+                                       var a = entry as UsingAliasNamespace;
+                                       if (a != null && a.Alias.Value == un.Alias.Value) {
+                                               Compiler.Report.SymbolRelatedToPreviousError (a.Location, "");
+                                               Compiler.Report.Error (1537, un.Location,
+                                                       "The using alias `{0}' appeared previously in this namespace", un.Alias.Value);
                                        }
                                }
                        }
 
-                       if (not_first)
-                               Report.Error (439, loc, "An extern alias declaration must precede all other elements");
-
-                       if (alias == "global") {
-                               Error_GlobalNamespaceRedefined (loc, Report);
-                               return;
-                       }
+                       clauses.Add (un);
+               }
 
-                       AddUsingAlias (new NamespaceUsingAlias (alias, loc));
+               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;
+                       AddPartial (next_part, td);
                }
 
-               void AddUsingAlias (NamespaceUsingAlias uae)
+               public override void AddTypeContainer (TypeContainer tc)
                {
-                       if (using_aliases == null) {
-                               using_aliases = new List<NamespaceUsingAlias> ();
+                       string name = tc.Basename;
+
+                       var mn = tc.MemberName;
+                       while (mn.Left != null) {
+                               mn = mn.Left;
+                               name = mn.Name;
+                       }
+
+                       var names_container = Parent == null ? Module : (TypeContainer) this;
+
+                       MemberCore mc;
+                       if (names_container.DefinedNames.TryGetValue (name, out mc)) {
+                               if (tc is NamespaceContainer && mc is NamespaceContainer) {
+                                       containers.Add (tc);
+                                       return;
+                               }
+
+                               Report.SymbolRelatedToPreviousError (mc);
+                               if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (tc is ClassOrStruct || tc is Interface)) {
+                                       Error_MissingPartialModifier (tc);
+                               } else {
+                                       Report.Error (101, tc.Location, "The namespace `{0}' already contains a definition for `{1}'",
+                                               GetSignatureForError (), mn.GetSignatureForError ());
+                               }
                        } else {
-                               foreach (NamespaceUsingAlias entry in using_aliases) {
-                                       if (uae.Alias == entry.Alias) {
-                                               Compiler.Report.SymbolRelatedToPreviousError (uae.Location, uae.Alias);
-                                               Compiler.Report.Error (1537, entry.Location, "The using alias `{0}' appeared previously in this namespace",
-                                                       entry.Alias);
-                                               return;
+                               names_container.DefinedNames.Add (name, tc);
+
+                               var tdef = tc.PartialContainer;
+                               if (tdef != null) {
+                                       //
+                                       // Same name conflict in different namespace containers
+                                       //
+                                       var conflict = ns.GetAllTypes (name);
+                                       if (conflict != null) {
+                                               foreach (var e in conflict) {
+                                                       if (e.Arity == mn.Arity) {
+                                                               mc = (MemberCore) e.MemberDefinition;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+
+                                       if (mc != null) {
+                                               Report.SymbolRelatedToPreviousError (mc);
+                                               Report.Error (101, tc.Location, "The namespace `{0}' already contains a definition for `{1}'",
+                                                       GetSignatureForError (), mn.GetSignatureForError ());
+                                       } else {
+                                               ns.AddType (Module, tdef.Definition);
                                        }
                                }
                        }
 
-                       using_aliases.Add (uae);
+                       base.AddTypeContainer (tc);
                }
 
-               //
-               // Does extension methods look up to find a method which matches name and extensionType.
-               // Search starts from this namespace and continues hierarchically up to top level.
-               //
-               public IList<MethodSpec> LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope)
+               public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
                {
-                       List<MethodSpec> candidates = null;
-                       foreach (Namespace n in GetUsingTable ()) {
-                               var a = n.LookupExtensionMethod (this, extensionType, name, arity);
-                               if (a == null)
-                                       continue;
-
-                               if (candidates == null)
-                                       candidates = a;
-                               else
-                                       candidates.AddRange (a);
-                       }
+                       throw new NotSupportedException ();
+               }
 
-                       scope = parent;
-                       if (candidates != null)
-                               return candidates;
+               public override void EmitContainer ()
+               {
+                       VerifyClsCompliance ();
 
-                       if (parent == null)
-                               return null;
+                       base.EmitContainer ();
+               }
 
+               public ExtensionMethodCandidates LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity, int position)
+               {
                        //
-                       // Inspect parent namespaces in namespace expression
+                       // Here we try to resume the search for extension method at the point
+                       // where the last bunch of candidates was found. It's more tricky than
+                       // it seems as we have to check both namespace containers and namespace
+                       // in correct order.
                        //
-                       Namespace parent_ns = ns.Parent;
+                       // Consider:
+                       // 
+                       // namespace A {
+                       //      using N1;
+                       //  namespace B.C.D {
+                       //              <our first search found candidates in A.B.C.D
+                       //  }
+                       // }
+                       //
+                       // In the example above namespace A.B.C.D, A.B.C and A.B have to be
+                       // checked before we hit A.N1 using
+                       //
+                       ExtensionMethodCandidates candidates;
+                       var container = this;
                        do {
-                               candidates = parent_ns.LookupExtensionMethod (this, extensionType, name, arity);
-                               if (candidates != null)
+                               candidates = container.LookupExtensionMethodCandidates (invocationContext, extensionType, name, arity, ref position);
+                               if (candidates != null || container.MemberName == null)
                                        return candidates;
 
-                               parent_ns = parent_ns.Parent;
-                       } while (parent_ns != null);
+                               var container_ns = container.ns.Parent;
+                               var mn = container.MemberName.Left;
+                               int already_checked = position - 2;
+                               while (already_checked-- > 0) {
+                                       mn = mn.Left;
+                                       container_ns = container_ns.Parent;
+                               }
 
-                       //
-                       // Continue in parent scope
-                       //
-                       return parent.LookupExtensionMethod (extensionType, name, arity, ref scope);
+                               while (mn != null) {
+                                       ++position;
+
+                                       var methods = container_ns.LookupExtensionMethod (invocationContext, extensionType, name, arity);
+                                       if (methods != null) {
+                                               return new ExtensionMethodCandidates (invocationContext, methods, container, position);
+                                       }
+
+                                       mn = mn.Left;
+                                       container_ns = container_ns.Parent;
+                               }
+
+                               position = 0;
+                               container = container.Parent;
+                       } while (container != null);
+
+                       return null;
                }
 
-               public FullNamedExpression LookupNamespaceOrType (string name, int arity, Location loc, bool ignore_cs0104)
+               ExtensionMethodCandidates LookupExtensionMethodCandidates (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity, ref int position)
                {
-                       // Precondition: Only simple names (no dots) will be looked up with this function.
-                       FullNamedExpression resolved = null;
-                       for (NamespaceContainer curr_ns = this; curr_ns != null; curr_ns = curr_ns.ImplicitParent) {
-                               if ((resolved = curr_ns.Lookup (name, arity, loc, ignore_cs0104)) != null)
-                                       break;
+                       List<MethodSpec> candidates = null;
+
+                       if (position == 0) {
+                               ++position;
+
+                               candidates = ns.LookupExtensionMethod (invocationContext, extensionType, name, arity);
+                               if (candidates != null) {
+                                       return new ExtensionMethodCandidates (invocationContext, candidates, this, position);
+                               }
                        }
 
-                       return resolved;
+                       if (position == 1) {
+                               ++position;
+
+                               foreach (Namespace n in namespace_using_table) {
+                                       var a = n.LookupExtensionMethod (invocationContext, extensionType, name, arity);
+                                       if (a == null)
+                                               continue;
+
+                                       if (candidates == null)
+                                               candidates = a;
+                                       else
+                                               candidates.AddRange (a);
+                               }
+
+                               if (candidates != null)
+                                       return new ExtensionMethodCandidates (invocationContext, candidates, this, position);
+                       }
+
+                       return null;
                }
 
-               public IList<string> CompletionGetTypesStartingWith (string prefix)
+               public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
                {
+                       //
+                       // Only simple names (no dots) will be looked up with this function
+                       //
+                       FullNamedExpression resolved;
+                       for (NamespaceContainer container = this; container != null; container = container.Parent) {
+                               resolved = container.Lookup (name, arity, mode, loc);
+                               if (resolved != null || container.MemberName == null)
+                                       return resolved;
+
+                               var container_ns = container.ns.Parent;
+                               var mn = container.MemberName.Left;
+                               while (mn != null) {
+                                       resolved = container_ns.LookupTypeOrNamespace (this, name, arity, mode, loc);
+                                       if (resolved != null)
+                                               return resolved;
+
+                                       mn = mn.Left;
+                                       container_ns = container_ns.Parent;
+                               }
+                       }
+
+                       return null;
+               }
+
+               public override void GetCompletionStartingWith (string prefix, List<string> results)
+               {
+                       foreach (var un in Usings) {
+                               if (un.Alias != null)
+                                       continue;
+
+                               var name = un.NamespaceExpression.Name;
+                               if (name.StartsWith (prefix))
+                                       results.Add (name);
+                       }
+
+
                        IEnumerable<string> all = Enumerable.Empty<string> ();
-                       
-                       for (NamespaceContainer curr_ns = this; curr_ns != null; curr_ns = curr_ns.ImplicitParent){
-                               foreach (Namespace using_ns in GetUsingTable ()){
-                                       if (prefix.StartsWith (using_ns.Name)){
-                                               int ld = prefix.LastIndexOf ('.');
-                                               if (ld != -1){
-                                                       string rest = prefix.Substring (ld+1);
-
-                                                       all = all.Concat (using_ns.CompletionGetTypesStartingWith (rest));
-                                               }
+
+                       foreach (Namespace using_ns in namespace_using_table) {
+                               if (prefix.StartsWith (using_ns.Name)) {
+                                       int ld = prefix.LastIndexOf ('.');
+                                       if (ld != -1) {
+                                               string rest = prefix.Substring (ld + 1);
+
+                                               all = all.Concat (using_ns.CompletionGetTypesStartingWith (rest));
                                        }
-                                       all = all.Concat (using_ns.CompletionGetTypesStartingWith (prefix));
                                }
+                               all = all.Concat (using_ns.CompletionGetTypesStartingWith (prefix));
                        }
 
-                       return all.Distinct ().ToList ();
+                       results.AddRange (all);
+
+                       base.GetCompletionStartingWith (prefix, results);
+               }
+
+               
+               //
+               // Looks-up a alias named @name in this and surrounding namespace declarations
+               //
+               public FullNamedExpression LookupExternAlias (string name)
+               {
+                       if (aliases == null)
+                               return null;
+
+                       UsingAliasNamespace uan;
+                       if (aliases.TryGetValue (name, out uan) && uan is UsingExternAlias)
+                               return uan.ResolvedExpression;
+
+                       return null;
                }
                
+               //
                // Looks-up a alias named @name in this and surrounding namespace declarations
-               public FullNamedExpression LookupNamespaceAlias (string name)
+               //
+               public override FullNamedExpression LookupNamespaceAlias (string name)
                {
-                       for (NamespaceContainer n = this; n != null; n = n.ImplicitParent) {
-                               if (n.using_aliases == null)
+                       for (NamespaceContainer n = this; n != null; n = n.Parent) {
+                               if (n.aliases == null)
                                        continue;
 
-                               foreach (NamespaceUsingAlias ue in n.using_aliases) {
-                                       if (ue.Alias == name)
-                                               return ue.Resolve (Doppelganger ?? this, Doppelganger == null);
-                               }
+                               UsingAliasNamespace uan;
+                               if (n.aliases.TryGetValue (name, out uan))
+                                       return uan.ResolvedExpression;
                        }
 
                        return null;
                }
 
-               private FullNamedExpression Lookup (string name, int arity, Location loc, bool ignore_cs0104)
+               FullNamedExpression Lookup (string name, int arity, LookupMode mode, Location loc)
                {
                        //
                        // Check whether it's in the namespace.
                        //
-                       FullNamedExpression fne = ns.LookupTypeOrNamespace (this, name, arity, loc);
+                       FullNamedExpression fne = ns.LookupTypeOrNamespace (this, name, arity, mode, loc);
 
                        //
                        // Check aliases. 
                        //
-                       if (using_aliases != null && arity == 0) {
-                               foreach (NamespaceUsingAlias ue in using_aliases) {
-                                       if (ue.Alias == name) {
-                                               if (fne != null) {
-                                                       if (Doppelganger != null) {
-                                                               // TODO: Namespace has broken location
-                                                               //Report.SymbolRelatedToPreviousError (fne.Location, null);
-                                                               Compiler.Report.SymbolRelatedToPreviousError (ue.Location, null);
-                                                               Compiler.Report.Error (576, loc,
-                                                                       "Namespace `{0}' contains a definition with same name as alias `{1}'",
-                                                                       GetSignatureForError (), name);
-                                                       } else {
-                                                               return fne;
-                                                       }
-                                               }
-
-                                               return ue.Resolve (Doppelganger ?? this, Doppelganger == null);
+                       if (aliases != null && arity == 0) {
+                               UsingAliasNamespace uan;
+                               if (aliases.TryGetValue (name, out uan)) {
+                                       if (fne != null) {
+                                               // TODO: Namespace has broken location
+                                               //Report.SymbolRelatedToPreviousError (fne.Location, null);
+                                               Compiler.Report.SymbolRelatedToPreviousError (uan.Location, null);
+                                               Compiler.Report.Error (576, loc,
+                                                       "Namespace `{0}' contains a definition with same name as alias `{1}'",
+                                                       GetSignatureForError (), name);
                                        }
+
+                                       return uan.ResolvedExpression;
                                }
                        }
 
-                       if (fne != null) {
-                               if (!((fne.Type.Modifiers & Modifiers.INTERNAL) != 0 && !fne.Type.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly)))
-                                       return fne;
-                       }
+                       if (fne != null)
+                               return fne;
 
-                       if (IsImplicit)
-                               return null;
+                       //
+                       // Lookup can be called before the namespace is defined from different namespace using alias clause
+                       //
+                       if (namespace_using_table == null) {
+                               DoDefineNamespace ();
+                       }
 
                        //
                        // Check using entries.
                        //
                        FullNamedExpression match = null;
-                       foreach (Namespace using_ns in GetUsingTable ()) {
+                       foreach (Namespace using_ns in namespace_using_table) {
+                               //
                                // A using directive imports only types contained in the namespace, it
                                // does not import any nested namespaces
-                               fne = using_ns.LookupType (this, name, arity, loc);
+                               //
+                               fne = using_ns.LookupType (this, name, arity, mode, loc);
                                if (fne == null)
                                        continue;
 
@@ -937,16 +1190,16 @@ namespace Mono.CSharp {
                                        continue;
                                }
 
-                               if (ignore_cs0104)
-                                       return match;
-
                                // It can be top level accessibility only
-                               var better = Namespace.IsImportedTypeOverride (module, texpr_match.Type, texpr_fne.Type);
+                               var better = Namespace.IsImportedTypeOverride (Module, texpr_match.Type, texpr_fne.Type);
                                if (better == null) {
-                                       Compiler.Report.SymbolRelatedToPreviousError (texpr_match.Type);
-                                       Compiler.Report.SymbolRelatedToPreviousError (texpr_fne.Type);
-                                       Compiler.Report.Error (104, loc, "`{0}' is an ambiguous reference between `{1}' and `{2}'",
-                                               name, texpr_match.GetSignatureForError (), texpr_fne.GetSignatureForError ());
+                                       if (mode == LookupMode.Normal) {
+                                               Compiler.Report.SymbolRelatedToPreviousError (texpr_match.Type);
+                                               Compiler.Report.SymbolRelatedToPreviousError (texpr_fne.Type);
+                                               Compiler.Report.Error (104, loc, "`{0}' is an ambiguous reference between `{1}' and `{2}'",
+                                                       name, texpr_match.GetSignatureForError (), texpr_fne.GetSignatureForError ());
+                                       }
+
                                        return match;
                                }
 
@@ -957,266 +1210,339 @@ namespace Mono.CSharp {
                        return match;
                }
 
-               Namespace [] GetUsingTable ()
+               protected override void DefineNamespace ()
                {
-                       if (namespace_using_table != null)
-                               return namespace_using_table;
+                       if (namespace_using_table == null)
+                               DoDefineNamespace ();
 
-                       if (using_clauses == null) {
-                               namespace_using_table = empty_namespaces;
-                               return namespace_using_table;
-                       }
+                       base.DefineNamespace ();
+               }
 
-                       var list = new List<Namespace> (using_clauses.Count);
+               void DoDefineNamespace ()
+               {
+                       namespace_using_table = empty_namespaces;
+
+                       if (clauses != null) {
+                               var list = new List<Namespace> (clauses.Count);
+                               bool post_process_using_aliases = false;
+
+                               for (int i = 0; i < clauses.Count; ++i) {
+                                       var entry = clauses[i];
+
+                                       if (entry.Alias != null) {
+                                               if (aliases == null)
+                                                       aliases = new Dictionary<string, UsingAliasNamespace> ();
+
+                                               //
+                                               // Aliases are not available when resolving using section
+                                               // except extern aliases
+                                               //
+                                               if (entry is UsingExternAlias) {
+                                                       entry.Define (this);
+                                                       if (entry.ResolvedExpression != null)
+                                                               aliases.Add (entry.Alias.Value, (UsingExternAlias) entry);
+
+                                                       clauses.RemoveAt (i--);
+                                               } else {
+                                                       post_process_using_aliases = true;
+                                               }
 
-                       foreach (NamespaceUsing ue in using_clauses) {
-                               Namespace using_ns = ue.Resolve (Doppelganger);
-                               if (using_ns == null)
-                                       continue;
+                                               continue;
+                                       }
 
-                               list.Add (using_ns);
-                       }
+                                       entry.Define (this);
 
-                       namespace_using_table = list.ToArray ();
-                       return namespace_using_table;
-               }
+                                       //
+                                       // It's needed for repl only, when using clause cannot be resolved don't hold it in
+                                       // global list which is resolved for each evaluation
+                                       //
+                                       if (entry.ResolvedExpression == null) {
+                                               clauses.RemoveAt (i--);
+                                               continue;
+                                       }
 
-               public int SymbolFileID {
-                       get {
-                               if (symfile_id == 0 && file.SourceFileEntry != null) {
-                                       int parent_id = parent == null ? 0 : parent.SymbolFileID;
-
-                                       string [] using_list = empty_using_list;
-                                       if (using_clauses != null) {
-                                               using_list = new string [using_clauses.Count];
-                                               for (int i = 0; i < using_clauses.Count; i++)
-                                                       using_list [i] = ((NamespaceUsing) using_clauses [i]).MemberName.GetName ();
+                                       Namespace using_ns = entry.ResolvedExpression as Namespace;
+                                       if (using_ns == null)
+                                               continue;
+
+                                       if (list.Contains (using_ns)) {
+                                               // Ensure we don't report the warning multiple times in repl
+                                               clauses.RemoveAt (i--);
+
+                                               Compiler.Report.Warning (105, 3, entry.Location,
+                                                       "The using directive for `{0}' appeared previously in this namespace", using_ns.GetSignatureForError ());
+                                       } else {
+                                               list.Add (using_ns);
                                        }
+                               }
 
-                                       symfile_id = SymbolWriter.DefineNamespace (ns.Name, file.CompileUnitEntry, using_list, parent_id);
+                               namespace_using_table = list.ToArray ();
+
+                               if (post_process_using_aliases) {
+                                       for (int i = 0; i < clauses.Count; ++i) {
+                                               var entry = clauses[i];
+                                               if (entry.Alias != null) {
+                                                       entry.Define (this);
+                                                       if (entry.ResolvedExpression != null) {
+                                                               aliases.Add (entry.Alias.Value, (UsingAliasNamespace) entry);
+                                                       }
+
+                                                       clauses.RemoveAt (i--);
+                                               }
+                                       }
                                }
-                               return symfile_id;
                        }
                }
 
-               static void MsgtryRef (string s)
+               public void EnableRedefinition ()
                {
-                       Console.WriteLine ("    Try using -r:" + s);
+                       is_defined = false;
+                       namespace_using_table = null;
                }
 
-               static void MsgtryPkg (string s)
+               internal override void GenerateDocComment (DocumentationBuilder builder)
                {
-                       Console.WriteLine ("    Try using -pkg:" + s);
+                       if (containers != null) {
+                               foreach (var tc in containers)
+                                       tc.GenerateDocComment (builder);
+                       }
                }
 
-               public static void Error_GlobalNamespaceRedefined (Location loc, Report Report)
+               public override string GetSignatureForError ()
                {
-                       Report.Error (1681, loc, "The global extern alias cannot be redefined");
+                       return MemberName == null ? "global::" : base.GetSignatureForError ();
                }
 
-               public static void Error_NamespaceNotFound (Location loc, string name, Report Report)
+               public override void RemoveContainer (TypeContainer cont)
                {
-                       Report.Error (246, loc, "The type or namespace name `{0}' could not be found. Are you missing a using directive or an assembly reference?",
-                               name);
-
-                       switch (name) {
-                       case "Gtk": case "GtkSharp":
-                               MsgtryPkg ("gtk-sharp-2.0");
-                               break;
-
-                       case "Gdk": case "GdkSharp":
-                               MsgtryPkg ("gdk-sharp-2.0");
-                               break;
-
-                       case "Glade": case "GladeSharp":
-                               MsgtryPkg ("glade-sharp-2.0");
-                               break;
-
-                       case "System.Drawing":
-                       case "System.Web.Services":
-                       case "System.Web":
-                       case "System.Data":
-                       case "System.Windows.Forms":
-                               MsgtryRef (name);
-                               break;
-                       }
+                       base.RemoveContainer (cont);
+                       NS.RemoveContainer (cont);
                }
 
-               /// <summary>
-               ///   Used to validate that all the using clauses are correct
-               ///   after we are finished parsing all the files.  
-               /// </summary>
-               public void Resolve ()
+               protected override bool VerifyClsCompliance ()
                {
-                       if (resolved)
-                               return;
-
-                       resolved = true;
-
-                       if (using_aliases != null) {
-                               foreach (NamespaceUsingAlias ue in using_aliases)
-                                       ue.Resolve (Doppelganger, Doppelganger == null);
-                       }
+                       if (Module.IsClsComplianceRequired ()) {
+                               if (MemberName != null && MemberName.Name[0] == '_') {
+                                       Warning_IdentifierNotCompliant ();
+                               }
 
-                       if (using_clauses != null) {
-                               foreach (NamespaceUsing ue in using_clauses)
-                                       ue.Resolve (Doppelganger);
+                               ns.VerifyClsCompliance ();
+                               return true;
                        }
 
-                       if (parent != null)
-                               parent.Resolve ();
-               }
-
-               public string GetSignatureForError ()
-               {
-                       return ns.GetSignatureForError ();
-               }
-
-               #region IMemberContext Members
-
-               CompilerContext Compiler {
-                       get { return module.Compiler; }
-               }
-
-               public TypeSpec CurrentType {
-                       get { return SlaveDeclSpace.CurrentType; }
+                       return false;
                }
+       }
 
-               public MemberCore CurrentMemberDefinition {
-                       get { return SlaveDeclSpace.CurrentMemberDefinition; }
-               }
+       public class UsingNamespace
+       {
+               readonly ATypeNameExpression expr;
+               readonly Location loc;
+               protected FullNamedExpression resolved;
 
-               public TypeParameter[] CurrentTypeParameters {
-                       get { return SlaveDeclSpace.CurrentTypeParameters; }
+               public UsingNamespace (ATypeNameExpression expr, Location loc)
+               {
+                       this.expr = expr;
+                       this.loc = loc;
                }
 
-               // FIXME: It's false for expression types
-               public bool HasUnresolvedConstraints {
-                       get { return true; }
-               }
+               #region Properties
 
-               public bool IsObsolete {
-                       get { return SlaveDeclSpace.IsObsolete; }
+               public virtual SimpleMemberName Alias {
+                       get {
+                               return null;
+                       }
                }
 
-               public bool IsUnsafe {
-                       get { return SlaveDeclSpace.IsUnsafe; }
+               public Location Location {
+                       get {
+                               return loc;
+                       }
                }
 
-               public bool IsStatic {
-                       get { return SlaveDeclSpace.IsStatic; }
+               public ATypeNameExpression NamespaceExpression  {
+                       get {
+                               return expr;
+                       }
                }
 
-               public ModuleContainer Module {
-                       get { return module; }
+               public FullNamedExpression ResolvedExpression {
+                       get {
+                               return resolved;
+                       }
                }
 
                #endregion
-       }
-
-       public class NamespaceUsing
-       {
-               readonly MemberName name;
-               Namespace resolved;
-
-               public NamespaceUsing (MemberName name)
-               {
-                       this.name = name;
-               }
 
                public string GetSignatureForError ()
                {
-                       return name.GetSignatureForError ();
+                       return expr.GetSignatureForError ();
                }
 
-               public Location Location
+               public virtual void Define (NamespaceContainer ctx)
                {
-                       get { return name.Location; }
+                       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 ());
+                               }
+                       }
                }
 
-               public MemberName MemberName
+               public override string ToString()
                {
-                       get { return name; }
+                       return resolved.ToString();
                }
+       }
 
-               public string Name
+       public class UsingExternAlias : UsingAliasNamespace
+       {
+               public UsingExternAlias (SimpleMemberName alias, Location loc)
+                       : base (alias, null, loc)
                {
-                       get { return GetSignatureForError (); }
                }
 
-               public Namespace Resolve (IMemberContext rc)
+               public override void Define (NamespaceContainer ctx)
                {
-                       if (resolved != null)
-                               return resolved;
-
-                       FullNamedExpression fne = name.GetTypeExpression ().ResolveAsTypeOrNamespace (rc);
-                       if (fne == null)
-                               return null;
-
-                       resolved = fne as Namespace;
+                       resolved = ctx.Module.GetRootNamespace (Alias.Value);
                        if (resolved == null) {
-                               rc.Module.Compiler.Report.SymbolRelatedToPreviousError (fne.Type);
-                               rc.Module.Compiler.Report.Error (138, Location,
-                                       "`{0}' is a type not a namespace. A using namespace directive can only be applied to namespaces",
-                                       GetSignatureForError ());
+                               ctx.Module.Compiler.Report.Error (430, Location,
+                                       "The extern alias `{0}' was not specified in -reference option",
+                                       Alias.Value);
                        }
-                       return resolved;
                }
        }
 
-       public class NamespaceUsingAlias
+       public class UsingAliasNamespace : UsingNamespace
        {
-               public readonly string Alias;
-               public Location Location;
+               readonly SimpleMemberName alias;
 
-               public NamespaceUsingAlias (string alias, Location loc)
+               public struct AliasContext : IMemberContext
                {
-                       this.Alias = alias;
-                       this.Location = loc;
-               }
+                       readonly NamespaceContainer ns;
 
-               public virtual FullNamedExpression Resolve (IMemberContext rc, bool local)
-               {
-                       FullNamedExpression fne = rc.Module.GetRootNamespace (Alias);
-                       if (fne == null) {
-                               rc.Module.Compiler.Report.Error (430, Location,
-                                       "The extern alias `{0}' was not specified in -reference option",
-                                       Alias);
+                       public AliasContext (NamespaceContainer ns)
+                       {
+                               this.ns = ns;
                        }
 
-                       return fne;
-               }
-       }
+                       public TypeSpec CurrentType {
+                               get {
+                                       return null;
+                               }
+                       }
 
-       class LocalUsingAliasEntry : NamespaceUsingAlias
-       {
-               FullNamedExpression resolved;
-               MemberName value;
+                       public TypeParameters CurrentTypeParameters {
+                               get {
+                                       return null;
+                               }
+                       }
 
-               public LocalUsingAliasEntry (string alias, MemberName name, Location loc)
-                       : base (alias, loc)
-               {
-                       this.value = name;
-               }
+                       public MemberCore CurrentMemberDefinition {
+                               get {
+                                       return null;
+                               }
+                       }
 
-               public override FullNamedExpression Resolve (IMemberContext rc, bool local)
-               {
-                       if (resolved != null || value == null)
-                               return resolved;
+                       public bool IsObsolete {
+                               get {
+                                       return false;
+                               }
+                       }
 
-                       if (local)
+                       public bool IsUnsafe {
+                               get {
+                                       throw new NotImplementedException ();
+                               }
+                       }
+
+                       public bool IsStatic {
+                               get {
+                                       throw new NotImplementedException ();
+                               }
+                       }
+
+                       public ModuleContainer Module {
+                               get {
+                                       return ns.Module;
+                               }
+                       }
+
+                       public string GetSignatureForError ()
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
+                       {
                                return null;
+                       }
+
+                       public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
+                       {
+                               var fne = ns.NS.LookupTypeOrNamespace (ns, name, arity, mode, loc);
+                               if (fne != null)
+                                       return fne;
+
+                               //
+                               // Only extern aliases are allowed in this context
+                               //
+                               fne = ns.LookupExternAlias (name);
+                               if (fne != null || ns.MemberName == null)
+                                       return fne;
+
+                               var container_ns = ns.NS.Parent;
+                               var mn = ns.MemberName.Left;
+                               while (mn != null) {
+                                       fne = container_ns.LookupTypeOrNamespace (this, name, arity, mode, loc);
+                                       if (fne != null)
+                                               return fne;
+
+                                       mn = mn.Left;
+                                       container_ns = container_ns.Parent;
+                               }
+
+                               if (ns.Parent != null)
+                                       return ns.Parent.LookupNamespaceOrType (name, arity, mode, loc);
 
-                       resolved = value.GetTypeExpression ().ResolveAsTypeOrNamespace (rc);
-                       if (resolved == null) {
-                               value = null;
                                return null;
                        }
 
-                       if (resolved is TypeExpr)
-                               resolved = resolved.ResolveAsType (rc);
+                       public FullNamedExpression LookupNamespaceAlias (string name)
+                       {
+                               return ns.LookupNamespaceAlias (name);
+                       }
+               }
+
+               public UsingAliasNamespace (SimpleMemberName alias, ATypeNameExpression expr, Location loc)
+                       : base (expr, loc)
+               {
+                       this.alias = alias;
+               }
+
+               public override SimpleMemberName Alias {
+                       get {
+                               return alias;
+                       }
+               }
 
-                       return resolved;
+               public override void Define (NamespaceContainer ctx)
+               {
+                       //
+                       // The namespace-or-type-name of a using-alias-directive is resolved as if
+                       // the immediately containing compilation unit or namespace body had no
+                       // using-directives. A using-alias-directive may however be affected
+                       // by extern-alias-directives in the immediately containing compilation
+                       // unit or namespace body
+                       //
+                       // 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));
                }
        }
 }