Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2a48175
Add SuppressWarnings classes with AnnotatedFor methods
aosen-xiong May 4, 2026
66e664f
Remove redundant check for AnnotatedFor in SourceChecker
aosen-xiong May 4, 2026
90c6889
Remove redundant check for AnnotatedFor in SourceChecker
aosen-xiong May 5, 2026
87b149f
Apply suggestions from code review
aosen-xiong May 5, 2026
19dfafc
Apply formatter
aosen-xiong May 5, 2026
ca073e6
Enhance documentation and logic for @AnnotatedFor and @SuppressWarnin…
aosen-xiong May 11, 2026
569903b
Merge branch 'master' into fix-annotatedfor-warning
aosen-xiong May 11, 2026
f63127a
Merge branch 'master' into fix-annotatedfor-warning
aosen-xiong May 13, 2026
da31816
Merge branch 'master' into fix-annotatedfor-warning
wmdietl May 15, 2026
f11ee59
Merge branch 'master' into fix-annotatedfor-warning
wmdietl May 15, 2026
2d93fb8
Merge branch 'master' into fix-annotatedfor-warning
aosen-xiong May 18, 2026
8e85969
Merge branch 'master' into fix-annotatedfor-warning
wmdietl Jun 5, 2026
2844c1c
Merge branch 'master' into fix-annotatedfor-warning
wmdietl Jun 8, 2026
5963c8e
Clarify AnnotatedFor warning suppression docs
aosen-xiong Jun 19, 2026
e747ab5
Refine suppression lookup for AnnotatedFor
aosen-xiong Jun 19, 2026
f7ea97b
Merge branch 'master' into fix-annotatedfor-warning
aosen-xiong Jun 19, 2026
a481619
Clarify SuppressWarnings scope docs
aosen-xiong Jun 19, 2026
a82e290
Refine AnnotatedFor suppression wording
aosen-xiong Jun 19, 2026
c4fb0fa
Merge branch 'master' into fix-annotatedfor-warning
wmdietl Jul 17, 2026
1e400ff
Add failing test for shouldSuppressWarnings(Element) issue
wmdietl Jul 17, 2026
19b2e07
Fix shouldSuppressWarnings(Element) AnnotatedFor behavior and update …
wmdietl Jul 17, 2026
dd4e56f
Document element suppression tests
aosen-xiong Jul 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,14 @@ void bar() {
annotatedForNullness(initializedField);
annotatedForNullnessAndInitialization(initializedField);
}

// @SuppressWarnings("nullness") should suppress all nullness diagnostics within the annotated
// declaration's scope, including those in nested @AnnotatedFor("nullness") scopes.
@SuppressWarnings("nullness")
class SuppressWarningsClassWithAnnotatedForMethod {
@AnnotatedFor("nullness")
@NonNull Object m() {
return null;
}
}
}
8 changes: 6 additions & 2 deletions docs/manual/annotating-libraries.tex
Original file line number Diff line number Diff line change
Expand Up @@ -384,8 +384,12 @@
conservative defaults
(see Section~\ref{defaults-classfile}) for any type use with no explicit
user-written annotation, \emph{and} the checker issues no warnings.
The command-line argument \code{-AonlyAnnotatedFor} can be used to suppress errors and warnings outside of the scope of an \<@AnnotatedFor> annotation,
but does not change the default qualifiers for source code (See Section~\ref{aonlyannotatedfor}).
Warnings in code with a relevant \<@AnnotatedFor> annotation can still be suppressed by
Comment thread
aosen-xiong marked this conversation as resolved.
Outdated
an in-scope \<@SuppressWarnings> annotation.
The command-line argument \code{-AonlyAnnotatedFor} can be used to suppress
errors and warnings outside of the scope of an \<@AnnotatedFor> annotation,
but does not change the default qualifiers for source code (see
Section~\ref{aonlyannotatedfor}).
\end{sloppypar}

The \refqualclass{framework/qual}{AnnotatedFor} annotation, written on a
Expand Down
7 changes: 5 additions & 2 deletions docs/manual/warnings.tex
Original file line number Diff line number Diff line change
Expand Up @@ -694,8 +694,11 @@

\sectionAndLabel{\code{-AonlyAnnotatedFor} command-line option}{aonlyannotatedfor}

