public bool ContainsMethod(Method method, bool check_ifaces, bool check_base_ifaces) { // background: bug #10123. // Visibility check was introduced - and required so far - to block "public overrides protected" methods // (which is allowed in Java but not in C#). // The problem is, it does not *always* result in error and generates callable code, and we depend on // that fact in several classes that implements some interface that requires "public Object clone()". // // This visibility inconsistency results in 1) error for abstract methods and 2) warning for virtual methods. // Hence, for abstract methods we dare to ignore visibility difference and treat it as override, // *then* C# compiler will report this inconsistency as error that users need to fix manually, but // with obvious message saying "it is because of visibility consistency", // not "abstract member not implemented" (it is *implemented* in different visibility and brings confusion). // For virtual methods, just check the visibility difference and treat as different method. // Regardless of whether it is actually an override or not, we just invoke Java method. if (jni_sig_hash.ContainsKey(method.JavaName + method.JniSignature)) { var bm = jni_sig_hash [method.JavaName + method.JniSignature]; if (bm.Visibility == method.Visibility || bm.IsAbstract) { return(true); } } if (check_ifaces) { foreach (ISymbol isym in Interfaces) { if ((isym is GenericSymbol ? (isym as GenericSymbol).Gen : isym) is InterfaceGen igen && igen.ContainsMethod(method, true)) { return(true); } } } return(BaseSymbol != null && BaseSymbol.ContainsMethod(method, check_base_ifaces, check_base_ifaces)); }
protected virtual bool OnValidate(CodeGenerationOptions opt, GenericParameterDefinitionList type_params) { if (Name.Length > TypeNamePrefix.Length && (Name [TypeNamePrefix.Length] == '.' || Char.IsDigit(Name [TypeNamePrefix.Length]))) // see bug #5111 { return(false); } if (!support.ValidateNamespace()) { return(false); } List <GenBase> valid_nests = new List <GenBase> (); foreach (GenBase gen in nested_types) { if (gen.Validate(opt, TypeParameters)) { valid_nests.Add(gen); } } nested_types = valid_nests; AdjustNestedTypeFullName(this); foreach (string iface_name in iface_names) { ISymbol isym = SymbolTable.Lookup(iface_name); if (isym != null && isym.Validate(opt, TypeParameters)) { ifaces.Add(isym); } else { if (isym == null) { Report.Warning(0, Report.WarningGenBase + 0, "For type {0}, base interface {1} does not exist.", FullName, iface_name); } else { Report.Warning(0, Report.WarningGenBase + 0, "For type {0}, base interface {1} is invalid.", FullName, iface_name); } iface_validation_failed = true; } } List <Field> valid_fields = new List <Field> (); foreach (Field f in fields) { if (!f.Validate(opt, TypeParameters)) { continue; } valid_fields.Add(f); } fields = valid_fields; int method_cnt = methods.Count; methods = methods.Where(m => ValidateMethod(opt, m)).ToList(); method_validation_failed = method_cnt != methods.Count; foreach (Method m in methods) { if (m.IsVirtual) { has_virtual_methods = true; } if (m.Name == "HashCode" && m.Parameters.Count == 0) { m.IsOverride = true; m.Name = "GetHashCode"; } jni_sig_hash [m.JavaName + m.JniSignature] = m; if ((m.Name == "ToString" && m.Parameters.Count == 0) || (BaseSymbol != null && BaseSymbol.ContainsMethod(m, true))) { m.IsOverride = true; } } return(true); }
public void Generate(StreamWriter sw, string indent, CodeGenerationOptions opt, GenBase type, bool generate_callbacks) { if (!IsValid) { return; } bool gen_as_formatted = IsReturnCharSequence; if (generate_callbacks && IsVirtual) { GenerateCallback(sw, indent, opt, type, null, gen_as_formatted); } string name_and_jnisig = JavaName + JniSignature.Replace("java/lang/CharSequence", "java/lang/String"); bool gen_string_overload = !IsOverride && Parameters.HasCharSequence && !type.ContainsMethod(name_and_jnisig); string static_arg = IsStatic ? " static" : String.Empty; string virt_ov = IsOverride ? " override" : IsVirtual ? " virtual" : String.Empty; string seal = IsOverride && IsFinal ? " sealed" : null; string ret = opt.GetOutputName(RetVal.FullName); GenerateIdField(sw, indent, opt); sw.WriteLine("{0}// Metadata.xml XPath method reference: path=\"{1}\"", indent, GetMetadataXPathReference(this.DeclaringType)); if (Deprecated != null) { sw.WriteLine("{0}[Obsolete (@\"{1}\")]", indent, Deprecated.Replace("\"", "\"\"")); } if (IsReturnEnumified) { sw.WriteLine("{0}[return:global::Android.Runtime.GeneratedEnum]", indent); } sw.WriteLine("{0}[Register (\"{1}\", \"{2}\", \"{3}\"{4})]", indent, JavaName, JniSignature, IsVirtual ? ConnectorName : String.Empty, this.AdditionalAttributeString()); GenerateCustomAttributes(sw, indent); sw.WriteLine("{0}{1}{2}{3}{4} unsafe {5} {6} ({7})", indent, Visibility, static_arg, virt_ov, seal, ret, AdjustedName, GenBase.GetSignature(this, opt)); sw.WriteLine("{0}{{", indent); GenerateBody(sw, indent + "\t", opt); sw.WriteLine("{0}}}", indent); sw.WriteLine(); if (gen_string_overload || gen_as_formatted) { GenerateStringOverload(sw, indent, opt); } GenerateAsyncWrapper(sw, indent, opt); }