[Mono-dev] Extern alias patch (latest modifications)

Marek Safar marek.safar at seznam.cz
Fri Oct 14 04:25:47 EDT 2005


Hello,

>The attached patch contains the impl of extern alias, and also the clean
>ups to the original code needed for my patch, as required by Hari.
>
>I'm also attaching some tests and tests for errors (observe that cs1679
>and cs1780 are receiving an error, since it looks like '=' in the comp
>options is not handled). Errors 1769 and 1680 are handled since my first
>patch, but hadn't included tests for them ;-) (as required by Marek).
>
>  
>
Sorry, but without complete error test suite I am not going to approve.

         public string GetSignatureForError ()
         {
-            if (NS == Namespace.Root)
+            if (NS == GlobalRootNamespace.Global)
                 return "::global";
             else
                 return ns.Name;
@@ -656,7 +927,7 @@
 
         public override string ToString ()
         {
-            if (NS == Namespace.Root)
+            if (NS == GlobalRootNamespace.Global)
                 return "NamespaceEntry (<root>)";
             else
                 return String.Format ("NamespaceEntry ({0},{1},{2})", 
ns.Name, IsImplicit, ID);

It should be enough to use NS.GetSignatureForError () and NS.ToString ()


+                    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);

Ouch, this is 20 lines copy&paste.

Marek

>By the way, all the tests are running fine.
>  
>
>------------------------------------------------------------------------
>
>Index: typemanager.cs
>===================================================================
>--- typemanager.cs	(revisión: 51651)
>+++ 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,110 +593,26 @@
> 		return (Type) ret;
> 	}
> 
>-	public static 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;
>-			}
>-		}
>-
>-		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;
>-		}
>-
>-		return found_type;
>-	}
>-
> 	/// <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);
>+		foreach (Assembly assembly in assemblies)
>+			GlobalRootNamespace.Global.AddAssemblyReference (assembly);
>+		
>+		foreach (Module m in modules)
>+			GlobalRootNamespace.Global.AddModuleReference (m);
> 
>-		Hashtable cache = null;
>+	}
> 
>-		//
>-		// First add the assembly namespaces
>-		//
>-		if (assembly_get_namespaces != null){
>-			int count = assemblies.Length;
>-
>-			for (int i = 0; i < count; i++){
>-				Assembly a = assemblies [i];
>-				string [] namespaces = (string []) assembly_get_namespaces.Invoke (a, null);
>-				foreach (string ns in namespaces){
>-					if (ns.Length == 0)
>-						continue;
>-					Namespace.LookupNamespace (ns, true);
>-				}
>-			}
>-		} else {
>-			cache = new Hashtable ();
>-			cache.Add ("", null);
>-			foreach (Assembly a in assemblies) {
>-				foreach (Type t in a.GetExportedTypes ()) {
>-					string ns = t.Namespace;
>-					if (ns == null || cache.Contains (ns))
>-						continue;
>-
>-					Namespace.LookupNamespace (ns, true);
>-					cache.Add (ns, null);
>-				}
>-			}
>-		}
>-
>-		//
>-		// Then add module namespaces
>-		//
>-		foreach (Module m in modules) {
>-			if (m == CodeGen.Module.Builder)
>-				continue;
>-			if (cache == null) {
>-				cache = new Hashtable ();
>-				cache.Add ("", null);
>-			}
>-			foreach (Type t in m.GetTypes ()) {
>-				string ns = t.Namespace;
>-				if (ns == null || cache.Contains (ns))
>-					continue;
>-				Namespace.LookupNamespace (ns, true);
>-				cache.Add (ns, null);
>-			}
>-		}
>+	public static Namespace ComputeNamespacesForAlias (string name)
>+	{
>+		Assembly assembly = (Assembly) external_aliases [name];
>+		if (assembly == null)
>+			return null;
>+		
>+		return GlobalRootNamespace.DefineRootNamespace (name, assembly);
> 	}
> 
> 	/// <summary>
>@@ -700,7 +631,7 @@
> 
> 	public static bool NamespaceClash (string name, Location loc)
> 	{
>-		if (Namespace.LookupNamespace (name, false) == null)
>+		if (GlobalRootNamespace.Global.GetNamespace (name, false) == null)
> 			return false;
> 
> 		Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
>@@ -835,7 +766,7 @@
> 	/// </summary>
> 	static Type CoreLookupType (string ns_name, string name)
> 	{
>-		Namespace ns = Namespace.LookupNamespace (ns_name, true);
>+		Namespace ns = GlobalRootNamespace.Global.GetNamespace (ns_name, true);
> 		FullNamedExpression fne = ns.Lookup (RootContext.Tree.Types, name, Location.Null);
> 		Type t = fne == null ? null : fne.Type;
> 		if (t == null)
>Index: namespace.cs
>===================================================================
>--- namespace.cs	(revisión: 51651)
>+++ namespace.cs	(copia de trabajo)
>@@ -9,9 +9,248 @@
> using System;
> using System.Collections;
> using System.Collections.Specialized;
>+using System.Reflection;
> 
> namespace Mono.CSharp {
> 
>+	public class RootNamespace : Namespace
>+	{
>+		static MethodInfo get_namespaces_method;
>+
>+		Assembly referenced_assembly;
>+		Hashtable cached_namespaces;
>+		
>+		static RootNamespace ()
>+		{
>+			get_namespaces_method = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance | BindingFlags.NonPublic);
>+		}
>+
>+		public RootNamespace (Assembly assembly) : base (null, String.Empty)
>+		{
>+			this.referenced_assembly = assembly;
>+			this.cached_namespaces = new Hashtable ();
>+			this.cached_namespaces.Add ("", null);
>+
>+			if (this.referenced_assembly != null)
>+				ComputeNamespacesForAssembly (this.referenced_assembly);
>+		}
>+
>+		public virtual Type LookupTypeReflection (string name, Location loc)
>+		{
>+			return GetTypeInAssembly (referenced_assembly, name);
>+		}
>+
>+		public virtual void RegisterNamespace (Namespace ns)
>+		{
>+			// Do nothing.
>+		}
>+		
>+		protected void ComputeNamespacesForAssembly (Assembly assembly)
>+		{
>+			if (get_namespaces_method != null) {
>+				string [] namespaces = (string []) get_namespaces_method.Invoke (assembly, null);
>+				foreach (string ns in namespaces) {
>+					if (ns.Length == 0)
>+						continue;
>+
>+					// Method from parent class Namespace
>+					GetNamespace (ns, true);
>+				}
>+			} else {
>+				//cached_namespaces.Add ("", null);
>+				foreach (Type t in assembly.GetExportedTypes ()) {
>+					string ns = t.Namespace;
>+					if (ns == null || cached_namespaces.Contains (ns))
>+						continue;
>+
>+					// Method from parent class Namespace
>+					GetNamespace (ns, true);
>+					cached_namespaces.Add (ns, null);
>+				}
>+			}
>+		}
>+		
>+		protected Type GetTypeInAssembly (Assembly assembly, string name)
>+		{
>+			Type t = 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;
>+		}
>+
>+		protected Hashtable CachedNamespaces {
>+			get {
>+				return cached_namespaces;
>+			}
>+		}
>+
>+	}
>+
>+	public class GlobalRootNamespace : RootNamespace
>+	{
>+		static ArrayList all_namespaces;
>+		static Hashtable namespaces_map;
>+		static Hashtable root_namespaces;
>+		public static GlobalRootNamespace Global;
>+		
>+		Assembly [] assemblies;
>+		Module [] modules;
>+		
>+		public static void Reset ()
>+		{
>+			all_namespaces = new ArrayList ();
>+			namespaces_map = new Hashtable ();
>+			root_namespaces = new Hashtable ();
>+			
>+			Global = new GlobalRootNamespace ();
>+		}
>+		
>+		static GlobalRootNamespace ()
>+		{
>+			Reset ();
>+		}
>+
>+		public GlobalRootNamespace () : base (null)
>+		{
>+			assemblies = new Assembly [0];
>+			modules = new Module [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;
>+			ComputeNamespacesForAssembly (assembly);
>+		}
>+
>+		public void AddModuleReference (Module module)
>+		{
>+			Module [] tmp = new Module [modules.Length + 1];
>+			Array.Copy (modules, 0, tmp, 0, modules.Length);
>+			tmp [modules.Length] = module;
>+
>+			modules = tmp;
>+			
>+			if (module != CodeGen.Module.Builder)
>+				ComputeNamespacesForModule (module);
>+		}
>+
>+		void ComputeNamespacesForModule (Module module)
>+		{
>+			foreach (Type t in module.GetTypes ()) {
>+				string ns = t.Namespace;
>+				if (ns == null || CachedNamespaces.Contains (ns))
>+					continue;
>+
>+				GetNamespace (ns, true);
>+				CachedNamespaces.Add (ns, null);
>+			}
>+		}
>+
>+		public override Type LookupTypeReflection (string name, Location loc)
>+		{
>+			Type found_type = null;
>+		
>+			foreach (Assembly a in assemblies) {
>+				Type t = GetTypeInAssembly (a, name);
>+				if (t == null)
>+					continue;
>+					
>+				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 module in modules) {
>+				Type t = module.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;
>+			}
>+
>+			return found_type;
>+		}
>+
>+		public override void RegisterNamespace (Namespace child)
>+		{
>+			all_namespaces.Add (child);
>+			if (namespaces_map.Contains (child.Name))
>+				return;
>+			namespaces_map [child.Name] = true;
>+		}
>+		
>+		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;
>+		}
>+		
>+		public static bool IsNamespace (string name)
>+		{
>+			return namespaces_map [name] != null;
>+		}
>+
>+		public static ArrayList UserDefinedNamespaces {
>+			get { return all_namespaces; }
>+		}
>+
>+		public static void VerifyUsingForAll ()
>+		{
>+			foreach (Namespace ns in all_namespaces)
>+				ns.VerifyUsing ();
>+		}
>+		
>+		public static void DefineNamespacesForAll (SymbolWriter symwriter)
>+		{
>+			foreach (Namespace ns in all_namespaces)
>+				ns.DefineNamespaces (symwriter);
>+		}
>+
>+		public override string ToString ()
>+		{
>+			return "Namespace (<root>)";
>+		}
>+
>+		public override string GetSignatureForError ()
>+		{
>+			return "::global";
>+		}
>+
>+	}
>+
> 	/// <summary>
> 	///   Keeps track of the namespaces defined in the C# code.
> 	///
>@@ -19,8 +258,6 @@
> 	///   compiler parse/intermediate tree during name resolution.
> 	/// </summary>
> 	public class Namespace : FullNamedExpression {
>-		static ArrayList all_namespaces;
>-		static Hashtable namespaces_map;
> 		
> 		Namespace parent;
> 		string fullname;
>@@ -28,24 +265,10 @@
> 		Hashtable namespaces;
> 		IDictionary declspaces;
> 		Hashtable cached_types;
>+		RootNamespace root;
> 
> 		public readonly MemberName MemberName;
> 
>-		public static Namespace Root;
>-
>-		static Namespace ()
>-		{
>-			Reset ();
>-		}
>-
>-		public static void Reset ()
>-		{
>-			all_namespaces = new ArrayList ();
>-			namespaces_map = new Hashtable ();
>-
>-			Root = new Namespace (null, "");
>-		}
>-
> 		/// <summary>
> 		///   Constructor Takes the current namespace and the
> 		///   name.  This is bootstrapped with parent == null
>@@ -60,6 +283,14 @@
> 
> 			this.parent = parent;
> 
>+			if (parent != null)
>+				this.root = parent.root;
>+			else
>+				this.root = this as RootNamespace;
>+
>+			if (this.root == null)
>+				throw new InternalErrorException ("Root namespaces must be created using RootNamespace");
>+			
> 			string pname = parent != null ? parent.Name : "";
> 				
> 			if (pname == "")
>@@ -81,10 +312,7 @@
> 			namespaces = new Hashtable ();
> 			cached_types = new Hashtable ();
> 
>-			all_namespaces.Add (this);
>-			if (namespaces_map.Contains (fullname))
>-				return;
>-			namespaces_map [fullname] = true;
>+			root.RegisterNamespace (this);
> 		}
> 
> 		public override Expression DoResolve (EmitContext ec)
>@@ -97,14 +325,9 @@
> 			throw new InternalErrorException ("Expression tree referenced namespace " + fullname + " during Emit ()");
> 		}
> 
>-		public static bool IsNamespace (string name)
>-		{
>-			return namespaces_map [name] != null;
>-		}
>-
> 		public override string GetSignatureForError ()
> 		{
>-			return Name.Length == 0 ? "::global" : Name;
>+			return Name;
> 		}
> 		
> 		public Namespace GetNamespace (string name, bool create)
>@@ -133,11 +356,6 @@
> 			return ns;
> 		}
> 
>-		public static Namespace LookupNamespace (string name, bool create)
>-		{
>-			return Root.GetNamespace (name, create);
>-		}
>-
> 		TypeExpr LookupType (string name, Location loc)
> 		{
> 			if (cached_types.Contains (name))
>@@ -161,7 +379,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;
> 
>@@ -195,10 +413,22 @@
> 			declspaces.Add (name, ds);
> 		}
> 
>-		static public ArrayList UserDefinedNamespaces {
>-			get { return all_namespaces; }
>+		/// <summary>
>+		///   Used to validate that all the using clauses are correct
>+		///   after we are finished parsing all the files.  
>+		/// </summary>
>+		public void VerifyUsing ()
>+		{
>+			foreach (NamespaceEntry entry in entries)
>+				entry.VerifyUsing ();
> 		}
> 
>+		public void DefineNamespaces (SymbolWriter symwriter)
>+		{
>+			foreach (NamespaceEntry entry in entries)
>+				entry.DefineNamespace (symwriter);
>+		}
>+
> 		/// <summary>
> 		///   The qualified name of the current namespace
> 		/// </summary>
>@@ -218,32 +448,9 @@
> 			get { return parent; }
> 		}
> 
>-		public static void DefineNamespaces (SymbolWriter symwriter)
>-		{
>-			foreach (Namespace ns in all_namespaces) {
>-				foreach (NamespaceEntry entry in ns.entries)
>-					entry.DefineNamespace (symwriter);
>-			}
>-		}
>-
>-		/// <summary>
>-		///   Used to validate that all the using clauses are correct
>-		///   after we are finished parsing all the files.  
>-		/// </summary>
>-		public static void VerifyUsing ()
>-		{
>-			foreach (Namespace ns in all_namespaces) {
>-				foreach (NamespaceEntry entry in ns.entries)
>-					entry.VerifyUsing ();
>-			}
>-		}
>-
> 		public override string ToString ()
> 		{
>-			if (this == Root)
>-				return "Namespace (<root>)";
>-			else
>-				return String.Format ("Namespace ({0})", Name);
>+			return String.Format ("Namespace ({0})", Name);
> 		}
> 	}
> 
>@@ -256,6 +463,7 @@
> 		Hashtable aliases;
> 		ArrayList using_clauses;
> 		public bool DeclarationFound = false;
>+		public bool UsingFound = false;
> 
> 		//
> 		// This class holds the location where a using definition is
>@@ -304,24 +512,35 @@
> 			}
> 		}
> 
>-		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, Location loc)
> 			{
> 				Name = name;
>-				Alias = alias.GetTypeExpression ();
> 				NamespaceEntry = entry;
> 				Location = loc;
> 			}
>+			
>+			protected FullNamedExpression resolved;
> 
>-			FullNamedExpression resolved;
>+			public abstract FullNamedExpression Resolve ();
>+		}
> 
>-			public FullNamedExpression Resolve ()
>+		public class LocalAliasEntry : AliasEntry
>+		{
>+			public readonly Expression Alias;
>+			
>+			public LocalAliasEntry (NamespaceEntry entry, string name, MemberName alias, Location loc) :
>+				base (entry, name, loc)
> 			{
>+				Alias = alias.GetTypeExpression ();
>+			}
>+
>+			public override FullNamedExpression Resolve ()
>+			{
> 				if (resolved != null)
> 					return resolved;
> 
>@@ -334,6 +553,28 @@
> 			}
> 		}
> 
>+		public class ExternAliasEntry : AliasEntry 
>+		{
>+			public ExternAliasEntry (NamespaceEntry entry, string name, Location loc) :
>+				base (entry, name, loc)
>+			{
>+			}
>+
>+			public override FullNamedExpression Resolve ()
>+			{
>+				if (resolved != null)
>+					return resolved;
>+
>+				resolved = TypeManager.ComputeNamespacesForAlias (Name);
>+				if (resolved == null) {
>+					Report.Error (430, Location, "The extern alias '" + Name +
>+									"' was not specified in a /reference option");
>+				}
>+				
>+				return resolved;
>+			}
>+		}
>+
> 		public NamespaceEntry (NamespaceEntry parent, SourceFile file, string name, Location loc)
> 		{
> 			this.parent = parent;
>@@ -344,9 +585,10 @@
> 			if (parent != null)
> 				ns = parent.NS.GetNamespace (name, true);
> 			else if (name != null)
>-				ns = Namespace.LookupNamespace (name, true);
>+				ns = GlobalRootNamespace.Global.GetNamespace (name, true);
> 			else
>-				ns = Namespace.Root;
>+				ns = GlobalRootNamespace.Global;
>+			
> 			ns.AddNamespaceEntry (this);
> 		}
> 
>@@ -456,9 +698,35 @@
> 				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);
> 		}
> 
>+		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,14 +909,17 @@
> 				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) {
>+							LocalAliasEntry local = alias as LocalAliasEntry;
>+							Error_NamespaceNotFound (local.Location, local.Alias.ToString ());
>+						}
> 				}
> 			}
> 		}
> 
> 		public string GetSignatureForError ()
> 		{
>-			if (NS == Namespace.Root)
>+			if (NS == GlobalRootNamespace.Global)
> 				return "::global";
> 			else
> 				return ns.Name;
>@@ -656,7 +927,7 @@
> 
> 		public override string ToString ()
> 		{
>-			if (NS == Namespace.Root)
>+			if (NS == GlobalRootNamespace.Global)
> 				return "NamespaceEntry (<root>)";
> 			else
> 				return String.Format ("NamespaceEntry ({0},{1},{2})", ns.Name, IsImplicit, ID);
>Index: ecore.cs
>===================================================================
>--- ecore.cs	(revisión: 51651)
>+++ ecore.cs	(copia de trabajo)
>@@ -2212,7 +2212,7 @@
> 				lookup_name = name.Substring (0, pos);
> 			}
> 
>-			FullNamedExpression resolved = Namespace.Root.Lookup (ec.DeclSpace, lookup_name, Location.Null);
>+			FullNamedExpression resolved = GlobalRootNamespace.Global.Lookup (ec.DeclSpace, lookup_name, Location.Null);
> 
> 			if (resolved != null && rest != null) {
> 				// Now handle the rest of the the name.
>Index: delegate.cs
>===================================================================
>--- delegate.cs	(revisión: 51651)
>+++ delegate.cs	(copia de trabajo)
>@@ -82,7 +82,7 @@
> 			ec = new EmitContext (this, this, Location, null, null, ModFlags, false);
> 
> 			if (TypeManager.multicast_delegate_type == null && !RootContext.StdLib) {
>-				Namespace system = Namespace.LookupNamespace ("System", true);
>+				Namespace system = GlobalRootNamespace.Global.GetNamespace ("System", true);
> 				TypeExpr expr = system.Lookup (this, "MulticastDelegate", Location) as TypeExpr;
> 				TypeManager.multicast_delegate_type = expr.ResolveType (ec);
> 			}
>@@ -239,7 +239,7 @@
> 			}
> 			if (Parameters.ArrayParameter != null){
> 				if (TypeManager.param_array_type == null && !RootContext.StdLib) {
>-					Namespace system = Namespace.LookupNamespace ("System", true);
>+					Namespace system = GlobalRootNamespace.Global.GetNamespace ("System", true);
> 					TypeExpr expr = system.Lookup (this, "ParamArrayAttribute", Location) as TypeExpr;
> 					TypeManager.param_array_type = expr.ResolveType (ec);
> 				}
>Index: cs-parser.jay
>===================================================================
>--- cs-parser.jay	(revisión: 51651)
>+++ 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
>@@ -337,6 +358,7 @@
> 	  {
> 		LocatedToken lt = (LocatedToken) $2;
> 		current_namespace.UsingAlias (lt.Value, (MemberName) $4, (Location) $1);
>+		current_namespace.UsingFound = true;
> 	  }
> 	| USING error {
> 		CheckIdentifierToken (yyToken, GetLocation ($2));
>@@ -347,6 +369,7 @@
> 	: USING namespace_name SEMICOLON 
> 	  {
> 		current_namespace.Using ((MemberName) $2, (Location) $1);
>+		current_namespace.UsingFound = true;
>           }
> 	;
> 
>@@ -393,6 +416,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 +427,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: 51651)
>+++ 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 ();
>@@ -1612,7 +1690,7 @@
> 			//
> 			// Verify using aliases now
> 			//
>-			Namespace.VerifyUsing ();
>+			GlobalRootNamespace.VerifyUsingForAll ();
> 			
> 			if (Report.Errors > 0){
> 				return false;
>@@ -1825,7 +1903,7 @@
> 			Report.Reset ();
> 			TypeManager.Reset ();
> 			TypeHandle.Reset ();
>-			Namespace.Reset ();
>+			GlobalRootNamespace.Reset ();
> 			CodeGen.Reset ();
> 		}
> 	}
>Index: expression.cs
>===================================================================
>--- expression.cs	(revisión: 51651)
>+++ expression.cs	(copia de trabajo)
>@@ -7339,7 +7339,7 @@
> 		public override FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent)
> 		{
> 			if (alias == "global")
>-				return new MemberAccess (Namespace.Root, identifier, loc).ResolveAsTypeStep (ec, silent);
>+				return new MemberAccess (GlobalRootNamespace.Global, identifier, loc).ResolveAsTypeStep (ec, silent);
> 
> 			int errors = Report.Errors;
> 			FullNamedExpression fne = ec.DeclSpace.NamespaceEntry.LookupAlias (alias);
>@@ -7360,7 +7360,7 @@
> 		{
> 			FullNamedExpression fne;
> 			if (alias == "global") {
>-				fne = Namespace.Root;
>+				fne = GlobalRootNamespace.Global;
> 			} else {
> 				int errors = Report.Errors;
> 				fne = ec.DeclSpace.NamespaceEntry.LookupAlias (alias);
>Index: symbolwriter.cs
>===================================================================
>--- symbolwriter.cs	(revisión: 51651)
>+++ symbolwriter.cs	(copia de trabajo)
>@@ -51,7 +51,7 @@
> 				typeof (GetGuidFunc), mi);
> 
> 			Location.DefineSymbolDocuments (this);
>-			Namespace.DefineNamespaces (this);
>+			GlobalRootNamespace.DefineNamespacesForAll (this);
> 
> 			return true;
> 		}
>Index: doc.cs
>===================================================================
>--- doc.cs	(revisión: 51651)
>+++ doc.cs	(copia de trabajo)
>@@ -594,7 +594,7 @@
> 			}
> 
> 			// don't use identifier here. System[] is not alloed.
>-			if (Namespace.IsNamespace (name)) {
>+			if (GlobalRootNamespace.IsNamespace (name)) {
> 				xref.SetAttribute ("cref", "N:" + name);
> 				return; // a namespace
> 			}
>  
>
>------------------------------------------------------------------------
>
>_______________________________________________
>Mono-devel-list mailing list
>Mono-devel-list at lists.ximian.com
>http://lists.ximian.com/mailman/listinfo/mono-devel-list
>  
>




More information about the Mono-devel-list mailing list