public void GenerateAbstractDeclaration(StreamWriter sw, string indent, CodeGenerationOptions opt, GenBase gen) { bool overrides = false; var baseProp = gen.BaseSymbol != null?gen.BaseSymbol.GetPropertyByName(name, true) : null; if (baseProp != null) { if (baseProp.Type != Getter.Return) { // This may not be required if we can change generic parameter support to return constrained type (not just J.L.Object). sw.WriteLine("{0}// skipped generating property {1} because its Java method declaration is variant that we cannot represent in C#", indent, name); return; } overrides = true; } bool requiresNew = false; string abstract_name = AdjustedName; string visibility = Getter.RetVal.IsGeneric ? "protected" : Getter.Visibility; if (!overrides) { requiresNew = gen.RequiresNew(abstract_name); GenerateCallbacks(sw, indent, opt, gen, abstract_name); } sw.WriteLine("{0}{1}{2} abstract{3} {4} {5} {{", indent, visibility, requiresNew ? " new" : "", overrides ? " override" : "", opt.GetOutputName(Getter.ReturnType), abstract_name); if (gen.IsGeneratable) { sw.WriteLine("{0}\t// Metadata.xml XPath method reference: path=\"{1}/method[@name='{2}'{3}]\"", indent, gen.MetadataXPathReference, Getter.JavaName, Getter.Parameters.GetMethodXPathPredicate()); } if (Getter.IsReturnEnumified) { sw.WriteLine("{0}[return:global::Android.Runtime.GeneratedEnum]", indent); } opt.CodeGenerator.WriteMethodCustomAttributes(Getter, sw, indent); sw.WriteLine("{0}\t[Register (\"{1}\", \"{2}\", \"{3}\"{4})] get;", indent, Getter.JavaName, Getter.JniSignature, Getter.ConnectorName, Getter.AdditionalAttributeString()); if (Setter != null) { if (gen.IsGeneratable) { sw.WriteLine("{0}\t// Metadata.xml XPath method reference: path=\"{1}/method[@name='{2}'{3}]\"", indent, gen.MetadataXPathReference, Setter.JavaName, Setter.Parameters.GetMethodXPathPredicate()); } opt.CodeGenerator.WriteMethodCustomAttributes(Setter, sw, indent); sw.WriteLine("{0}\t[Register (\"{1}\", \"{2}\", \"{3}\"{4})] set;", indent, Setter.JavaName, Setter.JniSignature, Setter.ConnectorName, Setter.AdditionalAttributeString()); } sw.WriteLine("{0}}}", indent); sw.WriteLine(); if (Type.StartsWith("Java.Lang.ICharSequence")) { GenerateStringVariant(sw, indent); } }
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; if ((string.IsNullOrEmpty(virt_ov) || virt_ov == " virtual") && type.RequiresNew(AdjustedName)) { virt_ov = " new" + virt_ov; } string seal = IsOverride && IsFinal ? " sealed" : null; string ret = opt.GetOutputName(RetVal.FullName); GenerateIdField(sw, indent, opt); if (DeclaringType.IsGeneratable) { 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(); //NOTE: Invokers are the only place false is passed for generate_callbacks, they do not need string overloads if (generate_callbacks && (gen_string_overload || gen_as_formatted)) { GenerateStringOverload(sw, indent, opt); } GenerateAsyncWrapper(sw, indent, opt); }
public void Generate(GenBase gen, StreamWriter sw, string indent, CodeGenerationOptions opt, bool with_callbacks, bool force_override) { // <TechnicalDebt> // This is a special workaround for AdapterView inheritance. // (How it is special? They have hand-written bindings AND brings generic // version of AdapterView<T> in the inheritance, also added by metadata!) // // They are on top of fragile hand-bound code, and when we are making changes // in generator, they bite. Since we are not going to bring API breakage // right now, we need special workarounds to get things working. // // So far, what we need here is to have AbsSpinner.Adapter compile. // // > platforms/*/src/generated/Android.Widget.AbsSpinner.cs(156,56): error CS0533: // > `Android.Widget.AbsSpinner.Adapter' hides inherited abstract member // > `Android.Widget.AdapterView<Android.Widget.ISpinnerAdapter>.Adapter // // It is because the AdapterView<T>.Adapter is hand-bound and cannot be // detected by generator! // // So, we explicitly treat it as a special-case. // // Then, Spinner, ListView and GridView instantiate them, so they are also special cases. // </TechnicalDebt> if (Name == "Adapter" && (Getter.DeclaringType.BaseGen.FullName == "Android.Widget.AdapterView" || Getter.DeclaringType.BaseGen.BaseGen != null && Getter.DeclaringType.BaseGen.BaseGen.FullName == "Android.Widget.AdapterView")) { force_override = true; } // ... and the above breaks generator tests... if (Name == "Adapter" && (Getter.DeclaringType.BaseGen.FullName == "Xamarin.Test.AdapterView" || Getter.DeclaringType.BaseGen.BaseGen != null && Getter.DeclaringType.BaseGen.BaseGen.FullName == "Xamarin.Test.AdapterView")) { force_override = true; } string decl_name = AdjustedName; string needNew = gen.RequiresNew(decl_name) ? " new" : ""; string virtual_override = String.Empty; bool is_virtual = Getter.IsVirtual && (Setter == null || Setter.IsVirtual); if (with_callbacks && is_virtual) { virtual_override = needNew + " virtual"; opt.CodeGenerator.WriteMethodCallback(Getter, sw, indent, opt, gen, AdjustedName); } if (with_callbacks && is_virtual && Setter != null) { virtual_override = needNew + " virtual"; opt.CodeGenerator.WriteMethodCallback(Setter, sw, indent, opt, gen, AdjustedName); } virtual_override = force_override ? " override" : virtual_override; if ((Getter ?? Setter).IsStatic) { virtual_override = " static"; } // It should be using AdjustedName instead of Name, but ICharSequence ("Formatted") properties are not caught by this... else if (gen.BaseSymbol != null && gen.BaseSymbol.GetPropertyByName(Name, true) != null) { virtual_override = " override"; } opt.CodeGenerator.WriteMethodIdField(Getter, sw, indent, opt); if (Setter != null) { opt.CodeGenerator.WriteMethodIdField(Setter, sw, indent, opt); } string visibility = Getter.IsAbstract && Getter.RetVal.IsGeneric ? "protected" : (Setter ?? Getter).Visibility; // Unlike [Register], mcs does not allow applying [Obsolete] on property accessors, so we can apply them only under limited condition... if (Getter.Deprecated != null && (Setter == null || Setter.Deprecated != null)) { sw.WriteLine("{0}[Obsolete (@\"{1}\")]", indent, Getter.Deprecated.Replace("\"", "\"\"").Trim() + (Setter != null && Setter.Deprecated != Getter.Deprecated ? " " + Setter.Deprecated.Replace("\"", "\"\"").Trim() : null)); } opt.CodeGenerator.WriteMethodCustomAttributes(Getter, sw, indent); sw.WriteLine("{0}{1}{2} unsafe {3} {4} {{", indent, visibility, virtual_override, opt.GetOutputName(Getter.ReturnType), decl_name); if (gen.IsGeneratable) { sw.WriteLine("{0}\t// Metadata.xml XPath method reference: path=\"{1}/method[@name='{2}'{3}]\"", indent, gen.MetadataXPathReference, Getter.JavaName, Getter.Parameters.GetMethodXPathPredicate()); } sw.WriteLine("{0}\t[Register (\"{1}\", \"{2}\", \"{3}\"{4})]", indent, Getter.JavaName, Getter.JniSignature, Getter.ConnectorName, Getter.AdditionalAttributeString()); sw.WriteLine("{0}\tget {{", indent); opt.CodeGenerator.WriteMethodBody(Getter, sw, indent + "\t\t", opt); sw.WriteLine("{0}\t}}", indent); if (Setter != null) { if (gen.IsGeneratable) { sw.WriteLine("{0}\t// Metadata.xml XPath method reference: path=\"{1}/method[@name='{2}'{3}]\"", indent, gen.MetadataXPathReference, Setter.JavaName, Setter.Parameters.GetMethodXPathPredicate()); } opt.CodeGenerator.WriteMethodCustomAttributes(Setter, sw, indent); sw.WriteLine("{0}\t[Register (\"{1}\", \"{2}\", \"{3}\"{4})]", indent, Setter.JavaName, Setter.JniSignature, Setter.ConnectorName, Setter.AdditionalAttributeString()); sw.WriteLine("{0}\tset {{", indent); string pname = Setter.Parameters [0].Name; Setter.Parameters [0].Name = "value"; opt.CodeGenerator.WriteMethodBody(Setter, sw, indent + "\t\t", opt); Setter.Parameters [0].Name = pname; sw.WriteLine("{0}\t}}", indent); } else if (GenerateDispatchingSetter) { sw.WriteLine("{0}// This is a dispatching setter", indent + "\t"); sw.WriteLine("{0}set {{ Set{1} (value); }}", indent + "\t", Name); } sw.WriteLine("{0}}}", indent); sw.WriteLine(); if (Type.StartsWith("Java.Lang.ICharSequence") && virtual_override != " override") { GenerateStringVariant(sw, indent); } }