public override bool Define () { if (!base.Define ()) return false; if (!CheckBase ()) return false; MemberKind kind; if (this is Operator) kind = MemberKind.Operator; else if (this is Destructor) kind = MemberKind.Destructor; else kind = MemberKind.Method; string explicit_name; if (IsPartialDefinition) { caching_flags &= ~Flags.Excluded_Undetected; caching_flags |= Flags.Excluded; // Add to member cache only when a partial method implementation has not been found yet if ((caching_flags & Flags.PartialDefinitionExists) != 0) return true; if (IsExplicitImpl) return true; explicit_name = null; } else { MethodData = new MethodData (this, ModFlags, flags, this, base_method); if (!MethodData.Define (Parent.PartialContainer, GetFullName (MemberName))) return false; explicit_name = MethodData.MetadataName; } spec = new MethodSpec (kind, Parent.Definition, this, ReturnType, parameters, ModFlags); if (MemberName.Arity > 0) spec.IsGeneric = true; Parent.MemberCache.AddMember (this, explicit_name, spec); return true; }
public override void Define (TypeContainer parent) { parameters.Resolve (this); base.Define (parent); Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, ParameterInfo, ModFlags); method_data = new MethodData (method, ModFlags, flags, this); method_data.Define (parent.PartialContainer, method.GetFullName (MemberName)); }
public virtual void Define (TypeContainer parent) { // Fill in already resolved event type to speed things up and // avoid confusing duplicate errors ((Parameter) parameters.FixedParameters[0]).Type = method.member_type; parameters.Types = new TypeSpec[] { method.member_type }; method_data = new MethodData (method, method.ModFlags, method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this); if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName))) return; if (Compiler.Settings.WriteMetadataOnly) block = null; Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, ParameterInfo, method.ModFlags); Spec.IsAccessor = true; }
/// <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 MethodSpec InterfaceMethod (MemberName name, TypeSpec iType, MethodData method, Operation op, out MethodSpec ambiguousCandidate, ref bool optional) { ambiguousCandidate = null; if (pending_implementations == null) return null; TypeSpec ret_type = method.method.ReturnType; ParametersCompiled args = method.method.ParameterInfo; bool is_indexer = method.method is Indexer.SetIndexerMethod || method.method is Indexer.GetIndexerMethod; MethodSpec m; foreach (TypeAndMethods tm in pending_implementations){ if (!(iType == null || tm.type == iType)) continue; int method_count = tm.methods.Count; for (int i = 0; i < method_count; i++){ m = tm.methods [i]; if (m == null) continue; if (is_indexer) { if (!m.IsAccessor || m.Parameters.IsEmpty) continue; } else { if (name.Name != m.Name) continue; if (m.Arity != name.Arity) continue; } if (!TypeSpecComparer.Override.IsEqual (m.Parameters, args)) continue; if (!TypeSpecComparer.Override.IsEqual (m.ReturnType, ret_type)) { tm.found[i] = method; 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 (op != Operation.Lookup) { if (m.IsAccessor != method.method.IsAccessor) continue; // 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. if (m.DeclaringType.IsInterface && iType == null && name.Name != m.Name) { // TODO: This is very expensive comparison tm.need_proxy[i] = method.method.Spec; } else { tm.methods[i] = null; } } else { tm.found [i] = method; optional = tm.optional; } if (op == Operation.Lookup && name.ExplicitInterface != null && ambiguousCandidate == null) { ambiguousCandidate = m; continue; } // // Lookups and ClearOne return // if (op != Operation.ClearAll) return m; } // If a specific type was requested, we can stop now. if (tm.type == iType) break; } m = ambiguousCandidate; ambiguousCandidate = null; return m; }
public void ImplementMethod (MemberName name, TypeSpec ifaceType, MethodData method, bool clear_one, out MethodSpec ambiguousCandidate, ref bool optional) { InterfaceMethod (name, ifaceType, method, clear_one ? Operation.ClearOne : Operation.ClearAll, out ambiguousCandidate, ref optional); }
/// <summary> /// Whether the specified method is an interface method implementation /// </summary> public MethodSpec IsInterfaceMethod (MemberName name, TypeSpec ifaceType, MethodData method, out MethodSpec ambiguousCandidate, ref bool optional) { return InterfaceMethod (name, ifaceType, method, Operation.Lookup, out ambiguousCandidate, ref optional); }