You can suppress all errors and warnings for code outside of a corresponding \code{@AnnotatedFor} by applying this command-line option.
Note that the \code{@AnnotatedFor} annotation must include the checker's name to enable warnings from that checker.
You can suppress all errors and warnings for code outside of a corresponding
\code{@AnnotatedFor} by applying this command-line option.
Note that the \code{@AnnotatedFor} annotation must include the checker's name to
enable warnings from that checker, except for warnings suppressed by another
Comment thread
aosen-xiong marked this conversation as resolved.
Outdated
mechanism such as \code{@SuppressWarnings}.
For example, use \code{@AnnotatedFor("nullness")} for the Nullness Checker.
This flag only suppresses warnings, compared to \code{-AuseConservativeDefaultsForUncheckedCode=source},
which also applies conservative defaults for code outside the scope of an \code{@AnnotatedFor} annotation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2773,6 +2773,12 @@ public boolean shouldSuppressWarnings(Tree tree, String errKey) {
* otherwise
*/
public boolean shouldSuppressWarnings(TreePath path, String errKey) {
if (shouldSuppress(getSuppressWarningsStringsFromOption(), errKey)) {
Comment thread
aosen-xiong marked this conversation as resolved.
return true;
}

boolean foundAnnotatedFor = false;

// iterate through the path; continue until path contains no declarations
for (TreePath declPath = TreePathUtil.enclosingDeclarationPath(path);
declPath != null;
Expand All @@ -2781,49 +2787,46 @@ public boolean shouldSuppressWarnings(TreePath path, String errKey) {

if (decl instanceof VariableTree) {
Element elt = TreeUtils.elementFromDeclaration((VariableTree) decl);
if (shouldSuppressWarnings(elt, errKey)) {
if (shouldSuppressWarningsOnElement(elt, errKey)) {
return true;
}
} else if (decl instanceof MethodTree) {
Element elt = TreeUtils.elementFromDeclaration((MethodTree) decl);
if (shouldSuppressWarnings(elt, errKey)) {
if (shouldSuppressWarningsOnElement(elt, errKey)) {
return true;
}

if (isAnnotatedForThisCheckerOrUpstreamChecker(elt)) {
// Return false immediately. Do NOT check for AnnotatedFor in the enclosing
// elements as the closest AnnotatedFor is already found.
return false;
if (!foundAnnotatedFor && isAnnotatedForThisCheckerOrUpstreamChecker(elt)) {
foundAnnotatedFor = true;
}
} else if (TreeUtils.classTreeKinds().contains(decl.getKind())) {
// A class tree
Element elt = TreeUtils.elementFromDeclaration((ClassTree) decl);
if (shouldSuppressWarnings(elt, errKey)) {
if (shouldSuppressWarningsOnElement(elt, errKey)) {
return true;
}

if (isAnnotatedForThisCheckerOrUpstreamChecker(elt)) {
// Return false immediately. Do NOT check for AnnotatedFor in the enclosing
// elements as the closest AnnotatedFor is already found.
return false;
if (!foundAnnotatedFor && isAnnotatedForThisCheckerOrUpstreamChecker(elt)) {
foundAnnotatedFor = true;
}
Element packageElement = elt.getEnclosingElement();
if (packageElement != null && packageElement.getKind() == ElementKind.PACKAGE) {
if (shouldSuppressWarnings(packageElement, errKey)) {
if (shouldSuppressWarningsOnElement(packageElement, errKey)) {
return true;
}
if (isAnnotatedForThisCheckerOrUpstreamChecker(packageElement)) {
// Return false immediately. Do NOT check for AnnotatedFor in the enclosing
// elements as the closest AnnotatedFor is already found.
return false;
if (!foundAnnotatedFor
&& isAnnotatedForThisCheckerOrUpstreamChecker(packageElement)) {
foundAnnotatedFor = true;
}
}
} else {
throw new BugInCF("Unexpected declaration kind: " + decl.getKind() + " " + decl);
}
}

if (useConservativeDefaultsSource || onlyAnnotatedFor) {
if (foundAnnotatedFor) {
return false;
} else if (useConservativeDefaultsSource || onlyAnnotatedFor) {
// If we got this far without hitting an @AnnotatedFor and returning
// false, we DO suppress the warning.
return true;
Expand Down Expand Up @@ -2882,20 +2885,30 @@ public boolean shouldSuppressWarnings(Element elt, String errKey) {
}

for (Element currElt = elt; currElt != null; currElt = currElt.getEnclosingElement()) {
SuppressWarnings suppressWarningsAnno = currElt.getAnnotation(SuppressWarnings.class);
if (suppressWarningsAnno != null) {
String[] suppressWarningsStrings = suppressWarningsAnno.value();
if (shouldSuppress(suppressWarningsStrings, errKey)) {
if (warnUnneededSuppressions) {
elementsWithSuppressedWarnings.add(currElt);
}
return true;
}
if (shouldSuppressWarningsOnElement(currElt, errKey)) {
return true;
}
if (isAnnotatedForThisCheckerOrUpstreamChecker(elt)) {
Comment thread
aosen-xiong marked this conversation as resolved.
// Return false immediately. Do NOT check for AnnotatedFor in the
// enclosing elements, because they may not have an @AnnotatedFor.
return false;
}
return false;
}

/**
* Returns true if the given element has a {@code @SuppressWarnings} annotation that suppresses
* the given error key.
*
* @param elt the element whose annotations to check
* @param errKey the error key the checker is emitting
* @return true if {@code elt} has an corresponding {@code @SuppressWarnings} annotation
*/
private boolean shouldSuppressWarningsOnElement(Element elt, String errKey) {
Comment thread
aosen-xiong marked this conversation as resolved.
Outdated
SuppressWarnings suppressWarningsAnno = elt.getAnnotation(SuppressWarnings.class);
if (suppressWarningsAnno != null) {
String[] suppressWarningsStrings = suppressWarningsAnno.value();
if (shouldSuppress(suppressWarningsStrings, errKey)) {
if (warnUnneededSuppressions) {
elementsWithSuppressedWarnings.add(elt);
}
return true;
}
}
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,4 +247,14 @@ static class staticAnnotatedAndWarningsSuppressedClass {
so4 = staticUnannotatedMethod(so1);
}
}

// @SuppressWarnings("subtyping") should suppress all subtyping diagnostics within the annotated
// declaration's scope, including those in nested @AnnotatedFor("subtyping") scopes.
@SuppressWarnings("subtyping")
class SuppressWarningsClassWithAnnotatedForMethod {
@AnnotatedFor("subtyping")
@SubQual Object m(@SuperQual Object p) {
return p;
}
}
}
Loading