Loading tools/processors/devicepolicy/src/android/processor/devicepolicy/Enum.kt +15 −9 Original line number Diff line number Diff line Loading @@ -114,7 +114,11 @@ class EnumProcessor(processingEnv: ProcessingEnvironment) : Processor<EnumPolicy } val enumName = intDefElement.qualifiedName.toString() val enumDoc = processingEnv.elementUtils.getDocComment(intDefElement) val enumDoc = processingEnv.elementUtils.getDocComment(intDefElement) ?: "" if (enumDoc.trim().isEmpty()) { printError(intDefElement, "Missing JavaDoc for IntDef used by $element") } // In the class-level example above, these would be ENUM_ENTRY_1 and ENUM_ENTRY_2. val entries = getIntDefIdentifiers(annotationMirror, intDefElement) Loading Loading @@ -168,13 +172,13 @@ class EnumProcessor(processingEnv: ProcessingEnvironment) : Processor<EnumPolicy // In the class-level example above, these would be {ENUM_ENTRY_1,ENUM_ENTRY_2}. @Suppress("UNCHECKED_CAST") val values = annotationValue.value as List<AnnotationValue> val documentations = identifiers.map { identifier -> // TODO(b/442973945): Fail gracefully when the element is not part of the parent class. val identifierElement = intDefElement.enclosingElement.enclosedElements.find { val documentations: List<String?> = identifiers.map { identifier -> // TODO(b/442973945): Support identifiers outside of same class. intDefElement.enclosingElement.enclosedElements.firstOrNull { it.simpleName.toString() == identifier } ?.let { processingEnv.elementUtils.getDocComment(it) } processingEnv.elementUtils.getDocComment(identifierElement) } return identifiers.mapIndexed { i, identifier -> Loading Loading @@ -217,7 +221,7 @@ class EnumProcessor(processingEnv: ProcessingEnvironment) : Processor<EnumPolicy } } class EnumEntryMetadata(val name: String, val value: Int, val documentation: String) { class EnumEntryMetadata(val name: String, val value: Int, val documentation: String?) { fun dump(writer: JsonWriter) { writer.apply { beginObject() Loading @@ -228,8 +232,10 @@ class EnumEntryMetadata(val name: String, val value: Int, val documentation: Str name("value") value(value.toLong()) if (documentation != null) { name("documentation") value(documentation) } endObject() } Loading tools/processors/devicepolicy/src/android/processor/devicepolicy/Processor.kt +5 −1 Original line number Diff line number Diff line Loading @@ -151,8 +151,12 @@ abstract class Processor<T : Annotation>(protected val processingEnv: Processing val enclosingType = element.enclosingElement.asType() val name = "$enclosingType.$element" val documentation = processingEnv.elementUtils.getDocComment(element) val type = policyType(element).toString() val documentation = processingEnv.elementUtils.getDocComment(element) ?: "" if (documentation.trim().isEmpty()) { printError(element, "Missing JavaDoc") } return Policy(name, type, documentation, metadata) } Loading tools/processors/devicepolicy/test/resources/android/processor/devicepolicy/test/missingDocumentation/PolicyIdentifier.java 0 → 100644 +34 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app.admin; import android.processor.devicepolicy.BooleanPolicyDefinition; import android.processor.devicepolicy.PolicyDefinition; public final class PolicyIdentifier<T> { // We don't actually do anything with this. public PolicyIdentifier(String id) { } private static final String TEST_POLICY_1_KEY = "test_policy_1_key"; @BooleanPolicyDefinition( base = @PolicyDefinition ) public static final PolicyIdentifier<Boolean> TEST_POLICY_1 = new PolicyIdentifier<>( TEST_POLICY_1_KEY); } tools/processors/devicepolicy/test/src/android/processor/devicepolicy/test/PolicyProcessorTest.kt +12 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,8 @@ class PolicyProcessorTest { const val OTHER_CLASS_JAVA = "$RESOURCE_ROOT/OtherClass.java" const val POLICY_IDENTIFIER_INVALID_TYPE_JAVA = "$RESOURCE_ROOT/invalidtype/PolicyIdentifier.java" const val POLICY_IDENTIFIER_DIRECT_DEFINITION_JAVA = "$RESOURCE_ROOT/directPolicyDefinition/PolicyIdentifier.java" const val POLICY_IDENTIFIER_MISSING_DOCUMENTATION_JAVA = "$RESOURCE_ROOT/missingDocumentation/PolicyIdentifier.java" /** * Comes from the actual IntDef.java in the source, located in a different folder. Loading Loading @@ -110,6 +112,15 @@ class PolicyProcessorTest { assertThat(compilation).hadErrorContaining("@PolicyDefinition should not be applied to any element") } @Test fun test_missingDocumentation_failsToCompile() { val compilation: Compilation = mCompiler.compile( JavaFileObjects.forResource(POLICY_IDENTIFIER_MISSING_DOCUMENTATION_JAVA) ) assertThat(compilation).failed() assertThat(compilation).hadErrorContaining("Missing JavaDoc") } /** * Errors should only come from our processor. */ Loading @@ -127,5 +138,6 @@ class PolicyProcessorTest { checkCompileSucceeds(OTHER_CLASS_JAVA, POLICY_IDENTIFIER_JAVA, INT_DEF_JAVA) checkCompileSucceeds(POLICY_IDENTIFIER_INVALID_TYPE_JAVA) checkCompileSucceeds(POLICY_IDENTIFIER_DIRECT_DEFINITION_JAVA) checkCompileSucceeds(POLICY_IDENTIFIER_MISSING_DOCUMENTATION_JAVA) } } No newline at end of file Loading
tools/processors/devicepolicy/src/android/processor/devicepolicy/Enum.kt +15 −9 Original line number Diff line number Diff line Loading @@ -114,7 +114,11 @@ class EnumProcessor(processingEnv: ProcessingEnvironment) : Processor<EnumPolicy } val enumName = intDefElement.qualifiedName.toString() val enumDoc = processingEnv.elementUtils.getDocComment(intDefElement) val enumDoc = processingEnv.elementUtils.getDocComment(intDefElement) ?: "" if (enumDoc.trim().isEmpty()) { printError(intDefElement, "Missing JavaDoc for IntDef used by $element") } // In the class-level example above, these would be ENUM_ENTRY_1 and ENUM_ENTRY_2. val entries = getIntDefIdentifiers(annotationMirror, intDefElement) Loading Loading @@ -168,13 +172,13 @@ class EnumProcessor(processingEnv: ProcessingEnvironment) : Processor<EnumPolicy // In the class-level example above, these would be {ENUM_ENTRY_1,ENUM_ENTRY_2}. @Suppress("UNCHECKED_CAST") val values = annotationValue.value as List<AnnotationValue> val documentations = identifiers.map { identifier -> // TODO(b/442973945): Fail gracefully when the element is not part of the parent class. val identifierElement = intDefElement.enclosingElement.enclosedElements.find { val documentations: List<String?> = identifiers.map { identifier -> // TODO(b/442973945): Support identifiers outside of same class. intDefElement.enclosingElement.enclosedElements.firstOrNull { it.simpleName.toString() == identifier } ?.let { processingEnv.elementUtils.getDocComment(it) } processingEnv.elementUtils.getDocComment(identifierElement) } return identifiers.mapIndexed { i, identifier -> Loading Loading @@ -217,7 +221,7 @@ class EnumProcessor(processingEnv: ProcessingEnvironment) : Processor<EnumPolicy } } class EnumEntryMetadata(val name: String, val value: Int, val documentation: String) { class EnumEntryMetadata(val name: String, val value: Int, val documentation: String?) { fun dump(writer: JsonWriter) { writer.apply { beginObject() Loading @@ -228,8 +232,10 @@ class EnumEntryMetadata(val name: String, val value: Int, val documentation: Str name("value") value(value.toLong()) if (documentation != null) { name("documentation") value(documentation) } endObject() } Loading
tools/processors/devicepolicy/src/android/processor/devicepolicy/Processor.kt +5 −1 Original line number Diff line number Diff line Loading @@ -151,8 +151,12 @@ abstract class Processor<T : Annotation>(protected val processingEnv: Processing val enclosingType = element.enclosingElement.asType() val name = "$enclosingType.$element" val documentation = processingEnv.elementUtils.getDocComment(element) val type = policyType(element).toString() val documentation = processingEnv.elementUtils.getDocComment(element) ?: "" if (documentation.trim().isEmpty()) { printError(element, "Missing JavaDoc") } return Policy(name, type, documentation, metadata) } Loading
tools/processors/devicepolicy/test/resources/android/processor/devicepolicy/test/missingDocumentation/PolicyIdentifier.java 0 → 100644 +34 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app.admin; import android.processor.devicepolicy.BooleanPolicyDefinition; import android.processor.devicepolicy.PolicyDefinition; public final class PolicyIdentifier<T> { // We don't actually do anything with this. public PolicyIdentifier(String id) { } private static final String TEST_POLICY_1_KEY = "test_policy_1_key"; @BooleanPolicyDefinition( base = @PolicyDefinition ) public static final PolicyIdentifier<Boolean> TEST_POLICY_1 = new PolicyIdentifier<>( TEST_POLICY_1_KEY); }
tools/processors/devicepolicy/test/src/android/processor/devicepolicy/test/PolicyProcessorTest.kt +12 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,8 @@ class PolicyProcessorTest { const val OTHER_CLASS_JAVA = "$RESOURCE_ROOT/OtherClass.java" const val POLICY_IDENTIFIER_INVALID_TYPE_JAVA = "$RESOURCE_ROOT/invalidtype/PolicyIdentifier.java" const val POLICY_IDENTIFIER_DIRECT_DEFINITION_JAVA = "$RESOURCE_ROOT/directPolicyDefinition/PolicyIdentifier.java" const val POLICY_IDENTIFIER_MISSING_DOCUMENTATION_JAVA = "$RESOURCE_ROOT/missingDocumentation/PolicyIdentifier.java" /** * Comes from the actual IntDef.java in the source, located in a different folder. Loading Loading @@ -110,6 +112,15 @@ class PolicyProcessorTest { assertThat(compilation).hadErrorContaining("@PolicyDefinition should not be applied to any element") } @Test fun test_missingDocumentation_failsToCompile() { val compilation: Compilation = mCompiler.compile( JavaFileObjects.forResource(POLICY_IDENTIFIER_MISSING_DOCUMENTATION_JAVA) ) assertThat(compilation).failed() assertThat(compilation).hadErrorContaining("Missing JavaDoc") } /** * Errors should only come from our processor. */ Loading @@ -127,5 +138,6 @@ class PolicyProcessorTest { checkCompileSucceeds(OTHER_CLASS_JAVA, POLICY_IDENTIFIER_JAVA, INT_DEF_JAVA) checkCompileSucceeds(POLICY_IDENTIFIER_INVALID_TYPE_JAVA) checkCompileSucceeds(POLICY_IDENTIFIER_DIRECT_DEFINITION_JAVA) checkCompileSucceeds(POLICY_IDENTIFIER_MISSING_DOCUMENTATION_JAVA) } } No newline at end of file