Skip to content

Commit

Permalink
[generator] Mark abstract methods as [Obsolete] if needed (#1011)
Browse files Browse the repository at this point in the history
Fixes: #969

If you have a Java `abstract` method which is deprecated:

	// Java
	public abstract class Example {
	    @deprecated
	    public abstract void m();
	}

then the C# binding is *not* `[Obsolete]`, *and* the `*Invoker`
override *is* `[Obsolete]`:

	// Binding
	public abstract partial class Example : Java.Lang.Object {
	    // Note: *not* [Obsolete]
	    [Register (…)]
	    public abstract void M();
	}

	internal partial class ExampleInvoker : Example {
	    [Obsolete]
	    public override void M() => …
	}

This state of affairs results in a [CS0809 warning][0]:

	warning CS0809: Obsolete member 'ExampleInvoker.M()' overrides non-obsolete member 'Example.M()'

Commit 37cff25 added a fix for this for `JavaInterop1` output, asking:

> TODO: should this change be done for *all* codegen targets?

The answer: Yes.

Expand the fix from 37cff25 to apply to `XAJavaInterop1` codegen,
and add unit tests for this scenario.

[0]: https://docs.microsoft.com/en-us/dotnet/csharp/misc/cs0809
  • Loading branch information
jpobst committed Jul 14, 2022
1 parent 275fa75 commit fe60483
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 3 deletions.
25 changes: 25 additions & 0 deletions tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,31 @@ public void ExplicitInterfaceMetadata_AbstractClassProperty ()
// Ensure explicit interface was written
Assert.True (writer.ToString ().Contains ("abstract int IHasAge.Age {"), $"was: `{writer}`");
}

[Test]
public void ObsoleteBoundMethodAbstractDeclaration ()
{
var xml = @"<api>
<package name='java.lang' jni-name='java/lang'>
<class abstract='false' deprecated='not deprecated' final='false' name='Object' static='false' visibility='public' jni-signature='Ljava/lang/Object;' />
</package>
<package name='com.xamarin.android' jni-name='com/xamarin/android'>
<class abstract='false' deprecated='not deprecated' extends='java.lang.Object' extends-generic-aware='java.lang.Object' jni-extends='Ljava/lang/Object;' final='false' name='MyClass' static='false' visibility='public' jni-signature='Lcom/xamarin/android/MyClass;'>
<method abstract='true' deprecated='This is so old!' final='false' name='countAffectedRows' jni-signature='()I' bridge='false' native='false' return='int' jni-return='I' static='false' synchronized='false' synthetic='false' visibility='public'></method>
</class>
</package>
</api>";

var gens = ParseApiDefinition (xml);
var iface = gens.Single (g => g.Name == "MyClass");

generator.Context.ContextTypes.Push (iface);
generator.WriteType (iface, string.Empty, new GenerationInfo ("", "", "MyAssembly"));
generator.Context.ContextTypes.Pop ();

// Ensure [Obsolete] was written
Assert.True (writer.ToString ().Contains ("[Obsolete (@\"This is so old!\")]"), writer.ToString ());
}
}

[TestFixture]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,8 @@ public BoundMethodAbstractDeclaration (GenBase gen, Method method, CodeGeneratio
if (method.DeclaringType.IsGeneratable)
Comments.Add ($"// Metadata.xml XPath method reference: path=\"{method.GetMetadataXPathReference (method.DeclaringType)}\"");

// TODO: shouldn't `[Obsolete]` be added for *all* CodeGenerationTargets?
if (opt.CodeGenerationTarget == CodeGenerationTarget.JavaInterop1 && method.Deprecated.HasValue ()) {
if (method.Deprecated.HasValue ())
Attributes.Add (new ObsoleteAttr (method.Deprecated.Replace ("\"", "\"\"")));
}

SourceWriterExtensions.AddSupportedOSPlatform (Attributes, method, opt);

Expand Down

0 comments on commit fe60483

Please sign in to comment.