Skip to content
This repository was archived by the owner on Jul 6, 2026. It is now read-only.

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

8 files changed

Lines changed: 5370 additions & 2 deletions

File tree

‎Directory.Build.targets‎

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

‎src/Java.Base-ref.cs‎

Lines changed: 5312 additions & 0 deletions
Large diffs are not rendered by default.

‎src/Java.Base/Java.Base.targets‎

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

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

82+
<TargetName="_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+
<ExecCommand="$(DotnetToolPath) $(_GenApi) &quot;$(TargetPath)&quot; $(_Libpath) $(_Output)" />
93+
</Target>
94+
7895
</Project>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
usingSystem;
2+
usingSystem.Collections.Generic;
3+
usingJava.Interop;
4+
5+
namespaceJava.IO{
6+
7+
publicpartialclassPrintStream:Java.Lang.IAppendable{
8+
9+
Java.Lang.IAppendable?Java.Lang.IAppendable.Append(charp0)=>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,intp1,intp2)=>Append(p0,p1,p2);
12+
}
13+
}

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
usingSystem;
2+
usingSystem.Collections.Generic;
3+
usingJava.Interop;
4+
5+
namespaceJava.IO{
6+
7+
publicpartialclassWriter:Java.Lang.IAppendable{
8+
9+
Java.Lang.IAppendable?Java.Lang.IAppendable.Append(charp0)=>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,intp1,intp2)=>Append(p0,p1,p2);
12+
}
13+
}

‎src/Java.Base/Transforms/Metadata.xml‎

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

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

‎tools/generator/SourceWriters/BoundFieldAsProperty.cs‎

Lines changed: 6 additions & 1 deletion
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‎

Lines changed: 5 additions & 0 deletions
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(newObsoleteAttr(method.Deprecated.Replace("\"","\"\"")));
58+
}
59+
5560
SourceWriterExtensions.AddSupportedOSPlatform(Attributes,method,opt);
5661

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

0 commit comments

Comments
 (0)