Skip to content

Commit 37cff25

Browse files
authored
[Java.Base, generator] Bind all of package java.io (#968)
Context: bc5bcf4 Bind all classes and interfaces in the `java.io` package. Binding the [`java.io.StringBufferInputStream.buffer`][0] field exposed a `generator` bug: property setters for `String` fields would not compile, producing: partial class StringBufferInputStream { protected string? Buffer { get { ... } set { const string __id = "buffer.Ljava/lang/String;"; var native_value = global::Java.Interop.JniEnvironment.Strings.NewString (value); try { _members.InstanceFields.SetValue (__id, this, native_value?.PeerReference ?? default); } finally { global::Java.Interop.JniObjectReference.Dispose (ref native_value); GC.KeepAlive (value); } } } } Specifically, `native_value?.PeerReference` is not valid, and unnecessary. This was due to a bug in `BoundFieldAsProperty.cs`, as `String` field marshaling hit the "Object" marshaling path, which was not warranted in this case, as `String` is treated specially. Fix this bug. Binding [`java.io.ObjectOutputStream.PutField.write(ObjectOutput)`][1] presented a larger binding problem: it's an `abstract` method on an `abstract` class, *but* the `PutFieldInvoker.Write()` method was `[Obsolete]` when `PutField.Write()` was not! public abstract partial class /* ObjectOutputStream. */ PutField { public abstract void Write (Java.IO.IObjectOutput? p0); } internal partial class /* ObjectOutputStream. */ PutFieldInvoker : PutField { [Obsolete (@"deprecated")] public override void Write (Java.IO.IObjectOutput? p0) => ... } This state of affairs triggers a CS0809 warning, which is an error in Release configuration builds: ##[error]src/Java.Base/obj/Release-net6.0/mcw/Java.IO.ObjectOutputStream.cs(311,32) Error CS0809: Obsolete member 'ObjectOutputStream.PutFieldInvoker.Write(IObjectOutput?)' overrides non-obsolete member 'ObjectOutputStream.PutField.Write(IObjectOutput?)' Turns Out™ that `BoundMethodAbstractDeclaration.cs` never "forwarded" deprecated attributes? Meaning that `abstract` methods would *never* be `[Obsolete]`, even if their Java peer was `@deprecated`? Update `BoundMethodAbstractDeclaration` so that if the Java method is deprecated, the bound `abstract` method is `[Obsolete]`. This fixes the CS0809, as now `PutField.Write()` and `PutFieldInvoker.Write()` are consistent with each other. TODO: should this change be done for *all* codegen targets? Finally, in order to make it easier to view and review the current `Java.Base.dll` API -- without requiring that it be built locally -- add a `_GenerateRefApi` target to `Java.Base.targets` which uses the `Microsoft.DotNet.GenAPI` NuGet package to generate "reference assembly source" for `Java.Base.dll`. This is stored in `src\Java.Base-ref.cs`. [0]: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/StringBufferInputStream.html#buffer [1]: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/ObjectOutputStream.PutField.html#write(java.io.ObjectOutput)
1 parent a65d6fb commit 37cff25

File tree

8 files changed

+5370
-2
lines changed

8 files changed

+5370
-2
lines changed

Directory.Build.targets

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
<PackageReference Update="Microsoft.Build.Framework" Version="16.11.0" />
1919
<PackageReference Update="Microsoft.Build.Utilities.Core" Version="16.11.0" />
2020
<PackageReference Update="Microsoft.CodeAnalysis.CSharp" Version="3.11.0" />
21+
<PackageReference Update="Microsoft.DotNet.GenAPI" Version="7.0.0-beta.22103.1" />
2122
<PackageReference Update="Microsoft.NET.Test.Sdk" Version="16.11.0" />
2223
<PackageReference Update="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.2" />
2324
<PackageReference Update="Mono.CSharp" Version="4.0.0.143" />

src/Java.Base-ref.cs

+5,312
Large diffs are not rendered by default.

src/Java.Base/Java.Base.targets

+17
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
<GeneratorPath>$(UtilityOutputFullPath)generator.dll</GeneratorPath>
55
</PropertyGroup>
66

7+
<ItemGroup>
8+
<PackageReference Include="Microsoft.DotNet.GenAPI" GeneratePathProperty="true" IncludeAssets="none" />
9+
</ItemGroup>
10+
711
<Target Name="_GetJavaBaseJmodPath">
812
<PropertyGroup Condition=" '$(Java11SdkDirectory)' != '' ">
913
<_JavaBaseJmod>$(Java11SdkDirectory)/jmods/java.base.jmod</_JavaBaseJmod>
@@ -75,4 +79,17 @@
7579
</PropertyGroup>
7680
</Target>
7781

82+
<Target Name="_GenerateRefApi"
83+
Condition=" '$(PkgMicrosoft_DotNet_GenAPI)' != '' And '$(TargetPath)' != '' "
84+
AfterTargets="Build"
85+
Inputs="$(TargetPath)"
86+
Outputs="..\Java.Base-ref.cs">
87+
<PropertyGroup>
88+
<_GenApi>$(PkgMicrosoft_DotNet_GenAPI)/tools/netcoreapp3.1/Microsoft.DotNet.GenAPI.dll</_GenApi>
89+
<_Output>-o "../Java.Base-ref.cs"</_Output>
90+
<_Libpath>--lib-path "$(OutputPath.TrimEnd('\'))"</_Libpath>
91+
</PropertyGroup>
92+
<Exec Command="$(DotnetToolPath) $(_GenApi) &quot;$(TargetPath)&quot; $(_Libpath) $(_Output)" />
93+
</Target>
94+
7895
</Project>

src/Java.Base/Java.IO/PrintStream.cs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Java.Interop;
4+
5+
namespace Java.IO {
6+
7+
public partial class PrintStream : Java.Lang.IAppendable {
8+
9+
Java.Lang.IAppendable? Java.Lang.IAppendable.Append (char p0) => Append (p0);
10+
Java.Lang.IAppendable? Java.Lang.IAppendable.Append (Java.Lang.ICharSequence? p0) => Append (p0);
11+
Java.Lang.IAppendable? Java.Lang.IAppendable.Append (Java.Lang.ICharSequence? p0, int p1, int p2) => Append (p0, p1, p2);
12+
}
13+
}

src/Java.Base/Java.IO/Writer.cs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Java.Interop;
4+
5+
namespace Java.IO {
6+
7+
public partial class Writer : Java.Lang.IAppendable {
8+
9+
Java.Lang.IAppendable? Java.Lang.IAppendable.Append (char p0) => Append (p0);
10+
Java.Lang.IAppendable? Java.Lang.IAppendable.Append (Java.Lang.ICharSequence? p0) => Append (p0);
11+
Java.Lang.IAppendable? Java.Lang.IAppendable.Append (Java.Lang.ICharSequence? p0, int p1, int p2) => Append (p0, p1, p2);
12+
}
13+
}

src/Java.Base/Transforms/Metadata.xml

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<metadata>
22
<!-- For now, just bind java.lang.* -->
3-
<remove-node path="//api/package[not(starts-with(@name, 'java.lang'))]" />
3+
<remove-node path="//api/package[not(starts-with(@name, 'java.lang')
4+
or starts-with(@name, 'java.io')
5+
)]" />
46

