2006-05-06 Marek Safar <marek.safar@seznam.cz>
[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 // (C) 2001 Ximian, Inc.
9 //
10 using System;
11 using System.Collections;
12 using System.Collections.Specialized;
13 using System.Reflection;
14
15 namespace Mono.CSharp {
16
17         public class RootNamespace : Namespace {
18                 static MethodInfo get_namespaces_method;
19
20                 string alias_name;
21                 Assembly referenced_assembly;
22
23                 Hashtable all_namespaces;
24
25                 static Hashtable root_namespaces;
26                 public static GlobalRootNamespace Global;
27                 
28                 static RootNamespace ()
29                 {
30                         get_namespaces_method = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance | BindingFlags.NonPublic);
31
32                         Reset ();
33                 }
34
35                 public static void Reset ()
36                 {
37                         root_namespaces = new Hashtable ();
38                         Global = new GlobalRootNamespace ();
39                         root_namespaces ["global"] = Global;
40                 }
41
42                 protected RootNamespace (string alias_name, Assembly assembly)
43                         : base (null, String.Empty)
44                 {
45                         this.alias_name = alias_name;
46                         referenced_assembly = assembly;
47
48                         all_namespaces = new Hashtable ();
49                         all_namespaces.Add ("", this);
50
51                         if (referenced_assembly != null)
52                                 ComputeNamespaces (this.referenced_assembly);
53                 }
54
55                 public static void DefineRootNamespace (string name, Assembly assembly)
56                 {
57                         if (name == "global") {
58                                 // FIXME: Add proper error number
59                                 Report.Error (-42, "Cannot define an external alias named `global'");
60                                 return;
61                         }
62                         RootNamespace retval = GetRootNamespace (name);
63                         if (retval == null || retval.referenced_assembly != assembly)
64                                 root_namespaces [name] = new RootNamespace (name, assembly);
65                 }
66
67                 public static RootNamespace GetRootNamespace (string name)
68                 {
69                         return (RootNamespace) root_namespaces [name];
70                 }
71
72                 public virtual Type LookupTypeReflection (string name, Location loc)
73                 {
74                         return GetTypeInAssembly (referenced_assembly, name);
75                 }
76
77                 public void RegisterNamespace (Namespace child)
78                 {
79                         if (child != this)
80                                 all_namespaces.Add (child.Name, child);
81                 }
82
83                 public bool IsNamespace (string name)
84                 {
85                         return all_namespaces.Contains (name);
86                 }
87
88                 protected void EnsureNamespace (string dotted_name)
89                 {
90                         if (dotted_name != null && dotted_name.Length != 0 && ! IsNamespace (dotted_name))
91                                 GetNamespace (dotted_name, true);
92                 }
93
94                 protected void ComputeNamespaces (Assembly assembly)
95                 {
96                         if (get_namespaces_method != null) {
97                                 string [] namespaces = (string []) get_namespaces_method.Invoke (assembly, null);
98                                 foreach (string ns in namespaces)
99                                         EnsureNamespace (ns);
100                                 return;
101                         }
102
103                         foreach (Type t in assembly.GetExportedTypes ())
104                                 EnsureNamespace (t.Namespace);
105                 }
106                 
107                 protected static Type GetTypeInAssembly (Assembly assembly, string name)
108                 {
109                         Type t = assembly.GetType (name);
110                         if (t == null)
111                                 return null;
112
113                         if (t.IsPointer)
114                                 throw new InternalErrorException ("Use GetPointerType() to get a pointer");
115                         
116                         TypeAttributes ta = t.Attributes & TypeAttributes.VisibilityMask;
117                         if (ta == TypeAttributes.NotPublic ||
118                             ta == TypeAttributes.NestedPrivate ||
119                             ta == TypeAttributes.NestedAssembly ||
120                             ta == TypeAttributes.NestedFamANDAssem)
121                                 return null;
122
123                         return t;
124                 }
125
126                 public override string ToString ()
127                 {
128                         return String.Format ("RootNamespace ({0}::)", alias_name);
129                 }
130
131                 public override string GetSignatureForError ()
132                 {
133                         return alias_name + "::";
134                 }
135         }
136
137         public class GlobalRootNamespace : RootNamespace {
138                 Assembly [] assemblies;
139                 Module [] modules;
140
141                 public GlobalRootNamespace ()
142                         : base ("global", null)
143                 {
144                         assemblies = new Assembly [0];
145                 }
146
147                 public Assembly [] Assemblies {
148                         get { return assemblies; }
149                 }
150
151                 public Module [] Modules {
152                         get { return modules; }
153                 }
154
155                 public void AddAssemblyReference (Assembly a)
156                 {
157                         foreach (Assembly assembly in assemblies) {
158                                 if (a == assembly)
159                                         return;
160                         }
161
162                         int top = assemblies.Length;
163                         Assembly [] n = new Assembly [top + 1];
164                         assemblies.CopyTo (n, 0);
165                         n [top] = a;
166                         assemblies = n;
167
168                         ComputeNamespaces (a);
169                 }
170
171                 public void AddModuleReference (Module m)
172                 {
173                         int top = modules != null ? modules.Length : 0;
174                         Module [] n = new Module [top + 1];
175                         if (modules != null)
176                                 modules.CopyTo (n, 0);
177                         n [top] = m;
178                         modules = n;
179
180                         if (m == CodeGen.Module.Builder)
181                                 return;
182
183                         foreach (Type t in m.GetTypes ())
184                                 EnsureNamespace (t.Namespace);
185                 }
186
187                 public override Type LookupTypeReflection (string name, Location loc)
188                 {
189                         Type found_type = null;
190                 
191                         foreach (Assembly a in assemblies) {
192                                 Type t = GetTypeInAssembly (a, name);
193                                 if (t == null)
194                                         continue;
195                                         
196                                 if (found_type == null) {
197                                         found_type = t;
198                                         continue;
199                                 }
200
201                                 Report.SymbolRelatedToPreviousError (found_type);
202                                 Report.SymbolRelatedToPreviousError (t);
203                                 Report.Error (433, loc, "The imported type `{0}' is defined multiple times", name);
204                                         
205                                 return found_type;
206                         }
207
208                         if (modules != null) {
209                                 foreach (Module module in modules) {
210                                         Type t = module.GetType (name);
211                                         if (t == null)
212                                                 continue;
213
214                                         if (found_type == null) {
215                                                 found_type = t;
216                                                 continue;
217                                         }
218                                         
219                                         Report.SymbolRelatedToPreviousError (t);
220                                         Report.SymbolRelatedToPreviousError (found_type);
221                                         Report.Warning (436, 2, loc, "Ignoring imported type `{0}' since the current assembly already has a declaration with the same name",
222                                                 TypeManager.CSharpName (t));
223                                         return t;
224                                 }
225                         }
226
227                         return found_type;
228                 }
229         }
230
231         /// <summary>
232         ///   Keeps track of the namespaces defined in the C# code.
233         ///
234         ///   This is an Expression to allow it to be referenced in the
235         ///   compiler parse/intermediate tree during name resolution.
236         /// </summary>
237         public class Namespace : FullNamedExpression {
238                 
239                 Namespace parent;
240                 string fullname;
241                 Hashtable namespaces;
242                 IDictionary declspaces;
243                 Hashtable cached_types;
244                 RootNamespace root;
245
246                 public readonly MemberName MemberName;
247
248                 /// <summary>
249                 ///   Constructor Takes the current namespace and the
250                 ///   name.  This is bootstrapped with parent == null
251                 ///   and name = ""
252                 /// </summary>
253                 public Namespace (Namespace parent, string name)
254                 {
255                         // Expression members.
256                         this.eclass = ExprClass.Namespace;
257                         this.Type = null;
258                         this.loc = Location.Null;
259
260                         this.parent = parent;
261
262                         if (parent != null)
263                                 this.root = parent.root;
264                         else
265                                 this.root = this as RootNamespace;
266
267                         if (this.root == null)
268                                 throw new InternalErrorException ("Root namespaces must be created using RootNamespace");
269                         
270                         string pname = parent != null ? parent.Name : "";
271                                 
272                         if (pname == "")
273                                 fullname = name;
274                         else
275                                 fullname = parent.Name + "." + name;
276
277                         if (fullname == null)
278                                 throw new InternalErrorException ("Namespace has a null fullname");
279
280                         if (parent != null && parent.MemberName != MemberName.Null)
281                                 MemberName = new MemberName (parent.MemberName, name);
282                         else if (name.Length == 0)
283                                 MemberName = MemberName.Null;
284                         else
285                                 MemberName = new MemberName (name);
286
287                         namespaces = new Hashtable ();
288                         cached_types = new Hashtable ();
289
290                         root.RegisterNamespace (this);
291                 }
292
293                 public override Expression DoResolve (EmitContext ec)
294                 {
295                         return this;
296                 }
297
298                 public override void Emit (EmitContext ec)
299                 {
300                         throw new InternalErrorException ("Expression tree referenced namespace " + fullname + " during Emit ()");
301                 }
302
303                 public override string GetSignatureForError ()
304                 {
305                         return Name;
306                 }
307                 
308                 public Namespace GetNamespace (string name, bool create)
309                 {
310                         int pos = name.IndexOf ('.');
311
312                         Namespace ns;
313                         string first;
314                         if (pos >= 0)
315                                 first = name.Substring (0, pos);
316                         else
317                                 first = name;
318
319                         ns = (Namespace) namespaces [first];
320                         if (ns == null) {
321                                 if (!create)
322                                         return null;
323
324                                 ns = new Namespace (this, first);
325                                 namespaces.Add (first, ns);
326                         }
327
328                         if (pos >= 0)
329                                 ns = ns.GetNamespace (name.Substring (pos + 1), create);
330
331                         return ns;
332                 }
333
334                 TypeExpr LookupType (string name, Location loc)
335                 {
336                         if (cached_types.Contains (name))
337                                 return cached_types [name] as TypeExpr;
338
339                         Type t = null;
340                         if (declspaces != null) {
341                                 DeclSpace tdecl = declspaces [name] as DeclSpace;
342                                 if (tdecl != null) {
343                                         //
344                                         // Note that this is not:
345                                         //
346                                         //   t = tdecl.DefineType ()
347                                         //
348                                         // This is to make it somewhat more useful when a DefineType
349                                         // fails due to problems in nested types (more useful in the sense
350                                         // of fewer misleading error messages)
351                                         //
352                                         tdecl.DefineType ();
353                                         t = tdecl.TypeBuilder;
354                                 }
355                         }
356                         string lookup = t != null ? t.FullName : (fullname.Length == 0 ? name : fullname + "." + name);
357                         Type rt = root.LookupTypeReflection (lookup, loc);
358                         if (t == null)
359                                 t = rt;
360
361                         TypeExpr te = t == null ? null : new TypeExpression (t, Location.Null);
362                         cached_types [name] = te;
363                         return te;
364                 }
365
366                 public FullNamedExpression Lookup (DeclSpace ds, string name, Location loc)
367                 {
368                         if (namespaces.Contains (name))
369                                 return (Namespace) namespaces [name];
370
371                         TypeExpr te = LookupType (name, loc);
372                         if (te == null || !ds.CheckAccessLevel (te.Type))
373                                 return null;
374
375                         return te;
376                 }
377
378                 public void AddDeclSpace (string name, DeclSpace ds)
379                 {
380                         if (declspaces == null)
381                                 declspaces = new HybridDictionary ();
382                         declspaces.Add (name, ds);
383                 }
384
385                 /// <summary>
386                 ///   The qualified name of the current namespace
387                 /// </summary>
388                 public string Name {
389                         get { return fullname; }
390                 }
391
392                 public override string FullName {
393                         get { return fullname; }
394                 }
395
396                 /// <summary>
397                 ///   The parent of this namespace, used by the parser to "Pop"
398                 ///   the current namespace declaration
399                 /// </summary>
400                 public Namespace Parent {
401                         get { return parent; }
402                 }
403
404                 public override string ToString ()
405                 {
406                         return String.Format ("Namespace ({0})", Name);
407                 }
408         }
409
410         public class NamespaceEntry {
411                 Namespace ns;
412                 NamespaceEntry parent, implicit_parent;
413                 SourceFile file;
414                 int symfile_id;
415                 Hashtable aliases;
416                 ArrayList using_clauses;
417                 public bool DeclarationFound = false;
418                 bool UsingFound;
419
420                 ListDictionary extern_aliases;
421
422                 static ArrayList entries = new ArrayList ();
423
424                 public static void Reset ()
425                 {
426                         entries = new ArrayList ();
427                 }
428
429                 //
430                 // This class holds the location where a using definition is
431                 // done, and whether it has been used by the program or not.
432                 //
433                 // We use this to flag using clauses for namespaces that do not
434                 // exist.
435                 //
436                 public class UsingEntry {
437                         public readonly MemberName Name;
438                         readonly Expression Expr;
439                         readonly NamespaceEntry NamespaceEntry;
440                         readonly Location Location;
441                         
442                         public UsingEntry (NamespaceEntry entry, MemberName name, Location loc)
443                         {
444                                 Name = name;
445                                 Expr = name.GetTypeExpression ();
446                                 NamespaceEntry = entry;
447                                 Location = loc;
448                         }
449
450                         internal Namespace resolved;
451
452                         public Namespace Resolve ()
453                         {
454                                 if (resolved != null)
455                                         return resolved;
456
457                                 DeclSpace root = RootContext.Tree.Types;
458                                 root.NamespaceEntry = NamespaceEntry;
459                                 FullNamedExpression fne = Expr.ResolveAsTypeStep (root, false);
460                                 root.NamespaceEntry = null;
461
462                                 if (fne == null) {
463                                         Error_NamespaceNotFound (Location, Name.ToString ());
464                                         return null;
465                                 }
466
467                                 resolved = fne as Namespace;
468                                 if (resolved == null) {
469                                         Report.Error (138, Location,
470                                                 "`{0} is a type not a namespace. A using namespace directive can only be applied to namespaces", Name.ToString ());
471                                 }
472                                 return resolved;
473                         }
474                 }
475
476                 public abstract class AliasEntry {
477                         public readonly string Name;
478                         public readonly NamespaceEntry NamespaceEntry;
479                         public readonly Location Location;
480                         
481                         protected AliasEntry (NamespaceEntry entry, string name, Location loc)
482                         {
483                                 Name = name;
484                                 NamespaceEntry = entry;
485                                 Location = loc;
486                         }
487                         
488                         protected FullNamedExpression resolved;
489                         bool error;
490
491                         public FullNamedExpression Resolve ()
492                         {
493                                 if (resolved != null || error)
494                                         return resolved;
495                                 resolved = DoResolve ();
496                                 if (resolved == null)
497                                         error = true;
498                                 return resolved;
499                         }
500
501                         protected abstract FullNamedExpression DoResolve ();
502                 }
503
504                 public class LocalAliasEntry : AliasEntry
505                 {
506                         public readonly Expression Alias;
507                         
508                         public LocalAliasEntry (NamespaceEntry entry, string name, MemberName alias, Location loc) :
509                                 base (entry, name, loc)
510                         {
511                                 Alias = alias.GetTypeExpression ();
512                         }
513
514                         protected override FullNamedExpression DoResolve ()
515                         {
516                                 DeclSpace root = RootContext.Tree.Types;
517                                 root.NamespaceEntry = NamespaceEntry;
518                                 resolved = Alias.ResolveAsTypeStep (root, false);
519                                 root.NamespaceEntry = null;
520
521                                 if (resolved == null)
522                                         return null;
523
524                                 if (resolved.Type != null) {
525                                         TypeAttributes attr = resolved.Type.Attributes & TypeAttributes.VisibilityMask;
526                                         if (attr == TypeAttributes.NestedPrivate || attr == TypeAttributes.NestedFamily ||
527                                                 ((attr == TypeAttributes.NestedFamORAssem || attr == TypeAttributes.NestedAssembly) && 
528                                                 TypeManager.LookupDeclSpace (resolved.Type) == null)) {
529                                                 Expression.ErrorIsInaccesible (Alias.Location, Alias.ToString ());
530                                                 return null;
531                                         }
532                                 }
533
534                                 return resolved;
535                         }
536                 }
537
538                 public class ExternAliasEntry : AliasEntry 
539                 {
540                         public ExternAliasEntry (NamespaceEntry entry, string name, Location loc) :
541                                 base (entry, name, loc)
542                         {
543                         }
544
545                         protected override FullNamedExpression DoResolve ()
546                         {
547                                 resolved = RootNamespace.GetRootNamespace (Name);
548                                 if (resolved == null)
549                                         Report.Error (430, Location, "The extern alias '" + Name +
550                                                                         "' was not specified in a /reference option");
551
552                                 return resolved;
553                         }
554                 }
555
556                 public NamespaceEntry (NamespaceEntry parent, SourceFile file, string name)
557                 {
558                         this.parent = parent;
559                         this.file = file;
560                         entries.Add (this);
561                         this.ID = entries.Count;
562
563                         if (parent != null)
564                                 ns = parent.NS.GetNamespace (name, true);
565                         else if (name != null)
566                                 ns = RootNamespace.Global.GetNamespace (name, true);
567                         else
568                                 ns = RootNamespace.Global;
569                 }
570
571                 private NamespaceEntry (NamespaceEntry parent, SourceFile file, Namespace ns)
572                 {
573                         this.parent = parent;
574                         this.file = file;
575                         // no need to add self to 'entries', since we don't have any aliases or using entries.
576                         this.ID = -1;
577                         this.IsImplicit = true;
578                         this.ns = ns;
579                 }
580
581                 //
582                 // According to section 16.3.1 (using-alias-directive), the namespace-or-type-name is
583                 // resolved as if the immediately containing namespace body has no using-directives.
584                 //
585                 // Section 16.3.2 says that the same rule is applied when resolving the namespace-name
586                 // in the using-namespace-directive.
587                 //
588                 // To implement these rules, the expressions in the using directives are resolved using 
589                 // the "doppelganger" (ghostly bodiless duplicate).
590                 //
591                 NamespaceEntry doppelganger;
592                 NamespaceEntry Doppelganger {
593                         get {
594                                 if (!IsImplicit && doppelganger == null)
595                                         doppelganger = new NamespaceEntry (ImplicitParent, file, ns);
596                                 return doppelganger;
597                         }
598                 }
599
600                 public readonly int ID;
601                 public readonly bool IsImplicit;
602
603                 public Namespace NS {
604                         get { return ns; }
605                 }
606
607                 public NamespaceEntry Parent {
608                         get { return parent; }
609                 }
610
611                 public NamespaceEntry ImplicitParent {
612                         get {
613                                 if (parent == null)
614                                         return null;
615                                 if (implicit_parent == null) {
616                                         implicit_parent = (parent.NS == ns.Parent)
617                                                 ? parent
618                                                 : new NamespaceEntry (parent, file, ns.Parent);
619                                 }
620                                 return implicit_parent;
621                         }
622                 }
623
624                 /// <summary>
625                 ///   Records a new namespace for resolving name references
626                 /// </summary>
627                 public void Using (MemberName name, Location loc)
628                 {
629                         if (DeclarationFound){
630                                 Report.Error (1529, loc, "A using clause must precede all other namespace elements except extern alias declarations");
631                                 return;
632                         }
633
634                         UsingFound = true;
635
636                         if (name.Equals (ns.MemberName))
637                                 return;
638                         
639                         if (using_clauses == null)
640                                 using_clauses = new ArrayList ();
641
642                         foreach (UsingEntry old_entry in using_clauses) {
643                                 if (name.Equals (old_entry.Name)) {
644                                         Report.Warning (105, 3, loc, "The using directive for `{0}' appeared previously in this namespace", name.GetName ());
645                                         return;
646                                 }
647                         }
648
649                         UsingEntry ue = new UsingEntry (Doppelganger, name, loc);
650                         using_clauses.Add (ue);
651                 }
652
653                 public void UsingAlias (string name, MemberName alias, Location loc)
654                 {
655                         if (DeclarationFound){
656                                 Report.Error (1529, loc, "A using clause must precede all other namespace elements except extern alias declarations");
657                                 return;
658                         }
659
660                         UsingFound = true;
661
662                         if (aliases == null)
663                                 aliases = new Hashtable ();
664
665                         if (aliases.Contains (name)) {
666                                 AliasEntry ae = (AliasEntry) aliases [name];
667                                 Report.SymbolRelatedToPreviousError (ae.Location, ae.Name);
668                                 Report.Error (1537, loc, "The using alias `{0}' appeared previously in this namespace", name);
669                                 return;
670                         }
671
672                         if (RootContext.Version == LanguageVersion.Default &&
673                             name == "global" && RootContext.WarningLevel >= 2)
674                                 Report.Warning (440, 2, loc, "An alias named `global' will not be used when resolving 'global::';" +
675                                         " the global namespace will be used instead");
676
677                         // FIXME: get correct error number.  See if the above check can be merged
678                         if (extern_aliases != null && extern_aliases.Contains (name)) {
679                                 AliasEntry ae = (AliasEntry) extern_aliases [name];
680                                 Report.SymbolRelatedToPreviousError (ae.Location, ae.Name);
681                                 Report.Error (1537, loc, "The using alias `{0}' appeared previously in this namespace", name);
682                                 return;
683                         }
684
685                         aliases [name] = new LocalAliasEntry (Doppelganger, name, alias, loc);
686                 }
687
688                 public void UsingExternalAlias (string name, Location loc)
689                 {
690                         if (UsingFound || DeclarationFound) {
691                                 Report.Error (439, loc, "An extern alias declaration must precede all other elements");
692                                 return;
693                         }
694                         
695                         // Share the extern_aliases field with the Doppelganger
696                         if (extern_aliases == null) {
697                                 extern_aliases = new ListDictionary ();
698                                 Doppelganger.extern_aliases = extern_aliases;
699                         }
700
701                         if (extern_aliases.Contains (name)) {
702                                 AliasEntry ae = (AliasEntry) extern_aliases [name];
703                                 Report.SymbolRelatedToPreviousError (ae.Location, ae.Name);
704                                 Report.Error (1537, loc, "The using alias `{0}' appeared previously in this namespace", name);
705                                 return;
706                         }
707
708                         if (name == "global") {
709                                 Report.Error (1681, loc, "You cannot redefine the global extern alias");
710                                 return;
711                         }
712
713                         // Register the alias in aliases and extern_aliases, since we need both of them
714                         // to keep things simple (different resolution scenarios)
715                         ExternAliasEntry alias = new ExternAliasEntry (Doppelganger, name, loc);
716                         extern_aliases [name] = alias;
717                 }
718
719                 public FullNamedExpression LookupNamespaceOrType (DeclSpace ds, string name, Location loc, bool ignore_cs0104)
720                 {
721                         // Precondition: Only simple names (no dots) will be looked up with this function.
722                         FullNamedExpression resolved = null;
723                         for (NamespaceEntry curr_ns = this; curr_ns != null; curr_ns = curr_ns.ImplicitParent) {
724                                 if ((resolved = curr_ns.Lookup (ds, name, loc, ignore_cs0104)) != null)
725                                         break;
726                         }
727                         return resolved;
728                 }
729
730                 static void Error_AmbiguousTypeReference (Location loc, string name, FullNamedExpression t1, FullNamedExpression t2)
731                 {
732                         Report.Error (104, loc, "`{0}' is an ambiguous reference between `{1}' and `{2}'",
733                                 name, t1.FullName, t2.FullName);
734                 }
735
736                 // Looks-up a alias named @name in this and surrounding namespace declarations
737                 public FullNamedExpression LookupAlias (string name)
738                 {
739                         AliasEntry entry = null;
740                         for (NamespaceEntry n = this; n != null; n = n.ImplicitParent) {
741                                 if (n.extern_aliases != null && (entry = n.extern_aliases [name] as AliasEntry) != null)
742                                         break;
743                                 if (n.aliases != null && (entry = n.aliases [name] as AliasEntry) != null)
744                                         break;
745                         }
746                         return entry == null ? null : entry.Resolve ();
747                 }
748
749                 private FullNamedExpression Lookup (DeclSpace ds, string name, Location loc, bool ignore_cs0104)
750                 {
751                         //
752                         // Check whether it's in the namespace.
753                         //
754                         FullNamedExpression fne = NS.Lookup (ds, name, loc);
755                         if (fne != null)
756                                 return fne;
757
758                         if (extern_aliases != null) {
759                                 AliasEntry entry = extern_aliases [name] as AliasEntry;
760                                 if (entry != null)
761                                         return entry.Resolve ();
762                         }
763                         
764                         if (IsImplicit)
765                                 return null;
766                         
767                         //
768                         // Check aliases. 
769                         //
770                         if (aliases != null) {
771                                 AliasEntry entry = aliases [name] as AliasEntry;
772                                 if (entry != null)
773                                         return entry.Resolve ();
774                         }
775
776                         //
777                         // Check using entries.
778                         //
779                         FullNamedExpression match = null;
780                         foreach (Namespace using_ns in GetUsingTable ()) {
781                                 match = using_ns.Lookup (ds, name, loc);
782                                 if (match == null || !(match is TypeExpr))
783                                         continue;
784                                 if (fne != null) {
785                                         if (!ignore_cs0104)
786                                                 Error_AmbiguousTypeReference (loc, name, fne, match);
787                                         return null;
788                                 }
789                                 fne = match;
790                         }
791
792                         return fne;
793                 }
794
795                 // Our cached computation.
796                 readonly Namespace [] empty_namespaces = new Namespace [0];
797                 Namespace [] namespace_using_table;
798                 Namespace [] GetUsingTable ()
799                 {
800                         if (namespace_using_table != null)
801                                 return namespace_using_table;
802
803                         if (using_clauses == null) {
804                                 namespace_using_table = empty_namespaces;
805                                 return namespace_using_table;
806                         }
807
808                         ArrayList list = new ArrayList (using_clauses.Count);
809
810                         foreach (UsingEntry ue in using_clauses) {
811                                 Namespace using_ns = ue.Resolve ();
812                                 if (using_ns == null)
813                                         continue;
814
815                                 list.Add (using_ns);
816                         }
817
818                         namespace_using_table = new Namespace [list.Count];
819                         list.CopyTo (namespace_using_table, 0);
820                         return namespace_using_table;
821                 }
822
823                 readonly string [] empty_using_list = new string [0];
824
825                 public int SymbolFileID {
826                         get {
827                                 if (symfile_id == 0 && file.SourceFileEntry != null) {
828                                         int parent_id = parent == null ? 0 : parent.SymbolFileID;
829
830                                         string [] using_list = empty_using_list;
831                                         if (using_clauses != null) {
832                                                 using_list = new string [using_clauses.Count];
833                                                 for (int i = 0; i < using_clauses.Count; i++)
834                                                         using_list [i] = ((UsingEntry) using_clauses [i]).Name.ToString ();
835                                         }
836
837                                         symfile_id = CodeGen.SymbolWriter.DefineNamespace (ns.Name, file.SourceFileEntry, using_list, parent_id);
838                                 }
839                                 return symfile_id;
840                         }
841                 }
842
843                 static void MsgtryRef (string s)
844                 {
845                         Console.WriteLine ("    Try using -r:" + s);
846                 }
847
848                 static void MsgtryPkg (string s)
849                 {
850                         Console.WriteLine ("    Try using -pkg:" + s);
851                 }
852
853                 public static void Error_NamespaceNotFound (Location loc, string name)
854                 {
855                         Report.Error (246, loc, "The type or namespace name `{0}' could not be found. Are you missing a using directive or an assembly reference?",
856                                 name);
857
858                         switch (name) {
859                         case "Gtk": case "GtkSharp":
860                                 MsgtryPkg ("gtk-sharp");
861                                 break;
862
863                         case "Gdk": case "GdkSharp":
864                                 MsgtryPkg ("gdk-sharp");
865                                 break;
866
867                         case "Glade": case "GladeSharp":
868                                 MsgtryPkg ("glade-sharp");
869                                 break;
870
871                         case "System.Drawing":
872                         case "System.Web.Services":
873                         case "System.Web":
874                         case "System.Data":
875                         case "System.Windows.Forms":
876                                 MsgtryRef (name);
877                                 break;
878                         }
879                 }
880
881                 /// <summary>
882                 ///   Used to validate that all the using clauses are correct
883                 ///   after we are finished parsing all the files.  
884                 /// </summary>
885                 void VerifyUsing ()
886                 {
887                         if (extern_aliases != null) {
888                                 foreach (DictionaryEntry de in extern_aliases)
889                                         ((AliasEntry) de.Value).Resolve ();
890                         }               
891
892                         if (using_clauses != null) {
893                                 foreach (UsingEntry ue in using_clauses)
894                                         ue.Resolve ();
895                         }
896
897                         if (aliases != null) {
898                                 foreach (DictionaryEntry de in aliases)
899                                         ((AliasEntry) de.Value).Resolve ();
900                         }
901                 }
902
903                 /// <summary>
904                 ///   Used to validate that all the using clauses are correct
905                 ///   after we are finished parsing all the files.  
906                 /// </summary>
907                 static public void VerifyAllUsing ()
908                 {
909                         foreach (NamespaceEntry entry in entries)
910                                 entry.VerifyUsing ();
911                 }
912
913                 public string GetSignatureForError ()
914                 {
915                         return ns.GetSignatureForError ();
916                 }
917
918                 public override string ToString ()
919                 {
920                         return ns.ToString ();
921                 }
922         }
923 }