Skip to content

Commit bfc0273

Browse files
authored
[generator] Ensure property setter parameter name is "value" (#566)
Fixes: #565 In a case with generics, we were not renaming the property setter parameter to `value`, which meant it could be left as `p0`, which is not valid C#: // This method is explicitly implemented as a member of an instantiated Google.Android.Material.DatePicker.IDateSelector global::Java.Lang.Object global::Google.Android.Material.DatePicker.IDateSelector.Selection { // Metadata.xml XPath method reference: path="/api/package[@name='com.google.android.material.datepicker']/interface[@name='DateSelector']/method[@name='getSelection' and count(parameter)=0]" [Register ("getSelection", "()Ljava/lang/Object;", "GetGetSelectionHandler:Google.Android.Material.DatePicker.IDateSelectorInvoker, Xamarin.Google.Android.Material")] get { return Selection; } // Metadata.xml XPath method reference: path="/api/package[@name='com.google.android.material.datepicker']/interface[@name='DateSelector']/method[@name='setSelection' and count(parameter)=1 and parameter[1][@type='S']]" [Register ("setSelection", "(Ljava/lang/Object;)V", "GetSetSelection_Ljava_lang_Object_Handler:Google.Android.Material.DatePicker.IDateSelectorInvoker, Xamarin.Google.Android.Material")] set { Selection = global::Java.Interop.JavaObjectExtensions.JavaCast<global::Java.Lang.Long>(p0); } } This would result in a C# error: error CS0103: The name 'p0' does not exist in the current context. The fix is to temporarily override the property's setter's parameter name to `value` so that we emit compilable C# code: set { Selection = JavaObjectExtensions.JavaCast<Long>(value); }
1 parent 3226a4b commit bfc0273

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,5 +967,54 @@ public void WriteMethodWithInvalidParameterName ()
967967
// Ensure we escape dollar signs
968968
Assert.False (result.Contains ("$this"));
969969
}
970+
971+
[Test]
972+
public void WritePropertyExplicitInterfaceParameterName ()
973+
{
974+
// Fix a case where we were not overriding a property setter's parameter name ("p0")
975+
// to "value", resulting in invalid C#. Like:
976+
// public string MyProperty {
977+
// set => my_property = p0;
978+
// }
979+
var gens = ParseApiDefinition (@"<api>
980+
<package name='java.lang' jni-name='java/lang'>
981+
<class abstract='false' deprecated='not deprecated' final='false' name='Object' static='false' visibility='public' jni-signature='Ljava/lang/Object;' />
982+
<class abstract='false' deprecated='not deprecated' extends='java.lang.Object' final='false' name='Long' static='false' visibility='public' jni-signature='Ljava/lang/Long;' />
983+
</package>
984+
985+
<package name='com.google.android.material.datepicker' jni-name='com/google/android/material/datepicker'>
986+
<class abstract='false' deprecated='not deprecated' extends='java.lang.Object' extends-generic-aware='java.lang.Object' jni-extends='Ljava/lang/Object;' final='false' name='SingleDateSelector' static='false' visibility='public' jni-signature='Lcom/google/android/material/datepicker/SingleDateSelector;'>
987+
<implements name='com.google.android.material.datepicker.DateSelector' name-generic-aware='com.google.android.material.datepicker.DateSelector&lt;java.lang.Long&gt;' jni-type='Lcom/google/android/material/datepicker/DateSelector&lt;Ljava/lang/Long;&gt;;'>
988+
</implements>
989+
<method abstract='false' deprecated='not deprecated' final='false' name='getSelection' jni-signature='()Ljava/lang/Long;' bridge='false' native='false' return='java.lang.Long' jni-return='Ljava/lang/Long;' static='false' synchronized='false' synthetic='false' visibility='public'>
990+
</method>
991+
<method abstract='false' deprecated='not deprecated' final='false' name='setSelection' jni-signature='(Ljava/lang/Long;)V' bridge='false' native='false' return='void' jni-return='V' static='false' synchronized='false' synthetic='false' visibility='public'>
992+
<parameter name='selection' type='java.lang.Long' jni-type='Ljava/lang/Long;'>
993+
</parameter>
994+
</method>
995+
</class>
996+
<interface abstract='true' deprecated='not deprecated' final='false' name='DateSelector' static='false' visibility='public' jni-signature='Lcom/google/android/material/datepicker/DateSelector;'>
997+
<typeParameters>
998+
<typeParameter name='S' classBound='java.lang.Object' jni-classBound='Ljava/lang/Object;'></typeParameter>
999+
</typeParameters>
1000+
<method abstract='true' deprecated='not deprecated' final='false' name='getSelection' jni-signature='()Ljava/lang/Object;' bridge='false' native='false' return='S' jni-return='TS;' static='false' synchronized='false' synthetic='false' visibility='public'>
1001+
</method>
1002+
<method abstract='true' deprecated='not deprecated' final='false' name='setSelection' jni-signature='(Ljava/lang/Object;)V' bridge='false' native='false' return='void' jni-return='V' static='false' synchronized='false' synthetic='false' visibility='public'>
1003+
<parameter name='p0' type='S' jni-type='TS;'>
1004+
</parameter>
1005+
</method>
1006+
</interface>
1007+
</package>
1008+
</api>");
1009+
1010+
var @class = gens.OfType<ClassGen> ().First (c => c.Name == "SingleDateSelector");
1011+
1012+
generator.Context.ContextTypes.Push (@class);
1013+
generator.WriteClass (@class, string.Empty, new GenerationInfo ("", "", "MyAssembly"));
1014+
generator.Context.ContextTypes.Pop ();
1015+
1016+
var result = writer.ToString ().NormalizeLineEndings ();
1017+
Assert.False (result.Contains ("p0"));
1018+
}
9701019
}
9711020
}

tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1605,7 +1605,13 @@ public void WritePropertyExplicitInterface (Property property, string indent, Ge
16051605
if (property.Setter.GenericArguments != null && property.Setter.GenericArguments.Any ())
16061606
writer.WriteLine ("{0}{1}", indent, property.Setter.GenericArguments.ToGeneratedAttributeString ());
16071607
writer.WriteLine ("{0}\t[Register (\"{1}\", \"{2}\", \"{3}:{4}\"{5})] set {{", indent, property.Setter.JavaName, property.Setter.JniSignature, property.Setter.ConnectorName, property.Setter.GetAdapterName (opt, adapter), property.Setter.AdditionalAttributeString ());
1608+
1609+
// Temporarily rename the parameter to "value"
1610+
var pname = property.Setter.Parameters [0].Name;
1611+
property.Setter.Parameters [0].Name = "value";
16081612
writer.WriteLine ("{0}\t\t{1} = {2};", indent, property.Name, property.Setter.Parameters.GetGenericCall (opt, mappings));
1613+
property.Setter.Parameters [0].Name = pname;
1614+
16091615
writer.WriteLine ("{0}\t}}", indent);
16101616
}
16111617
writer.WriteLine ("{0}}}", indent);

0 commit comments

Comments
 (0)