⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decl.cs

📁 C#编译器源代码。Micorsoft开放源代码
💻 CS
📖 第 1 页 / 共 4 页
字号:
		/// <summary>		///   The `MemberTypes' enumeration type is a [Flags] type which means that it may		///   denote multiple member types.  Returns true if the given flags value denotes a		///   single member types.		/// </summary>		public static bool IsSingleMemberType (MemberTypes mt)		{			switch (mt) {			case MemberTypes.Constructor:			case MemberTypes.Event:			case MemberTypes.Field:			case MemberTypes.Method:			case MemberTypes.Property:			case MemberTypes.NestedType:				return true;			default:				return false;			}		}		/// <summary>		///   We encode the MemberTypes and BindingFlags of each members in a "magic"		///   number to speed up the searching process.		/// </summary>		[Flags]		protected enum EntryType {			None		= 0x000,			Instance	= 0x001,			Static		= 0x002,			MaskStatic	= Instance|Static,			Public		= 0x004,			NonPublic	= 0x008,			MaskProtection	= Public|NonPublic,			Declared	= 0x010,			Constructor	= 0x020,			Event		= 0x040,			Field		= 0x080,			Method		= 0x100,			Property	= 0x200,			NestedType	= 0x400,			MaskType	= Constructor|Event|Field|Method|Property|NestedType		}		protected class CacheEntry {			public readonly IMemberContainer Container;			public readonly EntryType EntryType;			public readonly MemberInfo Member;			public CacheEntry (IMemberContainer container, MemberInfo member,					   MemberTypes mt, BindingFlags bf)			{				this.Container = container;				this.Member = member;				this.EntryType = GetEntryType (mt, bf);			}			public override string ToString ()			{				return String.Format ("CacheEntry ({0}:{1}:{2})", Container.Name,						      EntryType, Member);			}		}		/// <summary>		///   This is called each time we're walking up one level in the class hierarchy		///   and checks whether we can abort the search since we've already found what		///   we were looking for.		/// </summary>		protected bool DoneSearching (ArrayList list)		{			//			// We've found exactly one member in the current class and it's not			// a method or constructor.			//			if (list.Count == 1 && !(list [0] is MethodBase))				return true;			//			// Multiple properties: we query those just to find out the indexer			// name			//			if ((list.Count > 0) && (list [0] is PropertyInfo))				return true;			return false;		}		/// <summary>		///   Looks up members with name `name'.  If you provide an optional		///   filter function, it'll only be called with members matching the		///   requested member name.		///		///   This method will try to use the cache to do the lookup if possible.		///		///   Unlike other FindMembers implementations, this method will always		///   check all inherited members - even when called on an interface type.		///		///   If you know that you're only looking for methods, you should use		///   MemberTypes.Method alone since this speeds up the lookup a bit.		///   When doing a method-only search, it'll try to use a special method		///   cache (unless it's a dynamic type or an interface) and the returned		///   MemberInfo's will have the correct ReflectedType for inherited methods.		///   The lookup process will automatically restart itself in method-only		///   search mode if it discovers that it's about to return methods.		/// </summary>		ArrayList global = new ArrayList ();		bool using_global = false;				static MemberInfo [] emptyMemberInfo = new MemberInfo [0];				public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf, string name,						  MemberFilter filter, object criteria)		{			if (using_global)				throw new Exception ();						bool declared_only = (bf & BindingFlags.DeclaredOnly) != 0;			bool method_search = mt == MemberTypes.Method;			// If we have a method cache and we aren't already doing a method-only search,			// then we restart a method search if the first match is a method.			bool do_method_search = !method_search && (method_hash != null);			ArrayList applicable;			// If this is a method-only search, we try to use the method cache if			// possible; a lookup in the method cache will return a MemberInfo with			// the correct ReflectedType for inherited methods.						if (method_search && (method_hash != null))				applicable = (ArrayList) method_hash [name];			else				applicable = (ArrayList) member_hash [name];			if (applicable == null)				return emptyMemberInfo;			//			// 32  slots gives 53 rss/54 size			// 2/4 slots gives 55 rss			//			// Strange: from 25,000 calls, only 1,800			// are above 2.  Why does this impact it?			//			global.Clear ();			using_global = true;			Timer.StartTimer (TimerType.CachedLookup);			EntryType type = GetEntryType (mt, bf);			IMemberContainer current = Container;			// `applicable' is a list of all members with the given member name `name'			// in the current class and all its base classes.  The list is sorted in			// reverse order due to the way how the cache is initialy created (to speed			// things up, we're doing a deep-copy of our base).			for (int i = applicable.Count-1; i >= 0; i--) {				CacheEntry entry = (CacheEntry) applicable [i];				// This happens each time we're walking one level up in the class				// hierarchy.  If we're doing a DeclaredOnly search, we must abort				// the first time this happens (this may already happen in the first				// iteration of this loop if there are no members with the name we're				// looking for in the current class).				if (entry.Container != current) {					if (declared_only || DoneSearching (global))						break;					current = entry.Container;				}				// Is the member of the correct type ?				if ((entry.EntryType & type & EntryType.MaskType) == 0)					continue;				// Is the member static/non-static ?				if ((entry.EntryType & type & EntryType.MaskStatic) == 0)					continue;				// Apply the filter to it.				if (filter (entry.Member, criteria)) {					if ((entry.EntryType & EntryType.MaskType) != EntryType.Method)						do_method_search = false;					global.Add (entry.Member);				}			}			Timer.StopTimer (TimerType.CachedLookup);			// If we have a method cache and we aren't already doing a method-only			// search, we restart in method-only search mode if the first match is			// a method.  This ensures that we return a MemberInfo with the correct			// ReflectedType for inherited methods.			if (do_method_search && (global.Count > 0)){				using_global = false;				return FindMembers (MemberTypes.Method, bf, name, filter, criteria);			}			using_global = false;			MemberInfo [] copy = new MemberInfo [global.Count];			global.CopyTo (copy);			return copy;		}				// find the nested type @name in @this.		public Type FindNestedType (string name)		{			ArrayList applicable = (ArrayList) member_hash [name];			if (applicable == null)				return null;						for (int i = applicable.Count-1; i >= 0; i--) {				CacheEntry entry = (CacheEntry) applicable [i];				if ((entry.EntryType & EntryType.NestedType & EntryType.MaskType) != 0)					return (Type) entry.Member;			}						return null;		}				//		// This finds the method or property for us to override. invocationType is the type where		// the override is going to be declared, name is the name of the method/property, and		// paramTypes is the parameters, if any to the method or property		//		// Because the MemberCache holds members from this class and all the base classes,		// we can avoid tons of reflection stuff.		//		public MemberInfo FindMemberToOverride (Type invocationType, string name, Type [] paramTypes, bool is_property)		{			ArrayList applicable;			if (method_hash != null && !is_property)				applicable = (ArrayList) method_hash [name];			else				applicable = (ArrayList) member_hash [name];						if (applicable == null)				return null;			//			// Walk the chain of methods, starting from the top.			//			for (int i = applicable.Count - 1; i >= 0; i--) {				CacheEntry entry = (CacheEntry) applicable [i];								if ((entry.EntryType & (is_property ? (EntryType.Property | EntryType.Field) : EntryType.Method)) == 0)					continue;				PropertyInfo pi = null;				MethodInfo mi = null;				FieldInfo fi = null;				Type [] cmpAttrs = null;								if (is_property) {					if ((entry.EntryType & EntryType.Field) != 0) {						fi = (FieldInfo)entry.Member;						// TODO: For this case we ignore member type						//fb = TypeManager.GetField (fi);						//cmpAttrs = new Type[] { fb.MemberType };					} else {						pi = (PropertyInfo) entry.Member;						cmpAttrs = TypeManager.GetArgumentTypes (pi);					}				} else {					mi = (MethodInfo) entry.Member;					cmpAttrs = TypeManager.GetArgumentTypes (mi);				}				if (fi != null) {					// TODO: Almost duplicate !					// Check visibility					switch (fi.Attributes & FieldAttributes.FieldAccessMask) {						case FieldAttributes.Private:							//							// A private method is Ok if we are a nested subtype.							// The spec actually is not very clear about this, see bug 52458.							//							if (invocationType != entry.Container.Type &								TypeManager.IsNestedChildOf (invocationType, entry.Container.Type))								continue;							break;						case FieldAttributes.FamANDAssem:						case FieldAttributes.Assembly:							//							// Check for assembly methods							//							if (mi.DeclaringType.Assembly != CodeGen.Assembly.Builder)								continue;							break;					}					return entry.Member;				}				//				// Check the arguments				//				if (cmpAttrs.Length != paramTypes.Length)					continue;					for (int j = cmpAttrs.Length - 1; j >= 0; j --)					if (paramTypes [j] != cmpAttrs [j])						goto next;								//				// get one of the methods because this has the visibility info.				//				if (is_property) {					mi = pi.GetGetMethod (true);					if (mi == null)						mi = pi.GetSetMethod (true);				}								//				// Check visibility				//				switch (mi.Attributes & MethodAttributes.MemberAccessMask) {				case MethodAttributes.Private:					//					// A private method is Ok if we are a nested subtype.					// The spec actually is not very clear about this, see bug 52458.					//					if (invocationType == entry.Container.Type ||					    TypeManager.IsNestedChildOf (invocationType, entry.Container.Type))						return entry.Member;										break;				case MethodAttributes.FamANDAssem:				case MethodAttributes.Assembly:					//					// Check for assembly methods					//					if (mi.DeclaringType.Assembly == CodeGen.Assembly.Builder)						return entry.Member;										break;				default:					//					// A protected method is ok, because we are overriding.					// public is always ok.					//					return entry.Member;				}			next:				;			}						return null;		} 		/// <summary> 		/// The method is looking for conflict with inherited symbols (errors CS0108, CS0109). 		/// We handle two cases. The first is for types without parameters (events, field, properties). 		/// The second are methods, indexers and this is why ignore_complex_types is here. 		/// The latest param is temporary hack. See DoDefineMembers method for more info. 		/// </summary> 		public MemberInfo FindMemberWithSameName (string name, bool ignore_complex_types, MemberInfo ignore_member) 		{ 			ArrayList applicable = null;  			if (method_hash != null) 				applicable = (ArrayList) method_hash [name];  			if (applicable != null) { 				for (int i = applicable.Count - 1; i >= 0; i--) { 					CacheEntry entry = (CacheEntry) applicable [i]; 					if ((entry.EntryType & EntryType.Public) != 0) 						return entry.Member; 				} 			}  			if (member_hash == null) 				return null; 			applicable = (ArrayList) member_hash [name]; 			 			if (applicable != null) { 				for (int i = applicable.Count - 1; i >= 0; i--) { 					CacheEntry entry = (CacheEntry) applicable [i]; 					if ((entry.EntryType & EntryType.Public) != 0 & entry.Member != ignore_member) { 						if (ignore_complex_types) { 							if ((entry.EntryType & EntryType.Method) != 0) 								continue;  							// Does exist easier way how to detect indexer ? 							if ((entry.EntryType & EntryType.Property) != 0) { 								Type[] arg_types = TypeManager.GetArgumentTypes ((PropertyInfo)entry.Member); 								if (arg_types.Length > 0) 									continue; 							} 						} 						return entry.Member; 					} 				} 			}  			return null;  		} 		Hashtable locase_table;  		/// <summary> 		/// Builds low-case table for CLS Compliance test 		/// </summary> 		public Hashtable GetPublicMembers () 		{ 			if (locase_table != null) 				return locase_table;  			locase_table = new Hashtable (); 			foreach (DictionaryEntry entry in member_hash) { 				ArrayList members = (ArrayList)entry.Value; 				for (int ii = 0; ii < members.Count; ++ii) { 					CacheEntry member_entry = (CacheEntry) members [ii];  					if ((member_entry.EntryType & EntryType.Public) == 0) 						continue;  					// TODO: Does anyone know easier way how to detect that member is internal ? 					switch (member_entry.EntryType & EntryType.MaskType) { 						case EntryType.Constructor: 							continue;  						case EntryType.Field: 							if ((((FieldInfo)member_entry.Member).Attributes & (FieldAttributes.Assembly | FieldAttributes.Public)) == FieldAttributes.Assembly) 								continue; 							break;  						case EntryType.Method: 							if ((((MethodInfo)member_entry.Member).Attributes & (MethodAttributes.Assembly | MethodAttributes.Public)) == MethodAttributes.Assembly) 								continue; 							break;  						case EntryType.Property: 							PropertyInfo pi = (PropertyInfo)member_entry.Member; 							if (pi.GetSetMethod () == null && pi.GetGetMethod () == null) 								continue; 							break;  						case EntryType.Event: 							EventInfo ei = (EventInfo)member_entry.Member; 							MethodInfo mi = ei.GetAddMethod (); 							if ((mi.Attributes & (MethodAttributes.Assembly | MethodAttributes.Public)) == MethodAttributes.Assembly) 								continue; 							break; 					} 					string lcase = ((string)entry.Key).ToLower (System.Globalization.CultureInfo.InvariantCulture); 					locase_table [lcase] = member_entry.Member; 					break; 				} 			} 			return locase_table; 		}  		public Hashtable Members { 			get { 				return member_hash; 			} 		}  		/// <summary> 		/// Cls compliance check whether methods or constructors parameters differing only in ref or out, or in array rank 		/// </summary> 		public void VerifyClsParameterConflict (ArrayList al, MethodCore method, MemberInfo this_builder) 		{ 			EntryType tested_type = (method is Constructor ? EntryType.Constructor : EntryType.Method) | EntryType.Public;  			for (int i = 0; i < al.Count; ++i) { 				MemberCache.CacheEntry entry = (MemberCache.CacheEntry) al [i]; 		 				// skip itself 				if (entry.Member == this_builder) 					continue; 		 				if ((entry.EntryType & tested_type) != tested_type) 					continue; 						MethodBase method_to_compare = (MethodBase)entry.Member;				AttributeTester.Result result = AttributeTester.AreOverloadedMethodParamsClsCompliant (					method.ParameterTypes, TypeManager.GetArgumentTypes (method_to_compare)); 				if (result == AttributeTester.Result.Ok) 					continue;				IMethodData md = TypeManager.GetMethod (method_to_compare);				// TODO: now we are ignoring CLSCompliance(false) on method from other assembly which is buggy.				// However it is exactly what csc does.				if (md != null && !md.IsClsCompliaceRequired (method.Parent))					continue; 		 				Report.SymbolRelatedToPreviousError (entry.Member);				switch (result) {					case AttributeTester.Result.RefOutArrayError:						Report.Error (3006, method.Location, "Overloaded method `{0}' differing only in ref or out, or in array rank, is not CLS-compliant", method.GetSignatureForError ());						continue;					case AttributeTester.Result.ArrayArrayError:						Report.Error (3007, method.Location, "Overloaded method `{0}' differing only by unnamed array types is not CLS-compliant", method.GetSignatureForError ());						continue;				}				throw new NotImplementedException (result.ToString ()); 			}  		}	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -