Generated javadoc for Android project is empty - android

Generating the javadoc worked perfectly fine with Java 8 but does not work with the newly bundled Java 11 in Android Studio.
I get errors like error: package ... does not exist or error: cannot find symbol, but these are all files and references that should not be public or documented in any case.
As additional info: I am working on an SDK (thats why some classes need to be not documented) and here is the task that creates the javadoc.
I would appreciate any help on this matter.
And yes I read this post: javadoc: "package [...] does not exist" for external references without docs but it is not applicable, since the files that are causing the issue are not third party.
task("generate${variant.name.capitalize()}Javadoc", type: Javadoc) {
options.memberLevel = JavadocMemberLevel.PUBLIC
options.encoding = "utf-8"
failOnError = false
source = variant.javaCompiler.source
def androidJar = "${android.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar"
doFirst {
classpath = files(variant.javaCompile.classpath.files) + files(androidJar)
}
options {
links "http://docs.oracle.com/javase/7/docs/api/"
linksOffline "http://d.android.com/reference", "${android.sdkDirectory}/docs/reference"
}
// and then there are includes of packages and files
}
Edit:
When removing the includes the javadoc is created without an issue, but of course for all the classes.
Edit 2:
Found an interim solution by ignoring source errors.
options.addStringOption('-ignore-source-errors', '-quiet')

Related

Enable compose metrics in android application

I want to enable compose metrics by this official docs.
In root gradle I added this:
subprojects {
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions {
if (project.findProperty("composeCompilerReports") == "true") {
kotlinOptions.freeCompilerArgs = kotlinOptions.freeCompilerArgs + listOf(
"-P",
"plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" +
project.buildDir.absolutePath + "/compose_reports"
)
kotlinOptions.freeCompilerArgs = kotlinOptions.freeCompilerArgs + listOf(
"-P",
"plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=" +
project.buildDir.absolutePath + "/compose_metrics"
)
}
}
}
}
and start the building by this command:
./gradlew assembleRelease -PcomposeCompilerReports=true --rerun-tasks
the building starts and even one report for one application module in its build folder created. But as I understand the further process stuck with an error:
> Task :core-common-feature-utils:kaptGenerateStubsReleaseKotlin FAILED
e: Multiple values are not allowed for plugin option androidx.compose.compiler.plugins.kotlin:metricsDestination
Plugin "androidx.compose.compiler.plugins.kotlin" usage:
liveLiterals <true|false> Enable Live Literals code generation
liveLiteralsEnabled <true|false>
Enable Live Literals code generation (with per-file enabled flags)
generateFunctionKeyMetaClasses <true|false>
Generate function key meta classes with annotations indicating the functions and their group keys. Generally used for tooling.
sourceInformation <true|false>
Include source information in generated code
metricsDestination <path> Save compose build metrics to this folder
reportsDestination <path> Save compose build reports to this folder
intrinsicRemember <true|false>
Include source information in generated code
suppressKotlinVersionCompatibilityCheck <true|false>
Suppress Kotlin version compatibility check
generateDecoys <true|false>
Generate decoy methods in IR transform
FAILURE: Build completed with 2 failures.
Also, I noticed that every time the process give the error with different module after one successful and can give my 2 same errors or three - and finally stackoverflow error.
please, help with idea how to overcome this
gradle plugin ver 7.4.1
P.S. As I understand from investigations, the modules without in their gradle
kotlin("kapt")
id("dagger.hilt.android.plugin")
creates the report. The using of kotlin("kapt") gives that error. But I do not know how to compile the project without it, because I am using hilt.
P.P.S. As I am trying more, I have managed to make reports after deleting hilt from build.gradle in modules. In this case the command runs till 100%. But application will not run of course. This is a little "inconvenient" to make report in such a way.
Please, if you have an idea..
Do not add it to root gradle file. You may add this code to module gradle file with compose:
android {
kotlinOptions {
if (project.findProperty("enableComposeReports") == "true") {
val outputDir = project.buildDir.path + "/compose-reports"
freeCompilerArgs = freeCompilerArgs + listOf(
"-P",
"plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=$outputDir",
"-P",
"plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=$outputDir"
)
}
}
}
or use buildSrc scripts to prevent code duplication. See this repo for example https://github.com/olshevski/compose-navigation-reimagined/blob/main/buildSrc/src/main/kotlin/compose-compiler-reports.gradle.kts

How to generate OpenAPI sources from gradle when building Android app

