From 2a48175d20c0df40911e31f778613a7f67fe38ff Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Mon, 4 May 2026 19:15:29 -0400 Subject: [PATCH 01/10] Add SuppressWarnings classes with AnnotatedFor methods --- .../annotatedfornullness/AnnotatedForNullness.java | 8 ++++++++ .../annotatedfor/AnnotatedForTest.java | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/checker/tests/nulless-conservative-defaults/annotatedfornullness/AnnotatedForNullness.java b/checker/tests/nulless-conservative-defaults/annotatedfornullness/AnnotatedForNullness.java index b0c4472ec506..86534cb02189 100644 --- a/checker/tests/nulless-conservative-defaults/annotatedfornullness/AnnotatedForNullness.java +++ b/checker/tests/nulless-conservative-defaults/annotatedfornullness/AnnotatedForNullness.java @@ -73,4 +73,12 @@ void bar() { annotatedForNullness(initializedField); annotatedForNullnessAndInitialization(initializedField); } + + @SuppressWarnings("nullness") + class SuppressWarningsClassWithAnnotatedForMethod { + @AnnotatedFor("nullness") + @NonNull Object m() { + return null; + } + } } diff --git a/framework/tests/conservative-defaults/annotatedfor/AnnotatedForTest.java b/framework/tests/conservative-defaults/annotatedfor/AnnotatedForTest.java index b73ea47242b4..967ca6dca4fe 100644 --- a/framework/tests/conservative-defaults/annotatedfor/AnnotatedForTest.java +++ b/framework/tests/conservative-defaults/annotatedfor/AnnotatedForTest.java @@ -247,4 +247,14 @@ static class staticAnnotatedAndWarningsSuppressedClass { so4 = staticUnannotatedMethod(so1); } } + + // Class-level @SuppressWarnings("subtyping") should override a method-level + // @AnnotatedFor("subtyping") + @SuppressWarnings("subtyping") + class SuppressWarningsClassWithAnnotatedForMethod { + @AnnotatedFor("subtyping") + @SubQual Object m(@SuperQual Object p) { + return p; + } + } } From 66e664f497b198e9b1dcc430ea23cdd2aa1f4368 Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Mon, 4 May 2026 19:28:19 -0400 Subject: [PATCH 02/10] Remove redundant check for AnnotatedFor in SourceChecker --- .../org/checkerframework/framework/source/SourceChecker.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java b/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java index c3133c10c211..1263e01f931b 100644 --- a/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java +++ b/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java @@ -2875,11 +2875,6 @@ public boolean shouldSuppressWarnings(Element elt, String errKey) { return true; } } - if (isAnnotatedForThisCheckerOrUpstreamChecker(elt)) { - // Return false immediately. Do NOT check for AnnotatedFor in the - // enclosing elements, because they may not have an @AnnotatedFor. - return false; - } } return false; } From 90c6889df9af476634622fbfdfeeda95be11a55a Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Mon, 4 May 2026 22:31:29 -0400 Subject: [PATCH 03/10] Remove redundant check for AnnotatedFor in SourceChecker --- .../annotatedfornullness/AnnotatedForNullness.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/checker/tests/nulless-conservative-defaults/annotatedfornullness/AnnotatedForNullness.java b/checker/tests/nulless-conservative-defaults/annotatedfornullness/AnnotatedForNullness.java index 86534cb02189..4f7b9aa7da62 100644 --- a/checker/tests/nulless-conservative-defaults/annotatedfornullness/AnnotatedForNullness.java +++ b/checker/tests/nulless-conservative-defaults/annotatedfornullness/AnnotatedForNullness.java @@ -74,6 +74,8 @@ void bar() { annotatedForNullnessAndInitialization(initializedField); } + // Class-level @SuppressWarnings("nullness") should override a method-level + // @AnnotatedFor("nullness") @SuppressWarnings("nullness") class SuppressWarningsClassWithAnnotatedForMethod { @AnnotatedFor("nullness") From 87b149f430341e5f93d7712dda5787c108f331b9 Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Tue, 5 May 2026 15:26:33 -0400 Subject: [PATCH 04/10] Apply suggestions from code review Co-authored-by: Alex Cook <43047600+thisisalexandercook@users.noreply.github.com> --- .../annotatedfornullness/AnnotatedForNullness.java | 4 ++-- .../conservative-defaults/annotatedfor/AnnotatedForTest.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/checker/tests/nulless-conservative-defaults/annotatedfornullness/AnnotatedForNullness.java b/checker/tests/nulless-conservative-defaults/annotatedfornullness/AnnotatedForNullness.java index 4f7b9aa7da62..bd933cf471e4 100644 --- a/checker/tests/nulless-conservative-defaults/annotatedfornullness/AnnotatedForNullness.java +++ b/checker/tests/nulless-conservative-defaults/annotatedfornullness/AnnotatedForNullness.java @@ -74,8 +74,8 @@ void bar() { annotatedForNullnessAndInitialization(initializedField); } - // Class-level @SuppressWarnings("nullness") should override a method-level - // @AnnotatedFor("nullness") + // @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") diff --git a/framework/tests/conservative-defaults/annotatedfor/AnnotatedForTest.java b/framework/tests/conservative-defaults/annotatedfor/AnnotatedForTest.java index 967ca6dca4fe..bc655da0ecc3 100644 --- a/framework/tests/conservative-defaults/annotatedfor/AnnotatedForTest.java +++ b/framework/tests/conservative-defaults/annotatedfor/AnnotatedForTest.java @@ -248,8 +248,8 @@ static class staticAnnotatedAndWarningsSuppressedClass { } } - // Class-level @SuppressWarnings("subtyping") should override a method-level - // @AnnotatedFor("subtyping") + // @SuppressWarnings("subtyping") should suppress all subtying diagnostics within the annotated declaration's scope, + // including those in nested @AnnotatedFor("subtyping") scopes. @SuppressWarnings("subtyping") class SuppressWarningsClassWithAnnotatedForMethod { @AnnotatedFor("subtyping") From 19dfafc1254fe44b4b50b50b920d769981410ad8 Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Tue, 5 May 2026 17:23:18 -0400 Subject: [PATCH 05/10] Apply formatter --- .../annotatedfornullness/AnnotatedForNullness.java | 4 ++-- .../conservative-defaults/annotatedfor/AnnotatedForTest.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/checker/tests/nulless-conservative-defaults/annotatedfornullness/AnnotatedForNullness.java b/checker/tests/nulless-conservative-defaults/annotatedfornullness/AnnotatedForNullness.java index bd933cf471e4..81f2dcafb2e4 100644 --- a/checker/tests/nulless-conservative-defaults/annotatedfornullness/AnnotatedForNullness.java +++ b/checker/tests/nulless-conservative-defaults/annotatedfornullness/AnnotatedForNullness.java @@ -74,8 +74,8 @@ void bar() { annotatedForNullnessAndInitialization(initializedField); } - // @SuppressWarnings("nullness") should suppress all nullness diagnostics within the annotated declaration's scope, - // including those in nested @AnnotatedFor("nullness") scopes. + // @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") diff --git a/framework/tests/conservative-defaults/annotatedfor/AnnotatedForTest.java b/framework/tests/conservative-defaults/annotatedfor/AnnotatedForTest.java index bc655da0ecc3..c7885f64cc29 100644 --- a/framework/tests/conservative-defaults/annotatedfor/AnnotatedForTest.java +++ b/framework/tests/conservative-defaults/annotatedfor/AnnotatedForTest.java @@ -248,8 +248,8 @@ static class staticAnnotatedAndWarningsSuppressedClass { } } - // @SuppressWarnings("subtyping") should suppress all subtying diagnostics within the annotated declaration's scope, - // including those in nested @AnnotatedFor("subtyping") scopes. + // @SuppressWarnings("subtyping") should suppress all subtying diagnostics within the annotated + // declaration's scope, including those in nested @AnnotatedFor("subtyping") scopes. @SuppressWarnings("subtyping") class SuppressWarningsClassWithAnnotatedForMethod { @AnnotatedFor("subtyping") From ca073e683fa1fff2d915684a111e74bf5d865a3e Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Mon, 11 May 2026 11:46:44 -0400 Subject: [PATCH 06/10] Enhance documentation and logic for @AnnotatedFor and @SuppressWarnings handling --- docs/manual/annotating-libraries.tex | 8 ++- docs/manual/warnings.tex | 7 +- .../framework/source/SourceChecker.java | 68 ++++++++++++------- .../annotatedfor/AnnotatedForTest.java | 2 +- 4 files changed, 55 insertions(+), 30 deletions(-) diff --git a/docs/manual/annotating-libraries.tex b/docs/manual/annotating-libraries.tex index db580a20531c..aa0ba05f7645 100644 --- a/docs/manual/annotating-libraries.tex +++ b/docs/manual/annotating-libraries.tex @@ -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 +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 diff --git a/docs/manual/warnings.tex b/docs/manual/warnings.tex index 5fbfacc8c911..773b066750d4 100644 --- a/docs/manual/warnings.tex +++ b/docs/manual/warnings.tex @@ -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 +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. diff --git a/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java b/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java index 1263e01f931b..c49a58670d45 100644 --- a/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java +++ b/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java @@ -2756,6 +2756,12 @@ public boolean shouldSuppressWarnings(Tree tree, String errKey) { * otherwise */ public boolean shouldSuppressWarnings(TreePath path, String errKey) { + if (shouldSuppress(getSuppressWarningsStringsFromOption(), errKey)) { + return true; + } + + boolean foundAnnotatedFor = false; + // iterate through the path; continue until path contains no declarations for (TreePath declPath = TreePathUtil.enclosingDeclarationPath(path); declPath != null; @@ -2764,41 +2770,36 @@ 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 { @@ -2806,7 +2807,9 @@ public boolean shouldSuppressWarnings(TreePath path, String errKey) { } } - 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; @@ -2865,15 +2868,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; + } + } + 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) { + 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; diff --git a/framework/tests/conservative-defaults/annotatedfor/AnnotatedForTest.java b/framework/tests/conservative-defaults/annotatedfor/AnnotatedForTest.java index c7885f64cc29..b44e03eb3650 100644 --- a/framework/tests/conservative-defaults/annotatedfor/AnnotatedForTest.java +++ b/framework/tests/conservative-defaults/annotatedfor/AnnotatedForTest.java @@ -248,7 +248,7 @@ static class staticAnnotatedAndWarningsSuppressedClass { } } - // @SuppressWarnings("subtyping") should suppress all subtying diagnostics within the annotated + // @SuppressWarnings("subtyping") should suppress all subtyping diagnostics within the annotated // declaration's scope, including those in nested @AnnotatedFor("subtyping") scopes. @SuppressWarnings("subtyping") class SuppressWarningsClassWithAnnotatedForMethod { From 5963c8e8580027a88c2406a2fe2e131c5c534969 Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Fri, 19 Jun 2026 13:27:30 -0400 Subject: [PATCH 07/10] Clarify AnnotatedFor warning suppression docs --- docs/manual/annotating-libraries.tex | 4 ++-- docs/manual/warnings.tex | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/manual/annotating-libraries.tex b/docs/manual/annotating-libraries.tex index aa0ba05f7645..ca068587c82a 100644 --- a/docs/manual/annotating-libraries.tex +++ b/docs/manual/annotating-libraries.tex @@ -384,12 +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. -Warnings in code with a relevant \<@AnnotatedFor> annotation can still be suppressed by -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}). +In code with a relevant \<@AnnotatedFor> annotation, warnings can be suppressed +by an in-scope \<@SuppressWarnings> annotation. \end{sloppypar} The \refqualclass{framework/qual}{AnnotatedFor} annotation, written on a diff --git a/docs/manual/warnings.tex b/docs/manual/warnings.tex index 773b066750d4..87b4ada46f9c 100644 --- a/docs/manual/warnings.tex +++ b/docs/manual/warnings.tex @@ -697,8 +697,9 @@ 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 -mechanism such as \code{@SuppressWarnings}. +enable warnings from that checker. +An explicit \code{@SuppressWarnings} annotation can suppress warnings in +\code{@AnnotatedFor} code. 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. From e747ab5840e1c762400efae55c10288fe53f6b58 Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Fri, 19 Jun 2026 13:51:21 -0400 Subject: [PATCH 08/10] Refine suppression lookup for AnnotatedFor --- .../framework/source/SourceChecker.java | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java b/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java index 7851a7e5dff2..3cb1674f7b87 100644 --- a/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java +++ b/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java @@ -2740,21 +2740,6 @@ private boolean shouldSuppressWarnings(Object src, String errKey) { * otherwise */ public boolean shouldSuppressWarnings(Tree tree, String errKey) { - Collection prefixes = getSuppressWarningsPrefixes(); - if (prefixes.isEmpty() - || (prefixes.contains(SUPPRESS_ALL_PREFIX) && prefixes.size() == 1)) { - throw new BugInCF( - "Checker must provide a SuppressWarnings prefix." - + " SourceChecker#getSuppressWarningsPrefixes was not overridden" - + " correctly."); - } - - if (shouldSuppress(getSuppressWarningsStringsFromOption(), errKey)) { - // If the error key matches a warning string in the -AsuppressWarnings, then suppress - // the warning. - return true; - } - assert this.currentRoot != null : "this.currentRoot == null"; TreePath path = getTreePathCacher().getPath(currentRoot, tree); @@ -2766,6 +2751,11 @@ public boolean shouldSuppressWarnings(Tree tree, String errKey) { * Returns true if the path is within the scope of a @SuppressWarnings annotation, one of whose * values suppresses the checker's warning. * + *

