5384ee1368607a30ea61290b5f19610aa15349e0
[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                                 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
88                 public void RegisterNamespace (Namespace child)
89                 {
90                         if (child != this)
91                                 all_namespaces.Add (child.Name, child);
92                 }
93
94                 public override string GetSignatureForError ()
95                 {
96                         return alias_name + "::";
97                 }
98         }
99
100         public sealed class GlobalRootNamespace : RootNamespace
101         {
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>
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
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
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
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
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
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
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
234                 public virtual string GetSignatureForError ()
235                 {
236                         return fullname;
237                 }
238
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
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                 //
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                 //
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
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                 //
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
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
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
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
590                 public CompilationSourceFile (ModuleContainer parent, SourceFile sourceFile)
591                         : this (parent)
592                 {
593                         this.file = sourceFile;
594                 }
595
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
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
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
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
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                 //
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
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
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
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
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
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
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
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
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
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
867                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
868                 {
869                         throw new NotSupportedException ();
870                 }
871
872                 public override void EmitContainer ()
873                 {
874                         VerifyClsCompliance ();
875
876                         base.EmitContainer ();
877                 }
878
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
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
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
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                 //
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                 //
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
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) {
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
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
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
1237                 protected override void DefineNamespace ()
1238                 {
1239                         if (namespace_using_table == null)
1240                                 DoDefineNamespace ();
1241
1242                         base.DefineNamespace ();
1243                 }
1244
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
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
1356                 public void EnableRedefinition ()
1357                 {
1358                         is_defined = false;
1359                         namespace_using_table = null;
1360                 }
1361
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
1370                 public override string GetSignatureForError ()
1371                 {
1372                         return MemberName == null ? "global::" : base.GetSignatureForError ();
1373                 }
1374
1375                 public override void RemoveContainer (TypeContainer cont)
1376                 {
1377                         base.RemoveContainer (cont);
1378                         NS.RemoveContainer (cont);
1379                 }
1380
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
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
1402                 public override void Accept (StructuralVisitor visitor)
1403                 {
1404                         visitor.Visit (this);
1405                 }
1406         }
1407
1408         public class UsingNamespace : UsingClause
1409         {
1410                 public UsingNamespace (ATypeNameExpression expr, Location loc)
1411                         : base (expr, loc)
1412                 {
1413                 }
1414
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         {
1438                 public UsingType (ATypeNameExpression expr, Location loc)
1439                         : base (expr, loc)
1440                 {
1441                 }
1442
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
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
1507                 public string GetSignatureForError ()
1508                 {
1509                         return expr.GetSignatureForError ();
1510                 }
1511
1512                 public virtual void Define (NamespaceContainer ctx)
1513                 {
1514                         resolved = expr.ResolveAsTypeOrNamespace (ctx, false);
1515                 }
1516
1517                 public override string ToString()
1518                 {
1519                         return resolved.ToString();
1520                 }
1521         }
1522
1523         public class UsingExternAlias : UsingAliasNamespace
1524         {
1525                 public UsingExternAlias (SimpleMemberName alias, Location loc)
1526                         : base (alias, null, loc)
1527                 {
1528                 }
1529
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
1552                         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
1599                         public string GetSignatureForError ()
1600                         {
1601                                 throw new NotImplementedException ();
1602                         }
1603
1604                         public ExtensionMethodCandidates LookupExtensionMethod (string name, int arity)
1605                         {
1606                                 return null;
1607                         }
1608
1609                         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
1639                         public FullNamedExpression LookupNamespaceAlias (string name)
1640                         {
1641                                 return ns.LookupNamespaceAlias (name);
1642                         }
1643                 }
1644
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
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 }