What I'm trying to achieve
I'm trying to generate my REST API client for Android using OpenAPI Generator from the build.gradle script. That way, I wouldn't have to run the generator command line every time the specs change. Ideally, this would be generated when I build/assemble my app, and the sources would end up in the java (generated) folder, where generated sources are then accessible from the code (this is what happens with the BuildConfig.java file for example).
What I've tried so far
Following this link from their official GitHub, here's the build.gradle file I ended up with:
apply plugin: 'com.android.application'
apply plugin: 'org.openapi.generator'
...
openApiValidate {
inputSpec = "$rootDir/app/src/main/openapi/my-api.yaml"
recommend = true
}
openApiGenerate {
generatorName = "java"
inputSpec = "$rootDir/app/src/main/openapi/my-api.yaml"
outputDir = "$buildDir/generated/openapi"
groupId = "$project.group"
id = "$project.name-openapi"
version = "$project.version"
apiPackage = "com.example.mypackage.api"
invokerPackage = "com.example.mypackage.invoker"
modelPackage = "com.example.mypackage.model"
configOptions = [
java8 : "true",
dateLibrary : "java8",
library : "retrofit2"
]
}
...
First, I've never managed to get the API generated with the build/assemble task, even when I tried adding:
compileJava.dependsOn tasks.openApiGenerate
or
assemble.dependsOn tasks.openApiGenerate
The only way I could generate the sources was by manually triggering the openApiGenerate task:
Then, when I do generate my sources this way, they end up in the build folder but aren't accessible from my code, and aren't visible in the java (generated) folder:
I then have to manually copy/paste the generated source files to my project sources in order to use the API.
Even though I'm able to work around these issues by adding manual procedures, it would be way more maintainable if the whole process was simply automatic. I was able to achieve a similar result with another tool, Protobuf. Indeed, my gradle task gets triggered every time I build the app, and the sources end up in the java (generated) folder, so I don't have to do any additional work. The task is much simpler though, so I assume the main work that I'm not able to replicate with OpenAPI Generator is handled by the Protobuf plugin itself.
You have to specify path to the generated sources as a custom source set for your Gradle module, which is app in this case, as described here – https://developer.android.com/studio/build/build-variants#configure-sourcesets. That way Gradle will treat your sources as accessible from your code.
Something like this:
android {
...
sourceSets {
main {
java.srcDirs = ['build/generated/openapi/src/main/java']
}
}
...
}
I solved the issue you described like this, I'm using gradle.kts however.
See my build.gradle.kts
plugins {
// Your other plugins
id("org.openapi.generator") version "5.3.0"
}
openApiGenerate {
generatorName.set("kotlin")
inputSpec.set("$rootDir/app/src/main/openapi/my-api.yaml")
outputDir.set("$buildDir/generated/api")
// Your other specification
}
application {
// Your other code
sourceSets {
main {
java {
// TODO: Set this path according to what was generated for you
srcDir("$buildDir/generated/api/src/main/kotlin")
}
}
}
}
tasks.compileKotlin {
dependsOn(tasks.openApiGenerate)
}
You need to build the application at least once for the IDE to detect the library (at least this is the case for me in Intellij)
Your build should automatically generate the open api classes , to refer the generated classes in your java project you should add the generated class path to your source directory like it was mentioned in the other answers
https://developer.android.com/studio/build/build-variants#configure-sourcesets
As far as the task dependency goes , in android tasks are generated after configuration thus for gradle to recognize the task , wrap it inside afterEvaluate block like
afterEvaluate {
tasks.compileDebugJavaWithJavac.dependsOn(tasks.openApiGenerate)
}
I had this issue, and this answer https://stackoverflow.com/a/55646891/14111809 led me to a more informative error:
error: incompatible types: Object cannot be converted to Annotation
#java.lang.Object()
Taking a look at the generated files that were causing this error, noticed:
import com.squareup.moshi.Json;
After including a Moshi in the app build.gradle, the build succeeded and the generated code was accessible.
implementation("com.squareup.moshi:moshi-kotlin:1.13.0")

Dokka - skip generating javadoc for default android packages

