📄 namespace.cs
字号:
//// namespace.cs: Tracks namespaces//// Author:// Miguel de Icaza (miguel@ximian.com)//// (C) 2001 Ximian, Inc.//using System;using System.Collections;using System.Collections.Specialized;using System.Reflection;namespace Mono.CSharp { public class RootNamespace : Namespace { static MethodInfo get_namespaces_method; string alias_name; Assembly referenced_assembly; Hashtable all_namespaces; static Hashtable root_namespaces; public static GlobalRootNamespace Global; static RootNamespace () { get_namespaces_method = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance | BindingFlags.NonPublic); Reset (); } public static void Reset () { root_namespaces = new Hashtable (); Global = new GlobalRootNamespace (); root_namespaces ["global"] = Global; } protected RootNamespace (string alias_name, Assembly assembly) : base (null, String.Empty) { this.alias_name = alias_name; referenced_assembly = assembly; all_namespaces = new Hashtable (); all_namespaces.Add ("", this); if (referenced_assembly != null) ComputeNamespaces (this.referenced_assembly); } public static void DefineRootNamespace (string name, Assembly assembly) { if (name == "global") { // FIXME: Add proper error number Report.Error (-42, "Cannot define an external alias named `global'"); return; } RootNamespace retval = GetRootNamespace (name); if (retval == null || retval.referenced_assembly != assembly) root_namespaces [name] = new RootNamespace (name, assembly); } public static RootNamespace GetRootNamespace (string name) { return (RootNamespace) root_namespaces [name]; } public virtual Type LookupTypeReflection (string name, Location loc) { return GetTypeInAssembly (referenced_assembly, name); } public void RegisterNamespace (Namespace child) { if (child != this) all_namespaces.Add (child.Name, child); } public bool IsNamespace (string name) { return all_namespaces.Contains (name); } protected void EnsureNamespace (string dotted_name) { if (dotted_name != null && dotted_name != "" && ! IsNamespace (dotted_name)) GetNamespace (dotted_name, true); } protected void ComputeNamespaces (Assembly assembly) { if (get_namespaces_method != null) { string [] namespaces = (string []) get_namespaces_method.Invoke (assembly, null); foreach (string ns in namespaces) EnsureNamespace (ns); return; } foreach (Type t in assembly.GetExportedTypes ()) EnsureNamespace (t.Namespace); } protected static 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 null; return t; } public override string ToString () { return String.Format ("RootNamespace ({0}::)", alias_name); } public override string GetSignatureForError () { return alias_name + "::"; } } public class GlobalRootNamespace : RootNamespace { Assembly [] assemblies; Module [] modules; public GlobalRootNamespace () : base ("global", null) { assemblies = new Assembly [0]; } public Assembly [] Assemblies { get { return assemblies; } } public Module [] Modules { get { return modules; } } public void AddAssemblyReference (Assembly a) { foreach (Assembly assembly in assemblies) { if (a == assembly) return; } int top = assemblies.Length; Assembly [] n = new Assembly [top + 1]; assemblies.CopyTo (n, 0); n [top] = a; assemblies = n; ComputeNamespaces (a); } public void AddModuleReference (Module m) { int top = modules != null ? modules.Length : 0; Module [] n = new Module [top + 1]; if (modules != null) modules.CopyTo (n, 0); n [top] = m; modules = n; if (m == CodeGen.Module.Builder) return; foreach (Type t in m.GetTypes ()) EnsureNamespace (t.Namespace); } 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; } if (modules != null) { 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; } } /// <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 : FullNamedExpression { Namespace parent; string fullname; Hashtable namespaces; IDictionary declspaces; Hashtable cached_types; RootNamespace root; public readonly MemberName MemberName; /// <summary> /// Constructor Takes the current namespace and the /// name. This is bootstrapped with parent == null /// and name = "" /// </summary> public Namespace (Namespace parent, string name) { // Expression members. this.eclass = ExprClass.Namespace; this.Type = null; this.loc = Location.Null; 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 == "") fullname = name; else fullname = parent.Name + "." + name; if (fullname == null) throw new InternalErrorException ("Namespace has a null fullname"); if (parent != null && parent.MemberName != MemberName.Null) MemberName = new MemberName (parent.MemberName, name); else if (name == "") MemberName = MemberName.Null; else MemberName = new MemberName (name); namespaces = new Hashtable (); cached_types = new Hashtable (); root.RegisterNamespace (this); } 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 override string GetSignatureForError () { return Name; } public Namespace GetNamespace (string name, bool create) { int pos = name.IndexOf ('.'); Namespace ns; string first; if (pos >= 0) first = name.Substring (0, pos); else first = name; ns = (Namespace) namespaces [first]; if (ns == null) { if (!create) return null; ns = new Namespace (this, first); namespaces.Add (first, ns); } if (pos >= 0) ns = ns.GetNamespace (name.Substring (pos + 1), create); return ns; } TypeExpr LookupType (string name, Location loc) { if (cached_types.Contains (name)) return cached_types [name] as TypeExpr; Type t = null; if (declspaces != null) { DeclSpace tdecl = declspaces [name] as DeclSpace; if (tdecl != null) { // // Note that this is not: // // t = tdecl.DefineType () // // This is to make it somewhat more useful when a DefineType // fails due to problems in nested types (more useful in the sense // of fewer misleading error messages) // tdecl.DefineType (); t = tdecl.TypeBuilder; } } string lookup = t != null ? t.FullName : (fullname == "" ? name : fullname + "." + name); Type rt = root.LookupTypeReflection (lookup, loc); if (t == null) t = rt; TypeExpr te = t == null ? null : new TypeExpression (t, Location.Null); cached_types [name] = te; return te; } public FullNamedExpression Lookup (DeclSpace ds, string name, Location loc) { if (namespaces.Contains (name)) return (Namespace) namespaces [name]; TypeExpr te = LookupType (name, loc); if (te == null || !ds.CheckAccessLevel (te.Type)) return null; return te; } public void AddDeclSpace (string name, DeclSpace ds) { if (declspaces == null) declspaces = new HybridDictionary (); declspaces.Add (name, ds); } /// <summary> /// The qualified name of the current namespace /// </summary> public string Name { get { return fullname; } } public override string FullName { get { return fullname; } } /// <summary> /// The parent of this namespace, used by the parser to "Pop" /// the current namespace declaration /// </summary> public Namespace Parent { get { return parent; } } public override string ToString () { return String.Format ("Namespace ({0})", Name); } } public class NamespaceEntry { Namespace ns; NamespaceEntry parent, implicit_parent; SourceFile file; int symfile_id; Hashtable aliases; ArrayList using_clauses; public bool DeclarationFound = false; public bool UsingFound = false; static ArrayList entries = new ArrayList (); public static void Reset () { entries = new ArrayList (); } // // This class holds the location where a using definition is // done, and whether it has been used by the program or not. // // We use this to flag using clauses for namespaces that do not // exist. // public class UsingEntry { public readonly MemberName Name; readonly Expression Expr; readonly NamespaceEntry NamespaceEntry; readonly Location Location; public UsingEntry (NamespaceEntry entry, MemberName name, Location loc) { Name = name; Expr = name.GetTypeExpression (); NamespaceEntry = entry; Location = loc;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -