1 //
2 // namespace.cs: Tracks namespaces
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //   Marek Safar (marek.safar@seznam.cz)
7 //
8 // Copyright 2001 Ximian, Inc.
9 // Copyright 2003-2008 Novell, Inc.
10 // Copyright 2011 Xamarin Inc
11 //
12 using System;
13 using System.Collections.Generic;
14 using System.Linq;
15 using Mono.CompilerServices.SymbolWriter;
16 
17 namespace Mono.CSharp {
18 
19 	public class RootNamespace : Namespace {
20 
21 		readonly string alias_name;
22 		readonly Dictionary<string, Namespace> all_namespaces;
23 
RootNamespace(string alias_name)24 		public RootNamespace (string alias_name)
25 			: base ()
26 		{
27 			this.alias_name = alias_name;
28 			RegisterNamespace (this);
29 
30 			all_namespaces = new Dictionary<string, Namespace> ();
31 			all_namespaces.Add ("", this);
32 		}
33 
34 		public string Alias {
35 			get {
36 				return alias_name;
37 			}
38 		}
39 
Error_GlobalNamespaceRedefined(Report report, Location loc)40 		public static void Error_GlobalNamespaceRedefined (Report report, Location loc)
41 		{
42 			report.Error (1681, loc, "The global extern alias cannot be redefined");
43 		}
44 
45 		//
46 		// For better error reporting where we try to guess missing using directive
47 		//
FindTypeNamespaces(IMemberContext ctx, string name, int arity)48 		public List<string> FindTypeNamespaces (IMemberContext ctx, string name, int arity)
49 		{
50 			List<string> res = null;
51 
52 			foreach (var ns in all_namespaces) {
53 				var type = ns.Value.LookupType (ctx, name, arity, LookupMode.Normal, Location.Null);
54 				if (type != null) {
55 					if (res == null)
56 						res = new List<string> ();
57 
58 					res.Add (ns.Key);
59 				}
60 			}
61 
62 			return res;
63 		}
64 
65 		//
66 		// For better error reporting where compiler tries to guess missing using directive
67 		//
FindExtensionMethodNamespaces(IMemberContext ctx, string name, int arity)68 		public List<string> FindExtensionMethodNamespaces (IMemberContext ctx, string name, int arity)
69 		{
70 			List<string> res = null;
71 
72 			foreach (var ns in all_namespaces) {
73 				if (ns.Key.Length == 0)
74 					continue;
75 
76 				var methods = ns.Value.LookupExtensionMethod (ctx, name, arity);
77 				if (methods != null) {
78 					if (res == null)
79 						res = new List<string> ();
80 
81 					res.Add (ns.Key);
82 				}
83 			}
84 
85 			return res;
86 		}
87 
RegisterNamespace(Namespace child)88 		public void RegisterNamespace (Namespace child)
89 		{
90 			if (child != this)
91 				all_namespaces.Add (child.Name, child);
92 		}
93 
GetSignatureForError()94 		public override string GetSignatureForError ()
95 		{
96 			return alias_name + "::";
97 		}
98 	}
99 
100 	public sealed class GlobalRootNamespace : RootNamespace
101 	{
GlobalRootNamespace()102 		public GlobalRootNamespace ()
103 			: base ("global")
104 		{
105 		}
106 	}
107 
108 	//
109 	// Namespace cache for imported and compiled namespaces
110 	//
111 	public class Namespace
112 	{
113 		readonly Namespace parent;
114 		string fullname;
115 		protected Dictionary<string, Namespace> namespaces;
116 		protected Dictionary<string, IList<TypeSpec>> types;
117 		List<TypeSpec> extension_method_types;
118 		Dictionary<string, TypeSpec> cached_types;
119 		bool cls_checked;
120 
121 		/// <summary>
122 		///   Constructor Takes the current namespace and the
123 		///   name.  This is bootstrapped with parent == null
124 		///   and name = ""
125 		/// </summary>
Namespace(Namespace parent, string name)126 		public Namespace (Namespace parent, string name)
127 			: this ()
128 		{
129 			if (name == null)
130 				throw new ArgumentNullException ("name");
131 
132 			this.parent = parent;
133 
134 			string pname = parent != null ? parent.fullname : null;
135 
136 			if (pname == null)
137 				fullname = name;
138 			else
139 				fullname = pname + "." + name;
140 
141 			while (parent.parent != null)
142 				parent = parent.parent;
143 
144 			var root = parent as RootNamespace;
145 			if (root == null)
146 				throw new InternalErrorException ("Root namespaces must be created using RootNamespace");
147 
148 			root.RegisterNamespace (this);
149 		}
150 
Namespace()151 		protected Namespace ()
152 		{
153 			namespaces = new Dictionary<string, Namespace> ();
154 			cached_types = new Dictionary<string, TypeSpec> ();
155 		}
156 
157 		#region Properties
158 
159 		/// <summary>
160 		///   The qualified name of the current namespace
161 		/// </summary>
162 		public string Name {
163 			get { return fullname; }
164 		}
165 
166 		/// <summary>
167 		///   The parent of this namespace, used by the parser to "Pop"
168 		///   the current namespace declaration
169 		/// </summary>
170 		public Namespace Parent {
171 			get { return parent; }
172 		}
173 
174 		#endregion
175 
AddNamespace(MemberName name)176 		public Namespace AddNamespace (MemberName name)
177 		{
178 			var ns_parent = name.Left == null ? this : AddNamespace (name.Left);
179 			return ns_parent.TryAddNamespace (name.Basename);
180 		}
181 
TryAddNamespace(string name)182 		Namespace TryAddNamespace (string name)
183 		{
184 			Namespace ns;
185 
186 			if (!namespaces.TryGetValue (name, out ns)) {
187 				ns = new Namespace (this, name);
188 				namespaces.Add (name, ns);
189 			}
190 
191 			return ns;
192 		}
193 
TryGetNamespace(string name, out Namespace ns)194 		public bool TryGetNamespace (string name, out Namespace ns)
195 		{
196 			return namespaces.TryGetValue (name, out ns);
197 		}
198 
199 		// TODO: Replace with CreateNamespace where MemberName is created for the method call
GetNamespace(string name, bool create)200 		public Namespace GetNamespace (string name, bool create)
201 		{
202 			int pos = name.IndexOf ('.');
203 
204 			Namespace ns;
205 			string first;
206 			if (pos >= 0)
207 				first = name.Substring (0, pos);
208 			else
209 				first = name;
210 
211 			if (!namespaces.TryGetValue (first, out ns)) {
212 				if (!create)
213 					return null;
214 
215 				ns = new Namespace (this, first);
216 				namespaces.Add (first, ns);
217 			}
218 
219 			if (pos >= 0)
220 				ns = ns.GetNamespace (name.Substring (pos + 1), create);
221 
222 			return ns;
223 		}
224 
GetAllTypes(string name)225 		public IList<TypeSpec> GetAllTypes (string name)
226 		{
227 			IList<TypeSpec> found;
228 			if (types == null || !types.TryGetValue (name, out found))
229 				return null;
230 
231 			return found;
232 		}
233 
GetSignatureForError()234 		public virtual string GetSignatureForError ()
235 		{
236 			return fullname;
237 		}
238 
LookupType(IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)239 		public TypeSpec LookupType (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)
240 		{
241 			if (types == null)
242 				return null;
243 
244 			TypeSpec best = null;
245 			if (arity == 0 && cached_types.TryGetValue (name, out best)) {
246 				if (best != null || mode != LookupMode.IgnoreAccessibility)
247 					return best;
248 			}
249 
250 			IList<TypeSpec> found;
251 			if (!types.TryGetValue (name, out found))
252 				return null;
253 
254 			foreach (var ts in found) {
255 				if (ts.Arity == arity) {
256 					if (best == null) {
257 						if ((ts.Modifiers & Modifiers.INTERNAL) != 0 && !ts.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly) && mode != LookupMode.IgnoreAccessibility)
258 							continue;
259 
260 						best = ts;
261 						continue;
262 					}
263 
264 					if (best.MemberDefinition.IsImported && ts.MemberDefinition.IsImported) {
265 						if (ts.Kind == MemberKind.MissingType)
266 							continue;
267 
268 						if (best.Kind == MemberKind.MissingType) {
269 							best = ts;
270 							continue;
271 						}
272 
273 						if (mode == LookupMode.Normal) {
274 							ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (best);
275 							ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts);
276 							ctx.Module.Compiler.Report.Error (433, loc, "The imported type `{0}' is defined multiple times", ts.GetSignatureForError ());
277 						}
278 
279 						break;
280 					}
281 
282 					if (ts.Kind == MemberKind.MissingType)
283 						continue;
284 
285 					if (best.MemberDefinition.IsImported)
286 						best = ts;
287 
288 					if ((best.Modifiers & Modifiers.INTERNAL) != 0 && !best.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly))
289 						continue;
290 
291 					if (mode != LookupMode.Normal)
292 						continue;
293 
294 					if (ts.MemberDefinition.IsImported) {
295 						ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (best);
296 						ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts);
297 					}
298 
299 					ctx.Module.Compiler.Report.Warning (436, 2, loc,
300 						"The type `{0}' conflicts with the imported type of same name'. Ignoring the imported type definition",
301 						best.GetSignatureForError ());
302 				}
303 
304 				//
305 				// Lookup for the best candidate with the closest arity match
306 				//
307 				if (arity < 0) {
308 					if (best == null) {
309 						best = ts;
310 					} else if (System.Math.Abs (ts.Arity + arity) < System.Math.Abs (best.Arity + arity)) {
311 						best = ts;
312 					}
313 				}
314 			}
315 
316 			// TODO MemberCache: Cache more
317 			if (arity == 0 && mode == LookupMode.Normal)
318 				cached_types.Add (name, best);
319 
320 			if (best != null) {
321 				var dep = best.GetMissingDependencies ();
322 				if (dep != null)
323 					ImportedTypeDefinition.Error_MissingDependency (ctx, dep, loc);
324 			}
325 
326 			return best;
327 		}
328 
LookupTypeOrNamespace(IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)329 		public FullNamedExpression LookupTypeOrNamespace (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)
330 		{
331 			var texpr = LookupType (ctx, name, arity, mode, loc);
332 
333 			Namespace ns;
334 			if (arity == 0 && namespaces.TryGetValue (name, out ns)) {
335 				if (texpr == null)
336 					return new NamespaceExpression (ns, loc);
337 
338 				if (mode != LookupMode.Probing) {
339 					//ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (texpr.Type);
340 					// ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ns.loc, "");
341 					ctx.Module.Compiler.Report.Warning (437, 2, loc,
342 						"The type `{0}' conflicts with the imported namespace `{1}'. Using the definition found in the source file",
343 						texpr.GetSignatureForError (), ns.GetSignatureForError ());
344 				}
345 
346 				if (texpr.MemberDefinition.IsImported)
347 					return new NamespaceExpression (ns, loc);
348 			}
349 
350 			if (texpr == null)
351 				return null;
352 
353 			return new TypeExpression (texpr, loc);
354 		}
355 
356 		//
357 		// Completes types with the given `prefix'
358 		//
CompletionGetTypesStartingWith(string prefix)359 		public IEnumerable<string> CompletionGetTypesStartingWith (string prefix)
360 		{
361 			if (types == null)
362 				return Enumerable.Empty<string> ();
363 
364 			var res = from item in types
365 					  where item.Key.StartsWith (prefix) && item.Value.Any (l => (l.Modifiers & Modifiers.PUBLIC) != 0)
366 					  select item.Key;
367 
368 			if (namespaces != null)
369 				res = res.Concat (from item in namespaces where item.Key.StartsWith (prefix) select item.Key);
370 
371 			return res;
372 		}
373 
374 		//
375 		// Looks for extension method in this namespace
376 		//
LookupExtensionMethod(IMemberContext invocationContext, string name, int arity)377 		public List<MethodSpec> LookupExtensionMethod (IMemberContext invocationContext, string name, int arity)
378 		{
379 			if (extension_method_types == null)
380 				return null;
381 
382 			List<MethodSpec> found = null;
383 			for (int i = 0; i < extension_method_types.Count; ++i) {
384 				var ts = extension_method_types[i];
385 
386 				//
387 				// When the list was built we didn't know what members the type
388 				// contains
389 				//
390 				if ((ts.Modifiers & Modifiers.METHOD_EXTENSION) == 0) {
391 					if (extension_method_types.Count == 1) {
392 						extension_method_types = null;
393 						return found;
394 					}
395 
396 					extension_method_types.RemoveAt (i--);
397 					continue;
398 				}
399 
400 				var res = ts.MemberCache.FindExtensionMethods (invocationContext, name, arity);
401 				if (res == null)
402 					continue;
403 
404 				if (found == null) {
405 					found = res;
406 				} else {
407 					found.AddRange (res);
408 				}
409 			}
410 
411 			return found;
412 		}
413 
AddType(ModuleContainer module, TypeSpec ts)414 		public void AddType (ModuleContainer module, TypeSpec ts)
415 		{
416 			if (types == null) {
417 				types = new Dictionary<string, IList<TypeSpec>> (64);
418 			}
419 
420 			if (ts.IsClass && ts.Arity == 0) {
421 				var extension_method_allowed = ts.MemberDefinition.IsImported ? (ts.Modifiers & Modifiers.METHOD_EXTENSION) != 0 : (ts.IsStatic || ts.MemberDefinition.IsPartial);
422 				if (extension_method_allowed) {
423 					if (extension_method_types == null)
424 						extension_method_types = new List<TypeSpec> ();
425 
426 					extension_method_types.Add (ts);
427 				}
428 			}
429 
430 			var name = ts.Name;
431 			IList<TypeSpec> existing;
432 			if (types.TryGetValue (name, out existing)) {
433 				TypeSpec better_type;
434 				TypeSpec found;
435 				if (existing.Count == 1) {
436 					found = existing[0];
437 					if (ts.Arity == found.Arity) {
438 						better_type = IsImportedTypeOverride (module, ts, found);
439 						if (better_type == found)
440 							return;
441 
442 						if (better_type != null) {
443 							existing [0] = better_type;
444 							return;
445 						}
446 					}
447 
448 					existing = new List<TypeSpec> ();
449 					existing.Add (found);
450 					types[name] = existing;
451 				} else {
452 					for (int i = 0; i < existing.Count; ++i) {
453 						found = existing[i];
454 						if (ts.Arity != found.Arity)
455 							continue;
456 
457 						better_type = IsImportedTypeOverride (module, ts, found);
458 						if (better_type == found)
459 							return;
460 
461 						if (better_type != null) {
462 							existing.RemoveAt (i);
463 							--i;
464 							continue;
465 						}
466 					}
467 				}
468 
469 				existing.Add (ts);
470 			} else {
471 				types.Add (name, new TypeSpec[] { ts });
472 			}
473 		}
474 
475 		//
476 		// We import any types but in the situation there are same types
477 		// but one has better visibility (either public or internal with friend)
478 		// the less visible type is removed from the namespace cache
479 		//
IsImportedTypeOverride(ModuleContainer module, TypeSpec ts, TypeSpec found)480 		public static TypeSpec IsImportedTypeOverride (ModuleContainer module, TypeSpec ts, TypeSpec found)
481 		{
482 			var ts_accessible = (ts.Modifiers & Modifiers.PUBLIC) != 0 || ts.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly);
483 			var found_accessible = (found.Modifiers & Modifiers.PUBLIC) != 0 || found.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly);
484 
485 			if (ts_accessible && !found_accessible)
486 				return ts;
487 
488 			// found is better always better for accessible or inaccessible ts
489 			if (!ts_accessible)
490 				return found;
491 
492 			return null;
493 		}
494 
RemoveContainer(TypeContainer tc)495 		public void RemoveContainer (TypeContainer tc)
496 		{
497 			IList<TypeSpec> found;
498 			if (types.TryGetValue (tc.MemberName.Name, out found)) {
499 				for (int i = 0; i < found.Count; ++i) {
500 					if (tc.MemberName.Arity != found [i].Arity)
501 						continue;
502 
503 					if (found.Count == 1)
504 						types.Remove (tc.MemberName.Name);
505 					else
506 						found.RemoveAt (i);
507 
508 					break;
509 				}
510 			}
511 
512 			cached_types.Remove (tc.MemberName.Basename);
513 		}
514 
SetBuiltinType(BuiltinTypeSpec pts)515 		public void SetBuiltinType (BuiltinTypeSpec pts)
516 		{
517 			var found = types[pts.Name];
518 			cached_types.Remove (pts.Name);
519 			if (found.Count == 1) {
520 				types[pts.Name][0] = pts;
521 			} else {
522 				throw new NotImplementedException ();
523 			}
524 		}
525 
VerifyClsCompliance()526 		public void VerifyClsCompliance ()
527 		{
528 			if (types == null || cls_checked)
529 				return;
530 
531 			cls_checked = true;
532 
533 			// TODO: This is quite ugly way to check for CLS compliance at namespace level
534 
535 			var locase_types = new Dictionary<string, List<TypeSpec>> (StringComparer.OrdinalIgnoreCase);
536 			foreach (var tgroup in types.Values) {
537 				foreach (var tm in tgroup) {
538 					if ((tm.Modifiers & Modifiers.PUBLIC) == 0 || !tm.IsCLSCompliant ())
539 						continue;
540 
541 					List<TypeSpec> found;
542 					if (!locase_types.TryGetValue (tm.Name, out found)) {
543 						found = new List<TypeSpec> ();
544 						locase_types.Add (tm.Name, found);
545 					}
546 
547 					found.Add (tm);
548 				}
549 			}
550 
551 			foreach (var locase in locase_types.Values) {
552 				if (locase.Count < 2)
553 					continue;
554 
555 				bool all_same = true;
556 				foreach (var notcompliant in locase) {
557 					all_same = notcompliant.Name == locase[0].Name;
558 					if (!all_same)
559 						break;
560 				}
561 
562 				if (all_same)
563 					continue;
564 
565 				TypeContainer compiled = null;
566 				foreach (var notcompliant in locase) {
567 					if (!notcompliant.MemberDefinition.IsImported) {
568 						if (compiled != null)
569 							compiled.Compiler.Report.SymbolRelatedToPreviousError (compiled);
570 
571 						compiled = notcompliant.MemberDefinition as TypeContainer;
572 					} else {
573 						compiled.Compiler.Report.SymbolRelatedToPreviousError (notcompliant);
574 					}
575 				}
576 
577 				compiled.Compiler.Report.Warning (3005, 1, compiled.Location,
578 					"Identifier `{0}' differing only in case is not CLS-compliant", compiled.GetSignatureForError ());
579 			}
580 		}
581 	}
582 
583 	public class CompilationSourceFile : NamespaceContainer
584 	{
585 		readonly SourceFile file;
586 		CompileUnitEntry comp_unit;
587 		Dictionary<string, SourceFile> include_files;
588 		Dictionary<string, bool> conditionals;
589 
CompilationSourceFile(ModuleContainer parent, SourceFile sourceFile)590 		public CompilationSourceFile (ModuleContainer parent, SourceFile sourceFile)
591 			: this (parent)
592 		{
593 			this.file = sourceFile;
594 		}
595 
CompilationSourceFile(ModuleContainer parent)596 		public CompilationSourceFile (ModuleContainer parent)
597 			: base (parent)
598 		{
599 		}
600 
601 		public CompileUnitEntry SymbolUnitEntry {
602 			get {
603 				return comp_unit;
604 			}
605 		}
606 
607 		public string FileName {
608 			get {
609 				return file.Name;
610 			}
611 		}
612 
613 		public SourceFile SourceFile {
614 			get {
615 				return file;
616 			}
617 		}
618 
AddIncludeFile(SourceFile file)619 		public void AddIncludeFile (SourceFile file)
620 		{
621 			if (file == this.file)
622 				return;
623 
624 			if (include_files == null)
625 				include_files = new Dictionary<string, SourceFile> ();
626 
627 			if (!include_files.ContainsKey (file.OriginalFullPathName))
628 				include_files.Add (file.OriginalFullPathName, file);
629 		}
630 
AddDefine(string value)631 		public void AddDefine (string value)
632 		{
633 			if (conditionals == null)
634 				conditionals = new Dictionary<string, bool> (2);
635 
636 			conditionals[value] = true;
637 		}
638 
AddUndefine(string value)639 		public void AddUndefine (string value)
640 		{
641 			if (conditionals == null)
642 				conditionals = new Dictionary<string, bool> (2);
643 
644 			conditionals[value] = false;
645 		}
646 
PrepareEmit()647 		public override void PrepareEmit ()
648 		{
649 			var sw = Module.DeclaringAssembly.SymbolWriter;
650 			if (sw != null) {
651 				CreateUnitSymbolInfo (sw, Compiler.Settings.PathMap);
652 			}
653 
654 			base.PrepareEmit ();
655 		}
656 
657 		//
658 		// Creates symbol file index in debug symbol file
659 		//
CreateUnitSymbolInfo(MonoSymbolFile symwriter, List<KeyValuePair<string, string>> pathMap)660 		void CreateUnitSymbolInfo (MonoSymbolFile symwriter, List<KeyValuePair<string, string>> pathMap)
661 		{
662 			var si = file.CreateSymbolInfo (symwriter, pathMap);
663 			comp_unit = new CompileUnitEntry (symwriter, si);
664 
665 			if (include_files != null) {
666 				foreach (SourceFile include in include_files.Values) {
667 					si = include.CreateSymbolInfo (symwriter, pathMap);
668 					comp_unit.AddFile (si);
669 				}
670 			}
671 		}
672 
IsConditionalDefined(string value)673 		public bool IsConditionalDefined (string value)
674 		{
675 			if (conditionals != null) {
676 				bool res;
677 				if (conditionals.TryGetValue (value, out res))
678 					return res;
679 
680 				// When conditional was undefined
681 				if (conditionals.ContainsKey (value))
682 					return false;
683 			}
684 
685 			return Compiler.Settings.IsConditionalSymbolDefined (value);
686 		}
687 
Accept(StructuralVisitor visitor)688 		public override void Accept (StructuralVisitor visitor)
689 		{
690 			visitor.Visit (this);
691 		}
692 	}
693 
694 
695 	//
696 	// Namespace block as created by the parser
697 	//
698 	public class NamespaceContainer : TypeContainer, IMemberContext
699 	{
700 		static readonly Namespace[] empty_namespaces = new Namespace[0];
701 
702 		readonly Namespace ns;
703 
704 		public new readonly NamespaceContainer Parent;
705 
706 		List<UsingClause> clauses;
707 
708 		// Used by parsed to check for parser errors
709 		public bool DeclarationFound;
710 
711 		Namespace[] namespace_using_table;
712 		TypeSpec[] types_using_table;
713 		Dictionary<string, UsingAliasNamespace> aliases;
714 
NamespaceContainer(MemberName name, NamespaceContainer parent)715 		public NamespaceContainer (MemberName name, NamespaceContainer parent)
716 			: base (parent, name, null, MemberKind.Namespace)
717 		{
718 			this.Parent = parent;
719 			this.ns = parent.NS.AddNamespace (name);
720 
721 			containers = new List<TypeContainer> ();
722 		}
723 
NamespaceContainer(ModuleContainer parent)724 		protected NamespaceContainer (ModuleContainer parent)
725 			: base (parent, null, null, MemberKind.Namespace)
726 		{
727 			ns = parent.GlobalRootNamespace;
728 			containers = new List<TypeContainer> (2);
729 		}
730 
731 		#region Properties
732 
733 		public override AttributeTargets AttributeTargets {
734 			get {
735 				throw new NotSupportedException ();
736 			}
737 		}
738 
739 		public override string DocCommentHeader {
740 			get {
741 				throw new NotSupportedException ();
742 			}
743 		}
744 
745 		public Namespace NS {
746 			get {
747 				return ns;
748 			}
749 		}
750 
751 		public List<UsingClause> Usings {
752 			get {
753 				return clauses;
754 			}
755 		}
756 
757 		public override string[] ValidAttributeTargets {
758 			get {
759 				throw new NotSupportedException ();
760 			}
761 		}
762 
763 		#endregion
764 
AddUsing(UsingClause un)765 		public void AddUsing (UsingClause un)
766 		{
767 			if (DeclarationFound){
768 				Compiler.Report.Error (1529, un.Location, "A using clause must precede all other namespace elements except extern alias declarations");
769 			}
770 
771 			if (clauses == null)
772 				clauses = new List<UsingClause> ();
773 
774 			clauses.Add (un);
775 		}
776 
AddUsing(UsingAliasNamespace un)777 		public void AddUsing (UsingAliasNamespace un)
778 		{
779 			if (DeclarationFound){
780 				Compiler.Report.Error (1529, un.Location, "A using clause must precede all other namespace elements except extern alias declarations");
781 			}
782 
783 			AddAlias (un);
784 		}
785 
AddAlias(UsingAliasNamespace un)786 		void AddAlias (UsingAliasNamespace un)
787 		{
788 			if (clauses == null) {
789 				clauses = new List<UsingClause> ();
790 			} else {
791 				foreach (var entry in clauses) {
792 					var a = entry as UsingAliasNamespace;
793 					if (a != null && a.Alias.Value == un.Alias.Value) {
794 						Compiler.Report.SymbolRelatedToPreviousError (a.Location, "");
795 						Compiler.Report.Error (1537, un.Location,
796 							"The using alias `{0}' appeared previously in this namespace", un.Alias.Value);
797 					}
798 				}
799 			}
800 
801 			clauses.Add (un);
802 		}
803 
AddPartial(TypeDefinition next_part)804 		public override void AddPartial (TypeDefinition next_part)
805 		{
806 			var existing = ns.LookupType (this, next_part.MemberName.Name, next_part.MemberName.Arity, LookupMode.Probing, Location.Null);
807 			var td = existing != null ? existing.MemberDefinition as TypeDefinition : null;
808 			AddPartial (next_part, td);
809 		}
810 
AddTypeContainer(TypeContainer tc)811 		public override void AddTypeContainer (TypeContainer tc)
812 		{
813 			var mn = tc.MemberName;
814 			var name = mn.Basename;
815 			while (mn.Left != null) {
816 				mn = mn.Left;
817 				name = mn.Name;
818 			}
819 
820 			var names_container = Parent == null ? Module : (TypeContainer) this;
821 
822 			MemberCore mc;
823 			if (names_container.DefinedNames.TryGetValue (name, out mc)) {
824 				if (tc is NamespaceContainer && mc is NamespaceContainer) {
825 					AddTypeContainerMember (tc);
826 					return;
827 				}
828 
829 				Report.SymbolRelatedToPreviousError (mc);
830 				if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (tc is ClassOrStruct || tc is Interface)) {
831 					Error_MissingPartialModifier (tc);
832 				} else {
833 					Report.Error (101, tc.Location, "The namespace `{0}' already contains a definition for `{1}'",
834 						GetSignatureForError (), mn.GetSignatureForError ());
835 				}
836 			} else {
837 				names_container.DefinedNames.Add (name, tc);
838 
839 				var tdef = tc.PartialContainer;
840 				if (tdef != null) {
841 					//
842 					// Same name conflict in different namespace containers
843 					//
844 					var conflict = ns.GetAllTypes (mn.Name);
845 					if (conflict != null) {
846 						foreach (var e in conflict) {
847 							if (e.Arity == mn.Arity) {
848 								mc = (MemberCore) e.MemberDefinition;
849 								break;
850 							}
851 						}
852 					}
853 
854 					if (mc != null) {
855 						Report.SymbolRelatedToPreviousError (mc);
856 						Report.Error (101, tc.Location, "The namespace `{0}' already contains a definition for `{1}'",
857 							GetSignatureForError (), mn.GetSignatureForError ());
858 					} else {
859 						ns.AddType (Module, tdef.Definition);
860 					}
861 				}
862 			}
863 
864 			base.AddTypeContainer (tc);
865 		}
866 
ApplyAttributeBuilder(Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)867 		public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
868 		{
869 			throw new NotSupportedException ();
870 		}
871 
EmitContainer()872 		public override void EmitContainer ()
873 		{
874 			VerifyClsCompliance ();
875 
876 			base.EmitContainer ();
877 		}
878 
LookupExtensionMethod(IMemberContext invocationContext, string name, int arity, int position)879 		public ExtensionMethodCandidates LookupExtensionMethod (IMemberContext invocationContext, string name, int arity, int position)
880 		{
881 			//
882 			// Here we try to resume the search for extension method at the point
883 			// where the last bunch of candidates was found. It's more tricky than
884 			// it seems as we have to check both namespace containers and namespace
885 			// in correct order.
886 			//
887 			// Consider:
888 			//
889 			// namespace A {
890 			//	using N1;
891 			//  namespace B.C.D {
892 			//		<our first search found candidates in A.B.C.D
893 			//  }
894 			// }
895 			//
896 			// In the example above namespace A.B.C.D, A.B.C and A.B have to be
897 			// checked before we hit A.N1 using
898 			//
899 			ExtensionMethodCandidates candidates;
900 			var container = this;
901 			do {
902 				candidates = container.LookupExtensionMethodCandidates (invocationContext, name, arity, ref position);
903 				if (candidates != null || container.MemberName == null)
904 					return candidates;
905 
906 				var container_ns = container.ns.Parent;
907 				var mn = container.MemberName.Left;
908 				int already_checked = position - 2;
909 				while (already_checked-- > 0) {
910 					mn = mn.Left;
911 					container_ns = container_ns.Parent;
912 				}
913 
914 				while (mn != null) {
915 					++position;
916 
917 					var methods = container_ns.LookupExtensionMethod (invocationContext, name, arity);
918 					if (methods != null) {
919 						return new ExtensionMethodCandidates (invocationContext, methods, container, position);
920 					}
921 
922 					mn = mn.Left;
923 					container_ns = container_ns.Parent;
924 				}
925 
926 				position = 0;
927 				container = container.Parent;
928 			} while (container != null);
929 
930 			return null;
931 		}
932 
LookupExtensionMethodCandidates(IMemberContext invocationContext, string name, int arity, ref int position)933 		ExtensionMethodCandidates LookupExtensionMethodCandidates (IMemberContext invocationContext, string name, int arity, ref int position)
934 		{
935 			List<MethodSpec> candidates = null;
936 
937 			if (position == 0) {
938 				++position;
939 
940 				candidates = ns.LookupExtensionMethod (invocationContext, name, arity);
941 				if (candidates != null) {
942 					return new ExtensionMethodCandidates (invocationContext, candidates, this, position);
943 				}
944 			}
945 
946 			if (position == 1) {
947 				++position;
948 
949 				foreach (Namespace n in namespace_using_table) {
950 					var a = n.LookupExtensionMethod (invocationContext, name, arity);
951 					if (a == null)
952 						continue;
953 
954 					if (candidates == null)
955 						candidates = a;
956 					else
957 						candidates.AddRange (a);
958 				}
959 
960 				if (types_using_table != null) {
961 					foreach (var t in types_using_table) {
962 
963 						var res = t.MemberCache.FindExtensionMethods (invocationContext, name, arity);
964 						if (res == null)
965 							continue;
966 
967 						if (candidates == null)
968 							candidates = res;
969 						else
970 							candidates.AddRange (res);
971 					}
972 				}
973 
974 				if (candidates != null)
975 					return new ExtensionMethodCandidates (invocationContext, candidates, this, position);
976 			}
977 
978 			return null;
979 		}
980 
LookupNamespaceOrType(string name, int arity, LookupMode mode, Location loc)981 		public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
982 		{
983 			//
984 			// Only simple names (no dots) will be looked up with this function
985 			//
986 			FullNamedExpression resolved;
987 			for (NamespaceContainer container = this; container != null; container = container.Parent) {
988 				resolved = container.Lookup (name, arity, mode, loc);
989 				if (resolved != null || container.MemberName == null)
990 					return resolved;
991 
992 				var container_ns = container.ns.Parent;
993 				var mn = container.MemberName.Left;
994 				while (mn != null) {
995 					resolved = container_ns.LookupTypeOrNamespace (this, name, arity, mode, loc);
996 					if (resolved != null)
997 						return resolved;
998 
999 					mn = mn.Left;
1000 					container_ns = container_ns.Parent;
1001 				}
1002 			}
1003 
1004 			return null;
1005 		}
1006 
GetCompletionStartingWith(string prefix, List<string> results)1007 		public override void GetCompletionStartingWith (string prefix, List<string> results)
1008 		{
1009 			if (Usings == null)
1010 				return;
1011 
1012 			foreach (var un in Usings) {
1013 				if (un.Alias != null)
1014 					continue;
1015 
1016 				var name = un.NamespaceExpression.Name;
1017 				if (name.StartsWith (prefix))
1018 					results.Add (name);
1019 			}
1020 
1021 
1022 			IEnumerable<string> all = Enumerable.Empty<string> ();
1023 
1024 			foreach (Namespace using_ns in namespace_using_table) {
1025 				if (prefix.StartsWith (using_ns.Name)) {
1026 					int ld = prefix.LastIndexOf ('.');
1027 					if (ld != -1) {
1028 						string rest = prefix.Substring (ld + 1);
1029 
1030 						all = all.Concat (using_ns.CompletionGetTypesStartingWith (rest));
1031 					}
1032 				}
1033 				all = all.Concat (using_ns.CompletionGetTypesStartingWith (prefix));
1034 			}
1035 
1036 			results.AddRange (all);
1037 
1038 			base.GetCompletionStartingWith (prefix, results);
1039 		}
1040 
1041 
1042 		//
1043 		// Looks-up a alias named @name in this and surrounding namespace declarations
1044 		//
LookupExternAlias(string name)1045 		public FullNamedExpression LookupExternAlias (string name)
1046 		{
1047 			if (aliases == null)
1048 				return null;
1049 
1050 			UsingAliasNamespace uan;
1051 			if (aliases.TryGetValue (name, out uan) && uan is UsingExternAlias)
1052 				return uan.ResolvedExpression;
1053 
1054 			return null;
1055 		}
1056 
1057 		//
1058 		// Looks-up a alias named @name in this and surrounding namespace declarations
1059 		//
LookupNamespaceAlias(string name)1060 		public override FullNamedExpression LookupNamespaceAlias (string name)
1061 		{
1062 			for (NamespaceContainer n = this; n != null; n = n.Parent) {
1063 				if (n.aliases == null)
1064 					continue;
1065 
1066 				UsingAliasNamespace uan;
1067 				if (n.aliases.TryGetValue (name, out uan)) {
1068 					if (uan.ResolvedExpression == null)
1069 						uan.Define (n);
1070 
1071 					return uan.ResolvedExpression;
1072 				}
1073 			}
1074 
1075 			return null;
1076 		}
1077 
Lookup(string name, int arity, LookupMode mode, Location loc)1078 		FullNamedExpression Lookup (string name, int arity, LookupMode mode, Location loc)
1079 		{
1080 			//
1081 			// Check whether it's in the namespace.
1082 			//
1083 			FullNamedExpression fne = ns.LookupTypeOrNamespace (this, name, arity, mode, loc);
1084 
1085 			//
1086 			// Check aliases.
1087 			//
1088 			if (aliases != null && arity == 0) {
1089 				UsingAliasNamespace uan;
1090 				if (aliases.TryGetValue (name, out uan)) {
1091 					if (fne != null && mode != LookupMode.Probing) {
1092 						// TODO: Namespace has broken location
1093 						//Report.SymbolRelatedToPreviousError (fne.Location, null);
1094 						Compiler.Report.SymbolRelatedToPreviousError (uan.Location, null);
1095 						Compiler.Report.Error (576, loc,
1096 							"Namespace `{0}' contains a definition with same name as alias `{1}'",
1097 							GetSignatureForError (), name);
1098 					}
1099 
1100 					if (uan.ResolvedExpression == null)
1101 						uan.Define (this);
1102 
1103 					return uan.ResolvedExpression;
1104 				}
1105 			}
1106 
1107 			if (fne != null)
1108 				return fne;
1109 
1110 			//
1111 			// Lookup can be called before the namespace is defined from different namespace using alias clause
1112 			//
1113 			if (namespace_using_table == null) {
1114 				DoDefineNamespace ();
1115 			}
1116 
1117 			//
1118 			// Check using entries.
1119 			//
1120 			FullNamedExpression match = null;
1121 			foreach (Namespace using_ns in namespace_using_table) {
1122 				//
1123 				// A using directive imports only types contained in the namespace, it
1124 				// does not import any nested namespaces
1125 				//
1126 				var t = using_ns.LookupType (this, name, arity, mode, loc);
1127 				if (t == null)
1128 					continue;
1129 
1130 				fne = new TypeExpression (t, loc);
1131 				if (match == null) {
1132 					match = fne;
1133 					continue;
1134 				}
1135 
1136 				// Prefer types over namespaces
1137 				var texpr_fne = fne as TypeExpr;
1138 				var texpr_match = match as TypeExpr;
1139 				if (texpr_fne != null && texpr_match == null) {
1140 					match = fne;
1141 					continue;
1142 				} else if (texpr_fne == null) {
1143 					continue;
1144 				}
1145 
1146 				// It can be top level accessibility only
1147 				var better = Namespace.IsImportedTypeOverride (Module, texpr_match.Type, texpr_fne.Type);
1148 				if (better == null) {
1149 					if (mode == LookupMode.Normal) {
1150 						Error_AmbiguousReference (name, texpr_match, texpr_fne, loc);
1151 					}
1152 
1153 					return match;
1154 				}
1155 
1156 				if (better == texpr_fne.Type)
1157 					match = texpr_fne;
1158 			}
1159 
1160 			if (types_using_table != null && (mode & LookupMode.IgnoreStaticUsing) == 0) {
1161 				foreach (var using_type in types_using_table) {
1162 					var type = MemberCache.FindNestedType (using_type, name, arity, true);
1163 					if (type == null)
1164 						continue;
1165 
1166 					fne = new TypeExpression (type, loc);
1167 					if (match == null) {
1168 						match = fne;
1169 						continue;
1170 					}
1171 
1172 					if (mode == LookupMode.Normal) {
1173 						Error_AmbiguousReference (name, match, fne, loc);
1174 					}
1175 				}
1176 			}
1177 
1178 			return match;
1179 		}
1180 
Error_AmbiguousReference(string name, FullNamedExpression a, FullNamedExpression b, Location loc)1181 		void Error_AmbiguousReference (string name, FullNamedExpression a, FullNamedExpression b, Location loc)
1182 		{
1183 			var report = Compiler.Report;
1184 			report.SymbolRelatedToPreviousError (a.Type);
1185 			report.SymbolRelatedToPreviousError (b.Type);
1186 			report.Error (104, loc, "`{0}' is an ambiguous reference between `{1}' and `{2}'",
1187 				name, a.GetSignatureForError (), b.GetSignatureForError ());
1188 		}
1189 
LookupStaticUsings(IMemberContext mc, string name, int arity, Location loc)1190 		public static Expression LookupStaticUsings (IMemberContext mc, string name, int arity, Location loc)
1191 		{
1192 			for (var m = mc.CurrentMemberDefinition; m != null; m = m.Parent) {
1193 
1194 				var nc = m as NamespaceContainer;
1195 				if (nc == null)
1196 					continue;
1197 
1198 				List<MemberSpec> candidates = null;
1199 				if (nc.types_using_table != null) {
1200 					foreach (var using_type in nc.types_using_table) {
1201 						var members = MemberCache.FindMembers (using_type, name, true);
1202 						if (members == null)
1203 							continue;
1204 
1205 						foreach (var member in members) {
1206 							if ((member.Kind & MemberKind.NestedMask) != 0) {
1207 								// non-static nested type is included with using static
1208 							} else {
1209 								if ((member.Modifiers & Modifiers.STATIC) == 0)
1210 									continue;
1211 
1212 								if ((member.Modifiers & Modifiers.METHOD_EXTENSION) != 0)
1213 									continue;
1214 							}
1215 
1216 							if (arity > 0 && member.Arity != arity)
1217 								continue;
1218 
1219 							if (candidates == null)
1220 								candidates = new List<MemberSpec> ();
1221 
1222 							candidates.Add (member);
1223 						}
1224 					}
1225 				}
1226 
1227 				if (candidates != null) {
1228 					var expr = Expression.MemberLookupToExpression (mc, candidates, false, null, name, arity, Expression.MemberLookupRestrictions.None, loc);
1229 					if (expr != null)
1230 						return expr;
1231 				}
1232 			}
1233 
1234 			return null;
1235 		}
1236 
DefineNamespace()1237 		protected override void DefineNamespace ()
1238 		{
1239 			if (namespace_using_table == null)
1240 				DoDefineNamespace ();
1241 
1242 			base.DefineNamespace ();
1243 		}
1244 
DoDefineNamespace()1245 		void DoDefineNamespace ()
1246 		{
1247 			namespace_using_table = empty_namespaces;
1248 
1249 			if (clauses != null) {
1250 				List<Namespace> namespaces = null;
1251 				List<TypeSpec> types = null;
1252 
1253 				bool post_process_using_aliases = false;
1254 
1255 				for (int i = 0; i < clauses.Count; ++i) {
1256 					var entry = clauses[i];
1257 
1258 					if (entry.Alias != null) {
1259 						if (aliases == null)
1260 							aliases = new Dictionary<string, UsingAliasNamespace> ();
1261 
1262 						//
1263 						// Aliases are not available when resolving using section
1264 						// except extern aliases
1265 						//
1266 						if (entry is UsingExternAlias) {
1267 							entry.Define (this);
1268 							if (entry.ResolvedExpression != null)
1269 								aliases.Add (entry.Alias.Value, (UsingExternAlias) entry);
1270 
1271 							clauses.RemoveAt (i--);
1272 						} else {
1273 							post_process_using_aliases = true;
1274 						}
1275 
1276 						continue;
1277 					}
1278 
1279 					try {
1280 						entry.Define (this);
1281 					} finally {
1282 						//
1283 						// It's needed for repl only, when using clause cannot be resolved don't hold it in
1284 						// global list which is resolved for every evaluation
1285 						//
1286 						if (entry.ResolvedExpression == null) {
1287 							clauses.RemoveAt (i--);
1288 						}
1289 					}
1290 
1291 					if (entry.ResolvedExpression == null)
1292 						continue;
1293 
1294 					var using_ns = entry.ResolvedExpression as NamespaceExpression;
1295 					if (using_ns == null) {
1296 
1297 						var type = entry.ResolvedExpression.Type;
1298 
1299 						if (types == null)
1300 							types = new List<TypeSpec> ();
1301 
1302 						if (types.Contains (type)) {
1303 							Warning_DuplicateEntry (entry);
1304 						} else {
1305 							types.Add (type);
1306 						}
1307 					} else {
1308 						if (namespaces == null)
1309 							namespaces = new List<Namespace> ();
1310 
1311 						if (namespaces.Contains (using_ns.Namespace)) {
1312 							// Ensure we don't report the warning multiple times in repl
1313 							clauses.RemoveAt (i--);
1314 
1315 							Warning_DuplicateEntry (entry);
1316 						} else {
1317 							namespaces.Add (using_ns.Namespace);
1318 						}
1319 					}
1320 				}
1321 
1322 				namespace_using_table = namespaces == null ? new Namespace [0] : namespaces.ToArray ();
1323 				if (types != null)
1324 					types_using_table = types.ToArray ();
1325 
1326 				if (post_process_using_aliases) {
1327 					for (int i = 0; i < clauses.Count; ++i) {
1328 						var entry = clauses[i];
1329 						if (entry.Alias != null) {
1330 							aliases[entry.Alias.Value] = (UsingAliasNamespace) entry;
1331 						}
1332 					}
1333 				}
1334 			}
1335 		}
1336 
DoDefineContainer()1337 		protected override void DoDefineContainer ()
1338 		{
1339 			base.DoDefineContainer ();
1340 
1341 			if (clauses != null) {
1342 				for (int i = 0; i < clauses.Count; ++i) {
1343 					var entry = clauses[i];
1344 
1345 					//
1346 					// Finish definition of using aliases not visited during container
1347 					// definition
1348 					//
1349 					if (entry.Alias != null && entry.ResolvedExpression == null) {
1350 						entry.Define (this);
1351 					}
1352 				}
1353 			}
1354 		}
1355 
EnableRedefinition()1356 		public void EnableRedefinition ()
1357 		{
1358 			is_defined = false;
1359 			namespace_using_table = null;
1360 		}
1361 
GenerateDocComment(DocumentationBuilder builder)1362 		internal override void GenerateDocComment (DocumentationBuilder builder)
1363 		{
1364 			if (containers != null) {
1365 				foreach (var tc in containers)
1366 					tc.GenerateDocComment (builder);
1367 			}
1368 		}
1369 
GetSignatureForError()1370 		public override string GetSignatureForError ()
1371 		{
1372 			return MemberName == null ? "global::" : base.GetSignatureForError ();
1373 		}
1374 
RemoveContainer(TypeContainer cont)1375 		public override void RemoveContainer (TypeContainer cont)
1376 		{
1377 			base.RemoveContainer (cont);
1378 			NS.RemoveContainer (cont);
1379 		}
1380 
VerifyClsCompliance()1381 		protected override bool VerifyClsCompliance ()
1382 		{
1383 			if (Module.IsClsComplianceRequired ()) {
1384 				if (MemberName != null && MemberName.Name[0] == '_') {
1385 					Warning_IdentifierNotCompliant ();
1386 				}
1387 
1388 				ns.VerifyClsCompliance ();
1389 				return true;
1390 			}
1391 
1392 			return false;
1393 		}
1394 
Warning_DuplicateEntry(UsingClause entry)1395 		void Warning_DuplicateEntry (UsingClause entry)
1396 		{
1397 			Compiler.Report.Warning (105, 3, entry.Location,
1398 				"The using directive for `{0}' appeared previously in this namespace",
1399 				entry.ResolvedExpression.GetSignatureForError ());
1400 		}
1401 
Accept(StructuralVisitor visitor)1402 		public override void Accept (StructuralVisitor visitor)
1403 		{
1404 			visitor.Visit (this);
1405 		}
1406 	}
1407 
1408 	public class UsingNamespace : UsingClause
1409 	{
UsingNamespace(ATypeNameExpression expr, Location loc)1410 		public UsingNamespace (ATypeNameExpression expr, Location loc)
1411 			: base (expr, loc)
1412 		{
1413 		}
1414 
Define(NamespaceContainer ctx)1415 		public override void Define (NamespaceContainer ctx)
1416 		{
1417 			base.Define (ctx);
1418 
1419 			var ns = resolved as NamespaceExpression;
1420 			if (ns != null)
1421 				return;
1422 
1423 			if (resolved != null) {
1424 				var compiler = ctx.Module.Compiler;
1425 				var type = resolved.Type;
1426 				resolved = null;
1427 
1428 				compiler.Report.SymbolRelatedToPreviousError (type);
1429 				compiler.Report.Error (138, Location,
1430 					"A `using' directive can only be applied to namespaces but `{0}' denotes a type. Consider using a `using static' instead",
1431 					type.GetSignatureForError ());
1432 			}
1433 		}
1434 	}
1435 
1436 	public class UsingType : UsingClause
1437 	{
UsingType(ATypeNameExpression expr, Location loc)1438 		public UsingType (ATypeNameExpression expr, Location loc)
1439 			: base (expr, loc)
1440 		{
1441 		}
1442 
Define(NamespaceContainer ctx)1443 		public override void Define (NamespaceContainer ctx)
1444 		{
1445 			base.Define (ctx);
1446 
1447 			if (resolved == null)
1448 				return;
1449 
1450 			var ns = resolved as NamespaceExpression;
1451 			if (ns != null) {
1452 				var compiler = ctx.Module.Compiler;
1453 				compiler.Report.Error (7007, Location,
1454 					"A 'using static' directive can only be applied to types but `{0}' denotes a namespace. Consider using a `using' directive instead",
1455 					ns.GetSignatureForError ());
1456 				return;
1457 			}
1458 
1459 			// TODO: Need to move it to post_process_using_aliases
1460 			//ObsoleteAttribute obsolete_attr = resolved.Type.GetAttributeObsolete ();
1461 			//if (obsolete_attr != null) {
1462 			//	AttributeTester.Report_ObsoleteMessage (obsolete_attr, resolved.GetSignatureForError (), Location, ctx.Compiler.Report);
1463 			//}
1464 		}
1465 	}
1466 
1467 	public class UsingClause
1468 	{
1469 		readonly ATypeNameExpression expr;
1470 		readonly Location loc;
1471 		protected FullNamedExpression resolved;
1472 
UsingClause(ATypeNameExpression expr, Location loc)1473 		public UsingClause (ATypeNameExpression expr, Location loc)
1474 		{
1475 			this.expr = expr;
1476 			this.loc = loc;
1477 		}
1478 
1479 		#region Properties
1480 
1481 		public virtual SimpleMemberName Alias {
1482 			get {
1483 				return null;
1484 			}
1485 		}
1486 
1487 		public Location Location {
1488 			get {
1489 				return loc;
1490 			}
1491 		}
1492 
1493 		public ATypeNameExpression NamespaceExpression	{
1494 			get {
1495 				return expr;
1496 			}
1497 		}
1498 
1499 		public FullNamedExpression ResolvedExpression {
1500 			get {
1501 				return resolved;
1502 			}
1503 		}
1504 
1505 		#endregion
1506 
GetSignatureForError()1507 		public string GetSignatureForError ()
1508 		{
1509 			return expr.GetSignatureForError ();
1510 		}
1511 
Define(NamespaceContainer ctx)1512 		public virtual void Define (NamespaceContainer ctx)
1513 		{
1514 			resolved = expr.ResolveAsTypeOrNamespace (ctx, false);
1515 		}
1516 
ToString()1517 		public override string ToString()
1518 		{
1519 			return resolved.ToString();
1520 		}
1521 	}
1522 
1523 	public class UsingExternAlias : UsingAliasNamespace
1524 	{
UsingExternAlias(SimpleMemberName alias, Location loc)1525 		public UsingExternAlias (SimpleMemberName alias, Location loc)
1526 			: base (alias, null, loc)
1527 		{
1528 		}
1529 
Define(NamespaceContainer ctx)1530 		public override void Define (NamespaceContainer ctx)
1531 		{
1532 			var ns = ctx.Module.GetRootNamespace (Alias.Value);
1533 			if (ns == null) {
1534 				ctx.Module.Compiler.Report.Error (430, Location,
1535 					"The extern alias `{0}' was not specified in -reference option",
1536 					Alias.Value);
1537 				return;
1538 			}
1539 
1540 			resolved = new NamespaceExpression (ns, Location);
1541 		}
1542 	}
1543 
1544 	public class UsingAliasNamespace : UsingNamespace
1545 	{
1546 		readonly SimpleMemberName alias;
1547 
1548 		public struct AliasContext : IMemberContext
1549 		{
1550 			readonly NamespaceContainer ns;
1551 
AliasContextMono.CSharp.UsingAliasNamespace.AliasContext1552 			public AliasContext (NamespaceContainer ns)
1553 			{
1554 				this.ns = ns;
1555 			}
1556 
1557 			public TypeSpec CurrentType {
1558 				get {
1559 					return null;
1560 				}
1561 			}
1562 
1563 			public TypeParameters CurrentTypeParameters {
1564 				get {
1565 					return null;
1566 				}
1567 			}
1568 
1569 			public MemberCore CurrentMemberDefinition {
1570 				get {
1571 					return null;
1572 				}
1573 			}
1574 
1575 			public bool IsObsolete {
1576 				get {
1577 					return false;
1578 				}
1579 			}
1580 
1581 			public bool IsUnsafe {
1582 				get {
1583 					throw new NotImplementedException ();
1584 				}
1585 			}
1586 
1587 			public bool IsStatic {
1588 				get {
1589 					throw new NotImplementedException ();
1590 				}
1591 			}
1592 
1593 			public ModuleContainer Module {
1594 				get {
1595 					return ns.Module;
1596 				}
1597 			}
1598 
GetSignatureForErrorMono.CSharp.UsingAliasNamespace.AliasContext1599 			public string GetSignatureForError ()
1600 			{
1601 				throw new NotImplementedException ();
1602 			}
1603 
LookupExtensionMethodMono.CSharp.UsingAliasNamespace.AliasContext1604 			public ExtensionMethodCandidates LookupExtensionMethod (string name, int arity)
1605 			{
1606 				return null;
1607 			}
1608 
LookupNamespaceOrTypeMono.CSharp.UsingAliasNamespace.AliasContext1609 			public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
1610 			{
1611 				var fne = ns.NS.LookupTypeOrNamespace (ns, name, arity, mode, loc);
1612 				if (fne != null)
1613 					return fne;
1614 
1615 				//
1616 				// Only extern aliases are allowed in this context
1617 				//
1618 				fne = ns.LookupExternAlias (name);
1619 				if (fne != null || ns.MemberName == null)
1620 					return fne;
1621 
1622 				var container_ns = ns.NS.Parent;
1623 				var mn = ns.MemberName.Left;
1624 				while (mn != null) {
1625 					fne = container_ns.LookupTypeOrNamespace (this, name, arity, mode, loc);
1626 					if (fne != null)
1627 						return fne;
1628 
1629 					mn = mn.Left;
1630 					container_ns = container_ns.Parent;
1631 				}
1632 
1633 				if (ns.Parent != null)
1634 					return ns.Parent.LookupNamespaceOrType (name, arity, mode, loc);
1635 
1636 				return null;
1637 			}
1638 
LookupNamespaceAliasMono.CSharp.UsingAliasNamespace.AliasContext1639 			public FullNamedExpression LookupNamespaceAlias (string name)
1640 			{
1641 				return ns.LookupNamespaceAlias (name);
1642 			}
1643 		}
1644 
UsingAliasNamespace(SimpleMemberName alias, ATypeNameExpression expr, Location loc)1645 		public UsingAliasNamespace (SimpleMemberName alias, ATypeNameExpression expr, Location loc)
1646 			: base (expr, loc)
1647 		{
1648 			this.alias = alias;
1649 		}
1650 
1651 		public override SimpleMemberName Alias {
1652 			get {
1653 				return alias;
1654 			}
1655 		}
1656 
Define(NamespaceContainer ctx)1657 		public override void Define (NamespaceContainer ctx)
1658 		{
1659 			//
1660 			// The namespace-or-type-name of a using-alias-directive is resolved as if
1661 			// the immediately containing compilation unit or namespace body had no
1662 			// using-directives. A using-alias-directive may however be affected
1663 			// by extern-alias-directives in the immediately containing compilation
1664 			// unit or namespace body
1665 			//
1666 			// We achieve that by introducing alias-context which redirect any local
1667 			// namespace or type resolve calls to parent namespace
1668 			//
1669 			resolved = NamespaceExpression.ResolveAsTypeOrNamespace (new AliasContext (ctx), false) ??
1670 				new TypeExpression (InternalType.ErrorType, NamespaceExpression.Location);
1671 		}
1672 	}
1673 }
1674