Skip to content

[TrimmableTypeMap] Close scanner and JCW generator gaps vs legacy pipeline - #10934

Closed
simonrozsival wants to merge 6 commits into
dev/simonrozsival/trimmable-typemap-override-detectionfrom
dev/simonrozsival/trimmable-typemap-scanner-gaps
Closed

[TrimmableTypeMap] Close scanner and JCW generator gaps vs legacy pipeline#10934
simonrozsival wants to merge 6 commits into
dev/simonrozsival/trimmable-typemap-override-detectionfrom
dev/simonrozsival/trimmable-typemap-scanner-gaps

Conversation

@simonrozsival

Copy link
Copy Markdown
Member

Part of #10933. Stacked on #10924 (override detection PR).

Summary

Closes gaps between the new trimmable scanner/JCW generator and the legacy Cecil-based pipeline, discovered by building the samples/HelloWorld app and deep analysis against CecilImporter.

What we can now detect

Interface method implementations without [Register]

// User code — no [Register] on OnClick:publicclassMyListener:Java.Lang.Object,IOnClickListener{publicvoidOnClick(Viewv){}}

The scanner now iterates implemented interfaces and adds their [Register]'d methods to the implementing type's marshal methods.

[Export] method access modifiers

[Export("protectedMethod")]protectedvoidProtectedMethod(){}// JCW now correctly emits:// protected void protectedMethod () { ... }// Previously always emitted "public".

[ExportField] attributes

[ExportField("VALUE")]publicstringGetValue()=>"hello";// JCW now emits:// public java.lang.String VALUE = GetValue ();// public java.lang.String GetValue () { return n_GetValue (); }

Constructor super() fallback patterns

// User ctor params don't match base — falls back to super():publicCustomParamActivity(string title,int count){super(); ...}

Already worked correctly; now has test coverage.

Covariant return type overrides

// Base: [Register ("getResult", "()Ljava/lang/Object;")]// Override with narrower return — JCW uses base's JNI signature.publicoverrideJava.Lang.ObjectGetResult()=>myString;

Already worked correctly; now has test coverage.

Tests

245 unit tests pass (+4 new test files, 25 new test methods).

simonrozsivaland others added 6 commits March 13, 2026 15:18
When a user type implements a Java interface, the implementing method
often has no [Register] attribute:
public class MyListener : Java.Lang.Object, IOnClickListener
{
public void OnClick (View v) { } // no [Register] here
}
The scanner must detect onClick from the interface definition.
5 of 7 tests fail, confirming the gap.
Part of #10933
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When a user type implements a Java interface, the implementing method
may not have [Register] directly on it:
// In Mono.Android — the interface defines [Register]:
[Register ("android/view/View$OnClickListener")]
public interface IOnClickListener
{
[Register ("onClick", "(Landroid/view/View;)V", "...")]
void OnClick (View v);
}
// User code — no [Register] on implementing method:
public class MyListener : Java.Lang.Object, IOnClickListener
{
public void OnClick (View v) { }
}
Add Pass 4 in CollectMarshalMethods that iterates implemented interfaces,
resolves their [Register]'d methods/properties, and adds them as marshal
methods. Gated behind !doNotGenerateAcw && !isInterface.
Part of #10933
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…rator
The legacy JCW generator respects the C# visibility for [Export] methods.
A protected export produces a protected Java method:
[Export ("protectedMethod")]
protected void ProtectedMethod () { }
// Generated JCW Java:
protected void protectedMethod () { ... }
protected native void n_protectedMethod ();
The new pipeline always used "public". Add IsExport and JavaAccess
properties to MarshalMethodInfo and use them in JcwJavaSourceGenerator.
Part of #10933
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
[ExportField] on a method produces a Java field initialized by calling it:
[ExportField ("VALUE")]
public string GetValue () => "hello";
// Generated Java:
public java.lang.String VALUE = GetValue ();
public java.lang.String GetValue () { return n_GetValue (); }
public native java.lang.String n_GetValue ();
Add JavaFieldInfo model, scan [ExportField] in Pass 1 alongside
[Register]/[Export], emit field declarations in JcwJavaSourceGenerator,
and resolve Java return types via JNI signatures.
Part of #10933
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Verifies the three super() argument patterns:
// 1. Compatible base ctor -> forward all params
public MyView (Context p0) { super (p0); ... }
// 2. No compatible params, parameterless fallback -> super()
public CustomParamActivity (String p0, int p1) { super (); ... }
// 3. [Export(SuperArgumentsString="p0")] -> custom super args
public MyService (Context p0, int p1) { super (p0); ... }
The existing CollectBaseConstructorChain already handles all three
cases correctly. These tests document the expected behavior.
Part of #10933
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When a derived type overrides a base method with a narrower return type,
the JCW must use the base method's JNI signature:
// Base: [Register ("getResult", "()Ljava/lang/Object;", "...")]
public virtual Java.Lang.Object GetResult () => null;
// User override — narrower return, no [Register]:
public override Java.Lang.Object GetResult () => myString;
// JCW must use base's "()Ljava/lang/Object;", not derived's type.
Also addresses review feedback: consolidated tests, JNI-based
ExportField type resolution, consistent signature-based dedup keys.
Part of #10933
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsivalforce-pushed the dev/simonrozsival/trimmable-typemap-scanner-gaps branch from 52ccc51 to c880856CompareMarch 13, 2026 14:21
@simonrozsival

Copy link
Copy Markdown
MemberAuthor

Closing — all scanner/JCW gap fixes (interface method detection, export access modifiers, export fields, constructor super() fallback, covariant return types) have been folded into the base PR #10924.

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 16, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@simonrozsival