From a7413a2389886082c3d3422c50a7e6cc84f43d8f Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Wed, 6 Jan 2021 09:25:23 -0500 Subject: [PATCH] [Mono.Android] Generate Mono.Android.xml; @(JavaSourceJar) on JDK11 (#5253) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://github.com/xamarin/xamarin-android/issues/4789 Context: https://github.com/xamarin/java.interop/commit/7574f166008bb45c0df97315aae7907ac25f8602 Context: https://github.com/xamarin/xamarin-android/issues/5200 What do we want? Updated documentation! Better Bindings! How do we get that? Uh… Historically, [Xamarin.Android API docs][0] were produced by parsing Android's HTML documentation from `docs-24_r01.zip` and converting it into [**mdoc**(5) documentation][1] via `tools/javadoc2mdoc`. The problem is that Google hasn't released an updated `docs*.zip` package since API-24 (~6 years ago), and thus our documentation is woefully out of date. We could have scraped developer.android.com/reference within that time frame, but web scraping is annoying, and we'd still have to deal with the pain of parsing HTML. There is an alternative, though: with API-30, there is a new `sources` package which contains the Java source code used for the API level, which in turn contains Javadoc source code comments. Previous API levels similarly contained an `android-stubs-src.jar` file which likewise contained Java source code containing Javadoc comments. The new approach is to: 1. Update `build-tools/xaprepare` to install the `sources` package. 2. Use [`java-source-tool.jar`][2] to parse the Java source code, creating an `android-javadoc.xml` file. 3. [Update `generator`][3] to consume `android-javadoc.xml` and convert the Javadocs into [C# XML documentation comments][4]. 4. Update `src/Mono.Android` so that `generator` will emit C# XML doc comments, and then produce a `Mono.Android.xml` file. The result is a `Mono.Android.xml` file which contains imported Android Javadoc documentation, e.g. Mono.Android Class Object is the root of the class hierarchy. Class Object is the root of the class hierarchy. … "Later", `Mono.Android.xml` can then be used alongside [`mdoc update --import=Mono.Android.xml`][5] to update our published API documentation. Generation of `Mono.Android.xml` is disabled by default on CI PR builds, as generating `Mono.Android.xml` increases `src/Mono.Android` build times by an unacceptable amount. With the inclusion of `java-source-tools.jar`, we can now fix the TODO mentioned in commit 380e95e3, and re-add support for `@(JavaSourceJar)` when running under JDK 11. Update `Xamarin.Android.Bindings.Core.targets` so that before invoking `generator`, we first run `java-source-utils.jar` on the `@(JavaSourceJar)` files, producing Javadoc XML files. The `` task in turn is updated to accept a new `BindingsGenerator.JavadocXml` property, which is converted into a `generator --with-javadoc-xml=FILE` option. The `@(JavaSourceJar)` item group is "extended" to support the following item metadata: * `%(CopyrightFile)`: A path to a file that contains copyright information for the Javadoc contents, which will be appended to all imported documentation. * `%(UrlPrefix)`: A URL prefix to support linking to online documentation within imported documentation. * `%(UrlStyle)`: The "style" of URLs to generate when linking to online documentation. Only one style is currently supported: `developer.android.com/reference@2020-Nov`. For .NET 6 ("One .NET") integration purposes, provide a default item group of `@(JavaSourceJar)` which includes `**\*-source*.jar` and `**\*-src.jar`. This will allow `dotnet build` of an "Android Java Library Binding" project (`dotnet new android-bindinglib`) to automatically process `.java` source code for documentation translation purposes. Add a new `$(AndroidJavadocVerbosity)` MSBuild property, which controls "how much" of the Javadoc comments are converted into C# XML documentation. Supported values are: * `full`: Convert as much Javadoc as possible. * `intellisense`: Only emit XML documentation for IDE-useful constructs: summary, parameters, returns, exceptions. The difference between the two is *build time* impact: `full` takes longer, and thus may not always be desirable. Finally, add a new `$(_UseLegacyJavadocImport)` MSBuild property which *disables* use of `java-source-utils.jar` for Javadoc importing, and instead use the previous, legacy, doesn't work on JDK 11, approach of using `javadoc` and HTML parsing. This shouldn't be needed, but just in case it *is* needed… [0]: https://github.com/xamarin/android-api-docs [1]: http://docs.go-mono.com/?link=man%3amdoc(5) [2]: https://github.com/xamarin/java.interop/commit/69e1b80afd81ac502494e4bc2a2de75f5171c73f [3]: https://github.com/xamarin/java.interop/pull/687 [4]: https://docs.microsoft.com/dotnet/csharp/codedoc [5]: http://docs.go-mono.com/?link=man%3amdoc-update(1) --- .../guides/building-apps/build-items.md | 31 ++++ .../guides/building-apps/build-properties.md | 27 +++ Documentation/release-notes/5253.md | 4 + Xamarin.Android.sln | 9 +- build-tools/automation/azure-pipelines.yaml | 1 + .../create-packs/Microsoft.Android.Sdk.proj | 1 + .../installers/create-installers.targets | 3 + .../Dependencies/AndroidToolchain.cs | 2 + .../ThirdPartyNotices/Java.Interop.cs | 13 ++ external/Java.Interop | 2 +- src/Mono.Android/Mono.Android.csproj | 11 ++ src/Mono.Android/Mono.Android.targets | 48 ++++- src/Mono.Android/javadoc-copyright.xml | 5 + ...amarin.Android.Bindings.ClassParse.targets | 40 ++++ .../Xamarin.Android.Bindings.Core.targets | 9 + ...rin.Android.Bindings.Documentation.targets | 10 +- .../Sdk/AutoImport.props | 7 +- .../Tasks/Generator.cs | 12 ++ .../Tasks/JavaSourceUtils.cs | 175 ++++++++++++++++++ .../BindingBuildTest.cs | 31 +--- .../Xamarin.Android.Build.Tests/XASdkTests.cs | 6 +- .../Xamarin.Android.Bindings.targets | 7 + .../Xamarin.Android.Common.targets | 6 + .../Xamarin.Android.McwGen-Tests.csproj | 4 + .../Xamarin.Android.McwGen-Tests.targets | 11 ++ .../android/DefaultMethodsInterface.java | 1 + 26 files changed, 435 insertions(+), 41 deletions(-) create mode 100644 Documentation/release-notes/5253.md create mode 100644 src/Mono.Android/javadoc-copyright.xml create mode 100644 src/Xamarin.Android.Build.Tasks/Tasks/JavaSourceUtils.cs diff --git a/Documentation/guides/building-apps/build-items.md b/Documentation/guides/building-apps/build-items.md index 64d4a1adc1f..0f81bf9e1ef 100644 --- a/Documentation/guides/building-apps/build-items.md +++ b/Documentation/guides/building-apps/build-items.md @@ -298,6 +298,37 @@ such as ``: ``` +## JavaSourceJar + +In a Xamarin.Android binding project, the **JavaSourceJar** build action +is used on `.jar` files which contain *Java source code*, which contains +[Javadoc documentation comments](https://www.oracle.com/technical-resources/articles/java/javadoc-tool.html). + +Prior to Xamarin.Android 11.3, the Javadoc would be converted into HTML +via the `javadoc` utility during build time, and later turned into +XML documentation. + +Starting with Xamarin.Android 11.3, Javadoc will instead be converted into +[C# XML Documentation Comments](https://docs.microsoft.com/en-us/dotnet/csharp/codedoc) +within the generated binding source code. + +[`$(AndroidJavadocVerbosity)`](~/android/deploy-test/building-apps/build-properties.md#androidjavadocverbosity) +controls how "verbose" or "complete" the imported Javadoc is. + +Starting in Xamarin.Android 11.3, the following MSBuild metadata is supported: + +* `%(CopyrightFile)`: A path to a file that contains copyright + information for the Javadoc contents, which will be appended to + all imported documentation. + +* `%(UrlPrefix)`: A URL prefix to support linking to online + documentation within imported documentation. + +* `%(UrlStyle)`: The "style" of URLs to generate when linking to + online documentation. Only one style is currently supported: + `developer.android.com/reference@2020-Nov`. + + ## LibraryProjectZip In a Xamarin.Android binding project, the **LibraryProjectZip** build diff --git a/Documentation/guides/building-apps/build-properties.md b/Documentation/guides/building-apps/build-properties.md index 3f1aa0ec2b3..00474a81f5f 100644 --- a/Documentation/guides/building-apps/build-properties.md +++ b/Documentation/guides/building-apps/build-properties.md @@ -633,6 +633,33 @@ APK root directory. The format of the path is `lib\ARCH\wrap.sh` where + `x86_64` + `x86` +## AndroidJavadocVerbosity + +Specifies how "verbose" +[C# XML Documentation Comments](https://docs.microsoft.com/en-us/dotnet/csharp/codedoc) +should be when importing Javadoc documentation within binding projects. + +Requires use of the +[`@(JavaSourceJar)`](~/android/deploy-test/building-apps/build-items.md#javasourcejar) +build action. + +This is an enum-style property, with possible values of `full` or +`intellisense`: + + * `intellisense`: Only emit the XML comments: + [`](https://docs.microsoft.com/en-us/dotnet/csharp/codedoc#exception), + [``](https://docs.microsoft.com/en-us/dotnet/csharp/codedoc#param), + [``](https://docs.microsoft.com/en-us/dotnet/csharp/codedoc#returns), + [``](https://docs.microsoft.com/en-us/dotnet/csharp/codedoc#summary). + * `full`: Emit `intellisense` elements, as well as + [``](https://docs.microsoft.com/en-us/dotnet/csharp/codedoc#remarks), + [``](https://docs.microsoft.com/en-us/dotnet/csharp/codedoc#seealso), + and anything else that's supportable. + +The default value is `intellisense`. + +Added in Xamarin.Android 11.3. + ## AndroidKeyStore A boolean value which indicates whether diff --git a/Documentation/release-notes/5253.md b/Documentation/release-notes/5253.md new file mode 100644 index 00000000000..31967f17c78 --- /dev/null +++ b/Documentation/release-notes/5253.md @@ -0,0 +1,4 @@ +#### Binding library build + + * [GitHub Issue 4789](https://github.com/xamarin/xamarin-android/issues/4789): + Support the `@(JavaSourceJar)` build action on JDK 11 and later. diff --git a/Xamarin.Android.sln b/Xamarin.Android.sln index 5f4525a319d..f672d86ece7 100644 --- a/Xamarin.Android.sln +++ b/Xamarin.Android.sln @@ -142,6 +142,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Xamarin.SourceWriter", "ext EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "apksigner", "src\apksigner\apksigner.csproj", "{9A9EF774-6EA6-414F-9D2F-DCD66C56B92A}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "java-source-utils", "external\Java.Interop\tools\java-source-utils\java-source-utils.csproj", "{37FCD325-1077-4603-98E7-4509CAD648D6}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution src\Xamarin.Android.NamingCustomAttributes\Xamarin.Android.NamingCustomAttributes.projitems*{3f1f2f50-af1a-4a5a-bedb-193372f068d7}*SharedItemsImports = 4 @@ -376,7 +378,7 @@ Global {071D9096-65BB-4359-822E-09788439F210}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU {071D9096-65BB-4359-822E-09788439F210}.Debug|AnyCPU.Build.0 = Debug|Any CPU {071D9096-65BB-4359-822E-09788439F210}.Release|AnyCPU.ActiveCfg = Release|Any CPU - {071D9096-65BB-4359-822E-09788439F210}.Release|AnyCPU.Build.0 = Release|Any CPU EndGlobalSection + {071D9096-65BB-4359-822E-09788439F210}.Release|AnyCPU.Build.0 = Release|Any CPU {2CE4CD4B-B7B7-4EAE-A9BE-2699824D6096}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU {2CE4CD4B-B7B7-4EAE-A9BE-2699824D6096}.Debug|AnyCPU.Build.0 = Debug|Any CPU {2CE4CD4B-B7B7-4EAE-A9BE-2699824D6096}.Release|AnyCPU.ActiveCfg = Release|Any CPU @@ -389,6 +391,10 @@ Global {9A9EF774-6EA6-414F-9D2F-DCD66C56B92A}.Debug|AnyCPU.Build.0 = Debug|Any CPU {9A9EF774-6EA6-414F-9D2F-DCD66C56B92A}.Release|AnyCPU.ActiveCfg = Release|Any CPU {9A9EF774-6EA6-414F-9D2F-DCD66C56B92A}.Release|AnyCPU.Build.0 = Release|Any CPU + {37FCD325-1077-4603-98E7-4509CAD648D6}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU + {37FCD325-1077-4603-98E7-4509CAD648D6}.Debug|AnyCPU.Build.0 = Debug|Any CPU + {37FCD325-1077-4603-98E7-4509CAD648D6}.Release|AnyCPU.ActiveCfg = Release|Any CPU + {37FCD325-1077-4603-98E7-4509CAD648D6}.Release|AnyCPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -454,6 +460,7 @@ Global {2CE4CD4B-B7B7-4EAE-A9BE-2699824D6096} = {04E3E11E-B47D-4599-8AFC-50515A95E715} {86A8DEFE-7ABB-4097-9389-C249581E243D} = {04E3E11E-B47D-4599-8AFC-50515A95E715} {9A9EF774-6EA6-414F-9D2F-DCD66C56B92A} = {04E3E11E-B47D-4599-8AFC-50515A95E715} + {37FCD325-1077-4603-98E7-4509CAD648D6} = {864062D3-A415-4A6F-9324-5820237BA058} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {53A1F287-EFB2-4D97-A4BB-4A5E145613F6} diff --git a/build-tools/automation/azure-pipelines.yaml b/build-tools/automation/azure-pipelines.yaml index 5b1ccba0dd4..9d045471a1a 100644 --- a/build-tools/automation/azure-pipelines.yaml +++ b/build-tools/automation/azure-pipelines.yaml @@ -67,6 +67,7 @@ variables: DotNetNUnitCategories: '& TestCategory != DotNetIgnore & TestCategory != AOT & TestCategory != MkBundle & TestCategory != MonoSymbolicate & TestCategory != PackagesConfig & TestCategory != StaticProject & TestCategory != Debugger' NUnit.NumberOfTestWorkers: 4 GitHub.Token: $(github--pat--vs-mobiletools-engineering-service2) + CONVERT_JAVADOC_TO_XMLDOC: $[ne(variables['Build.DefinitionName'], 'Xamarin.Android-PR')] # Stage and Job "display names" are shortened because they are combined to form the name of the corresponding GitHub check. stages: diff --git a/build-tools/create-packs/Microsoft.Android.Sdk.proj b/build-tools/create-packs/Microsoft.Android.Sdk.proj index 9240ef79571..84034a5f427 100644 --- a/build-tools/create-packs/Microsoft.Android.Sdk.proj +++ b/build-tools/create-packs/Microsoft.Android.Sdk.proj @@ -76,6 +76,7 @@ core workload sdk packs imported by Microsoft.NET.Workload.Android. <_PackageFiles Include="$(ToolsSourceDir)**" PackagePath="tools" /> <_PackageFiles Include="$(NetCoreAppToolsSourceDir)generator.dll" PackagePath="tools" /> <_PackageFiles Include="$(NetCoreAppToolsSourceDir)generator.runtimeconfig.json" PackagePath="tools" /> + <_PackageFiles Include="$(NetCoreAppToolsSourceDir)Java.Interop.Tools.Generator.dll" PackagePath="tools" /> <_PackageFiles Include="$(NetCoreAppToolsSourceDir)javadoc-to-mdoc.dll" PackagePath="tools" /> <_PackageFiles Include="$(NetCoreAppToolsSourceDir)javadoc-to-mdoc.runtimeconfig.json" PackagePath="tools" /> <_PackageFiles Include="$(XAInstallPrefix)xbuild-frameworks\Microsoft.Android\Version*" PackagePath="tools" /> diff --git a/build-tools/installers/create-installers.targets b/build-tools/installers/create-installers.targets index 08f8ad30baf..5a808aa767c 100644 --- a/build-tools/installers/create-installers.targets +++ b/build-tools/installers/create-installers.targets @@ -132,6 +132,7 @@ <_MSBuildFiles Include="$(MSBuildSrcDir)\illinkanalyzer.pdb" ExcludeFromAndroidNETSdk="true" /> <_MSBuildFiles Include="$(MSBuildSrcDir)\Irony.dll" /> <_MSBuildFiles Include="$(MSBuildSrcDir)\java-interop.jar" /> + <_MSBuildFiles Include="$(MSBuildSrcDir)\java-source-utils.jar" /> <_MSBuildFiles Include="$(MSBuildSrcDir)\javadoc-to-mdoc.exe" ExcludeFromAndroidNETSdk="true" /> <_MSBuildFiles Include="$(MSBuildSrcDir)\javadoc-to-mdoc.pdb" ExcludeFromAndroidNETSdk="true" /> <_MSBuildFiles Include="$(MSBuildSrcDir)\Java.Interop.dll" /> @@ -149,6 +150,8 @@ <_MSBuildFiles Include="$(MSBuildSrcDir)\Java.Interop.Tools.Generator.pdb" /> <_MSBuildFiles Include="$(MSBuildSrcDir)\Java.Interop.Tools.JavaCallableWrappers.dll" /> <_MSBuildFiles Include="$(MSBuildSrcDir)\Java.Interop.Tools.JavaCallableWrappers.pdb" /> + <_MSBuildFiles Include="$(MSBuildSrcDir)\Java.Interop.Tools.JavaSource.dll" /> + <_MSBuildFiles Include="$(MSBuildSrcDir)\Java.Interop.Tools.JavaSource.pdb" /> <_MSBuildFiles Include="$(MSBuildSrcDir)\Java.Runtime.Environment.dll" /> <_MSBuildFiles Include="$(MSBuildSrcDir)\Java.Runtime.Environment.pdb" /> <_MSBuildFiles Include="$(MSBuildSrcDir)\Java.Runtime.Environment.dll.config" Condition=" '$(HostOS)' != 'Windows' " /> diff --git a/build-tools/xaprepare/xaprepare/ConfigAndData/Dependencies/AndroidToolchain.cs b/build-tools/xaprepare/xaprepare/ConfigAndData/Dependencies/AndroidToolchain.cs index b2286001e72..6266f200528 100644 --- a/build-tools/xaprepare/xaprepare/ConfigAndData/Dependencies/AndroidToolchain.cs +++ b/build-tools/xaprepare/xaprepare/ConfigAndData/Dependencies/AndroidToolchain.cs @@ -62,6 +62,8 @@ public AndroidToolchain () new AndroidPlatformComponent ("platform-29_r01", apiLevel: "29", pkgRevision: "1"), new AndroidPlatformComponent ("platform-30_r01", apiLevel: "30", pkgRevision: "1"), + new AndroidToolchainComponent ("sources-30_r01", destDir: Path.Combine ("platforms", $"android-30", "src"), pkgRevision: "1", dependencyType: AndroidToolchainComponentType.BuildDependency), + new AndroidToolchainComponent ("docs-24_r01", destDir: "docs", pkgRevision: "1", dependencyType: AndroidToolchainComponentType.BuildDependency), new AndroidToolchainComponent ("android_m2repository_r47", destDir: Path.Combine ("extras", "android", "m2repository"), pkgRevision: "47.0.0", dependencyType: AndroidToolchainComponentType.BuildDependency), new AndroidToolchainComponent ($"x86_64-29_r07-{osTag}", destDir: Path.Combine ("system-images", "android-29", "default", "x86_64"), relativeUrl: new Uri ("sys-img/android/", UriKind.Relative), pkgRevision: "7", dependencyType: AndroidToolchainComponentType.EmulatorDependency), diff --git a/build-tools/xaprepare/xaprepare/ThirdPartyNotices/Java.Interop.cs b/build-tools/xaprepare/xaprepare/ThirdPartyNotices/Java.Interop.cs index c76d89ff01f..7128b63c9ca 100644 --- a/build-tools/xaprepare/xaprepare/ThirdPartyNotices/Java.Interop.cs +++ b/build-tools/xaprepare/xaprepare/ThirdPartyNotices/Java.Interop.cs @@ -12,6 +12,7 @@ class JavaInterop_External_Dependencies_Group : ThirdPartyNoticeGroup public override List Notices => new List { new JavaInterop_xamarin_Java_Interop_TPN (), new JavaInterop_gityf_crc_TPN (), + new JavaInterop_javaparser_javaparser_TPN (), new JavaInterop_jbevain_mono_linq_expressions_TPN (), new JavaInterop_mono_csharp_TPN (), new JavaInterop_mono_LineEditor_TPN (), @@ -69,6 +70,18 @@ POSSIBILITY OF SUCH DAMAGE. "; } + // via: https://github.com/xamarin/java.interop/blob/b588ef502d8d3b4c32e0ad731115e1b71fd56b5c/tools/java-source-utils/build.gradle#L33-L34 + class JavaInterop_javaparser_javaparser_TPN : ThirdPartyNotice + { + static readonly Uri url = new Uri ("https://github.com/javaparser/javaparser/"); + static readonly string licenseFile = Path.Combine (Configurables.Paths.ExternalJavaInteropDir, "LICENSE"); + + public override string LicenseFile => CommonLicenses.Apache20Path; + public override string Name => "javaparser/javaparser"; + public override Uri SourceUrl => url; + public override string LicenseText => String.Empty; + } + // git submodules of Java.Interop class JavaInterop_jbevain_mono_linq_expressions_TPN : ThirdPartyNotice { diff --git a/external/Java.Interop b/external/Java.Interop index 7d197f17a0f..7574f166008 160000 --- a/external/Java.Interop +++ b/external/Java.Interop @@ -1 +1 @@ -Subproject commit 7d197f17a0f9d73854522d6e1d68deafbcdbcaf6 +Subproject commit 7574f166008bb45c0df97315aae7907ac25f8602 diff --git a/src/Mono.Android/Mono.Android.csproj b/src/Mono.Android/Mono.Android.csproj index d5f343ca881..21378536fec 100644 --- a/src/Mono.Android/Mono.Android.csproj +++ b/src/Mono.Android/Mono.Android.csproj @@ -23,6 +23,16 @@ true + + True + intellisense + + + + $(OutputPath)Mono.Android.xml + $(NoWarn);CS1572;CS1573;CS1574;CS1587;CS1591; + + MonoAndroid v1.0 @@ -349,6 +359,7 @@ + diff --git a/src/Mono.Android/Mono.Android.targets b/src/Mono.Android/Mono.Android.targets index 76f9388fb5f..98364ae33dd 100644 --- a/src/Mono.Android/Mono.Android.targets +++ b/src/Mono.Android/Mono.Android.targets @@ -53,6 +53,50 @@ Replacements="@PACKAGE_VERSION@=$(_PackageVersion);@PACKAGE_VERSION_BUILD@=$(_PackageVersionBuild);@PACKAGE_HEAD_REV@=$(XAVersionHash);@PACKAGE_HEAD_BRANCH@=$(XAVersionBranch)"> + + <_JavaSourceUtilsJar>$(XAInstallPrefix)xbuild\Xamarin\Android\java-source-utils.jar + <_AndroidStableSrcDir>$(AndroidSdkDirectory)\platforms\android-$(AndroidLatestStableApiLevel)\src + <_AndroidJavadocXml>..\..\bin\Build$(Configuration)\android-javadoc.xml + + + + <_Doclink Include="--doc-copyright" /> + <_Doclink Include="$(MSBuildThisFileDirectory)javadoc-copyright.xml" /> + <_Doclink Include="--doc-url-prefix" /> + <_Doclink Include="https://developer.android.com/reference" /> + <_Doclink Include="--doc-url-style" /> + <_Doclink Include="developer.android.com/reference@2020-Nov" /> + + + <_AndroidSources Include="$(_AndroidStableSrcDir)\android\**\*.java" /> + <_AndroidSources Include="$(_AndroidStableSrcDir)\java\**\*.java" /> + <_AndroidSources Include="$(_AndroidStableSrcDir)\javax\**\*.java" /> + <_AndroidSources Include="$(_AndroidStableSrcDir)\org\**\*.java" /> + <_AndroidSources Remove="$(_AndroidStableSrcDir)\**\*.annotated.java" /> + + + <_Filenames>$(IntermediateOutputPath)\java-sources.txt + + + + <_JSIArg Include="-v" /> + <_JSIArg Include="--source "$(_AndroidStableSrcDir)"" /> + <_JSIArg Include="--output-javadoc "$(_AndroidJavadocXml)"" /> + <_JSIArg Include="@$(_Filenames)" /> + + + + --type-map-report=$(IntermediateOutputPath)mcw\type-mapping.txt <_Api>$(IntermediateOutputPath)mcw\api.xml <_Dirs>--enumdir=$(IntermediateOutputPath)mcw + <_WithJavadocXml Condition=" '$(IncludeAndroidJavadoc)' == 'True' ">--doc-comment-verbosity=$(AndroidJavadocVerbosity) "--with-javadoc-xml=$(_AndroidJavadocXml)" <_FullIntermediateOutputPath>$([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)')) <_LangFeatures>--lang-features=nullable-reference-types <_LangFeatures Condition="$(AndroidApiLevel) >= 30">$(_LangFeatures),default-interface-methods,nested-interface-types,interface-constants diff --git a/src/Mono.Android/javadoc-copyright.xml b/src/Mono.Android/javadoc-copyright.xml new file mode 100644 index 00000000000..7bca1d75e90 --- /dev/null +++ b/src/Mono.Android/javadoc-copyright.xml @@ -0,0 +1,5 @@ +Portions of this page are modifications based on work created and shared by the +Android Open Source Project + and used according to terms described in the +Creative Commons 2.5 Attribution License. + diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.ClassParse.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.ClassParse.targets index 9db19f1678d..7d61a578409 100644 --- a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.ClassParse.targets +++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.ClassParse.targets @@ -14,9 +14,14 @@ This file is only used by binding projects. + + <_AndroidDocumentationPath Include="@(JavaDocIndex->'%(RootDir)\%(Directory)')" /> <_AndroidDocumentationPath Include="$(JavaDocPaths)" /> <_AndroidDocumentationPath Include="$(Java7DocPaths)" /> @@ -43,4 +48,39 @@ This file is only used by binding projects. /> + + + + + + <_JavaSourceJavadocXml Include="@(_JavaSourceJarHashes->'$(IntermediateOutputPath)javadoc-%(Filename)-%(Hash).xml')" /> + + + + + + + + + + diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.Core.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.Core.targets index d9f69d77f6c..696536dbd59 100644 --- a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.Core.targets +++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.Core.targets @@ -12,15 +12,22 @@ It is shared between "legacy" binding projects and .NET 5 projects. + false $(IntermediateOutputPath)generated\ + intellisense $(IntermediateOutputPath)api.xml <_GeneratorStampFile>$(IntermediateOutputPath)generator.stamp + + $(OutputPath)$(AssemblyName).xml + $(NoWarn);CS1573;CS1591 + + @@ -52,6 +59,8 @@ It is shared between "legacy" binding projects and .NET 5 projects. ApiXmlInput="$(ApiOutputFile)" AnnotationsZipFiles="@(AnnotationsZip)" AssemblyName="$(AssemblyName)" + JavadocVerbosity="$(AndroidJavadocVerbosity)" + JavadocXml="@(_JavaSourceJavadocXml)" TransformFiles="@(TransformFile)" ReferencedManagedLibraries="@(ReferencePath);@(ReferenceDependencyPaths)" MonoAndroidFrameworkDirectories="$(_XATargetFrameworkDirectories)" diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.Documentation.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.Documentation.targets index c292195177d..4c66ae634b2 100644 --- a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.Documentation.targets +++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.Documentation.targets @@ -16,12 +16,8 @@ This file is only used by binding projects. .NET 5 can eventually use it, once ` - - <_JavadocSupported Condition=" $(_JdkVersion.StartsWith ('1.8')) ">True - - + + <_DefaultJavaSourceJarPattern>**\*-source.jar;**\*-sources.jar;**\*-src.jar + + @@ -33,9 +37,10 @@ https://github.com/dotnet/designs/blob/4703666296f5e59964961464c25807c727282cae/ - + + diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/Generator.cs b/src/Xamarin.Android.Build.Tasks/Tasks/Generator.cs index ea07cf51c96..78ab8091c0a 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/Generator.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/Generator.cs @@ -53,6 +53,9 @@ public class BindingsGenerator : AndroidDotnetToolTask public ITaskItem[] ReferencedManagedLibraries { get; set; } public ITaskItem[] AnnotationsZipFiles { get; set; } + public ITaskItem[] JavadocXml { get; set; } + public string JavadocVerbosity { get; set; } + private List> transform_files = new List> (); public override bool RunTask () @@ -179,6 +182,15 @@ protected override string GenerateCommandLineCommands () if (features.Any ()) WriteLine (sw, $"--lang-features={string.Join (",", features)}"); } + + if (!string.IsNullOrEmpty (JavadocVerbosity)) + WriteLine (sw, $"\"--doc-comment-verbosity={JavadocVerbosity}\""); + + if (JavadocXml != null) { + foreach (var xml in JavadocXml) { + WriteLine (sw, $"\"--with-javadoc-xml={Path.GetFullPath (xml.ItemSpec)}\""); + } + } } cmd.AppendSwitch (ApiXmlInput); diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/JavaSourceUtils.cs b/src/Xamarin.Android.Build.Tasks/Tasks/JavaSourceUtils.cs new file mode 100644 index 00000000000..b7a47426479 --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Tasks/JavaSourceUtils.cs @@ -0,0 +1,175 @@ +// Copyright (C) 2012 Xamarin, Inc. All rights reserved. + +using System; +using System.Linq; +using System.IO; +using System.Reflection; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using Xamarin.Android.Tools; + +namespace Xamarin.Android.Tasks +{ + public class JavaSourceUtils : AndroidToolTask + { + public override string TaskPrefix => "JSU"; + + [Required] + public string JavaSourceUtilsJar { get; set; } + + [Required] + public string JavaSdkDirectory { get; set; } + + [Required] + public ITaskItem[] InputFiles { get; set; } + + public ITaskItem[] References { get; set; } + + public ITaskItem[] BootClassPath { get; set; } + + public ITaskItem JavadocCopyrightFile { get; set; } + public string JavadocUrlPrefix { get; set; } + public string JavadocUrlStyle { get; set; } + + public string JavaOptions { get; set; } + + public string JavaMaximumHeapSize { get; set; } + + public ITaskItem OutputJavadocXml { get; set; } + + string responseFilePath; + + public override bool RunTask () + { + if (InputFiles == null || InputFiles.Count () == 0) { + Log.LogCodedError ("XA1020", Properties.Resources.XA1020); + return false; + } + + if (References != null) + foreach (var path in References) + if (!Directory.Exists (path.ItemSpec) && !File.Exists (path.ItemSpec)) + Log.LogCodedError ("XA1022", Properties.Resources.XA1022, path.ItemSpec); + + if (Log.HasLoggedErrors) + return false; + + try { + return base.RunTask (); + } + finally { + File.Delete (responseFilePath); + } + } + + static string GetOutputFileName (ITaskItem[] items) => + Files.HashString ( + string.Join ("\n", items.Select (item => Path.GetFullPath (item.ItemSpec).Replace ('\\', '/')))); + + + protected override string GenerateCommandLineCommands () + { + responseFilePath = CreateResponseFile (); + + var cmd = new CommandLineBuilder (); + + // Add the JavaOptions if they are not null + // These could be any of the additional options + if (!string.IsNullOrEmpty (JavaOptions)) { + cmd.AppendSwitch (JavaOptions); + } + + if (!string.IsNullOrEmpty (JavaMaximumHeapSize)) { + cmd.AppendSwitchIfNotNull("-Xmx", JavaMaximumHeapSize); + } + + // Arguments sent to java.exe + cmd.AppendSwitchIfNotNull ("-jar ", JavaSourceUtilsJar); + + cmd.AppendSwitch ($"@{responseFilePath}"); + + + return cmd.ToString (); + } + + string CreateResponseFile () + { + var responseFile = Path.GetTempFileName (); + + using var response = new StreamWriter (responseFile, append: false, encoding: MonoAndroidHelper.UTF8withoutBOM); + Log.LogDebugMessage ("[java-source-utils] response file contents: {0}", responseFile); + + if (BootClassPath != null && BootClassPath.Any ()) { + var classpath = string.Join (Path.PathSeparator.ToString (), BootClassPath.Select (p => Path.GetFullPath (p.ItemSpec))); + AppendArg (response, "--bootclasspath"); + AppendArg (response, classpath); + } + + if (References != null && References.Any ()) { + foreach (var r in References) { + if (Directory.Exists (r.ItemSpec)) { + AppendArg (response, "--source"); + AppendArg (response, Path.GetFullPath (r.ItemSpec)); + continue; + } + if (!File.Exists (r.ItemSpec)) { + Log.LogCodedError ("XA1022", Properties.Resources.XA1022, r.ItemSpec); + continue; + } + if (r.ItemSpec.EndsWith (".jar", StringComparison.OrdinalIgnoreCase)) { + AppendArg (response, "--jar"); + AppendArg (response, Path.GetFullPath (r.ItemSpec)); + continue; + } + if (r.ItemSpec.EndsWith (".aar", StringComparison.OrdinalIgnoreCase)) { + AppendArg (response, "--aar"); + AppendArg (response, Path.GetFullPath (r.ItemSpec)); + continue; + } + Log.LogError ($"Unsupported @(Reference) item: {r.ItemSpec}"); + } + } + AppendArg (response, "--output-javadoc"); + AppendArg (response, OutputJavadocXml.ItemSpec); + + if (!string.IsNullOrEmpty (JavadocCopyrightFile?.ItemSpec)) { + AppendArg (response, "--doc-copyright"); + AppendArg (response, Path.GetFullPath (JavadocCopyrightFile.ItemSpec)); + } + if (!string.IsNullOrEmpty (JavadocUrlPrefix)) { + AppendArg (response, "--doc-url-prefix"); + AppendArg (response, Path.GetFullPath (JavadocUrlPrefix)); + } + if (!string.IsNullOrEmpty (JavadocUrlStyle)) { + AppendArg (response, "--doc-link-style"); + AppendArg (response, Path.GetFullPath (JavadocUrlStyle)); + } + + foreach (var path in InputFiles) { + AppendArg (response, Path.GetFullPath (path.ItemSpec)); + } + + return responseFile; + + void AppendArg (TextWriter writer, string line) + { + writer.WriteLine (line); + Log.LogDebugMessage (line); + } + } + + protected override string ToolName { + get => "java-source-utils"; + } + + public override string ToolExe { + get { return OS.IsWindows ? "java.exe" : "java"; } + set { base.ToolExe = value; } + } + + protected override string GenerateFullPathToTool () + { + return Path.Combine (JavaSdkDirectory, "bin", ToolExe); + } + } +} diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs index f8b2d73d162..4b2ab09b74c 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs @@ -452,36 +452,11 @@ public void JavaSourceJar () BinaryContent = () => Convert.FromBase64String (InlineData.JavaSourcesJarBase64) }); Assert.IsTrue (bindingBuilder.Build (binding), "binding build should have succeeded"); - var jdkVersion = GetJdkVersion (); - if (jdkVersion > new Version (9, 0)) { - Assert.Ignore ("JDK 11 and @(JavaSourceJar) don't currently mix."); - return; - } - string xml = bindingBuilder.Output.GetIntermediaryAsText ("docs/Com.Xamarin.Android.Test.Msbuildtest/JavaSourceJarTest.xml"); - Assert.IsTrue (xml.Contains (" - name to display."), "missing doc"); - } - } - static Version GetJdkVersion () - { - var jdkPath = AndroidSdkResolver.GetJavaSdkPath (); - var releasePath = Path.Combine (jdkPath, "release"); - if (!File.Exists (releasePath)) - return null; - foreach (var line in File.ReadLines (releasePath)) { - const string JavaVersionStart = "JAVA_VERSION=\""; - if (!line.StartsWith (JavaVersionStart, StringComparison.OrdinalIgnoreCase)) - continue; - var value = line.Substring (JavaVersionStart.Length, line.Length - JavaVersionStart.Length - 1); - int last = 0; - for (last = 0; last < value.Length; ++last) { - if (char.IsDigit (value, last) || value [last] == '.') - continue; - break; - } - return Version.Parse (last == value.Length ? value : value.Substring (0, last)); + var path = Path.Combine (Root, bindingBuilder.ProjectDirectory, binding.OutputPath, "UnnamedProject.xml"); + var xml = File.ReadAllText (path); + Assert.IsTrue (xml.Contains ("name to display."), "param `name` documentation not imported!"); } - return null; } [Test] diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs index 8408db95581..6be1f4fd113 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs @@ -379,13 +379,15 @@ public void DotNetBuild (string runtimeIdentifiers, bool isRelease) .Select (Path.GetFileName) .OrderBy (f => f) .ToArray (); - CollectionAssert.AreEqual (new [] { + var expectedFiles = new[]{ "es", $"{proj.ProjectName}.dll", $"{proj.ProjectName}.pdb", $"{proj.PackageName}.apk", $"{proj.PackageName}-Signed.apk", - }, files); + $"{proj.ProjectName}.xml", + }; + CollectionAssert.AreEqual (expectedFiles, files, $"Expected: {string.Join (";", expectedFiles)}\n Found: {string.Join (";", files)}"); var assemblyPath = Path.Combine (outputPath, $"{proj.ProjectName}.dll"); FileAssert.Exists (assemblyPath); diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Bindings.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Bindings.targets index fe895d11e03..040a1d53f76 100755 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Bindings.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Bindings.targets @@ -19,6 +19,7 @@ Copyright (C) 2012 Xamarin Inc. All rights reserved. --> + diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 41fd8284eef..3f3b8b39c89 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -641,6 +641,12 @@ because xbuild doesn't support framework reference assemblies. /> + + + + + + + @@ -148,6 +151,7 @@ BuildTestJarFile; _CopyTestJarFiles; + _CreateJavaSourceJar; $(BuildDependsOn) diff --git a/tests/CodeGen-Binding/Xamarin.Android.McwGen-Tests/Xamarin.Android.McwGen-Tests.targets b/tests/CodeGen-Binding/Xamarin.Android.McwGen-Tests/Xamarin.Android.McwGen-Tests.targets index 72f6f5c59bf..45a38d3fd96 100644 --- a/tests/CodeGen-Binding/Xamarin.Android.McwGen-Tests/Xamarin.Android.McwGen-Tests.targets +++ b/tests/CodeGen-Binding/Xamarin.Android.McwGen-Tests/Xamarin.Android.McwGen-Tests.targets @@ -6,7 +6,18 @@ DestinationFolder="$(OutputPath)" /> + + + + + diff --git a/tests/CodeGen-Binding/Xamarin.Android.McwGen-Tests/java/com/xamarin/android/DefaultMethodsInterface.java b/tests/CodeGen-Binding/Xamarin.Android.McwGen-Tests/java/com/xamarin/android/DefaultMethodsInterface.java index 1323f0c5c4b..04f2af75255 100644 --- a/tests/CodeGen-Binding/Xamarin.Android.McwGen-Tests/java/com/xamarin/android/DefaultMethodsInterface.java +++ b/tests/CodeGen-Binding/Xamarin.Android.McwGen-Tests/java/com/xamarin/android/DefaultMethodsInterface.java @@ -1,5 +1,6 @@ package com.xamarin.android; +/** An interface which contains interface default methods. */ public interface DefaultMethodsInterface { default int foo () { return 0; }