Hey,

I applied the corrections made by Hari and all my tests are working
fine. 

Comments and suggestions are welcome.

Carlos.
Index: typemanager.cs
===================================================================
--- typemanager.cs	(revisión: 51315)
+++ typemanager.cs	(copia de trabajo)
@@ -215,6 +215,8 @@
 	// </remarks>
 	static Assembly [] assemblies;
 
+	static Hashtable external_aliases;
+
 	// <remarks>
 	//  Keeps a list of modules. We used this to do lookups
 	//  on the module using GetType -- needed for arrays
@@ -278,6 +280,7 @@
 		// Lets get everything clean so that we can collect before generating code
 		assemblies = null;
 		modules = null;
+		external_aliases = null;
 		builder_to_declspace = null;
 		builder_to_member_cache = null;
 		builder_to_ifaces = null;
@@ -379,6 +382,7 @@
 		assemblies = new Assembly [0];
 		modules = null;
 		
+		external_aliases = new Hashtable ();
 		builder_to_declspace = new PtrHashtable ();
 		builder_to_member_cache = new PtrHashtable ();
 		builder_to_method = new PtrHashtable ();
@@ -504,11 +508,22 @@
 		assemblies = n;
 	}
 
+	public static void AddExternAlias (string alias, Assembly a)
+	{
+		// Keep the new as the chosen one
+		external_aliases [alias] = a;
+	}
+
         public static Assembly [] GetAssemblies ()
         {
                 return assemblies;
         }
 
+	public static Assembly GetExternAlias (string alias)
+	{
+		return (Assembly) external_aliases [alias];
+	}
+
 	/// <summary>
 	///  Registers a module builder to lookup types from
 	/// </summary>
@@ -578,60 +593,33 @@
 		return (Type) ret;
 	}
 
-	public static Type LookupTypeReflection (string name, Location loc)
+	public static Type LookupTypeInModules (string name)
 	{
-		Type found_type = null;
-
-		foreach (Assembly a in assemblies) {
-			Type t = a.GetType (name);
-			if (t == null)
-				continue;
-
-			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 (found_type == null) {
-					found_type = t;
-					continue;
-				}
-
-				Report.SymbolRelatedToPreviousError (found_type);
-				Report.SymbolRelatedToPreviousError (t);
-				Report.Error (433, loc, "The imported type `{0}' is defined multiple times", name);
-				return found_type;
-			}
-		}
-
 		foreach (Module mb in modules) {
 			Type t = mb.GetType (name);
-			if (t == null)
-				continue;
-			
-			if (found_type == null) {
-				found_type = t;
-				continue;
-			}
-
-			Report.SymbolRelatedToPreviousError (t);
-			Report.SymbolRelatedToPreviousError (found_type);
-			Report.Warning (436, 2, loc, "Ignoring imported type `{0}' since the current assembly already has a declaration with the same name",
-				TypeManager.CSharpName (t));
-			return t;
+			if (t != null)
+				return t;
 		}
 
-		return found_type;
+		return null;
 	}
+	
+	//
+	// We use this for retrieving GetNamespaces method if avalaible
+	//
+	static MethodInfo assembly_get_namespaces;
 
 	/// <summary>
 	///   Computes the namespaces that we import from the assemblies we reference.
 	/// </summary>
 	public static void ComputeNamespaces ()
 	{
-		MethodInfo assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance|BindingFlags.NonPublic);
+		if (assembly_get_namespaces == null)
+			assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance|BindingFlags.NonPublic);
 
+		foreach (Assembly assembly in assemblies)
+			Namespace.Root.AddAssemblyReference (assembly);
+		
 		Hashtable cache = null;
 
 		//
@@ -682,8 +670,43 @@
 				cache.Add (ns, null);
 			}
 		}
+
 	}
 
