context: //
  // namespace.cs: Tracks namespaces
  //
  // Author:
  //   Miguel de Icaza (miguel@ximian.com)
  //   Marek Safar (marek.safar@seznam.cz)
  //
  // 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 {
  
  	public class RootNamespace : Namespace {
  
  		readonly string alias_name;
  		readonly Dictionary<string, Namespace> all_namespaces;
  
  		public RootNamespace (string alias_name)
  			: base ()
  		{
  			this.alias_name = alias_name;
  			RegisterNamespace (this);
  
  			all_namespaces = new Dictionary<string, Namespace> ();
  			all_namespaces.Add ("", this);
  		}
  
  		public string Alias {
  			get {
  				return alias_name;
  			}
  		}
  
  		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, string name, int arity)
  		{
  			List<string> res = null;
  
  			foreach (var ns in all_namespaces) {
  				if (ns.Key.Length == 0)
  					continue;
  
  				var methods = ns.Value.LookupExtensionMethod (ctx, 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)
  				all_namespaces.Add (child.Name, child);
  		}
  
  		public override string GetSignatureForError ()
  		{
  			return alias_name + "::";
  		}
  	}
  
  	public sealed class GlobalRootNamespace : RootNamespace
  	{
  		public GlobalRootNamespace ()
  			: base ("global")
  		{
  		}
  	}
  
  	//
  	// Namespace cache for imported and compiled namespaces
  	//
  	public class Namespace
  	{
  		readonly Namespace parent;
  		string fullname;
  		protected Dictionary<string, Namespace> namespaces;
  		protected Dictionary<string, IList<TypeSpec>> types;
  		List<TypeSpec> extension_method_types;
  		Dictionary<string, TypeSpec> cached_types;
  		bool cls_checked;
  
  		/// <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 ()
  		{
  			if (name == null)
  				throw new ArgumentNullException ("name");
  
  			this.parent = parent;
  
  			string pname = parent != null ? parent.fullname : null;
  				
  			if (pname == null)
  				fullname = name;
  			else
  				fullname = pname + "." + name;
  
  			while (parent.parent != null)
  				parent = parent.parent;
  
  			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>
  		///   The qualified name of the current namespace
  		/// </summary>
  		public string Name {
  			get { return fullname; }
  		}
  
  		/// <summary>
  		///   The parent of this namespace, used by the parser to "Pop"
  		///   the current namespace declaration
  		/// </summary>
  		public Namespace Parent {
  			get { return parent; }
  		}
  
  		#endregion
  
  		public Namespace AddNamespace (MemberName name)
  		{
  			var ns_parent = name.Left == null ? this : AddNamespace (name.Left);
  			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;
  		}
  
  		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)
  		{
  			int pos = name.IndexOf ('.');
  
  			Namespace ns;
  			string first;
  			if (pos >= 0)
  				first = name.Substring (0, pos);
  			else
  				first = name;
  
  			if (!namespaces.TryGetValue (first, out ns)) {
  				if (!create)
  					return null;
  
  				ns = new Namespace (this, first);
  				namespaces.Add (first, ns);
  			}
  
  			if (pos >= 0)
  				ns = ns.GetNamespace (name.Substring (pos + 1), create);
  
  			return ns;
  		}
  
  		public IList<TypeSpec> GetAllTypes (string name)
  		{
  			IList<TypeSpec> found;
  			if (types == null || !types.TryGetValue (name, out found))
  				return null;
  
  			return found;
  		}
  
  		public virtual string GetSignatureForError ()
  		{
  			return fullname;
  		}
  
  		public TypeSpec LookupType (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)
  		{
  			if (types == null)
  				return null;
  
  			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;
  
  			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) {
  						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;
  					}
  
  					if (ts.Kind == MemberKind.MissingType)
  						continue;
  
  					if (best.MemberDefinition.IsImported)
  						best = ts;
  
  					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 (best);
  						ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts);
  					}
  
  					ctx.Module.Compiler.Report.Warning (436, 2, loc,
  						"The type `{0}' conflicts with the imported type of same name'. Ignoring the imported type definition",
  						best.GetSignatureForError ());
  				}
  
  				//
  				// Lookup for the best candidate with the 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;
  					}
  				}
  			}
  
  			// TODO MemberCache: Cache more
  			if (arity == 0 && mode == LookupMode.Normal)
  				cached_types.Add (name, best);
  
  			if (best != null) {
  				var dep = best.GetMissingDependencies ();
  				if (dep != null)
  					ImportedTypeDefinition.Error_MissingDependency (ctx, dep, loc);
  			}
  
  			return best;
  		}
  
  		public FullNamedExpression LookupTypeOrNamespace (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)
  		{
  			var texpr = LookupType (ctx, name, arity, mode, loc);
  
  			Namespace ns;
  			if (arity == 0 && namespaces.TryGetValue (name, out ns)) {
  				if (texpr == null)
  					return new NamespaceExpression (ns, loc);
  
  				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.MemberDefinition.IsImported)
  					return new NamespaceExpression (ns, loc);
  			}
  
  			if (texpr == null)
  				return null;
  
  			return new TypeExpression (texpr, loc);
  		}
  
  		//
  		// Completes types with the given `prefix'
  		//
  		public IEnumerable<string> CompletionGetTypesStartingWith (string prefix)
  		{
  			if (types == null)
  				return Enumerable.Empty<string> ();
  
  			var res = from item in types
  					  where item.Key.StartsWith (prefix) && item.Value.Any (l => (l.Modifiers & Modifiers.PUBLIC) != 0)
  					  select item.Key;
  
  			if (namespaces != null)
  				res = res.Concat (from item in namespaces where item.Key.StartsWith (prefix) select item.Key);
  
  			return res;
  		}
  
  		// 
  		// Looks for extension method in this namespace
  		//
  		public List<MethodSpec> LookupExtensionMethod (IMemberContext invocationContext, string name, int arity)
  		{
  			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];
  
  				//
  				// 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;
  					}
  
  					extension_method_types.RemoveAt (i--);
  					continue;
  				}
  
  				var res = ts.MemberCache.FindExtensionMethods (invocationContext, name, arity);
  				if (res == null)
  					continue;
  
  				if (found == null) {
  					found = res;
  				} else {
  					found.AddRange (res);
  				}
  			}
  
  			return found;
  		}
  
  		public void AddType (ModuleContainer module, TypeSpec ts)
  		{
  			if (types == null) {
  				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)) {
  				TypeSpec better_type;
  				TypeSpec found;
  				if (existing.Count == 1) {
  					found = existing[0];
  					if (ts.Arity == found.Arity) {
  						better_type = IsImportedTypeOverride (module, ts, found);
  						if (better_type == found)
  							return;
  
  						if (better_type != null) {
  							existing [0] = better_type;
  							return;
  						}
  					}
  
  					existing = new List<TypeSpec> ();
  					existing.Add (found);
  					types[name] = existing;
  				} else {
  					for (int i = 0; i < existing.Count; ++i) {
  						found = existing[i];
  						if (ts.Arity != found.Arity)
  							continue;
  
  						better_type = IsImportedTypeOverride (module, ts, found);
  						if (better_type == found)
  							return;
  
  						if (better_type != null) {
  							existing.RemoveAt (i);
  							--i;
  							continue;
  						}
  					}
  				}
  
  				existing.Add (ts);
  			} else {
  				types.Add (name, new TypeSpec[] { ts });
  			}
  		}
  
  		//
  		// We import any types but in the situation there are same types
  		// but one has better visibility (either public or internal with friend)
  		// the less visible type is removed from the namespace cache
  		//
  		public static TypeSpec IsImportedTypeOverride (ModuleContainer module, TypeSpec ts, TypeSpec found)
  		{
  			var ts_accessible = (ts.Modifiers & Modifiers.PUBLIC) != 0 || ts.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly);
  			var found_accessible = (found.Modifiers & Modifiers.PUBLIC) != 0 || found.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly);
  
  			if (ts_accessible && !found_accessible)
  				return ts;
  
  			// found is better always better for accessible or inaccessible ts
  			if (!ts_accessible)
  				return found;
  
  			return null;
  		}
  
  		public void RemoveContainer (TypeContainer tc)
  		{
  			IList<TypeSpec> found;
  			if (types.TryGetValue (tc.MemberName.Name, out found)) {
  				for (int i = 0; i < found.Count; ++i) {
  					if (tc.MemberName.Arity != found [i].Arity)
  						continue;
  
  					if (found.Count == 1)
  						types.Remove (tc.MemberName.Name);
  					else
  						found.RemoveAt (i);
  
  					break;
  				}
  			}
  
  			cached_types.Remove (tc.MemberName.Basename);
  		}
  
  		public void SetBuiltinType (BuiltinTypeSpec pts)
  		{
  			var found = types[pts.Name];
  			cached_types.Remove (pts.Name);
  			if (found.Count == 1) {
  				types[pts.Name][0] = pts;
  			} else {
  				throw new NotImplementedException ();
  			}
  		}
  
  		public void VerifyClsCompliance ()
  		{
  			if (types == null || cls_checked)
  				return;
  
  			cls_checked = true;
  
  			// TODO: This is quite ugly way to check for CLS compliance at namespace level
  
  			var locase_types = new Dictionary<string, List<TypeSpec>> (StringComparer.OrdinalIgnoreCase);
  			foreach (var tgroup in types.Values) {
  				foreach (var tm in tgroup) {
  					if ((tm.Modifiers & Modifiers.PUBLIC) == 0 || !tm.IsCLSCompliant ())
  						continue;
  
  					List<TypeSpec> found;
  					if (!locase_types.TryGetValue (tm.Name, out found)) {
  						found = new List<TypeSpec> ();
  						locase_types.Add (tm.Name, found);
  					}
  
  					found.Add (tm);
  				}
  			}
  
  			foreach (var locase in locase_types.Values) {
  				if (locase.Count < 2)
  					continue;
  
  				bool all_same = true;
  				foreach (var notcompliant in locase) {
  					all_same = notcompliant.Name == locase[0].Name;
  					if (!all_same)
  						break;
  				}
  
  				if (all_same)
  					continue;
  
  				TypeContainer compiled = null;
  				foreach (var notcompliant in locase) {
  					if (!notcompliant.MemberDefinition.IsImported) {
  						if (compiled != null)
  							compiled.Compiler.Report.SymbolRelatedToPreviousError (compiled);
  
  						compiled = notcompliant.MemberDefinition as TypeContainer;
  					} else {
  						compiled.Compiler.Report.SymbolRelatedToPreviousError (notcompliant);
  					}
  				}
  
  				compiled.Compiler.Report.Warning (3005, 1, compiled.Location,
  					"Identifier `{0}' differing only in case is not CLS-compliant", compiled.GetSignatureForError ());
  			}
  		}
  	}
  
  	public class CompilationSourceFile : NamespaceContainer
  	{
  		readonly SourceFile file;
  		CompileUnitEntry comp_unit;
  		Dictionary<string, SourceFile> include_files;
  		Dictionary<string, bool> conditionals;
  
  		public CompilationSourceFile (ModuleContainer parent, SourceFile sourceFile)
  			: this (parent)
  		{
  			this.file = sourceFile;
  		}
  
  		public CompilationSourceFile (ModuleContainer parent)
  			: base (parent)
  		{
  		}
  
  		public CompileUnitEntry SymbolUnitEntry {
  			get {
  				return comp_unit;
  			}
  		}
  
  		public string FileName {
  			get {
  				return file.Name;
  			}
  		}
  
  		public SourceFile SourceFile {
  			get {
  				return file;
  			}
  		}
  
  		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);
  		}
  
  		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 ();
  		}
  
  		//
  		// Creates symbol file index in debug symbol file
  		//
  		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);
  				}
  			}
  		}
  
  		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);
  		}
  
  		public override void Accept (StructuralVisitor visitor)
  		{
  			visitor.Visit (this);
  		}
  	}
  
  
  	//
  	// 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<UsingClause> clauses;
  
  		// Used by parsed to check for parser errors
  		public bool DeclarationFound;
  
  		Namespace[] namespace_using_table;
  		TypeSpec[] types_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 {
  				throw new NotSupportedException ();
  			}
  		}
  
  		public override string DocCommentHeader {
  			get {
  				throw new NotSupportedException ();
  			}
  		}
  
  		public Namespace NS {
  			get {
  				return ns;
  			}
  		}
  
  		public List<UsingClause> Usings {
  			get {
  				return clauses;
  			}
  		}
  
  		public override string[] ValidAttributeTargets {
  			get {
  				throw new NotSupportedException ();
  			}
  		}
  
  		#endregion
  
  		public void AddUsing (UsingClause un)
  		{
  			if (DeclarationFound){
  				Compiler.Report.Error (1529, un.Location, "A using clause must precede all other namespace elements except extern alias declarations");
  			}
  
  			if (clauses == null)
  				clauses = new List<UsingClause> ();
  
  			clauses.Add (un);
  		}
  
  		public void AddUsing (UsingAliasNamespace un)
  		{
  			if (DeclarationFound){
  				Compiler.Report.Error (1529, un.Location, "A using clause must precede all other namespace elements except extern alias declarations");
  			}
  
  			AddAlias (un);
  		}
  
  		void AddAlias (UsingAliasNamespace un)
  		{
  			if (clauses == null) {
  				clauses = new List<UsingClause> ();
  			} 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);
  					}
  				}
  			}
  
  			clauses.Add (un);
  		}
  
  		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.MemberDefinition as TypeDefinition : null;
  			AddPartial (next_part, td);
  		}
  
  		public override void AddTypeContainer (TypeContainer tc)
  		{
  			var mn = tc.MemberName;
  			var name = mn.Basename;
  			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) {
  					AddTypeContainerMember (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 {
  				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);
  					}
  				}
  			}
  
  			base.AddTypeContainer (tc);
  		}
  
  		public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
  		{
  			throw new NotSupportedException ();
  		}
  
  		public override void EmitContainer ()
  		{
  			VerifyClsCompliance ();
  
  			base.EmitContainer ();
  		}
  
  		public ExtensionMethodCandidates LookupExtensionMethod (IMemberContext invocationContext, string name, int arity, int position)
  		{
  			//
  			// 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.
  			//
  			// 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 = container.LookupExtensionMethodCandidates (invocationContext, name, arity, ref position);
  				if (candidates != null || container.MemberName == null)
  					return candidates;
  
  				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;
  				}
  
  				while (mn != null) {
  					++position;
  
  					var methods = container_ns.LookupExtensionMethod (invocationContext, 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;
  		}
  
  		ExtensionMethodCandidates LookupExtensionMethodCandidates (IMemberContext invocationContext, string name, int arity, ref int position)
  		{
  			List<MethodSpec> candidates = null;
  
  			if (position == 0) {
  				++position;
  
  				candidates = ns.LookupExtensionMethod (invocationContext, name, arity);
  				if (candidates != null) {
  					return new ExtensionMethodCandidates (invocationContext, candidates, this, position);
  				}
  			}
  
  			if (position == 1) {
  				++position;
  
  				foreach (Namespace n in namespace_using_table) {
  					var a = n.LookupExtensionMethod (invocationContext, name, arity);
  					if (a == null)
  						continue;
  
  					if (candidates == null)
  						candidates = a;
  					else
  						candidates.AddRange (a);
  				}
  
  				if (types_using_table != null) {
  
gt: 					foreach (var t in types_using_table) {