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

📄 pending.cs

📁 C#编译器源代码。Micorsoft开放源代码
💻 CS
📖 第 1 页 / 共 2 页
字号:
			// If we are implementing an abstract class, and we are not			// ourselves abstract, and there are abstract methods (C# allows			// abstract classes that have no abstract methods), then allocate			// one slot.			//			// We also pre-compute the methods.			//			bool implementing_abstract = ((b != null) && b.IsAbstract && !type_builder.IsAbstract);			ArrayList abstract_methods = null;			if (implementing_abstract){				abstract_methods = GetAbstractMethods (b);								if (abstract_methods == null)					implementing_abstract = false;			}						int total = missing_interfaces.Length +  (implementing_abstract ? 1 : 0);			if (total == 0)				return null;			return new PendingImplementation (container, missing_interfaces, abstract_methods, total);		}		public enum Operation {			//			// If you change this, review the whole InterfaceMethod routine as there			// are a couple of assumptions on these three states			//			Lookup, ClearOne, ClearAll		}		/// <summary>		///   Whether the specified method is an interface method implementation		/// </summary>		public MethodInfo IsInterfaceMethod (Type t, string name, Type ret_type, ParameterData args)		{			return InterfaceMethod (t, name, ret_type, args, Operation.Lookup, null);		}		public MethodInfo IsInterfaceIndexer (Type t, Type ret_type, ParameterData args)		{			return InterfaceMethod (t, null, ret_type, args, Operation.Lookup, null);		}		public void ImplementMethod (Type t, string name, Type ret_type, ParameterData args, bool clear_one) 		{			InterfaceMethod (t, name, ret_type, args,					 clear_one ? Operation.ClearOne : Operation.ClearAll, null);		}		public void ImplementIndexer (Type t, MethodInfo mi, Type ret_type, ParameterData args, bool clear_one) 		{			InterfaceMethod (t, null, ret_type, args,					 clear_one ? Operation.ClearOne : Operation.ClearAll, mi);		}				/// <remarks>		///   If a method in Type `t' (or null to look in all interfaces		///   and the base abstract class) with name `Name', return type `ret_type' and		///   arguments `args' implements an interface, this method will		///   return the MethodInfo that this method implements.		///		///   If `name' is null, we operate solely on the method's signature.  This is for		///   instance used when implementing indexers.		///		///   The `Operation op' controls whether to lookup, clear the pending bit, or clear		///   all the methods with the given signature.		///		///   The `MethodInfo need_proxy' is used when we're implementing an interface's		///   indexer in a class.  If the new indexer's IndexerName does not match the one		///   that was used in the interface, then we always need to create a proxy for it.		///		/// </remarks>		public MethodInfo InterfaceMethod (Type t, string name, Type ret_type, ParameterData args,						   Operation op, MethodInfo need_proxy)		{			int arg_len = args.Count;			if (pending_implementations == null)				return null;			foreach (TypeAndMethods tm in pending_implementations){				if (!(t == null || tm.type == t))					continue;				int method_count = tm.methods.Length;				MethodInfo m;				for (int i = 0; i < method_count; i++){					m = tm.methods [i];					if (m == null)						continue;					//					// `need_proxy' is not null when we're implementing an					// interface indexer and this is Clear(One/All) operation.					//					// If `name' is null, then we do a match solely based on the					// signature and not on the name (this is done in the Lookup					// for an interface indexer).					//					if (name == null){						if (m.Name != tm.get_indexer_name && m.Name != tm.set_indexer_name)							continue;					} else if ((need_proxy == null) && (name != m.Name))						continue;					if (ret_type != m.ReturnType &&					    !(ret_type == null && m.ReturnType == TypeManager.void_type) &&					    !(m.ReturnType == null && ret_type == TypeManager.void_type))						continue;					//					// Check if we have the same parameters					//					if (tm.args [i] == null && arg_len != 0)						continue;					if (tm.args [i] != null && tm.args [i].Length != arg_len)						continue;					int j;					for (j = 0; j < arg_len; j++) {						if (tm.args [i][j] != args.ParameterType (j))							break;						if (tm.mods [i][j] == args.ParameterModifier (j))							continue;						// The modifiers are different, but if one of them						// is a PARAMS modifier, and the other isn't, ignore						// the difference.						if (tm.mods [i][j] != Parameter.Modifier.PARAMS &&						    args.ParameterModifier (j) != Parameter.Modifier.PARAMS)							break;					}					if (j != arg_len)						continue;					if (op != Operation.Lookup){						// If `t != null', then this is an explicitly interface						// implementation and we can always clear the method.						// `need_proxy' is not null if we're implementing an						// interface indexer.  In this case, we need to create						// a proxy if the implementation's IndexerName doesn't						// match the IndexerName in the interface.						bool name_matches = false;						if (name == m.Name || m.Name == tm.get_indexer_name || m.Name == tm.set_indexer_name)							name_matches = true;												if ((t == null) && (need_proxy != null) && !name_matches)							tm.need_proxy [i] = need_proxy;						else 							tm.methods [i] = null;					}					tm.found [i] = true;					//					// Lookups and ClearOne return					//					if (op != Operation.ClearAll)						return m;				}				// If a specific type was requested, we can stop now.				if (tm.type == t)					return null;			}			return null;		}		/// <summary>		///   C# allows this kind of scenarios:		///   interface I { void M (); }		///   class X { public void M (); }		///   class Y : X, I { }		///		///   For that case, we create an explicit implementation function		///   I.M in Y.		/// </summary>		void DefineProxy (Type iface, MethodInfo base_method, MethodInfo iface_method,				  Type [] args)		{			MethodBuilder proxy;			string proxy_name = iface.Name + "." + iface_method.Name;			proxy = container.TypeBuilder.DefineMethod (				proxy_name,				MethodAttributes.HideBySig |				MethodAttributes.NewSlot |				MethodAttributes.Virtual,				CallingConventions.Standard | CallingConventions.HasThis,				base_method.ReturnType, args);			int top = args.Length;			ILGenerator ig = proxy.GetILGenerator ();			for (int i = 0; i <= top; i++)				ParameterReference.EmitLdArg (ig, i);			ig.Emit (OpCodes.Call, base_method);			ig.Emit (OpCodes.Ret);			container.TypeBuilder.DefineMethodOverride (proxy, iface_method);		}				/// <summary>		///   This function tells whether one of our base classes implements		///   the given method (which turns out, it is valid to have an interface		///   implementation in a base		/// </summary>		bool BaseImplements (Type iface_type, MethodInfo mi)		{			MethodSignature ms;						Type [] args = TypeManager.GetArgumentTypes (mi);			ms = new MethodSignature (mi.Name, mi.ReturnType, args);			MemberList list = TypeContainer.FindMembers (				container.TypeBuilder.BaseType, MemberTypes.Method | MemberTypes.Property,				BindingFlags.Public | BindingFlags.Instance,				MethodSignature.method_signature_filter, ms);			if (list.Count == 0)				return false;			if (TypeManager.ImplementsInterface (container.TypeBuilder.BaseType, iface_type))				return true;			//			// FIXME: We should be creating fewer proxies.  The runtime can handle most cases.  			// 	  At worst, if we can't avoid creating the proxy, we may need to make the 			//        proxy use Callvirt.			//			MethodInfo base_method = (MethodInfo) list [0];			if (!base_method.IsAbstract && !base_method.IsVirtual)				DefineProxy (iface_type, base_method, mi, args);			return true;		}		/// <summary>		///   Verifies that any pending abstract methods or interface methods		///   were implemented.		/// </summary>		public bool VerifyPendingMethods ()		{			int top = pending_implementations.Length;			bool errors = false;			int i;						for (i = 0; i < top; i++){				Type type = pending_implementations [i].type;				int j = 0;				foreach (MethodInfo mi in pending_implementations [i].methods){					if (mi == null)						continue;					if (type.IsInterface){						MethodInfo need_proxy =							pending_implementations [i].need_proxy [j];						if (need_proxy != null) {							Type [] args = TypeManager.GetArgumentTypes (mi);							DefineProxy (type, need_proxy, mi, args);							continue;						}						if (BaseImplements (type, mi))							continue;												if (pending_implementations [i].optional)							continue;						Report.SymbolRelatedToPreviousError (mi);						if (pending_implementations [i].found [j]) {							if (mi.IsSpecialName) {								string name = TypeManager.CSharpName (mi.DeclaringType) + '.' + mi.Name.Substring (4);								Report.Error (551, container.Location, "Explicit interface implementation `{0}.{1}' is missing accessor `{2}'",									container.GetSignatureForError (), name, TypeManager.CSharpSignature (mi, true));							} else {								string[] methodLabel = TypeManager.CSharpSignature (mi).Split ('.');								Report.Error (536, container.Location,									"`{0}' does not implement interface member `{1}'. `{2}.{3}' " +									"is either static, not public, or has the wrong return type",									container.Name, TypeManager.CSharpSignature (mi),									container.Name, methodLabel[methodLabel.Length - 1]);							}						}						else {							Report.Error (535, container.Location, "`{0}' does not implement interface member `{1}'",								container.GetSignatureForError (), TypeManager.CSharpSignature (mi));						}					} else {						Report.Error (534, container.Location, "`{0}' does not implement inherited abstract member `{1}'",							container.GetSignatureForError (), TypeManager.CSharpSignature (mi, true));					}					errors = true;					j++;				}			}			return errors;		}	} /* end of class */}

⌨️ 快捷键说明

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