+	public static Namespace ComputeNamespacesForAlias (string name)
+	{
+		Assembly assembly = (Assembly) external_aliases [name];
+		if (assembly == null)
+			return null;
+		
+		if (assembly_get_namespaces == null)
+			assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance|BindingFlags.NonPublic);
+		
+		Namespace retval = Namespace.DefineRootNamespace (name, assembly);
+		if (assembly_get_namespaces != null) {
+			string [] namespaces = (string []) assembly_get_namespaces.Invoke (assembly, null);
+			foreach (string ns in namespaces) {
+				if (ns.Length == 0)
+					continue;
+				
+				retval.GetNamespace (ns, true);
+			}
+		} else {
+			Hashtable alias_cache = new Hashtable ();
+			alias_cache.Add ("", null);
+			foreach (Type t in assembly.GetExportedTypes ()) {
+				string ns = t.Namespace;
+				if (ns == null || alias_cache.Contains (ns))
+					continue;
+
+				retval.GetNamespace (ns, true);
+				alias_cache.Add (ns, null);
+			}
+		}
+
+		return retval;
+	}
+
 	/// <summary>
 	/// Fills static table with exported types from all referenced assemblies.
 	/// This information is required for CLS Compliance tests.
Index: namespace.cs
===================================================================
--- namespace.cs	(revisión: 51315)
+++ namespace.cs	(copia de trabajo)
@@ -9,9 +9,101 @@
 using System;
 using System.Collections;
 using System.Collections.Specialized;
+using System.Reflection;
 
 namespace Mono.CSharp {
 
+	public class RootNamespace : Namespace
+	{
+		Assembly referenced_assembly;
+
+		public RootNamespace (Assembly assembly) : base (null, String.Empty)
+		{
+			this.referenced_assembly = assembly;
+			this.root = this;
+		}
+
+		public virtual Type LookupTypeReflection (string name, Location loc)
+		{
+			Console.WriteLine ("Looking for type = {0} in assembly = {1}", name, referenced_assembly.FullName);
+			Type t = referenced_assembly.GetType (name);
+			if (t == null)
+				return null;
+
+			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)
+				return t;
+
+			return null;
+		}
+
+	}
+
+	public class GlobalRootNamespace : RootNamespace
+	{
+		Assembly [] assemblies;
+		
+		public GlobalRootNamespace () : base (null)
+		{
+			assemblies = new Assembly [0];
+		}
+
+		public void AddAssemblyReference (Assembly assembly)
+		{
+			Assembly [] tmp = new Assembly [assemblies.Length + 1];
+			Array.Copy (assemblies, 0, tmp, 0, assemblies.Length);
+			tmp [assemblies.Length] = assembly;
+
+			assemblies = tmp;
+		}
+
+		public override Type LookupTypeReflection (string name, Location loc)
+		{
+			Type found_type = null;
+		
+			foreach (Assembly a in assemblies) {
+				Type t = a.GetType (name);
+				if (t == null)
+					continue;
+				
+				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 (found_type == null) {
+						found_type = t;
+						continue;
+					}
+				
+					Report.SymbolRelatedToPreviousError (found_type);
+					Report.SymbolRelatedToPreviousError (t);
+					Report.Error (433, loc, "The imported type `{0}' is defined multiple times", name);
+					return found_type;
+				}
+			}
+
+			Type t2 = TypeManager.LookupTypeInModules (name);
+			if (t2 != null) {
+				if (found_type != null) {
+					Report.SymbolRelatedToPreviousError (t2);
+					Report.SymbolRelatedToPreviousError (found_type);
+					Report.Warning (436, 2, loc, "Ignoring imported type `{0}' since the current assembly already has a declaration with the same name",
+							TypeManager.CSharpName (t2));
+				}
+
+				return t2;
+			}
+
+			return found_type;
+		}
+	}
+
 	/// <summary>
 	///   Keeps track of the namespaces defined in the C# code.
 	///
