Skip to content

Commit ccf54bb

Browse files
graememorganError Prone Team
authored andcommitted
InvalidSnippet: flag snippets which seem to omit the ":" required for inline code.
PiperOrigin-RevId: 705529440
1 parent a26105b commit ccf54bb

File tree

3 files changed

+170
-0
lines changed

3 files changed

+170
-0
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright 2024 The Error Prone Authors.
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 com.google.errorprone.bugpatterns.javadoc;
18+
19+
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
20+
import static com.google.errorprone.bugpatterns.javadoc.Utils.diagnosticPosition;
21+
22+
import com.google.errorprone.BugPattern;
23+
import com.google.errorprone.VisitorState;
24+
import com.google.errorprone.bugpatterns.BugChecker;
25+
import com.google.errorprone.bugpatterns.BugChecker.ClassTreeMatcher;
26+
import com.google.errorprone.bugpatterns.BugChecker.MethodTreeMatcher;
27+
import com.google.errorprone.bugpatterns.BugChecker.VariableTreeMatcher;
28+
import com.google.errorprone.matchers.Description;
29+
import com.sun.source.doctree.DocTree;
30+
import com.sun.source.doctree.ErroneousTree;
31+
import com.sun.source.tree.ClassTree;
32+
import com.sun.source.tree.MethodTree;
33+
import com.sun.source.tree.VariableTree;
34+
import com.sun.source.util.DocTreePath;
35+
import com.sun.source.util.DocTreePathScanner;
36+
37+
/** A bug pattern; see the summary. */
38+
@BugPattern(summary = "This tag is invalid.", severity = WARNING, documentSuppression = false)
39+
public final class InvalidSnippet extends BugChecker
40+
implements ClassTreeMatcher, MethodTreeMatcher, VariableTreeMatcher {
41+
42+
private void scanTags(VisitorState state, DocTreePath path) {
43+
new InvalidTagChecker(state).scan(path, null);
44+
}
45+
46+
@Override
47+
public Description matchClass(ClassTree classTree, VisitorState state) {
48+
DocTreePath path = Utils.getDocTreePath(state);
49+
if (path != null) {
50+
scanTags(state, path);
51+
}
52+
return Description.NO_MATCH;
53+
}
54+
55+
@Override
56+
public Description matchMethod(MethodTree methodTree, VisitorState state) {
57+
DocTreePath path = Utils.getDocTreePath(state);
58+
if (path != null) {
59+
scanTags(state, path);
60+
}
61+
return Description.NO_MATCH;
62+
}
63+
64+
@Override
65+
public Description matchVariable(VariableTree variableTree, VisitorState state) {
66+
DocTreePath path = Utils.getDocTreePath(state);
67+
if (path != null) {
68+
scanTags(state, path);
69+
}
70+
return Description.NO_MATCH;
71+
}
72+
73+
final class InvalidTagChecker extends DocTreePathScanner<Void, Void> {
74+
private final VisitorState state;
75+
76+
private InvalidTagChecker(VisitorState state) {
77+
this.state = state;
78+
}
79+
80+
@Override
81+
public Void visitErroneous(ErroneousTree erroneousTree, Void unused) {
82+
if (erroneousTree.getBody().startsWith("{@snippet")) {
83+
String message =
84+
"This @snippet tag looks to be malformed. Did you forget the \":\"? Snippets should"
85+
+ " start with \"{@snippet :\" followed by a newline.";
86+
state.reportMatch(
87+
buildDescription(diagnosticPosition(getCurrentPath(), state))
88+
.setMessage(message)
89+
.build());
90+
}
91+
return null;
92+
}
93+
94+
@Override
95+
public Void scan(DocTree tree, Void unused) {
96+
return super.scan(tree, null);
97+
}
98+
}
99+
}

core/src/main/java/com/google/errorprone/scanner/BuiltInCheckerSuppliers.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@
545545
import com.google.errorprone.bugpatterns.javadoc.InvalidInlineTag;
546546
import com.google.errorprone.bugpatterns.javadoc.InvalidLink;
547547
import com.google.errorprone.bugpatterns.javadoc.InvalidParam;
548+
import com.google.errorprone.bugpatterns.javadoc.InvalidSnippet;
548549
import com.google.errorprone.bugpatterns.javadoc.InvalidThrows;
549550
import com.google.errorprone.bugpatterns.javadoc.InvalidThrowsLink;
550551
import com.google.errorprone.bugpatterns.javadoc.MalformedInlineTag;
@@ -966,6 +967,7 @@ public static ScannerSupplier warningChecks() {
966967
InvalidInlineTag.class,
967968
InvalidLink.class,
968969
InvalidParam.class,
970+
InvalidSnippet.class,
969971
InvalidTargetingOnScopingAnnotation.class,
970972
InvalidThrows.class,
971973
InvalidThrowsLink.class,
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright 2024 The Error Prone Authors.
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 com.google.errorprone.bugpatterns.javadoc;
18+
19+
import static com.google.common.truth.TruthJUnit.assume;
20+
21+
import com.google.errorprone.CompilationTestHelper;
22+
import org.junit.Test;
23+
import org.junit.runner.RunWith;
24+
import org.junit.runners.JUnit4;
25+
26+
/** Unit tests for {@link InvalidSnippet} bug pattern. */
27+
@RunWith(JUnit4.class)
28+
public final class InvalidSnippetTest {
29+
private final CompilationTestHelper helper =
30+
CompilationTestHelper.newInstance(InvalidSnippet.class, getClass());
31+
32+
@Test
33+
public void snippetWithoutBody_butWithFile() {
34+
assume().that(Runtime.version().feature()).isAtLeast(18);
35+
36+
helper
37+
.addSourceLines(
38+
"Test.java",
39+
"""
40+
/**
41+
*
42+
*
43+
* {@snippet file="foo.java"}
44+
*/
45+
interface Test {}
46+
""")
47+
.doTest();
48+
}
49+
50+
@Test
51+
public void snippetWithColon() {
52+
assume().that(Runtime.version().feature()).isAtLeast(18);
53+
54+
helper
55+
.addSourceLines(
56+
"Test.java",
57+
"""
58+
/**
59+
*
60+
*
61+
* {@snippet :
62+
* I have a colon
63+
* }
64+
*/
65+
interface Test {}
66+
""")
67+
.doTest();
68+
}
69+
}

0 commit comments

Comments
 (0)