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