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