Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
ed35681
[TrimmableTypeMap] Data model and metadata type providers
simonrozsival Feb 16, 2026
9db2c36
[TrimmableTypeMap] AssemblyIndex per-assembly metadata indexer
simonrozsival Feb 16, 2026
0bd2fd6
[TrimmableTypeMap] JavaPeerScanner execution logic
simonrozsival Feb 16, 2026
e7a3483
[TrimmableTypeMap] Test fixtures and foundational scanner tests
simonrozsival Feb 16, 2026
f63a831
[TrimmableTypeMap] Scanner behavior and contract tests
simonrozsival Feb 16, 2026
22d57ec
[TrimmableTypeMap] Scanner edge-case regression tests
simonrozsival Feb 16, 2026
142c6c7
[TrimmableTypeMap] Wire unit tests into solution and CI
simonrozsival Feb 16, 2026
bd35cdc
[TrimmableTypeMap] Integration parity test slice
simonrozsival Feb 13, 2026
e92938e
[TrimmableTypeMap] Wire integration tests into solution and CI
simonrozsival Feb 16, 2026
f525db4
[TypeMap] Add JCW and TypeMap assembly generators with IR model
simonrozsival Feb 11, 2026
b979fb2
Rename model types: drop IR/IL/AST terminology
simonrozsival Feb 11, 2026
13844f4
Add extensive fixture-based model builder and pipeline tests
simonrozsival Feb 11, 2026
b6568a2
Add 3-arg trimmable TypeMap attrs, alias detection, root assembly gen…
simonrozsival Feb 11, 2026
540c1bf
Fix review findings: ctor JNI sig bug, deterministic ordering, test c…
simonrozsival Feb 11, 2026
c0a9ace
Fix review round 2: canonical string encoding, type ref caching, comp…
simonrozsival Feb 11, 2026
5f19dde
Fix review round 3: static ModelBuilder, Implementor/EventDispatcher …
simonrozsival Feb 11, 2026
33d4dea
Fix review round 4: clear typeRefCache, extract constants, document n…
simonrozsival Feb 11, 2026
f1ba60d
Fix invoker handling, add dotnet version param, SuperArgumentsString …
simonrozsival Feb 12, 2026
1a28d4c
Change dotnetVersion parameter from int to Version
simonrozsival Feb 12, 2026
0a6f267
Fix RootTypeMapAssemblyGenerator to use generic TypeMapAssemblyTarget…
simonrozsival Feb 12, 2026
339549c
Refactor test sections into nested classes for better isolation
simonrozsival Feb 12, 2026
6a16b6a
Move Generator files to Microsoft.Android.Sdk.TrimmableTypeMap namespace
simonrozsival Feb 12, 2026
da5ae58
Fix CreateInstance to use proper activation patterns, add TypeMapAsso…
simonrozsival Feb 12, 2026
0b130ac
Simplify generator code
simonrozsival Feb 12, 2026
8dc353b
Further simplify generator code
simonrozsival Feb 12, 2026
5bb64d6
Remove redundant null checks in EmitCreateInstance
simonrozsival Feb 12, 2026
9c0bac5
Reduce allocations in TypeMapAssemblyEmitter
simonrozsival Feb 12, 2026
7420df4
Add generator model types and scanner enrichment for JCW/UCO generation
simonrozsival Feb 12, 2026
7088777
Fix UCO constructor wrappers to include full JNI parameter list
simonrozsival Feb 12, 2026
03e38b5
Add generator model types and scanner enrichment for JCW/UCO generation
simonrozsival Feb 12, 2026
f869d5c
Skip [Export] methods/constructors from UCO generation, fix JCW for […
simonrozsival Feb 12, 2026
f1c6cd1
Port legacy [Export] tests: full output comparison, name override, th…
simonrozsival Feb 12, 2026
a67f4a3
[Export] marshal method body generation
simonrozsival Feb 12, 2026
7917bc2
Fix return value loss in export marshal methods
simonrozsival Feb 12, 2026
6484226
Fix managed return type encoding in export method refs
simonrozsival Feb 12, 2026
e9b1373
Fix JNI registration name mismatch for [Export] methods
simonrozsival Feb 12, 2026
0b6a063
Fix JCW: no @Override on [Export] methods, use private native
simonrozsival Feb 12, 2026
636bfb9
Add static [Export] methods and [ExportField] support
simonrozsival Feb 12, 2026
d13646b
Simplify scanner and generator code
simonrozsival Feb 12, 2026
c13361c
Add integration tests verifying Export members in RegisterNatives
simonrozsival Feb 12, 2026
99bcbe2
Fix JNI boolean mapping: use byte (unsigned) to match legacy
simonrozsival Feb 13, 2026
45862e5
Full constructor marshal body generation
simonrozsival Feb 13, 2026
2b1860b
Implement remaining [Export] marshaling gaps
simonrozsival Feb 13, 2026
416ef5f
Separate legacy typemap targets from Common.targets into dedicated files
simonrozsival Feb 10, 2026
291a742
Fix target ordering: _GenerateLegacyTypeMappings must run before _Gen…
simonrozsival Feb 10, 2026
4f1a420
Move ILLink typemap targets to Legacy.targets
simonrozsival Feb 10, 2026
41afabb
Rename TypeMap targets to Microsoft.Android.Sdk.* and move to targets/
simonrozsival Feb 11, 2026
5d2565b
Address PR review feedback: restore TypeMappingStep, improve trimmabl…
simonrozsival Feb 12, 2026
471c547
Add shared tasks infrastructure for trimmable typemap
simonrozsival Feb 12, 2026
fedc90f
Simplify: remove premature ComponentDataSerializer and TrimmableTypeM…
simonrozsival Feb 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions Xamarin.Android.sln
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Xamarin.ProjectTools", "src
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Xamarin.Android.Build.Tests", "src\Xamarin.Android.Build.Tasks\Tests\Xamarin.Android.Build.Tests\Xamarin.Android.Build.Tests.csproj", "{53E4ABF0-1085-45F9-B964-DCAE4B819998}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Android.Sdk.TrimmableTypeMap", "src\Microsoft.Android.Sdk.TrimmableTypeMap\Microsoft.Android.Sdk.TrimmableTypeMap.csproj", "{507759AE-93DF-411B-8645-31F680319F5C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Android.Sdk.TrimmableTypeMap.Tests", "tests\Microsoft.Android.Sdk.TrimmableTypeMap.Tests\Microsoft.Android.Sdk.TrimmableTypeMap.Tests.csproj", "{F9CD012E-67AC-4A4E-B2A7-252387F91256}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestFixtures", "tests\Microsoft.Android.Sdk.TrimmableTypeMap.Tests\TestFixtures\TestFixtures.csproj", "{C5A44686-3469-45A7-B6AB-2798BA0625BC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Android.Sdk.TrimmableTypeMap.IntegrationTests", "tests\Microsoft.Android.Sdk.TrimmableTypeMap.IntegrationTests\Microsoft.Android.Sdk.TrimmableTypeMap.IntegrationTests.csproj", "{A14CB0A1-7A05-4F27-88B2-383798CE1DEE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UserTypesFixture", "tests\Microsoft.Android.Sdk.TrimmableTypeMap.IntegrationTests\UserTypesFixture\UserTypesFixture.csproj", "{2498F8A0-AA04-40EF-8691-59BBD2396B4D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "class-parse", "external\Java.Interop\tools\class-parse\class-parse.csproj", "{38C762AB-8FD1-44DE-9855-26AAE7129DC3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "logcat-parse", "external\Java.Interop\tools\logcat-parse\logcat-parse.csproj", "{7387E151-48E3-4885-B2CA-A74434A34045}"
Expand Down Expand Up @@ -231,6 +241,26 @@ Global
{53E4ABF0-1085-45F9-B964-DCAE4B819998}.Debug|AnyCPU.Build.0 = Debug|Any CPU
{53E4ABF0-1085-45F9-B964-DCAE4B819998}.Release|AnyCPU.ActiveCfg = Release|Any CPU
{53E4ABF0-1085-45F9-B964-DCAE4B819998}.Release|AnyCPU.Build.0 = Release|Any CPU
{507759AE-93DF-411B-8645-31F680319F5C}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU
{507759AE-93DF-411B-8645-31F680319F5C}.Debug|AnyCPU.Build.0 = Debug|Any CPU
{507759AE-93DF-411B-8645-31F680319F5C}.Release|AnyCPU.ActiveCfg = Release|Any CPU
{507759AE-93DF-411B-8645-31F680319F5C}.Release|AnyCPU.Build.0 = Release|Any CPU
{F9CD012E-67AC-4A4E-B2A7-252387F91256}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU
{F9CD012E-67AC-4A4E-B2A7-252387F91256}.Debug|AnyCPU.Build.0 = Debug|Any CPU
{F9CD012E-67AC-4A4E-B2A7-252387F91256}.Release|AnyCPU.ActiveCfg = Release|Any CPU
{F9CD012E-67AC-4A4E-B2A7-252387F91256}.Release|AnyCPU.Build.0 = Release|Any CPU
{C5A44686-3469-45A7-B6AB-2798BA0625BC}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU
{C5A44686-3469-45A7-B6AB-2798BA0625BC}.Debug|AnyCPU.Build.0 = Debug|Any CPU
{C5A44686-3469-45A7-B6AB-2798BA0625BC}.Release|AnyCPU.ActiveCfg = Release|Any CPU
{C5A44686-3469-45A7-B6AB-2798BA0625BC}.Release|AnyCPU.Build.0 = Release|Any CPU
{A14CB0A1-7A05-4F27-88B2-383798CE1DEE}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU
{A14CB0A1-7A05-4F27-88B2-383798CE1DEE}.Debug|AnyCPU.Build.0 = Debug|Any CPU
{A14CB0A1-7A05-4F27-88B2-383798CE1DEE}.Release|AnyCPU.ActiveCfg = Release|Any CPU
{A14CB0A1-7A05-4F27-88B2-383798CE1DEE}.Release|AnyCPU.Build.0 = Release|Any CPU
{2498F8A0-AA04-40EF-8691-59BBD2396B4D}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU
{2498F8A0-AA04-40EF-8691-59BBD2396B4D}.Debug|AnyCPU.Build.0 = Debug|Any CPU
{2498F8A0-AA04-40EF-8691-59BBD2396B4D}.Release|AnyCPU.ActiveCfg = Release|Any CPU
{2498F8A0-AA04-40EF-8691-59BBD2396B4D}.Release|AnyCPU.Build.0 = Release|Any CPU
{38C762AB-8FD1-44DE-9855-26AAE7129DC3}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU
{38C762AB-8FD1-44DE-9855-26AAE7129DC3}.Debug|AnyCPU.Build.0 = Debug|Any CPU
{38C762AB-8FD1-44DE-9855-26AAE7129DC3}.Release|AnyCPU.ActiveCfg = Release|Any CPU
Expand Down Expand Up @@ -398,6 +428,10 @@ Global
{645E1718-C8C4-4C23-8A49-5A37E4ECF7ED} = {04E3E11E-B47D-4599-8AFC-50515A95E715}
{2DD1EE75-6D8D-4653-A800-0A24367F7F38} = {CAB438D8-B0F5-4AF0-BEBD-9E2ADBD7B483}
{53E4ABF0-1085-45F9-B964-DCAE4B819998} = {CAB438D8-B0F5-4AF0-BEBD-9E2ADBD7B483}
{F9CD012E-67AC-4A4E-B2A7-252387F91256} = {CAB438D8-B0F5-4AF0-BEBD-9E2ADBD7B483}
{C5A44686-3469-45A7-B6AB-2798BA0625BC} = {CAB438D8-B0F5-4AF0-BEBD-9E2ADBD7B483}
{A14CB0A1-7A05-4F27-88B2-383798CE1DEE} = {CAB438D8-B0F5-4AF0-BEBD-9E2ADBD7B483}
{2498F8A0-AA04-40EF-8691-59BBD2396B4D} = {CAB438D8-B0F5-4AF0-BEBD-9E2ADBD7B483}
{38C762AB-8FD1-44DE-9855-26AAE7129DC3} = {864062D3-A415-4A6F-9324-5820237BA058}
{7387E151-48E3-4885-B2CA-A74434A34045} = {864062D3-A415-4A6F-9324-5820237BA058}
{8A6CB07C-E493-4A4F-AB94-038645A27118} = {E351F97D-EA4F-4E7F-AAA0-8EBB1F2A4A62}
Expand Down
30 changes: 30 additions & 0 deletions build-tools/automation/yaml-templates/build-windows-steps.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,36 @@ steps:
testRunTitle: Microsoft.Android.Sdk.Analysis.Tests
continueOnError: true

- template: /build-tools/automation/yaml-templates/run-dotnet-preview.yaml@self
parameters:
command: test
project: tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests.csproj
arguments: -c $(XA.Build.Configuration) --logger trx --results-directory $(Agent.TempDirectory)/trimmable-typemap-tests
displayName: Test Microsoft.Android.Sdk.TrimmableTypeMap.Tests $(XA.Build.Configuration)

- task: PublishTestResults@2
displayName: publish Microsoft.Android.Sdk.TrimmableTypeMap.Tests results
condition: always()
inputs:
testResultsFormat: VSTest
testResultsFiles: "$(Agent.TempDirectory)/trimmable-typemap-tests/*.trx"
testRunTitle: Microsoft.Android.Sdk.TrimmableTypeMap.Tests

- template: /build-tools/automation/yaml-templates/run-dotnet-preview.yaml@self
parameters:
command: test
project: bin/Test$(XA.Build.Configuration)/$(DotNetTargetFramework)/Microsoft.Android.Sdk.TrimmableTypeMap.IntegrationTests.dll
arguments: --logger trx --results-directory $(Agent.TempDirectory)/trimmable-typemap-integration-tests
displayName: Test Microsoft.Android.Sdk.TrimmableTypeMap.IntegrationTests $(XA.Build.Configuration)

- task: PublishTestResults@2
displayName: publish Microsoft.Android.Sdk.TrimmableTypeMap.IntegrationTests results
condition: always()
inputs:
testResultsFormat: VSTest
testResultsFiles: "$(Agent.TempDirectory)/trimmable-typemap-integration-tests/*.trx"
testRunTitle: Microsoft.Android.Sdk.TrimmableTypeMap.IntegrationTests

- task: BatchScript@1
displayName: Test dotnet-local.cmd - create template
inputs:
Expand Down
1 change: 1 addition & 0 deletions eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<MicrosoftTemplateEngineAuthoringTasksPackageVersion>11.0.100-preview.1.26076.102</MicrosoftTemplateEngineAuthoringTasksPackageVersion>
<MicrosoftDotNetCecilPackageVersion>0.11.5-preview.26076.102</MicrosoftDotNetCecilPackageVersion>
<SystemIOHashingPackageVersion>9.0.4</SystemIOHashingPackageVersion>
<SystemReflectionMetadataPackageVersion>11.0.0-preview.1.26104.118</SystemReflectionMetadataPackageVersion>
<!-- Previous .NET Android version -->
<MicrosoftNETSdkAndroidManifest100100PackageVersion>36.1.30</MicrosoftNETSdkAndroidManifest100100PackageVersion>
<AndroidNetPreviousVersion>$(MicrosoftNETSdkAndroidManifest100100PackageVersion)</AndroidNetPreviousVersion>
Expand Down
151 changes: 151 additions & 0 deletions src/Microsoft.Android.Sdk.TrimmableTypeMap/AcwMapWriter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Microsoft.Android.Sdk.TrimmableTypeMap;

/// <summary>
/// Generates acw-map.txt from JavaPeerInfo scanner results.
/// The acw-map is consumed by _ConvertCustomView to fix up custom view names in layout XML.
///
/// Each type produces 3 lines: PartialAssemblyQualifiedName;JavaKey, ManagedKey;JavaKey, CompatJniName;JavaKey.
/// Types with DoNotGenerateAcw = true are excluded (MCW binding types).
/// </summary>
static class AcwMapWriter
{
/// <summary>
/// Creates per-assembly acw-map entries for a single assembly's scan results.
/// </summary>
public static List<AcwMapEntry> CreateEntries (IReadOnlyList<JavaPeerInfo> peers, string assemblyName)
{
var entries = new List<AcwMapEntry> ();

foreach (var peer in peers) {
if (peer.DoNotGenerateAcw)
continue;

if (peer.AssemblyName != assemblyName)
continue;

var javaKey = peer.JavaName.Replace ('/', '.');
var managedKey = peer.ManagedTypeName;
var partialAssemblyQualifiedName = $"{peer.ManagedTypeName}, {peer.AssemblyName}";
// Compat JNI name uses the same format for now
var compatJniName = javaKey;

entries.Add (new AcwMapEntry {
JavaKey = javaKey,
ManagedKey = managedKey,
PartialAssemblyQualifiedName = partialAssemblyQualifiedName,
CompatJniName = compatJniName,
AssemblyName = peer.AssemblyName,
});
}

return entries;
}

/// <summary>
/// Writes acw-map.txt, detecting XA4214 (duplicate managed key) and XA4215 (duplicate Java key).
/// </summary>
public static AcwMapResult WriteMap (IReadOnlyList<AcwMapEntry> entries, TextWriter writer)
{
var managed = new Dictionary<string, AcwMapEntry> (entries.Count, StringComparer.Ordinal);
var java = new Dictionary<string, AcwMapEntry> (entries.Count, StringComparer.Ordinal);
var managedConflicts = new Dictionary<string, List<string>> (0, StringComparer.Ordinal);
var javaConflicts = new Dictionary<string, List<string>> (0, StringComparer.Ordinal);

foreach (var entry in entries.OrderBy (e => e.ManagedKey, StringComparer.Ordinal)) {
writer.Write (entry.PartialAssemblyQualifiedName);
writer.Write (';');
writer.WriteLine (entry.JavaKey);

bool hasConflict = false;

if (managed.TryGetValue (entry.ManagedKey, out var managedConflict)) {
if (!managedConflict.AssemblyName.Equals (entry.AssemblyName, StringComparison.Ordinal)) {
if (!managedConflicts.TryGetValue (entry.ManagedKey, out var list))
managedConflicts.Add (entry.ManagedKey, list = new List<string> { managedConflict.AssemblyName });
list.Add (entry.AssemblyName);
}
hasConflict = true;
}

if (java.TryGetValue (entry.JavaKey, out var javaConflict)) {
if (!javaConflict.AssemblyName.Equals (entry.AssemblyName, StringComparison.Ordinal)) {
if (!javaConflicts.TryGetValue (entry.JavaKey, out var list))
javaConflicts.Add (entry.JavaKey, list = new List<string> { javaConflict.PartialAssemblyQualifiedName });
list.Add (entry.PartialAssemblyQualifiedName);
}
hasConflict = true;
}

if (!hasConflict) {
managed.Add (entry.ManagedKey, entry);
java.Add (entry.JavaKey, entry);

writer.Write (entry.ManagedKey);
writer.Write (';');
writer.WriteLine (entry.JavaKey);

writer.Write (entry.CompatJniName);
writer.Write (';');
writer.WriteLine (entry.JavaKey);
}
}

return new AcwMapResult {
ManagedConflicts = managedConflicts,
JavaConflicts = javaConflicts,
};
}

/// <summary>
/// Writes acw-map.txt to a file, only if content changed.
/// </summary>
public static AcwMapResult WriteMapToFile (IReadOnlyList<AcwMapEntry> entries, string outputPath)
{
using var sw = new StringWriter ();
var result = WriteMap (entries, sw);

if (result.JavaConflicts.Count > 0)
return result;

var content = sw.ToString ();
WriteIfChanged (outputPath, content);
return result;
}

static void WriteIfChanged (string path, string content)
{
if (File.Exists (path)) {
var existing = File.ReadAllText (path);
if (string.Equals (existing, content, StringComparison.Ordinal))
return;
}

var dir = Path.GetDirectoryName (path);
if (!string.IsNullOrEmpty (dir) && !Directory.Exists (dir))
Directory.CreateDirectory (dir);

File.WriteAllText (path, content);
}
}

sealed class AcwMapEntry
{
public string JavaKey { get; set; } = "";
public string ManagedKey { get; set; } = "";
public string PartialAssemblyQualifiedName { get; set; } = "";
public string CompatJniName { get; set; } = "";
public string AssemblyName { get; set; } = "";
}

sealed class AcwMapResult
{
public Dictionary<string, List<string>> ManagedConflicts { get; set; } = new ();
public Dictionary<string, List<string>> JavaConflicts { get; set; } = new ();
public bool HasErrors => JavaConflicts.Count > 0;
public bool HasWarnings => ManagedConflicts.Count > 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Polyfills for C# language features on netstandard2.0

// Required for init-only setters
namespace System.Runtime.CompilerServices
{
static class IsExternalInit { }

[AttributeUsage (AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
sealed class RequiredMemberAttribute : Attribute { }

[AttributeUsage (AttributeTargets.All, AllowMultiple = true, Inherited = false)]
sealed class CompilerFeatureRequiredAttribute (string featureName) : Attribute
{
public string FeatureName { get; } = featureName;
public bool IsOptional { get; init; }
}
}

namespace System.Diagnostics.CodeAnalysis
{
[AttributeUsage (AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
sealed class SetsRequiredMembersAttribute : Attribute { }
}
Loading