Skip to content

Commit 1077258

Browse files
authored
Add InternalJavadoc custom error prone check (#5277)
* Add InternalJavadoc custom error prone check * Add example usage * Move to conventions * Revert "Move to conventions" This reverts commit d8a8209. * Just get it working * Clearer error message * versions * Apply almost everywhere * feedback * Always at the end of javadoc * Fix test * Missed (at least) one * No longer internal * Fix NPE * Spotless * Convert awslambda Java test to JUnit 5 so can reduce visibility * Reduce visibility * Rename the check * More * Move into errorprone-convention * Fix UserExcludedClassesConfigurerTest
1 parent 3cb1efc commit 1077258

File tree

83 files changed

+492
-31
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+492
-31
lines changed

conventions/src/main/kotlin/otel.errorprone-conventions.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ plugins {
66

77
dependencies {
88
errorprone("com.google.errorprone:error_prone_core")
9+
errorprone(project(":custom-checks"))
910
}
1011

1112
val disableErrorProne = properties["disableErrorProne"]?.toString()?.toBoolean() ?: false

custom-checks/build.gradle.kts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
plugins {
2+
`java-library`
3+
}
4+
5+
dependencies {
6+
implementation("com.google.errorprone:error_prone_core:2.10.0")
7+
8+
annotationProcessor("com.google.auto.service:auto-service:1.0.1")
9+
compileOnly("com.google.auto.service:auto-service-annotations:1.0.1")
10+
11+
testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.2")
12+
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.2")
13+
14+
testImplementation("com.google.errorprone:error_prone_test_helpers:2.11.0")
15+
}
16+
17+
tasks {
18+
test {
19+
useJUnitPlatform()
20+
}
21+
22+
withType<JavaCompile> {
23+
options.compilerArgs.addAll(listOf(
24+
"--add-exports", "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED",
25+
"--add-exports", "jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
26+
"--add-exports", "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED"
27+
))
28+
}
29+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.customchecks;
7+
8+
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
9+
10+
import com.google.auto.service.AutoService;
11+
import com.google.errorprone.BugPattern;
12+
import com.google.errorprone.VisitorState;
13+
import com.google.errorprone.bugpatterns.BugChecker;
14+
import com.google.errorprone.matchers.Description;
15+
import com.sun.source.doctree.DocCommentTree;
16+
import com.sun.source.tree.ClassTree;
17+
import com.sun.source.tree.PackageTree;
18+
import com.sun.tools.javac.api.JavacTrees;
19+
import java.util.regex.Pattern;
20+
import javax.annotation.Nullable;
21+
import javax.lang.model.element.Modifier;
22+
23+
@AutoService(BugChecker.class)
24+
@BugPattern(
25+
name = "OtelInternalJavadoc",
26+
summary =
27+
"This public internal class doesn't end with the javadoc disclaimer: \""
28+
+ InternalJavadoc.EXPECTED_INTERNAL_COMMENT
29+
+ "\"",
30+
severity = WARNING)
31+
public class InternalJavadoc extends BugChecker implements BugChecker.ClassTreeMatcher {
32+
33+
private static final Pattern INTERNAL_PACKAGE_PATTERN = Pattern.compile("\\binternal\\b");
34+
35+
private static final Pattern EXCLUDE_PACKAGE_PATTERN =
36+
Pattern.compile("^io\\.opentelemetry\\.javaagent\\.instrumentation\\.internal\\.");
37+
38+
static final String EXPECTED_INTERNAL_COMMENT =
39+
"This class is internal and is hence not for public use."
40+
+ " Its APIs are unstable and can change at any time.";
41+
42+
@Override
43+
public Description matchClass(ClassTree tree, VisitorState state) {
44+
if (!isPublic(tree) || !isInternal(state)) {
45+
return Description.NO_MATCH;
46+
}
47+
String javadoc = getJavadoc(state);
48+
if (javadoc != null && javadoc.endsWith(EXPECTED_INTERNAL_COMMENT)) {
49+
return Description.NO_MATCH;
50+
}
51+
return describeMatch(tree);
52+
}
53+
54+
private static boolean isPublic(ClassTree tree) {
55+
return tree.getModifiers().getFlags().contains(Modifier.PUBLIC);
56+
}
57+
58+
private static boolean isInternal(VisitorState state) {
59+
PackageTree packageTree = state.getPath().getCompilationUnit().getPackage();
60+
if (packageTree == null) {
61+
return false;
62+
}
63+
String packageName = packageTree.getPackageName().toString();
64+
return INTERNAL_PACKAGE_PATTERN.matcher(packageName).find()
65+
&& !EXCLUDE_PACKAGE_PATTERN.matcher(packageName).find();
66+
}
67+
68+
@Nullable
69+
private static String getJavadoc(VisitorState state) {
70+
DocCommentTree docCommentTree =
71+
JavacTrees.instance(state.context).getDocCommentTree(state.getPath());
72+
if (docCommentTree == null) {
73+
return null;
74+
}
75+
return docCommentTree.toString().replace("\n", "");
76+
}
77+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.customchecks;
7+
8+
import com.google.errorprone.CompilationTestHelper;
9+
import org.junit.jupiter.api.Test;
10+
11+
class InternalJavadocTest {
12+
13+
@Test
14+
void test() {
15+
doTest("internal/InternalJavadocPositiveCases.java");
16+
doTest("internal/InternalJavadocNegativeCases.java");
17+
}
18+
19+
private static void doTest(String path) {
20+
CompilationTestHelper.newInstance(InternalJavadoc.class, InternalJavadocTest.class)
21+
.addSourceFile(path)
22+
.doTest();
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.customchecks.internal;
7+
8+
/**
9+
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
10+
* any time.
11+
*/
12+
public class InternalJavadocNegativeCases {
13+
14+
/**
15+
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
16+
* any time.
17+
*/
18+
public static class One {}
19+
20+
static class Two {}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.customchecks.internal;
7+
8+
// BUG: Diagnostic contains: doesn't end with the javadoc disclaimer
9+
public class InternalJavadocPositiveCases {
10+
11+
// BUG: Diagnostic contains: doesn't end with the javadoc disclaimer
12+
public static class One {}
13+
14+
/** Doesn't have the disclaimer. */
15+
// BUG: Diagnostic contains: doesn't end with the javadoc disclaimer
16+
public static class Two {}
17+
}

dependencyManagement/build.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ val DEPENDENCY_SETS = listOf(
7373
DependencySet(
7474
"org.mockito",
7575
"4.2.0",
76-
listOf("mockito-core", "mockito-junit-jupiter")
76+
listOf("mockito-core", "mockito-junit-jupiter", "mockito-inline")
7777
),
7878
DependencySet(
7979
"org.slf4j",
@@ -91,6 +91,7 @@ val DEPENDENCIES = listOf(
9191
"ch.qos.logback:logback-classic:1.2.10",
9292
"com.github.stefanbirkner:system-lambda:1.2.1",
9393
"com.github.stefanbirkner:system-rules:1.19.0",
94+
"uk.org.webcompere:system-stubs-jupiter:2.0.1",
9495
"com.uber.nullaway:nullaway:0.9.5",
9596
"commons-beanutils:commons-beanutils:1.9.4",
9697
"commons-cli:commons-cli:1.5.0",
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
package io.opentelemetry.instrumentation.api.cache.internal;
6+
package io.opentelemetry.instrumentation.api.cache;
77

8-
import io.opentelemetry.instrumentation.api.cache.Cache;
98
import java.util.concurrent.TimeUnit;
109
import org.openjdk.jmh.annotations.Benchmark;
1110
import org.openjdk.jmh.annotations.Fork;

instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/cache/internal/weaklockfree/WeakConcurrentMap.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@
4040
*
4141
* <p>This class has been copied as is from
4242
* https://github.com/raphw/weak-lock-free/blob/ad0e5e0c04d4a31f9485bf12b89afbc9d75473b3/src/main/java/com/blogspot/mydailyjava/weaklockfree/WeakConcurrentMap.java
43+
*
44+
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
45+
* at any time.
4346
*/
4447
// Suppress warnings since this is copied as-is.
4548
@SuppressWarnings({
@@ -196,6 +199,9 @@ public int hashCode() {
196199
/**
197200
* A {@link WeakConcurrentMap} where stale entries are removed as a side effect of interacting
198201
* with this map.
202+
*
203+
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
204+
* at any time.
199205
*/
200206
public static class WithInlinedExpunction<K, V> extends WeakConcurrentMap<K, V> {
201207

instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/AsyncInstrumentRegistry.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
// OTel SDK in the agent, and therefore there must be only one AsyncInstrumentRegistry too -
2525
// otherwise some async metrics would get lost because of duplicate instrument registrations.
2626

27+
/**
28+
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
29+
* any time.
30+
*/
2731
// TODO: refactor this class, there's too much copy-paste here
2832
public final class AsyncInstrumentRegistry {
2933

@@ -251,6 +255,10 @@ private LongMeasurementSource(@Nullable T obj, ToLongFunction<T> metricFunction)
251255
}
252256
}
253257

258+
/**
259+
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
260+
* any time.
261+
*/
254262
public static final class AsyncMeasurementHandle {
255263

256264
private final MeasurementsRecorder<?> measurementsRecorder;

0 commit comments

Comments
 (0)