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