@@ -21,6 +113,7 @@
 	public class Namespace : FullNamedExpression {
 		static ArrayList all_namespaces;
 		static Hashtable namespaces_map;
+		static Hashtable root_namespaces;
 		
 		Namespace parent;
 		string fullname;
@@ -28,10 +121,11 @@
 		Hashtable namespaces;
 		IDictionary declspaces;
 		Hashtable cached_types;
+		protected RootNamespace root;
 
 		public readonly MemberName MemberName;
 
-		public static Namespace Root;
+		public static GlobalRootNamespace Root;
 
 		static Namespace ()
 		{
@@ -42,8 +136,9 @@
 		{
 			all_namespaces = new ArrayList ();
 			namespaces_map = new Hashtable ();
+			root_namespaces = new Hashtable ();
 
-			Root = new Namespace (null, "");
+			Root = new GlobalRootNamespace ();
 		}
 
 		/// <summary>
@@ -60,6 +155,12 @@
 
 			this.parent = parent;
 
+			if (parent != null)
+				if (parent is RootNamespace)
+					this.root = parent as RootNamespace;
+				else
+					this.root = parent.root;
+			
 			string pname = parent != null ? parent.Name : "";
 				
 			if (pname == "")
@@ -81,10 +182,12 @@
 			namespaces = new Hashtable ();
 			cached_types = new Hashtable ();
 
-			all_namespaces.Add (this);
-			if (namespaces_map.Contains (fullname))
-				return;
-			namespaces_map [fullname] = true;
+			if (this.root == Root) {
+				all_namespaces.Add (this);
+				if (namespaces_map.Contains (fullname))
+					return;
+				namespaces_map [fullname] = true;
+			}
 		}
 
 		public override Expression DoResolve (EmitContext ec)
@@ -138,6 +241,16 @@
 			return Root.GetNamespace (name, create);
 		}
 
+		public static RootNamespace DefineRootNamespace (string name, Assembly assembly)
+		{
+			RootNamespace retval = (RootNamespace) root_namespaces [name];
+			if (retval != null)
+				return retval;
+
+			retval = new RootNamespace (assembly);
+			return retval;
+		}
+
 		TypeExpr LookupType (string name, Location loc)
 		{
 			if (cached_types.Contains (name))
@@ -161,7 +274,7 @@
 				}
 			}
 			string lookup = t != null ? t.FullName : (fullname == "" ? name : fullname + "." + name);
-			Type rt = TypeManager.LookupTypeReflection (lookup, loc);
+			Type rt = root.LookupTypeReflection (lookup, loc);
 			if (t == null)
 				t = rt;
 
@@ -256,6 +369,7 @@
 		Hashtable aliases;
 		ArrayList using_clauses;
 		public bool DeclarationFound = false;
+		public bool UsingFound;
 
 		//
 		// This class holds the location where a using definition is
@@ -304,24 +418,34 @@
 			}
 		}
 
-		public class AliasEntry {
+		public abstract class AliasEntry {
 			public readonly string Name;
 			public readonly Expression Alias;
 			public readonly NamespaceEntry NamespaceEntry;
 			public readonly Location Location;
 			
-			public AliasEntry (NamespaceEntry entry, string name, MemberName alias, Location loc)
+			protected AliasEntry (NamespaceEntry entry, string name, MemberName alias, Location loc)
 			{
 				Name = name;
-				Alias = alias.GetTypeExpression ();
+				Alias = alias != null ? alias.GetTypeExpression () : null;
 				NamespaceEntry = entry;
 				Location = loc;
 			}
+			
+			protected FullNamedExpression resolved;
 
-			FullNamedExpression resolved;
+			public abstract FullNamedExpression Resolve ();
+		}
 
-			public FullNamedExpression Resolve ()
+		public class LocalAliasEntry : AliasEntry
+		{
+			public LocalAliasEntry (NamespaceEntry entry, string name, MemberName alias, Location loc) :
+				base (entry, name, alias, loc)
 			{
+			}
+
+			public override FullNamedExpression Resolve ()
+			{
 				if (resolved != null)
 					return resolved;
 
@@ -334,6 +458,24 @@
 			}
 		}
 
+		public class ExternAliasEntry : AliasEntry 
+		{
+			public ExternAliasEntry (NamespaceEntry entry, string name, Location loc) :
+				base (entry, name, null, loc)
+			{
+			}
+
+			public override FullNamedExpression Resolve ()
+			{
+				if (resolved != null)
+					return resolved;
+
+				resolved = TypeManager.ComputeNamespacesForAlias (Name);
+				
+				return resolved;
+			}
+		}
+
 		public NamespaceEntry (NamespaceEntry parent, SourceFile file, string name, Location loc)
 		{
 			this.parent = parent;
@@ -431,6 +573,7 @@
 
 			UsingEntry ue = new UsingEntry (Doppelganger, name, loc);
 			using_clauses.Add (ue);
+			UsingFound = true;
 		}
 
 		public void UsingAlias (string name, MemberName alias, Location loc)
@@ -456,9 +599,36 @@
 				Report.Warning (440, loc, "An alias named `global' will not be used when resolving 'global::';" +
 					" the global namespace will be used instead");
 
-			aliases [name] = new AliasEntry (Doppelganger, name, alias, loc);
+			aliases [name] = new LocalAliasEntry (Doppelganger, name, alias, loc);
+			UsingFound = true;
 		}
 
