In mcs:
[mono.git] / mcs / gmcs / namespace.cs
index 6fc813586c39a49db916f2f895d4b49f3f592665..be3ccbb59c03bd3e0274ff2b98e361d7fd519a60 100644 (file)
@@ -3,6 +3,7 @@
 //
 // Author:
 //   Miguel de Icaza (miguel@ximian.com)
+//   Marek Safar (marek.safar@seznam.cz)
 //
 // (C) 2001 Ximian, Inc.
 //
@@ -86,7 +87,7 @@ namespace Mono.CSharp {
 
                protected void EnsureNamespace (string dotted_name)
                {
-                       if (dotted_name != null && dotted_name != "" && ! IsNamespace (dotted_name))
+                       if (dotted_name != null && dotted_name.Length != 0 && ! IsNamespace (dotted_name))
                                GetNamespace (dotted_name, true);
                }
 
@@ -112,12 +113,16 @@ namespace Mono.CSharp {
                        if (t.IsPointer)
                                throw new InternalErrorException ("Use GetPointerType() to get a pointer");
                        
+                       
                        TypeAttributes ta = t.Attributes & TypeAttributes.VisibilityMask;
-                       if (ta == TypeAttributes.NotPublic ||
-                           ta == TypeAttributes.NestedPrivate ||
-                           ta == TypeAttributes.NestedAssembly ||
-                           ta == TypeAttributes.NestedFamANDAssem)
+                       if (ta == TypeAttributes.NestedPrivate)
                                return null;
+                       
+                       if (ta == TypeAttributes.NotPublic ||
+                                       ta == TypeAttributes.NestedAssembly ||
+                                       ta == TypeAttributes.NestedFamANDAssem)
+                               if (!TypeManager.IsFriendAssembly (t.Assembly))
+                                       return null;
 
                        return t;
                }
@@ -183,6 +188,12 @@ namespace Mono.CSharp {
                                EnsureNamespace (t.Namespace);
                }
 
+               public override void Error_NamespaceDoesNotExist(Location loc, string name)
+               {
+                       Report.Error (400, loc, "The type or namespace name `{0}' could not be found in the global namespace (are you missing an assembly reference?)",
+                               name);
+               }
+
                public override Type LookupTypeReflection (string name, Location loc)
                {
                        Type found_type = null;
@@ -277,9 +288,8 @@ namespace Mono.CSharp {
                                throw new InternalErrorException ("Namespace has a null fullname");
 
                        if (parent != null && parent.MemberName != MemberName.Null)
-                               MemberName = new MemberName (
-                                       parent.MemberName, name, parent.MemberName.Location);
-                       else if (name == "")
+                               MemberName = new MemberName (parent.MemberName, name, parent.MemberName.Location);
+                       else if (name.Length == 0)
                                MemberName = MemberName.Null;
                        else
                                MemberName = new MemberName (name, Location.Null);
@@ -295,6 +305,12 @@ namespace Mono.CSharp {
                        return this;
                }
 
+               public virtual void Error_NamespaceDoesNotExist (Location loc, string name)
+               {
+                       Report.Error (234, loc, "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing an assembly reference?",
+                               name, FullName);
+               }
+
                public override void Emit (EmitContext ec)
                {
                        throw new InternalErrorException ("Expression tree referenced namespace " + fullname + " during Emit ()");
@@ -353,7 +369,7 @@ namespace Mono.CSharp {
                                        t = tdecl.TypeBuilder;
                                }
                        }
-                       string lookup = t != null ? t.FullName : (fullname == "" ? name : fullname + "." + name);
+                       string lookup = t != null ? t.FullName : (fullname.Length == 0 ? name : fullname + "." + name);
                        Type rt = root.LookupTypeReflection (lookup, loc);
                        if (t == null)
                                t = rt;
@@ -415,7 +431,9 @@ namespace Mono.CSharp {
                Hashtable aliases;
                ArrayList using_clauses;
                public bool DeclarationFound = false;
-               public bool UsingFound = false;
+               bool UsingFound;
+
+               ListDictionary extern_aliases;
 
                static ArrayList entries = new ArrayList ();
 
@@ -454,7 +472,7 @@ namespace Mono.CSharp {
 
                                DeclSpace root = RootContext.Tree.Types;
                                root.NamespaceEntry = NamespaceEntry;
-                               FullNamedExpression fne = Expr.ResolveAsTypeStep (root.EmitContext, false);
+                               FullNamedExpression fne = Expr.ResolveAsTypeStep (root, false);
                                root.NamespaceEntry = null;
 
                                if (fne == null) {
@@ -513,11 +531,22 @@ namespace Mono.CSharp {
                        {
                                DeclSpace root = RootContext.Tree.Types;
                                root.NamespaceEntry = NamespaceEntry;
-                               resolved = Alias.ResolveAsTypeStep (root.EmitContext, false);
+                               resolved = Alias.ResolveAsTypeStep (root, false);
                                root.NamespaceEntry = null;
 
                                if (resolved == null)
-                                       Error_NamespaceNotFound (Location, Alias.ToString ());
+                                       return null;
+
+                               if (resolved.Type != null) {
+                                       TypeAttributes attr = resolved.Type.Attributes & TypeAttributes.VisibilityMask;
+                                       if (attr == TypeAttributes.NestedPrivate || attr == TypeAttributes.NestedFamily ||
+                                               ((attr == TypeAttributes.NestedFamORAssem || attr == TypeAttributes.NestedAssembly) && 
+                                               TypeManager.LookupDeclSpace (resolved.Type) == null)) {
+                                               Expression.ErrorIsInaccesible (Alias.Location, Alias.ToString ());
+                                               return null;
+                                       }
+                               }
+
                                return resolved;
                        }
                }
@@ -540,11 +569,10 @@ namespace Mono.CSharp {
                        }
                }
 
-               public NamespaceEntry (NamespaceEntry parent, SourceFile file, string name, Location loc)
+               public NamespaceEntry (NamespaceEntry parent, SourceFile file, string name)
                {
                        this.parent = parent;
                        this.file = file;
-                       this.IsImplicit = false;
                        entries.Add (this);
                        this.ID = entries.Count;
 
@@ -619,6 +647,8 @@ namespace Mono.CSharp {
                                return;
                        }
 
+                       UsingFound = true;
+
                        if (name.Equals (ns.MemberName))
                                return;
                        
@@ -627,8 +657,7 @@ namespace Mono.CSharp {
 
                        foreach (UsingEntry old_entry in using_clauses) {
                                if (name.Equals (old_entry.Name)) {
-                                       if (RootContext.WarningLevel >= 3)
-                                               Report.Warning (105, loc, "The using directive for `{0}' appeared previously in this namespace", name);
+                                       Report.Warning (105, 3, loc, "The using directive for `{0}' appeared previously in this namespace", name.GetName ());
                                                return;
                                        }
                                }
@@ -644,22 +673,31 @@ namespace Mono.CSharp {
                                return;
                        }
 
+                       UsingFound = true;
+
                        if (aliases == null)
                                aliases = new Hashtable ();
 
                        if (aliases.Contains (name)) {
-                               AliasEntry ae = (AliasEntry)aliases [name];
+                               AliasEntry ae = (AliasEntry) aliases [name];
                                Report.SymbolRelatedToPreviousError (ae.Location, ae.Name);
-                               Report.Error (1537, loc, "The using alias `" + name +
-                                             "' appeared previously in this namespace");
+                               Report.Error (1537, loc, "The using alias `{0}' appeared previously in this namespace", name);
                                return;
                        }
 
                        if (RootContext.Version == LanguageVersion.Default &&
                            name == "global" && RootContext.WarningLevel >= 2)
-                               Report.Warning (440, loc, "An alias named `global' will not be used when resolving 'global::';" +
+                               Report.Warning (440, 2, loc, "An alias named `global' will not be used when resolving 'global::';" +
                                        " the global namespace will be used instead");
 
+                       // FIXME: get correct error number.  See if the above check can be merged
+                       if (extern_aliases != null && extern_aliases.Contains (name)) {
+                               AliasEntry ae = (AliasEntry) extern_aliases [name];
+                               Report.SymbolRelatedToPreviousError (ae.Location, ae.Name);
+                               Report.Error (1537, loc, "The using alias `{0}' appeared previously in this namespace", name);
+                               return;
+                       }
+
                        aliases [name] = new LocalAliasEntry (Doppelganger, name, alias, loc);
                }
 
@@ -670,14 +708,16 @@ namespace Mono.CSharp {
                                return;
                        }
                        
-                       if (aliases == null)
-                               aliases = new Hashtable ();
-                       
-                       if (aliases.Contains (name)) {
-                               AliasEntry ae = (AliasEntry) aliases [name];
+                       // Share the extern_aliases field with the Doppelganger
+                       if (extern_aliases == null) {
+                               extern_aliases = new ListDictionary ();
+                               Doppelganger.extern_aliases = extern_aliases;
+                       }
+
+                       if (extern_aliases.Contains (name)) {
+                               AliasEntry ae = (AliasEntry) extern_aliases [name];
                                Report.SymbolRelatedToPreviousError (ae.Location, ae.Name);
-                               Report.Error (1537, loc, "The using alias `" + name +
-                                             "' appeared previously in this namespace");
+                               Report.Error (1537, loc, "The using alias `{0}' appeared previously in this namespace", name);
                                return;
                        }
 
@@ -686,7 +726,10 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       aliases [name] = new ExternAliasEntry (Doppelganger, name, loc);
+                       // Register the alias in aliases and extern_aliases, since we need both of them
+                       // to keep things simple (different resolution scenarios)
+                       ExternAliasEntry alias = new ExternAliasEntry (Doppelganger, name, loc);
+                       extern_aliases [name] = alias;
                }
 
                public FullNamedExpression LookupNamespaceOrType (DeclSpace ds, string name, Location loc, bool ignore_cs0104)
@@ -710,16 +753,13 @@ namespace Mono.CSharp {
                public FullNamedExpression LookupAlias (string name)
                {
                        AliasEntry entry = null;
-                       // We use Parent rather than ImplicitParent since we know implicit namespace declarations
-                       // cannot have using entries.
-                       for (NamespaceEntry n = this; n != null; n = n.Parent) {
-                               if (n.aliases == null)
-                                       continue;
-                               entry = n.aliases [name] as AliasEntry;
-                               if (entry != null)
-                                       return entry.Resolve ();
+                       for (NamespaceEntry n = this; n != null; n = n.ImplicitParent) {
+                               if (n.extern_aliases != null && (entry = n.extern_aliases [name] as AliasEntry) != null)
+                                       break;
+                               if (n.aliases != null && (entry = n.aliases [name] as AliasEntry) != null)
+                                       break;
                        }
-                       return null;
+                       return entry == null ? null : entry.Resolve ();
                }
 
                private FullNamedExpression Lookup (DeclSpace ds, string name, Location loc, bool ignore_cs0104)
@@ -731,11 +771,17 @@ namespace Mono.CSharp {
                        if (fne != null)
                                return fne;
 
+                       if (extern_aliases != null) {
+                               AliasEntry entry = extern_aliases [name] as AliasEntry;
+                               if (entry != null)
+                                       return entry.Resolve ();
+                       }
+                       
                        if (IsImplicit)
                                return null;
-
+                       
                        //
-                       // Check aliases.
+                       // Check aliases. 
                        //
                        if (aliases != null) {
                                AliasEntry entry = aliases [name] as AliasEntry;
@@ -854,6 +900,11 @@ namespace Mono.CSharp {
                /// </summary>
                void VerifyUsing ()
                {
+                       if (extern_aliases != null) {
+                               foreach (DictionaryEntry de in extern_aliases)
+                                       ((AliasEntry) de.Value).Resolve ();
+                       }               
+
                        if (using_clauses != null) {
                                foreach (UsingEntry ue in using_clauses)
                                        ue.Resolve ();