/// <summary>
/// Keeps track of the namespaces defined in the C# code.
+ ///
+ /// This is an Expression to allow it to be referenced in the
+ /// compiler parse/intermediate tree during name resolution.
/// </summary>
- public class Namespace : IAlias {
+ public class Namespace : FullNamedExpression, IAlias {
static ArrayList all_namespaces = new ArrayList ();
static Hashtable namespaces_map = new Hashtable ();
/// </summary>
public Namespace (Namespace parent, string name)
{
+ // Expression members.
+ this.eclass = ExprClass.Namespace;
+ this.Type = null;
+ this.loc = Location.Null;
+
this.parent = parent;
string pname = parent != null ? parent.Name : "";
namespaces_map [fullname] = true;
}
+ public override Expression DoResolve (EmitContext ec)
+ {
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ throw new InternalErrorException ("Expression tree referenced namespace " + fullname + " during Emit ()");
+ }
+
public static bool IsNamespace (string name)
{
return namespaces_map [name] != null;
return Root.GetNamespace (name, create);
}
- public IAlias Lookup (DeclSpace ds, string name, Location loc)
+ public FullNamedExpression Lookup (DeclSpace ds, string name, Location loc)
{
- IAlias o = Lookup (name);
+ IAlias o = (IAlias) defined_names [name];
Type t;
DeclSpace tdecl = o as DeclSpace;
if (tdecl != null) {
t = tdecl.DefineType ();
+ if (t == null)
+ return null;
if ((ds == null) || ds.CheckAccessLevel (t))
- return new TypeExpression (t, loc);
+ return new TypeExpression (t, Location.Null);
}
Namespace ns = GetNamespace (name, false);
if ((t == null) || ((ds != null) && !ds.CheckAccessLevel (t)))
return null;
- return new TypeExpression (t, loc);
+ return new TypeExpression (t, Location.Null);
}
public void AddNamespaceEntry (NamespaceEntry entry)
defined_names.Add (name, o);
}
- public IAlias Lookup (string name)
- {
- return (IAlias) defined_names [name];
- }
-
static public ArrayList UserDefinedNamespaces {
get {
return all_namespaces;
}
}
+ public override string FullName {
+ get {
+ return fullname;
+ }
+ }
+
/// <summary>
/// The parent of this namespace, used by the parser to "Pop"
/// the current namespace declaration
get { return false; }
}
- TypeExpr IAlias.Type {
- get {
- throw new InvalidOperationException ();
- }
+ TypeExpr IAlias.ResolveAsType (EmitContext ec)
+ {
+ throw new InvalidOperationException ();
}
}
if (resolved_ns != null)
return resolved_ns;
- Namespace curr_ns = NamespaceEntry.NS;
- while ((curr_ns != null) && (resolved_ns == null)) {
- resolved_ns = curr_ns.GetNamespace (Name, false);
-
- if (resolved_ns == null)
- curr_ns = curr_ns.Parent;
- }
-
+ FullNamedExpression resolved = NamespaceEntry.LookupForUsing (Name, Location);
+ resolved_ns = resolved as Namespace;
return resolved_ns;
}
}
public class AliasEntry {
public readonly string Name;
- public readonly TypeName Alias;
+ public readonly MemberName Alias;
public readonly NamespaceEntry NamespaceEntry;
public readonly Location Location;
- public AliasEntry (NamespaceEntry entry, string name, TypeName alias, Location loc)
+ public AliasEntry (NamespaceEntry entry, string name, MemberName alias, Location loc)
{
Name = name;
Alias = alias;
Location = loc;
}
- IAlias resolved;
+ FullNamedExpression resolved;
- public IAlias Resolve ()
+ public FullNamedExpression Resolve ()
{
if (resolved != null)
return resolved;
- NamespaceEntry curr_ns = NamespaceEntry;
-
//
// GENERICS: Cope with the expression and not with the string
// this will fail with `using A = Stack<int>'
//
- string alias = Alias.GetTypeName (true);
- while ((curr_ns != null) && (resolved == null)) {
- resolved = curr_ns.Lookup (
- null, alias, Alias.CountTypeArguments,
- false, Location);
-
- if (resolved == null)
- curr_ns = curr_ns.Parent;
- }
+ string alias = Alias.GetTypeName ();
+ resolved = NamespaceEntry.LookupForUsing (alias, Location);
if (resolved == null)
return null;
- if (resolved.IsType)
- resolved = new TypeAliasExpression (
- resolved.Type, Alias.TypeArguments, Location);
+ if (Alias.TypeArguments == null)
+ return resolved;
+
+ EmitContext ec = RootContext.Tree.Types.EmitContext;
+ resolved = new TypeAliasExpression (resolved, Alias.TypeArguments, Location);
+ resolved = resolved.ResolveAsTypeStep (ec);
return resolved;
}
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;
+ foreach (UsingEntry old_entry in using_clauses) {
+ if (old_entry.Name == ns) {
+ if (RootContext.WarningLevel >= 3)
+ Report.Warning (105, loc, "The using directive for '{0}' appeared previously in this namespace", ns);
+ return;
+ }
}
- }
UsingEntry ue = new UsingEntry (this, ns, loc);
using_clauses.Add (ue);
}
- public void UsingAlias (string name, TypeName alias, Location loc)
+ public void UsingAlias (string name, MemberName alias, Location loc)
{
+ if (DeclarationFound){
+ Report.Error (1529, loc, "A using clause must precede all other namespace elements");
+ return;
+ }
+
if (aliases == null)
aliases = new Hashtable ();
aliases [name] = new AliasEntry (this, name, alias, loc);
}
- protected AliasEntry GetAliasEntry (string alias)
+ public FullNamedExpression LookupAlias (string alias)
{
AliasEntry entry = null;
-
if (aliases != null)
entry = (AliasEntry) aliases [alias];
- if (entry == null && Parent != null)
- entry = Parent.GetAliasEntry (alias);
- return entry;
+ return entry == null ? null : entry.Resolve ();
}
- public IAlias LookupAlias (string alias)
+ //
+ // According to section 16.3.1 (using-alias-directive), the namespace-or-type-name is
+ // resolved as if the immediately containing namespace body has no using-directives.
+ //
+ // Section 16.3.2 says that the same rule is applied when resolving the namespace-name
+ // in the using-namespace-directive.
+ //
+ public FullNamedExpression LookupForUsing (string dotted_name, Location loc)
{
- AliasEntry entry = GetAliasEntry (alias);
+ int pos = dotted_name.IndexOf ('.');
+ string simple_name = dotted_name;
+ string rest = null;
+ if (pos >= 0) {
+ simple_name = dotted_name.Substring (0, pos);
+ rest = dotted_name.Substring (pos + 1);
+ }
+
+ FullNamedExpression o = NS.Lookup (null, simple_name, loc);
+ if (o == null && ImplicitParent != null)
+ o = ImplicitParent.LookupNamespaceOrType (null, simple_name, loc);
- if (entry == null)
+ if (o == null || rest == null)
+ return o;
+
+ Namespace ns = o as Namespace;
+ if (ns != null)
+ return ns.Lookup (null, rest, loc);
+
+ Type nested = TypeManager.LookupType (o.FullName + "." + rest);
+ if (nested == null)
return null;
- return entry.Resolve ();
+ return new TypeExpression (nested, Location.Null);
+ }
+
+ public FullNamedExpression LookupNamespaceOrType (DeclSpace ds, string name, Location loc)
+ {
+ FullNamedExpression resolved = null;
+ for (NamespaceEntry curr_ns = this; curr_ns != null; curr_ns = curr_ns.ImplicitParent) {
+ if ((resolved = curr_ns.Lookup (ds, name, loc)) != null)
+ break;
+ }
+ return resolved;
}
- public IAlias Lookup (DeclSpace ds, string name, int num_type_params,
- bool silent, Location loc)
+ private FullNamedExpression Lookup (DeclSpace ds, string name, Location loc)
{
- IAlias o;
+ FullNamedExpression o;
Namespace ns;
//
// If name is of the form `N.I', first lookup `N', then search a member `I' in it.
//
+ // FIXME: Remove this block. Only simple names should come here.
+ // The bug: The loop in LookupNamespaceOrType continues if
+ // the lookup for N succeeds but the nested lookup for I fails.
+ // This is one part of #52697.
+ //
int pos = name.IndexOf ('.');
if (pos >= 0) {
string first = name.Substring (0, pos);
string last = name.Substring (pos + 1);
- o = Lookup (ds, first, 0, silent, loc);
+ o = Lookup (ds, first, loc);
if (o == null)
return null;
return o;
}
- Type nested = TypeManager.LookupType (o.Name + "." + last);
+ Type nested = TypeManager.LookupType (o.FullName + "." + last);
if ((nested == null) || ((ds != null) && !ds.CheckAccessLevel (nested)))
return null;
- return new TypeExpression (nested, loc);
+ return new TypeExpression (nested, Location.Null);
}
//
- // Check whether it's a namespace.
+ // Check whether it's in the namespace.
//
o = NS.Lookup (ds, name, loc);
if (o != null)
//
// Check aliases.
//
- AliasEntry entry = GetAliasEntry (name);
- if (entry != null) {
- IAlias alias = entry.Resolve ();
- if (alias != null)
- return alias;
- }
+ o = LookupAlias (name);
+ if (o != null)
+ return o;
if (name.IndexOf ('.') > 0)
return null;
//
// Check using entries.
//
- IAlias t = null, match = null;
+ FullNamedExpression t = null, match = null;
foreach (Namespace using_ns in GetUsingTable ()) {
match = using_ns.Lookup (ds, name, loc);
- if ((match != null) && match.IsType){
+ if ((match != null) && (match is TypeExpr)) {
if (t != null) {
- if (!silent)
- DeclSpace.Error_AmbiguousTypeReference (loc, name, t.Name, match.Name);
+ DeclSpace.Error_AmbiguousTypeReference (loc, name, t.FullName, match.FullName);
return null;
} else {
t = match;
{
if (namespace_using_table != null)
return namespace_using_table;
-
- if (using_clauses == null)
- return new Namespace [0];
+
+ if (using_clauses == null) {
+ namespace_using_table = new Namespace [0];
+ return namespace_using_table;
+ }
ArrayList list = new ArrayList (using_clauses.Count);
}
int parent_id = parent != null ? parent.symfile_id : 0;
- symfile_id = symwriter.DefineNamespace (ns.Name, file, using_list, parent_id);
+ if (file.SourceFileEntry == null)
+ return;
+
+ symfile_id = symwriter.DefineNamespace (
+ ns.Name, file.SourceFileEntry, using_list, parent_id);
}
public int SymbolFileID {
}
}
- static void Msgtry (string s)
+ static void MsgtryRef (string s)
{
Console.WriteLine (" Try using -r:" + s);
}
+
+ static void MsgtryPkg (string s)
+ {
+ Console.WriteLine (" Try using -pkg:" + s);
+ }
protected void error246 (Location loc, string name)
{
- if (TypeManager.LookupType (name) != null)
- Report.Error (138, loc, "The using keyword only lets you specify a namespace, " +
- "`" + name + "' is a class not a namespace.");
- else {
- Report.Error (246, loc, "The namespace `" + name +
- "' can not be found (missing assembly reference?)");
-
- switch (name){
- case "Gtk": case "GtkSharp":
- Msgtry ("gtk-sharp");
- break;
-
- case "Gdk": case "GdkSharp":
- Msgtry ("gdk-sharp");
- break;
-
- case "Glade": case "GladeSharp":
- Msgtry ("glade-sharp");
- break;
-
- case "System.Drawing":
- Msgtry ("System.Drawing");
- break;
-
- case "System.Web.Services":
- Msgtry ("System.Web.Services");
- break;
-
- case "System.Web":
- Msgtry ("System.Web");
- break;
-
- case "System.Data":
- Msgtry ("System.Data");
- break;
-
- case "System.Windows.Forms":
- Msgtry ("System.Windows.Forms");
- break;
- }
+ Report.Error (246, loc, "The namespace `" + name +
+ "' can not be found (missing assembly reference?)");
+
+ switch (name) {
+ case "Gtk": case "GtkSharp":
+ MsgtryPkg ("gtk-sharp");
+ break;
+
+ case "Gdk": case "GdkSharp":
+ MsgtryPkg ("gdk-sharp");
+ break;
+
+ case "Glade": case "GladeSharp":
+ MsgtryPkg ("glade-sharp");
+ break;
+
+ case "System.Drawing":
+ case "System.Web.Services":
+ case "System.Web":
+ case "System.Data":
+ case "System.Windows.Forms":
+ MsgtryRef (name);
+ break;
}
}
/// </summary>
public void VerifyUsing ()
{
- TypeContainer dummy = new TypeContainer ();
- EmitContext ec = new EmitContext (
- dummy, Location.Null, null, null, 0, false);
-
if (using_clauses != null){
foreach (UsingEntry ue in using_clauses){
if (ue.Resolve () != null)
continue;
- error246 (ue.Location, ue.Name);
+ if (LookupForUsing (ue.Name, ue.Location) == null)
+ error246 (ue.Location, ue.Name);
+ else
+ Report.Error (138, ue.Location, "The using keyword only lets you specify a namespace, " +
+ "`" + ue.Name + "' is a class not a namespace.");
+
}
}
if (aliases != null){
foreach (DictionaryEntry de in aliases){
- AliasEntry entry = (AliasEntry) de.Value;
-
- IAlias alias = entry.Resolve ();
- if (alias != null) {
- if (alias.IsType)
- alias.Type.ResolveType (ec);
+ AliasEntry alias = (AliasEntry) de.Value;
+ if (alias.Resolve () != null)
continue;
- }
- error246 (entry.Location, entry.Alias.ToString ());
+ error246 (alias.Location, alias.Alias.GetTypeName ());
}
}
}