+		public void UsingExternalAlias (string name, Location loc)
+		{
+			if (UsingFound || DeclarationFound) {
+				Report.Error (439, loc, "An extern alias declaration must precede all other elements");
+				return;
+			}
+			
+			if (aliases == null)
+				aliases = new Hashtable ();
+			
+			if (aliases.Contains (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");
+				return;
+			}
+
+			if (name == "global") {
+				Report.Error (1681, loc, "You cannot redefine the global extern alias");
+				return;
+			}
+
+			aliases [name] = new ExternAliasEntry (Doppelganger, name, loc);
+		}
+
 		public FullNamedExpression LookupNamespaceOrType (DeclSpace ds, string name, Location loc, bool ignore_cs0104)
 		{
 			// Precondition: Only simple names (no dots) will be looked up with this function.
@@ -641,7 +811,12 @@
 				foreach (DictionaryEntry de in aliases) {
 					AliasEntry alias = (AliasEntry) de.Value;
 					if (alias.Resolve () == null)
-						Error_NamespaceNotFound (alias.Location, alias.Alias.ToString ());
+						if (alias is LocalAliasEntry)
+							Error_NamespaceNotFound (alias.Location, alias.Alias.ToString ());
+						else if (alias is ExternAliasEntry) {
+							Report.Error (430, alias.Location, "The extern alias '" + alias.Name +
+									"' was not specified in a /reference option");
+						}
 				}
 			}
 		}
Index: cs-parser.jay
===================================================================
--- cs-parser.jay	(revisión: 51315)
+++ cs-parser.jay	(copia de trabajo)
@@ -309,10 +309,31 @@
         ;
  
 outer_declaration
-        : using_directive
+	: extern_alias_directive
+        | using_directive 
         | namespace_member_declaration
         ;
-  
+
+extern_alias_directives
+	: extern_alias_directive
+	| extern_alias_directives extern_alias_directive;
+
+extern_alias_directive
+	: EXTERN IDENTIFIER IDENTIFIER SEMICOLON
+	  {
+		LocatedToken lt = (LocatedToken) $2;
+		string s = lt.Value;
+		if (s != "alias"){
+			Report.Error (1003, lt.Location, "'alias' expected");
+		} else if (RootContext.Version == LanguageVersion.ISO_1) {
+			Report.FeatureIsNotStandardized (lt.Location, "external alias");
+		} else {
+			lt = (LocatedToken) $3; 
+			current_namespace.UsingExternalAlias (lt.Value, lt.Location);
+		}
+	  }
+	;
+ 
 using_directives
 	: using_directive 
 	| using_directives using_directive
@@ -393,6 +414,7 @@
 		if (RootContext.Documentation != null)
 			Lexer.doc_state = XmlCommentState.Allowed;
 	  }
+	  opt_extern_alias_directives
 	  opt_using_directives
 	  opt_namespace_member_declarations
 	  CLOSE_BRACE
@@ -403,6 +425,11 @@
 	| using_directives
 	;
 
+opt_extern_alias_directives
+	: /* empty */
+	| extern_alias_directives
+	;
+
 opt_namespace_member_declarations
 	: /* empty */
 	| namespace_member_declarations
Index: driver.cs
===================================================================
--- driver.cs	(revisión: 51315)
+++ driver.cs	(copia de trabajo)
@@ -42,7 +42,12 @@
 		//
 		static ArrayList soft_references;
 
+		// 
+		// External aliases for assemblies.
 		//
+		static Hashtable external_aliases;
+
+		//
 		// Modules to be linked
 		//
 		static ArrayList modules;
@@ -305,6 +310,11 @@
 
 		static public void LoadAssembly (string assembly, bool soft)
 		{
+			LoadAssembly (assembly, null, soft);
+		}
+
+		static public void LoadAssembly (string assembly, string alias, bool soft)
+		{
 			Assembly a;
 			string total_log = "";
 
@@ -319,7 +329,11 @@
 						ass = assembly.Substring (0, assembly.Length - 4);
 					a = Assembly.Load (ass);
 				}
