1 /* <lambda>null2 * Copyright 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.build.docs 18 19 import androidx.build.AndroidXExtension 20 import androidx.build.SoftwareType 21 import androidx.build.addToBuildOnServer 22 import androidx.build.checkapi.shouldConfigureApiTasks 23 import androidx.build.getSupportRootFolder 24 import androidx.build.multiplatformExtension 25 import androidx.build.uptodatedness.cacheEvenIfNoOutputs 26 import org.gradle.api.DefaultTask 27 import org.gradle.api.GradleException 28 import org.gradle.api.Project 29 import org.gradle.api.file.RegularFileProperty 30 import org.gradle.api.provider.Property 31 import org.gradle.api.tasks.CacheableTask 32 import org.gradle.api.tasks.Input 33 import org.gradle.api.tasks.InputFile 34 import org.gradle.api.tasks.PathSensitive 35 import org.gradle.api.tasks.PathSensitivity 36 import org.gradle.api.tasks.TaskAction 37 38 /** 39 * Verifies that the text of the [projectPathProvider] can be found in the [tipOfTreeBuildFile] to 40 * enforce that projects enable docs generation. 41 */ 42 @CacheableTask 43 abstract class CheckTipOfTreeDocsTask : DefaultTask() { 44 @get:[InputFile PathSensitive(PathSensitivity.NONE)] 45 abstract val tipOfTreeBuildFile: RegularFileProperty 46 47 @get:Input abstract val projectPathProvider: Property<String> 48 49 @get:Input abstract val type: Property<DocsType> 50 51 @TaskAction 52 fun exec() { 53 val projectPath = projectPathProvider.get() 54 // Make sure not to allow a partial project path match, e.g. ":activity:activity" shouldn't 55 // match ":activity:activity-ktx", both need to be listed separately. 56 val projectDependency = "project(\"$projectPath\")" 57 58 val prefix = type.get().prefix 59 // Check that projects are listed with the right configuration type (docs, kmpDocs, samples) 60 val fullExpectedText = "$prefix($projectDependency)" 61 62 val fileContents = tipOfTreeBuildFile.asFile.get().readText() 63 val foundExpectedText = fileContents.contains(fullExpectedText) 64 65 if (!foundExpectedText) { 66 // If this is a KMP project, check if it is present but configured as non-KMP 67 val message = 68 if (fileContents.contains(projectDependency)) { 69 "Project $projectPath has the wrong configuration type in " + 70 "docs-tip-of-tree/build.gradle, should use $prefix\n\n" + 71 "Update the entry for $projectPath in docs-tip-of-tree/build.gradle to " + 72 "'$fullExpectedText'." 73 } else { 74 "Project $projectPath not found in docs-tip-of-tree/build.gradle\n\n" + 75 "Use the project creation script (development/project-creator/" + 76 "create_project.py) when setting up a project to make sure all required " + 77 "steps are complete.\n\n" + 78 "The project should be added to docs-tip-of-tree/build.gradle as " + 79 "\'$fullExpectedText\'.\n\n" + 80 "If this project should not have published refdocs, first check that the " + 81 "library type listed in its build.gradle file is accurate. If it is, opt out " + 82 "of refdoc generation using \'doNotDocumentReason = \"some reason\"\' in the " + 83 "'androidx' configuration section (this is not common)." 84 } 85 throw GradleException(message) 86 } 87 } 88 89 companion object { 90 fun Project.setUpCheckDocsTask(extension: AndroidXExtension) { 91 project.afterEvaluate { 92 if (!extension.requiresDocs()) return@afterEvaluate 93 94 val docsType = 95 if (extension.type == SoftwareType.Companion.SAMPLES) { 96 DocsType.SAMPLES 97 } else if (multiplatformExtension != null) { 98 DocsType.KMP 99 } else { 100 DocsType.STANDARD 101 } 102 103 val checkDocs = 104 project.tasks.register( 105 "checkDocsTipOfTree", 106 CheckTipOfTreeDocsTask::class.java 107 ) { task -> 108 task.tipOfTreeBuildFile.set( 109 project.getSupportRootFolder().resolve("docs-tip-of-tree/build.gradle") 110 ) 111 task.projectPathProvider.set(path) 112 task.type.set(docsType) 113 task.cacheEvenIfNoOutputs() 114 } 115 project.addToBuildOnServer(checkDocs) 116 } 117 } 118 119 enum class DocsType(val prefix: String) { 120 STANDARD("docs"), 121 KMP("kmpDocs"), 122 SAMPLES("samples"), 123 } 124 125 /** 126 * Whether the project should have public docs. True for API-tracked projects and samples, 127 * unless opted-out with [AndroidXExtension.doNotDocumentReason] 128 */ 129 fun AndroidXExtension.requiresDocs() = 130 shouldConfigureApiTasks() && doNotDocumentReason == null 131 } 132 } 133