57
<!-- Type / Namespace conflicts -->
68
<ns-replace source="java.lang.module" replacement="Java.Lang.Modules" />

tools/generator/SourceWriters/BoundFieldAsProperty.cs

+6-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,12 @@ protected override void WriteSetterBody (CodeWriter writer)
152152
writer.Write ($"\t_members.{indirect}.SetValue (__id{(field.IsStatic ? "" : ", this")}, ");
153153

154154
if (opt.CodeGenerationTarget == CodeGenerationTarget.JavaInterop1) {
155-
writer.WriteLine ($"{(invokeType != "Object" ? arg : $"{arg}?.PeerReference ?? default")});");
155+
if (invokeType != "Object" || have_prep) {
156+
writer.Write (arg);
157+
} else {
158+
writer.Write ($"{arg}?.PeerReference ?? default");
159+
}
160+
writer.WriteLine (");");
156161
} else {
157162
writer.WriteLine ($"{(invokeType != "Object" ? arg : "new JniObjectReference (" + arg + ")")});");
158163
}

tools/generator/SourceWriters/BoundMethodAbstractDeclaration.cs

+5
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ public BoundMethodAbstractDeclaration (GenBase gen, Method method, CodeGeneratio
5252
if (method.DeclaringType.IsGeneratable)
5353
Comments.Add ($"// Metadata.xml XPath method reference: path=\"{method.GetMetadataXPathReference (method.DeclaringType)}\"");
5454

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

5762
if (opt.CodeGenerationTarget != CodeGenerationTarget.JavaInterop1) {

0 commit comments

Comments
 (0)