-				TypeManager.AddAssembly (a);
+				// Extern aliased refs require special handling
+				if (alias == null)
+					TypeManager.AddAssembly (a);
+				else
+					TypeManager.AddExternAlias (alias, a);
 
 			} catch (FileNotFoundException){
 				foreach (string dir in link_paths){
@@ -329,7 +343,10 @@
 
 					try {
 						a = Assembly.LoadFrom (full_path);
-						TypeManager.AddAssembly (a);
+						if (alias == null)
+							TypeManager.AddAssembly (a);
+						else
+							TypeManager.AddExternAlias (alias, a);
 						return;
 					} catch (FileNotFoundException ff) {
 						total_log += ff.FusionLog;
@@ -405,6 +422,9 @@
 
 			foreach (string r in soft_references)
 				LoadAssembly (r, true);
+
+			foreach (DictionaryEntry entry in external_aliases)
+				LoadAssembly ((string) entry.Value, (string) entry.Key, false);
 			
 			return;
 		}
@@ -800,7 +820,25 @@
 					Environment.Exit (1);
 				}
 				
-				references.Add (args [++i]);
+				string val = args [++i];
+				int idx = val.IndexOf ('=');
+				if (idx > -1) {
+					string alias = val.Substring (0, idx);
+					string assembly = val.Substring (idx + 1);
+					if (assembly.Length == 0) {
+						Report.Error (1680, "Invalid reference alias '" + alias + "='. Missing filename");
+						Environment.Exit (1);
+					}
+					if (!IsExternAliasValid (alias)) {
+						Report.Error (1679, "Invalid extern alias for /reference. Alias '" + alias + "' is not a valid identifier");
+						Environment.Exit (1);
+					}
+					external_aliases [alias] = assembly;
+					val = assembly;
+					return true;
+				}
+
+				references.Add (val);
 				return true;
 				
 			case "-L":
@@ -1092,7 +1130,24 @@
 
 				string [] refs = value.Split (new char [] { ';', ',' });
 				foreach (string r in refs){
-					references.Add (r);
+					string val = r;
+					int index = val.IndexOf ("=");
+					if (index > -1) {
+						string alias = r.Substring (0, index);
+						string assembly = r.Substring (index + 1);
+						if (assembly.Length == 0) {
+							Report.Error (1680, "Invalid reference alias '" + alias + "='. Missing filename");
+							Environment.Exit (1);
+						}
+						if (!IsExternAliasValid (alias)) {
+							Report.Error (1679, "Invalid extern alias for /reference. Alias '" + alias + "' is not a valid identifier");
+							Environment.Exit (1);
+						}
+						external_aliases [alias] = assembly;
+						val = assembly;
+						return true;
+					}
+					references.Add (val);
 				}
 				return true;
 			}
@@ -1351,6 +1406,28 @@
 
 			return new_args;
 		}
+
+		static bool IsExternAliasValid (string identifier)
+		{
+			if (identifier.Length == 0)
+				return false;
+			if (identifier [0] != '_' && !Char.IsLetter (identifier [0]))
+				return false;
+
+			for (int i = 1; i < identifier.Length; i++) {
+				char c = identifier [i];
+				if (Char.IsLetter (c) || Char.IsDigit (c))
+					continue;
+
+				UnicodeCategory category = Char.GetUnicodeCategory (c);
+				if (category != UnicodeCategory.Format || category != UnicodeCategory.NonSpacingMark ||
+						category != UnicodeCategory.SpacingCombiningMark ||
+						category != UnicodeCategory.ConnectorPunctuation)
+					return false;
+			}
+			
+			return true;
+		}
 		
 		/// <summary>
 		///    Parses the arguments, and drives the compilation
@@ -1377,6 +1454,7 @@
 			encoding = default_encoding;
 
 			references = new ArrayList ();
+			external_aliases = new Hashtable ();
 			soft_references = new ArrayList ();
 			modules = new ArrayList ();
 			link_paths = new ArrayList ();
_______________________________________________
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list

Reply via email to