This overload also accounts for source-position-based suppression from unchecked code: if + * no matching {@code @SuppressWarnings} is found, then warnings outside a relevant {@link + * AnnotatedFor} scope are suppressed when {@code + * -AuseConservativeDefaultsForUncheckedCode=source} or {@code -AonlyAnnotatedFor} is in effect. + * * @param path the TreePath that might be a source of, or related to, a warning * @param errKey the error key the checker is emitting * @return true if no warning should be emitted for the given path because it is contained by a @@ -2773,6 +2763,15 @@ public boolean shouldSuppressWarnings(Tree tree, String errKey) { * otherwise */ public boolean shouldSuppressWarnings(TreePath path, String errKey) { + Collection prefixes = getSuppressWarningsPrefixes(); + if (prefixes.isEmpty() + || (prefixes.contains(SUPPRESS_ALL_PREFIX) && prefixes.size() == 1)) { + throw new BugInCF( + "Checker must provide a SuppressWarnings prefix." + + " SourceChecker#getSuppressWarningsPrefixes was not overridden" + + " correctly."); + } + if (shouldSuppress(getSuppressWarningsStringsFromOption(), errKey)) { return true; } @@ -2787,12 +2786,12 @@ public boolean shouldSuppressWarnings(TreePath path, String errKey) { if (decl instanceof VariableTree) { Element elt = TreeUtils.elementFromDeclaration((VariableTree) decl); - if (shouldSuppressWarningsOnElement(elt, errKey)) { + if (hasSuppressWarningsAnnotationForErrorKey(elt, errKey)) { return true; } } else if (decl instanceof MethodTree) { Element elt = TreeUtils.elementFromDeclaration((MethodTree) decl); - if (shouldSuppressWarningsOnElement(elt, errKey)) { + if (hasSuppressWarningsAnnotationForErrorKey(elt, errKey)) { return true; } @@ -2802,7 +2801,7 @@ public boolean shouldSuppressWarnings(TreePath path, String errKey) { } else if (TreeUtils.classTreeKinds().contains(decl.getKind())) { // A class tree Element elt = TreeUtils.elementFromDeclaration((ClassTree) decl); - if (shouldSuppressWarningsOnElement(elt, errKey)) { + if (hasSuppressWarningsAnnotationForErrorKey(elt, errKey)) { return true; } @@ -2811,7 +2810,7 @@ public boolean shouldSuppressWarnings(TreePath path, String errKey) { } Element packageElement = elt.getEnclosingElement(); if (packageElement != null && packageElement.getKind() == ElementKind.PACKAGE) { - if (shouldSuppressWarningsOnElement(packageElement, errKey)) { + if (hasSuppressWarningsAnnotationForErrorKey(packageElement, errKey)) { return true; } if (!foundAnnotatedFor @@ -2885,7 +2884,7 @@ public boolean shouldSuppressWarnings(Element elt, String errKey) { } for (Element currElt = elt; currElt != null; currElt = currElt.getEnclosingElement()) { - if (shouldSuppressWarningsOnElement(currElt, errKey)) { + if (hasSuppressWarningsAnnotationForErrorKey(currElt, errKey)) { return true; } } @@ -2898,9 +2897,9 @@ public boolean shouldSuppressWarnings(Element elt, String errKey) { * * @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 + * @return true if {@code elt} has a corresponding {@code @SuppressWarnings} annotation */ - private boolean shouldSuppressWarningsOnElement(Element elt, String errKey) { + private boolean hasSuppressWarningsAnnotationForErrorKey(Element elt, String errKey) { SuppressWarnings suppressWarningsAnno = elt.getAnnotation(SuppressWarnings.class); if (suppressWarningsAnno != null) { String[] suppressWarningsStrings = suppressWarningsAnno.value(); From a48161964bb8df82eeb46b1e27d4a91ec121d32f Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Fri, 19 Jun 2026 13:59:55 -0400 Subject: [PATCH 09/10] Clarify SuppressWarnings scope docs --- docs/manual/warnings.tex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/manual/warnings.tex b/docs/manual/warnings.tex index 87b4ada46f9c..f482cea3e4f2 100644 --- a/docs/manual/warnings.tex +++ b/docs/manual/warnings.tex @@ -699,7 +699,8 @@ Note that the \code{@AnnotatedFor} annotation must include the checker's name to enable warnings from that checker. An explicit \code{@SuppressWarnings} annotation can suppress warnings in -\code{@AnnotatedFor} code. +\code{@AnnotatedFor} code and code outside the scope of a corresponding +\code{@AnnotatedFor} annotation. 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. From a82e29003029d16b0f41626b1a3455eb1e8bc550 Mon Sep 17 00:00:00 2001 From: Aosen Xiong Date: Fri, 19 Jun 2026 14:02:15 -0400 Subject: [PATCH 10/10] Refine AnnotatedFor suppression wording --- docs/manual/annotating-libraries.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/manual/annotating-libraries.tex b/docs/manual/annotating-libraries.tex index ca068587c82a..b6936efaf227 100644 --- a/docs/manual/annotating-libraries.tex +++ b/docs/manual/annotating-libraries.tex @@ -389,7 +389,7 @@ but does not change the default qualifiers for source code (see Section~\ref{aonlyannotatedfor}). In code with a relevant \<@AnnotatedFor> annotation, warnings can be suppressed -by an in-scope \<@SuppressWarnings> annotation. +by an explicit \<@SuppressWarnings> annotation. \end{sloppypar} The \refqualclass{framework/qual}{AnnotatedFor} annotation, written on a