// // namespace.cs: Tracks namespaces // // Author: // Miguel de Icaza (miguel@ximian.com) // // (C) 2001 Ximian, Inc. // using System; using System.Collections; using Mono.Languages; namespace Mono.CSharp { /// /// Keeps track of the namespaces defined in the C# code. /// public class Namespace { static ArrayList all_namespaces = new ArrayList (); Namespace parent; string name; SourceFile file; int symfile_id; ArrayList using_clauses; Hashtable aliases; public bool DeclarationFound = false; // // This class holds the location where a using definition is // done, and whether it has been used by the program or not. // // We use this to flag using clauses for namespaces that do not // exist. // public class UsingEntry { public string Name; public bool Used; public Location Location; public UsingEntry (string name, Location loc) { Name = name; Location = loc; Used = false; } } /// /// Constructor Takes the current namespace and the /// name. This is bootstrapped with parent == null /// and name = "" /// public Namespace (Namespace parent, SourceFile file, string name) { this.name = name; this.file = file; this.parent = parent; all_namespaces.Add (this); } /// /// The qualified name of the current namespace /// public string Name { get { string pname = parent != null ? parent.Name : ""; if (pname == "") return name; else return String.Concat (parent.Name, ".", name); } } /// /// The parent of this namespace, used by the parser to "Pop" /// the current namespace declaration /// public Namespace Parent { get { return parent; } } public int SymbolFileID { get { return symfile_id; } } /// /// Records a new namespace for resolving name references /// public void Using (string ns, Location loc) { if (DeclarationFound){ Report.Error (1529, loc, "A using clause must precede all other namespace elements"); return; } if (ns == Name) return; if (using_clauses == null) using_clauses = new ArrayList (); foreach (UsingEntry old_entry in using_clauses){ if (old_entry.Name == ns){ Report.Warning (105, loc, "The using directive for '" + ns + "' appeared previously in this namespace"); return; } } UsingEntry ue = new UsingEntry (ns, loc); using_clauses.Add (ue); } public ArrayList UsingTable { get { return using_clauses; } } public void UsingAlias (string alias, string namespace_or_type, Location loc) { if (aliases == null) aliases = new Hashtable (); if (aliases.Contains (alias)){ Report.Error (1537, loc, "The using alias `" + alias + "' appeared previously in this namespace"); return; } aliases [alias] = namespace_or_type; } public string LookupAlias (string alias) { string value = null; // System.Console.WriteLine ("Lookup " + alias + " in " + name); if (aliases != null) value = (string) (aliases [alias]); if (value == null && Parent != null) value = Parent.LookupAlias (alias); return value; } void DefineNamespace (SymbolWriter symwriter) { if (symfile_id != 0) return; if (parent != null) parent.DefineNamespace (symwriter); string[] using_list; if (using_clauses != null) { using_list = new string [using_clauses.Count]; for (int i = 0; i < using_clauses.Count; i++) using_list [i] = ((UsingEntry) using_clauses [i]).Name; } else { using_list = new string [0]; } int parent_id = parent != null ? parent.symfile_id : 0; symfile_id = symwriter.DefineNamespace (name, file, using_list, parent_id); } public static void DefineNamespaces (SymbolWriter symwriter) { foreach (Namespace ns in all_namespaces) ns.DefineNamespace (symwriter); } /// /// Used to validate that all the using clauses are correct /// after we are finished parsing all the files. /// public static bool VerifyUsing () { ArrayList unused = new ArrayList (); int errors = 0; foreach (Namespace ns in all_namespaces){ ArrayList uses = ns.UsingTable; if (uses == null) continue; foreach (UsingEntry ue in uses){ if (ue.Used) continue; unused.Add (ue); } } // // If we have unused using aliases, load all namespaces and check // whether it is unused, or it was missing // if (unused.Count > 0){ Hashtable namespaces = TypeManager.GetNamespaces (); foreach (UsingEntry ue in unused){ if (namespaces.Contains (ue.Name)){ Report.Warning (6024, ue.Location, "Unused namespace in `using' declaration"); continue; } errors++; Report.Error (246, ue.Location, "The namespace `" + ue.Name + "' can not be found (missing assembly reference?)"); } } return errors == 0; } } }