//
// 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;
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, string name)
{
this.name = name;
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 parent.Name + "." + name;
}
}
///
/// The parent of this namespace, used by the parser to "Pop"
/// the current namespace declaration
///
public Namespace Parent {
get {
return parent;
}
}
///
/// 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 (using_clauses == null)
using_clauses = new ArrayList ();
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 CaseInsensitiveHashtable ();
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;
}
///
/// 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){
CaseInsensitiveHashtable 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;
}
}
}