Skip to content

Commit b00e644

Browse files
authored
[Java.Interop.Tools.Generator] Create a v2 version of map.csv (#646)
For ages, `generator --enumfields` has supported a `map.csv` format, which was used within xamarin-android to "enumify" `Mono.Android.dll`. This format was entirely undocumented. Add `Documentation/EnumMappingFile.md` and document the format. The previous `map.csv` line is 5-6 "columns", comma-delimited: * API level the field was added in * C# namespace and type of the C# enum to create. * C# enum member name to create. * C# enum member value * JNI field to convert to the C# enum member, in the format `{JNI type reference}.{Java field name}`. * Flags? If (1) present, and (2) has the value `flags`, the created C# enum has the `[Flags]` attribute. Add support for a new 7-8 column line format, also documented in `EnumMappingFile.md`: * Action: `E`num, `A`dd, `R`emove, `I`gnore, `?` (decide later) * API level * JNI field to convert to the C# enum member, in the format `{JNI type reference}.{Java field name}`. * C# enum member value (which is the Java field value) * C# namespace and type of C# enum to create * C# enum member name to create. * What to do with the Java field: `remove` it or `keep` it. Replaces the previous `- ENTER TRANSIENT MODE -` "command". * Flags? If (1) present, and (2) has the value `flags`, the created C# enum has the `[Flags]` attribute. Note that the column ordering for the 7-8 column format differs from the previous 5-6 column format. This change in ordering is done for improved "enumification workflow" support: future tooling will generate the 7-8 column output *without* knowing what the C# enum type and members will be. Placing the JNI information "leftmost" allows the output to be "sensibly grouped" by tooling: ?,0,com/example/Class.FIELD,0,,,remove, Support for parsing `map.csv` has been moved out of `generator.exe` and into the new `Java.Interop.Tools.Generator.dll` assembly, in `src/Java.Interop.Tools.Generator`. This new assembly will also be used by a forthcoming `generator-utilities` app.
1 parent 1708d8a commit b00e644

File tree

18 files changed

+1041
-58
lines changed

18 files changed

+1041
-58
lines changed

Documentation/EnumMappingFile.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Enumeration Mapping File Documentation
2+
3+
## Background
4+
5+
In order to help with binding enumification (the process of converting groups
6+
of Java constant int fields into C# enums), a file can be created that defines
7+
a map between the fields and the enums to be created.
8+
9+
There is a CSV format and an XML format of this file. In practice, users are
10+
guided to the XML format via our [documentation][0] and templates. The CSV format
11+
is mainly used internally for `Mono.Android.dll`, as it converts thousands of
12+
constants into hundreds of enums.
13+
14+
## CSV Format
15+
16+
The basic format since the beginning of Xamarin contains up to 6 fields:
17+
18+
* **API Level** - This is generally only used by `Mono.Android.dll` to denote
19+
the Android level the constant was introduced in. For other uses this
20+
is generally `0`.
21+
* **Enum Type** - C# namespace and type of the enum to create. For example:
22+
`Android.Views.WindowProgress`.
23+
* **Enum Member** - C# name of the enum to create. For example:
24+
`Start`
25+
* **Enum Value** - The value of the enum. For example: `0`.
26+
* **JNI Signature** - The JNI signature of the Java constant to convert. For example:
27+
`android/view/Window.PROGRESS_START`.
28+
* **Flags** - If this field contains `flags` the enum will be created with the
29+
`[Flags]` attribute. (Any member will `flags` will make the whole enum `[Flags]`.)
30+
31+
Full example:
32+
```
33+
10,Android.Views.WindowProgress,Start,android/view/Window.PROGRESS_START,0,flags
34+
```
35+
36+
---
37+
**NOTE**
38+
39+
Our CSV files also allow comments using `//`. Lines beginning with this
40+
sequence are ignored.
41+
42+
---
43+
44+
### Transient Mode
45+
46+
By default, Java constants referenced in this format are kept. However the
47+
file can contain a line like this at any point:
48+
```
49+
- ENTER TRANSIENT MODE -
50+
```
51+
52+
Any v1 constants referenced *AFTER* this line will be removed from the bindings.
53+
(This will not affect v2 constants.)
54+
55+
## CSV Format v2
56+
57+
Over time we have found some limitations to the format, such as being able
58+
to specify if the Java constant field should be removed. Additionally, since the
59+
format only specifies constants that *SHOULD* be mapped, we cannot use this
60+
to track constants that we have examined and determined *SHOULD NOT* be mapped.
61+
This has led to various blacklists and tooling of varying success to prevent
62+
us from needing to continually re-audit those constants.
63+
64+
There is now a "v2" version of defining constants. This is a line-level change
65+
and you can mix "v1" and "v2" lines in the same file for backwards compatibility,
66+
but for consistency it's probably better to stick to one style.
67+
68+
A "v2" line contains up to 8 fields:
69+
70+
* **Action** - The action to perform. This is what denotes a "v2" line, if the first
71+
character is not one of the following it will be treated as "v1".
72+
* `E` - Create a C# enum from a Java constant
73+
* `A` - Create a C# enum not mapped to a Java constant
74+
* `R` - Remove a Java constant but do not create a C# enum
75+
* `I` - Explicitly ignore this Java constant
76+
* `?` - Unknown, an explicit action has not been decided yet, will be ignored
77+
* **API Level** - This is generally only used by `Mono.Android.dll` to denote
78+
the Android level the constant was introduced in. For other uses this
79+
is generally `0`.
80+
* **JNI Signature** - The JNI signature of the Java constant to convert. For example:
81+
`android/view/Window.PROGRESS_START`.
82+
* **Enum Value** - The value of the enum. For example: `0`.
83+
* **Enum Type** - C# namespace and type of the enum to create. For example:
84+
`Android.Views.WindowProgress`.
85+
* **Enum Member** - C# name of the enum to create. For example:
86+
`Start`
87+
* **Field Action** - Action to take on the Java constant. (This replaces Transient mode.)
88+
* `remove` - Remove the Java constant
89+
* `keep` - Keeps the Java constant
90+
* **Flags** - If this field contains `flags` the enum will be created with the
91+
`[Flags]` attribute. (Any member will `flags` will make the whole enum `[Flags]`.)
92+
93+
Full example:
94+
```
95+
E,10,android/view/Window.PROGRESS_START,0,Android.Views.WindowProgress,Start,remove,flags
96+
```
97+
98+
[0]: https://docs.microsoft.com/en-us/xamarin/android/platform/binding-java-library/customizing-bindings/java-bindings-metadata#enumfieldsxml-and-enummethodsxml

Java.Interop.sln

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Java.Interop.Tools.JavaSour
8787
EndProject
8888
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "param-name-importer", "tools\param-name-importer\param-name-importer.csproj", "{0E3AF6C1-7638-464D-9174-485D494499DC}"
8989
EndProject
90+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Java.Interop.Tools.Generator", "src\Java.Interop.Tools.Generator\Java.Interop.Tools.Generator.csproj", "{C2FD2F12-DE3B-4FB9-A0D3-FA3EF597DD04}"
91+
EndProject
92+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Java.Interop.Tools.Generator-Tests", "tests\Java.Interop.Tools.Generator-Tests\Java.Interop.Tools.Generator-Tests.csproj", "{7F4828AB-3908-458C-B09F-33C74A1368F9}"
93+
EndProject
9094
Global
9195
GlobalSection(SharedMSBuildProjectFiles) = preSolution
9296
src\Java.Interop.NamingCustomAttributes\Java.Interop.NamingCustomAttributes.projitems*{58b564a1-570d-4da2-b02d-25bddb1a9f4f}*SharedItemsImports = 5
@@ -239,6 +243,14 @@ Global
239243
{0E3AF6C1-7638-464D-9174-485D494499DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
240244
{0E3AF6C1-7638-464D-9174-485D494499DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
241245
{0E3AF6C1-7638-464D-9174-485D494499DC}.Release|Any CPU.Build.0 = Release|Any CPU
246+
{C2FD2F12-DE3B-4FB9-A0D3-FA3EF597DD04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
247+
{C2FD2F12-DE3B-4FB9-A0D3-FA3EF597DD04}.Debug|Any CPU.Build.0 = Debug|Any CPU
248+
{C2FD2F12-DE3B-4FB9-A0D3-FA3EF597DD04}.Release|Any CPU.ActiveCfg = Release|Any CPU
249+
{C2FD2F12-DE3B-4FB9-A0D3-FA3EF597DD04}.Release|Any CPU.Build.0 = Release|Any CPU
250+
{7F4828AB-3908-458C-B09F-33C74A1368F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
251+
{7F4828AB-3908-458C-B09F-33C74A1368F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
252+
{7F4828AB-3908-458C-B09F-33C74A1368F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
253+
{7F4828AB-3908-458C-B09F-33C74A1368F9}.Release|Any CPU.Build.0 = Release|Any CPU
242254
EndGlobalSection
243255
GlobalSection(SolutionProperties) = preSolution
244256
HideSolutionNode = FALSE
@@ -280,6 +292,8 @@ Global
280292
{E34BCFA0-CAA4-412C-AA1C-75DB8D67D157} = {172B608B-E6F3-41CC-9949-203A76BA247C}
281293
{093B5E94-7FB7-499F-9C11-30944BAFEE25} = {271C9F30-F679-4793-942B-0D9527CB3E2F}
282294
{0E3AF6C1-7638-464D-9174-485D494499DC} = {C8F58966-94BF-407F-914A-8654F8B8AE3B}
295+
{C2FD2F12-DE3B-4FB9-A0D3-FA3EF597DD04} = {0998E45F-8BCE-4791-A944-962CD54E2D80}
296+
{7F4828AB-3908-458C-B09F-33C74A1368F9} = {271C9F30-F679-4793-942B-0D9527CB3E2F}
283297
EndGlobalSection
284298
GlobalSection(ExtensibilityGlobals) = postSolution
285299
SolutionGuid = {29204E0C-382A-49A0-A814-AD7FBF9774A5}

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ TESTS = \
2727
bin/Test$(CONFIGURATION)/logcat-parse-Tests.dll \
2828
bin/Test$(CONFIGURATION)/generator-Tests.dll \
2929
bin/Test$(CONFIGURATION)/Xamarin.Android.Tools.ApiXmlAdjuster-Tests.dll \
30-
bin/Test$(CONFIGURATION)/Xamarin.Android.Tools.Bytecode-Tests.dll
30+
bin/Test$(CONFIGURATION)/Xamarin.Android.Tools.Bytecode-Tests.dll \
31+
bin/Test$(CONFIGURATION)/Java.Interop.Tools.Generator-Tests.dll
3132

3233
PTESTS = \
3334
bin/Test$(CONFIGURATION)/Java.Interop-PerformanceTests.dll

build-tools/automation/azure-pipelines.yaml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ jobs:
5858
inputs:
5959
solution: build-tools/scripts/RunNUnitTests.targets
6060
configuration: $(Build.Configuration)
61-
msbuildArguments: /p:TestAssembly="bin\Test$(Build.Configuration)\generator-Tests.dll;bin\Test$(Build.Configuration)\Java.Interop.Tools.JavaCallableWrappers-Tests.dll;bin\Test$(Build.Configuration)\logcat-parse-Tests.dll;bin\Test$(Build.Configuration)\Xamarin.Android.Tools.ApiXmlAdjuster-Tests.dll;bin\Test$(Build.Configuration)\Xamarin.Android.Tools.Bytecode-Tests.dll"
61+
msbuildArguments: /p:TestAssembly="bin\Test$(Build.Configuration)\generator-Tests.dll;bin\Test$(Build.Configuration)\Java.Interop.Tools.JavaCallableWrappers-Tests.dll;bin\Test$(Build.Configuration)\logcat-parse-Tests.dll;bin\Test$(Build.Configuration)\Xamarin.Android.Tools.ApiXmlAdjuster-Tests.dll;bin\Test$(Build.Configuration)\Xamarin.Android.Tools.Bytecode-Tests.dll;bin\Test$(Build.Configuration)\Java.Interop.Tools.Generator-Tests.dll"
6262
condition: succeededOrFailed()
6363

6464
- task: PublishTestResults@2
@@ -95,6 +95,13 @@ jobs:
9595
projects: Java.Interop.sln
9696
arguments: '-c $(Build.Configuration)'
9797

98+
- task: DotNetCoreCLI@2
99+
displayName: 'Tests: Java.Interop.Tools.Generator'
100+
inputs:
101+
command: test
102+
arguments: bin\Test$(Build.Configuration)\Java.Interop.Tools.Generator-Tests.dll
103+
continueOnError: true
104+
98105
- task: DotNetCoreCLI@2
99106
displayName: 'Tests: generator'
100107
inputs:
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace Java.Interop.Tools.Generator.Enumification
2+
{
3+
public enum ConstantAction
4+
{
5+
None,
6+
Ignore,
7+
Enumify,
8+
Add,
9+
Remove
10+
}
11+
}

0 commit comments

Comments
 (0)