I am trying to use Dokka plugin to generate Javadoc for android Kotlin application. I added the plugin to my gradle:
classpath "org.jetbrains.dokka:dokka-gradle-plugin:0.9.15"
Then I made a basic configuration following project instructions:
dokka {
outputFormat = 'javadoc'
outputDirectory = "$rootDir/docs"
skipEmptyPackages = true
noStdlibLink = true
}
I generate documentation using basic gradle command:
[user#linux AppDir]$ bash gradlew dokka
Output is fine, but it includes multiple directories from android or plugins I have added to my project, for example:
android.R
android.support
com.google
com.crashlytics
.
.
.
etc.
How do I skip these packages? Is there any way to generate dock only for my /app/scr/java folder, and files I created? Any help is appreciated.
Dokka version 0.9.16 will include a bugfix to remove generated files from documentation.
In version 0.9.15, the following commit seemed to address that "Suppress output of android.R and other generated stuff in dokka-android", but apparently after creating the suppresedFiles map with the needed information, it was not really used to filter sourceSets.
UPDATE: Dokka 0.9.16 has been released with the fix, among other improvements.
#224 Filtered out Android generated classes from docs
Here is a working example with Dokka 0.9.16:
task dokka(overwrite: true, type: org.jetbrains.dokka.gradle.DokkaAndroidTask) {
outputFormat = 'javadoc'
outputDirectory = "$buildDir/docs"
// Do not create index pages for empty packages
skipEmptyPackages = true
//Do not output deprecated members. Applies globally, can be overridden by packageOptions
skipDeprecated = false
//No default documentation link to kotlin-stdlib
noStdlibLink = false
}
If you use Android then the type is important: org.jetbrains.dokka.gradle.DokkaAndroidTask
Not DokkaTask but DokkaAndroidTask.

Gradle exclude R.java in Android Javadocs when internal classes depend on R.java

I am building JavaDoc for an API wherein classes in the API depend on R.java. I want to build the Javadoc w/o symbol errors referencing the missing R.java file as even when I set failOnError false the build succeeds but our Jenkins job will report the build as Failed when errors occur in successful builds. The task below will successfully create the javadocs but will report errors during build relating to not finding R.java.
android.libraryVariants.all { variant ->
def name = variant.name.capitalize()
task("generate${name}Doclava", type: Javadoc) {
description "Generates Javadoc for $variant.name."
source = variant.javaCompile.source
title = null
// use android.bootClasspath instead of building our own path to android jar
//ext.androidJar = "${android.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar"
// hardcoded path to generated R.java file to avoid javadoc compile issues
ext.R = "build/generated/source/r/minSDK15/release"
classpath += project.files(android.sourceSets.main.java.srcDirs, variant.javaCompile.classpath.files, android.bootClasspath)
destinationDir = file("${project.docsDir}/${name}/doclava")
options {
docletpath = configurations.jaxDoclet.files.asType(List)
doclet "com.google.doclava.Doclava"
bootClasspath new File(System.getenv('JAVA_HOME') + "/jre/lib/rt.jar")
addStringOption "XDignore.symbol.file", "-quiet"
addStringOption "hdf project.name", "${project.name}"
addStringOption "federate android", "http://d.android.com/reference"
addStringOption "federationxml android", "http://doclava.googlecode.com/svn/static/api/android-10.xml"
addStringOption "federate JDK", "http://download.oracle.com/javase/6/docs/api/index.html?"
addStringOption "federationxml JDK", "http://doclava.googlecode.com/svn/static/api/openjdk-6.xml"
addStringOption "templatedir", "${project.docsDir}/${name}/doclava/templates"
addStringOption "apixml", "${project.docsDir}/${name}/doclava/api-${project.version}.xml"
addStringOption "since doclava/since/api-1.0.0.xml", "1.0.0"
addStringOption "apiversion", "${project.version}"
failOnError false
}
// exclude generated files
exclude '**/BuildConfig.java'
exclude '**/R.java'
// exclude internal packages
exclude '**/internal/**'
options.addStringOption "apixml", "${project.docsDir}/${name}/doclava/api-${project.version}.xml"
}
}
Some things I have tried:
Hardcode the path to the generated R.java file and add to the classpath.
classpath += project.files(android.sourceSets.main.java.srcDirs, variant.javaCompile.classpath.files, android.bootClasspath, ext.R)
This successfully removes the errors so the build succeeds, but the resulting javadoc has empty links to R.*.class in the javadoc.
Remove the exclude '**/R.java' line from the exclude list along with not including the path to R.java in the classpath.
This successfully removes the errors and the build succeeds, but the resulting javadoc has links to R.*.class files.
It seems the exclude statement is excluding from the classpath and not the javadoc. Any insight into how to generate a javadoc where classes depend on R.java but don't include R.java in the javadoc output would be deeply appreciated.
On Android Studio, go to the following settings (settings can be accessed via File > Settings):
Appearance & Behaviour > Scopes
You should be able to browse your project files here. Now select your files and use the buttons on the far right to include/exclude them to your scope (you can exclude, or not include R.java files and BuildConfig.java files). Make sure the checkbox at the bottom "Share scope" is ticked, and your scope has a memorable name.
Next go to the Javadoc generator dialog (Tools > Generate Javadoc). Select the bottom radio button ("Custom Scope") and then from the menu, select the scope you created earlier. There are other settings you can configure for your Javadocs.
Finally click 'OK', and you should have generated Javadocs.
Hopefully this should solve your problem.
I suspect you are trying to exclude R.java because the auto-generated javadoc in that class doesn't conform to doclint. So you are seeing a bunch of errors and warnings like:
R.java:530: error: unknown tag: colgroup
* <colgroup align="left" />
^
What about removing the exclude '**/R.java' and suppressing any errors generated by R.java instead?
Using this as a basis, and then looking at Xdoclint documentation, you should be able suppress R.java errors by adding:
options.addStringOption('Xdoclint:none R.java', '-quiet')
I have tested this and it removes the R.java errors. You'll still see them print to console, but it won't count in the final error numbers.

Gradle, Javadoc and Android documentation

I'm now using Gradle for all my projects, and even for javadoc generation.
android.libraryVariants.all { variant ->
task("generate${variant.name}Javadoc", type: Javadoc) {
title = "$name $version API"
source = variant.javaCompile.source
ext.androidJar = "${android.plugin.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar"
ext.googlePlayServicesJar = "${android.plugin.sdkDirectory}/extras/google/google_play_services/libproject/google-play-services_lib/libs/google-play-services.jar"
classpath = files(variant.javaCompile.classpath.files, ext.androidJar, ext.googlePlayServicesJar)
options.links("http://docs.oracle.com/javase/7/docs/api/");
options.links("http://d.android.com/reference/");
//options.linksOffline("http://d.android.com/reference", "${android.plugin.sdkDirectory}/docs/reference");
exclude '**/BuildConfig.java'
exclude '**/R.java'
}
}
With that code I got everything working, except one thing: regular Android API objects like Activity, Bitmap etc.
Java's links are working fine.
The final generated documentation does not link to http://d.android.com/reference.
I tried both options.links() and options.linksOffline() without success.
EDIT
Thanks to #ejb, the problem was that you cannot provide multiple options.links() at the same time.
So I used both options.links() for Java's documentation and options.linksOffline() for Android's documentation:
options {
links("http://docs.oracle.com/javase/7/docs/api/");
linksOffline("http://d.android.com/reference", "${android.plugin.sdkDirectory}/docs/reference");
//stylesheetFile = new File(projectDir, "stylesheet.css");
}
I was able to successfully link to http://d.android.com/reference using the following snippet which is functionally exactly what you have (as far as I can tell).
android.libraryVariants.all { variant ->
task("generate${variant.name.capitalize()}Javadoc", type: Javadoc) {
// title = ''
// description = ''
source = variant.javaCompile.source
classpath = files(variant.javaCompile.classpath.files, project.android.getBootClasspath())
options {
links "http://docs.oracle.com/javase/7/docs/api/"
linksOffline "http://d.android.com/reference","${android.sdkDirectory}/docs/reference"
}
exclude '**/BuildConfig.java'
exclude '**/R.java'
}
}
So there is something else amiss here.
You have to build the javadoc offline, as it doesn't seem the package-list is available on the path of the web service. Maybe double check that you actually have the docs loaded locally, and make sure there is a package-list in the /[android-sdk]/docs/reference directory.
If you still can't figure it out, perhaps you could post output.
Another thing you might check is the ./build/tmp/[taskname]/javadoc.options, the head of said file should show the appropriate options carefully set. Things to check for would include the proper inclusion of the android.jar in the -classpath and the presence of linksOffline with expected arguments: -linksoffline extDocURL packageListLoc
javadoc.options should have both options with only the respective arguments:
-linksoffline 'http://d.android.come/reference' '[sdkDir]/docs/reference'
-links 'http://docs.oracle.com/javase/7/docs/api/'
EDIT: android.getBootClasspath() is nicer, thanks to P-chan.
For Android Gradle plugin 1.1.2+ (com.android.tools.build:gradle:1.1.+)
libraryVariants - does not work anymore
use:
task javadoc(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
destinationDir = file("../javadoc/")
failOnError false
}
destinationDir = file("../javadoc/") - locate javadocs at root of project directory (in this way jenkins javadoc plugin could find it and show in special Document panel)
failOnError false - for suppress warnings that can cause fail build on jenkins
Alternative for Gradle JavaDocs
Doxygen - cross reference documentation tool.
could be run from UI or terminal: http://www.doxygen.nl/manual/doxygen_usage.html
Generating javadoc available throw java tool: 'javadoc'
run from command line:
javadoc -d docs -sourcepath app/src/main/java -subpackages com
docs - destination folder

Categories

Resources