Skip to content

Commit a9cc7cb

Browse files
committed
Merge branch 'master' into warn-on-unneeded-suppressions
2 parents 75ea740 + db62c8c commit a9cc7cb

File tree

88 files changed

+3118
-59718
lines changed

Some content is hidden

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

88 files changed

+3118
-59718
lines changed

.github/workflows/ci.yml

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,18 @@ jobs:
5858
java-version: 17
5959
distribution: 'zulu'
6060
cache: 'maven'
61-
- name: 'Set up JDK 23'
62-
uses: actions/setup-java@v4
63-
with:
64-
java-version: 23
65-
distribution: 'zulu'
66-
cache: 'maven'
6761
- name: 'Set up JDK 25 from jdk.java.net'
6862
uses: oracle-actions/setup-java@v1
6963
with:
7064
website: jdk.java.net
7165
release: 25
7266
cache: 'maven'
67+
- name: 'Set up JDK 26 from jdk.java.net'
68+
uses: oracle-actions/setup-java@v1
69+
with:
70+
website: jdk.java.net
71+
release: 26
72+
cache: 'maven'
7373
- name: 'Set up JDK ${{ matrix.java }} from jdk.java.net'
7474
if: ${{ matrix.java == 'EA' }}
7575
uses: oracle-actions/setup-java@v1
@@ -108,19 +108,13 @@ jobs:
108108
website: jdk.java.net
109109
release: 25
110110
cache: 'maven'
111-
- name: 'Set up JDK 23'
112-
uses: actions/setup-java@v4
113-
with:
114-
java-version: 23
115-
distribution: 'zulu'
116-
cache: 'maven'
117111
- name: 'Set up JDK 17'
118112
uses: actions/setup-java@v4
119113
with:
120114
java-version: 17
121115
distribution: 'zulu'
122116
cache: 'maven'
123-
server-id: ossrh
117+
server-id: sonatype-nexus-snapshots
124118
server-username: CI_DEPLOY_USERNAME
125119
server-password: CI_DEPLOY_PASSWORD
126120
- name: 'Publish'

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
java-version: 17
3737
distribution: 'zulu'
3838
cache: 'maven'
39-
server-id: ossrh
39+
server-id: central
4040
server-username: CI_DEPLOY_USERNAME
4141
server-password: CI_DEPLOY_PASSWORD
4242
gpg-private-key: ${{ secrets.GPG_SIGNING_KEY }}

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ Our documentation is at [errorprone.info](https://errorprone.info).
3131

3232
Error Prone works with [Bazel](https://bazel.build),
3333
[Maven](https://maven.apache.org), [Ant](https://ant.apache.org), and
34-
[Gradle](https://gradle.org). See our [installation
35-
instructions](https://errorprone.info/docs/installation) for details.
34+
[Gradle](https://gradle.org). See our
35+
[installation instructions](https://errorprone.info/docs/installation) for
36+
details.
3637

3738
## Developing Error Prone
3839

@@ -42,9 +43,8 @@ Developing and building Error Prone is documented on the
4243
## Links
4344

4445
- Mailing lists
45-
- [General
46-
discussion](https://groups.google.com/forum/#!forum/error-prone-discuss)
46+
- [General discussion](https://groups.google.com/forum/#!forum/error-prone-discuss)
4747
- [Announcements](https://groups.google.com/forum/#!forum/error-prone-announce)
4848
- [Javadoc](https://errorprone.info/api/latest/)
49-
- Pre-release snapshots are available from [Sonatype's snapshot
50-
repository](https://oss.sonatype.org/content/repositories/snapshots/com/google/errorprone/).
49+
- Pre-release snapshots are available from Sonatype's snapshot repository
50+
(https://central.sonatype.com/repository/maven-snapshots/)

annotations/src/main/java/com/google/errorprone/annotations/CompileTimeConstant.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
* <li>the expression is a {@link String}, and formed from the concatenation of symbols which meet
4242
* these conditions, or
4343
* <li>the expression is a ternary condition, where both branches satisfy these conditions, or
44+
* <li>the expression is a switch expression, where every case is either a constant expression or
45+
* throws, or
4446
* <li>the expression is an immutable collection with all values known to satisfy these conditions
4547
* (for example, {@code ImmutableSet.of("a", "b", "c")}).
4648
* </ol>

check_api/src/main/java/com/google/errorprone/JavacErrorDescriptionListener.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import com.sun.tools.javac.util.Log;
3333
import java.io.IOException;
3434
import java.io.UncheckedIOException;
35+
import java.util.EnumSet;
3536
import java.util.HashMap;
3637
import java.util.List;
3738
import java.util.Map;
@@ -119,7 +120,8 @@ public void onDescribed(Description description) {
119120
factory.create(
120121
type,
121122
/* lintCategory */ null,
122-
DIAGNOSTIC_FLAGS,
123+
// Make a defensive copy, as JDK at head mutates its arguments.
124+
EnumSet.copyOf(DIAGNOSTIC_FLAGS),
123125
log.currentSource(),
124126
pos,
125127
MESSAGE_BUNDLE_KEY,

check_api/src/main/java/com/google/errorprone/dataflow/nullnesspropagation/NullnessAnnotations.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,20 @@ public static Optional<Nullness> fromAnnotationMirrors(
7474

7575
public static boolean annotationsAreAmbiguous(
7676
Collection<? extends AnnotationMirror> annotations) {
77-
return annotations.stream()
78-
.map(a -> simpleName(a).toString())
79-
.filter(ANNOTATION_RELEVANT_TO_NULLNESS)
80-
.map(NULLABLE_ANNOTATION::test)
77+
return annotationsRelevantToNullness(annotations).stream()
78+
.map(a -> NULLABLE_ANNOTATION.test(simpleName(a).toString()))
8179
.distinct()
8280
.count()
8381
== 2;
8482
}
8583

84+
public static ImmutableList<AnnotationMirror> annotationsRelevantToNullness(
85+
Collection<? extends AnnotationMirror> annotations) {
86+
return annotations.stream()
87+
.filter(a -> ANNOTATION_RELEVANT_TO_NULLNESS.test(simpleName(a).toString()))
88+
.collect(toImmutableList());
89+
}
90+
8691
public static ImmutableList<AnnotationTree> annotationsRelevantToNullness(
8792
List<? extends AnnotationTree> annotations) {
8893
return annotations.stream()

check_api/src/main/java/com/google/errorprone/matchers/CompileTimeConstantExpressionMatcher.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,14 @@
3030
import com.google.errorprone.annotations.CompileTimeConstant;
3131
import com.google.errorprone.suppliers.Supplier;
3232
import com.sun.source.tree.BinaryTree;
33+
import com.sun.source.tree.CaseTree.CaseKind;
3334
import com.sun.source.tree.ConditionalExpressionTree;
3435
import com.sun.source.tree.ExpressionTree;
3536
import com.sun.source.tree.IdentifierTree;
3637
import com.sun.source.tree.MethodInvocationTree;
3738
import com.sun.source.tree.ParenthesizedTree;
39+
import com.sun.source.tree.SwitchExpressionTree;
40+
import com.sun.source.tree.ThrowTree;
3841
import com.sun.source.tree.Tree;
3942
import com.sun.source.tree.Tree.Kind;
4043
import com.sun.source.tree.TypeCastTree;
@@ -102,6 +105,17 @@ public Boolean visitConditionalExpression(ConditionalExpressionTree tree, Void u
102105
&& tree.getFalseExpression().accept(this, null);
103106
}
104107

108+
@Override
109+
public Boolean visitSwitchExpression(SwitchExpressionTree tree, Void unused) {
110+
// This is intentionally quite restrictive: only accept bare values and throws.
111+
return tree.getCases().stream()
112+
.allMatch(
113+
c ->
114+
c.getCaseKind().equals(CaseKind.RULE)
115+
&& (c.getBody().accept(this, null)
116+
|| c.getBody() instanceof ThrowTree));
117+
}
118+
105119
@Override
106120
public Boolean visitMethodInvocation(MethodInvocationTree tree, Void unused) {
107121
return IMMUTABLE_FACTORY.matches(tree, state)

check_api/src/main/java/com/google/errorprone/matchers/Description.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,7 @@ public Description applySeverityOverride(SeverityLevel severity) {
143143
explanation = "Use describeMatch or buildDescription on BugChecker instead.",
144144
link = "",
145145
allowedOnPath =
146-
".*/java/com/google/devtools/staticanalysis/errorprone/pluggabletype/LatticeAdapter.java"
147-
+ "|.*/java/com/google/devtools/staticanalysis/errorprone/pluggabletype/LatticeInfo.java"
148-
+ "|.*/third_party/java_src/error_prone/project/check_api/src/main/java/com/google/errorprone/bugpatterns/BugChecker.java")
146+
".*/third_party/java_src/error_prone/project/check_api/src/main/java/com/google/errorprone/bugpatterns/BugChecker.java")
149147
public static Builder builder(Tree node, String name, @Nullable String link, String message) {
150148
return new Builder((DiagnosticPosition) node, name, link, message);
151149
}
@@ -270,7 +268,6 @@ public Builder setLinkUrl(String linkUrl) {
270268
".*/third_party/java_src/error_prone/project/check_api/src/main/java/com/google/errorprone/matchers/Description.java$|"
271269
+ ".*/java/com/google/devtools/javatools/staticanalysis/xlang/java/BugCheckerUsingXlang.java$|"
272270
+ ".*/java/com/google/devtools/staticanalysis/errorprone/RestrictedInheritanceChecker.java$|"
273-
+ ".*/java/com/google/devtools/staticanalysis/errorprone/pluggabletype/LatticeAdapter.java$|"
274271
+ ".*/third_party/java_src/error_prone/project/core/src/main/java/com/google/errorprone/bugpatterns/RestrictedApiChecker.java$|"
275272
+ ".*/third_party/java_src/error_prone/project/core/src/main/java/com/google/errorprone/refaster/RefasterScanner.java$")
276273
@CanIgnoreReturnValue

check_api/src/main/java/com/google/errorprone/matchers/InjectMatchers.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,7 @@
3333
public final class InjectMatchers {
3434

3535
public static final Matcher<Tree> INSIDE_GUICE_MODULE =
36-
enclosingClass(
37-
anyOf(
38-
isSubtypeOf("com.google.inject.Module"),
39-
isSubtypeOf("com.google.gwt.inject.client.GinModule")));
36+
enclosingClass(isSubtypeOf("com.google.inject.Module"));
4037

4138
private InjectMatchers() {} // no instantiation
4239

check_api/src/main/java/com/google/errorprone/util/ASTHelpers.java

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import static com.google.common.base.Verify.verify;
2121
import static com.google.common.collect.ImmutableList.toImmutableList;
2222
import static com.google.common.collect.ImmutableSet.toImmutableSet;
23-
import static com.google.common.collect.Iterables.getOnlyElement;
2423
import static com.google.common.collect.MoreCollectors.onlyElement;
2524
import static com.google.common.collect.Streams.stream;
2625
import static com.google.common.collect.Streams.zip;
@@ -1057,13 +1056,9 @@ public static boolean hasDirectAnnotationWithSimpleName(Tree tree, String simple
10571056
}
10581057

10591058
/**
1060-
* Returns true if any of the given tree is a declaration annotated with an annotation with the
1061-
* simple name {@code @UsedReflectively} or {@code @Keep}, or any annotations meta-annotated with
1062-
* an annotation with that simple name.
1063-
*
1064-
* <p>This indicates the annotated element is used (e.g. by reflection, or referenced by generated
1065-
* code) and should not be removed.
1059+
* @deprecated use {@code @com.google.errorprone.bugpatterns.WellKnownKeep} instead.
10661060
*/
1061+
@Deprecated
10671062
public static boolean shouldKeep(Tree tree) {
10681063
ModifiersTree modifiers = getModifiers(tree);
10691064
if (modifiers == null) {
@@ -2012,9 +2007,23 @@ public static boolean isAbstract(MethodSymbol method) {
20122007
return method.getModifiers().contains(Modifier.ABSTRACT);
20132008
}
20142009

2015-
public static EnumSet<Flags.Flag> asFlagSet(long flags) {
2010+
/**
2011+
* Returns a set of strings representing the flags in the given long. This uses the bit encoding
2012+
* from {@link Flags}.
2013+
*
2014+
* @return a set of strings representing the flags in the given long, in lowercase. Elements of
2015+
* the set are strings like "static" or "final".
2016+
*/
2017+
public static ImmutableSet<String> asFlagSet(long flags) {
20162018
flags &= ~(Flags.ANONCONSTR_BASED | POTENTIALLY_AMBIGUOUS);
2017-
return Flags.asFlagSet(flags);
2019+
// The cast to EnumSet<?> is because Flags.asFlagSet() returns an EnumSet<Flags.Flag> in some
2020+
// versions of JDK, and an EnumSet<FlagsEnum> in others. Without the cast, whichever enum type
2021+
// it is gets referenced by the stream, so the code won't work if compiled with a JDK that has
2022+
// the change and executed with one that doesn't, or vice versa. Erasure means that the call to
2023+
// Flags.asFlagSet doesn't itself cause problems because EnumSet<Flags.Flag> gets erased to just
2024+
// EnumSet in the bytecode.
2025+
return ((EnumSet<?>) Flags.asFlagSet(flags))
2026+
.stream().map(Object::toString).collect(toImmutableSet());
20182027
}
20192028

20202029
// Removed in JDK 21 by JDK-8026369
@@ -2111,12 +2120,15 @@ private void scan(Type from, Type to) {
21112120

21122121
/** Returns whether this is a {@code var} or a lambda parameter that has no explicit type. */
21132122
public static boolean hasImplicitType(VariableTree tree, VisitorState state) {
2114-
/*
2115-
* For lambda expression parameters without an explicit type, both
2116-
* `JCVariableDecl#declaredUsingVar()` and `#isImplicitlyTyped()` may be false. So instead we
2117-
* check whether the variable's type is explicitly represented in the source code.
2118-
*/
2119-
return !hasExplicitSource(tree.getType(), state);
2123+
JCVariableDecl varDecl = (JCVariableDecl) tree;
2124+
if (varDecl.declaredUsingVar()) {
2125+
return true;
2126+
}
2127+
// after JDK-8358604, inferred variable types have source positions
2128+
if (!hasExplicitSource(tree.getType(), state)) {
2129+
return true;
2130+
}
2131+
return false;
21202132
}
21212133

21222134
/** Returns whether the given tree has an explicit source code representation. */
@@ -2184,16 +2196,18 @@ public static Optional<? extends CaseTree> getSwitchDefault(SwitchTree switchTre
21842196
return switchTree.getCases().stream().filter(c -> isSwitchDefault(c)).findFirst();
21852197
}
21862198

2187-
/** Returns whether {@code caseTree} is the default case of a switch statement. */
2199+
/**
2200+
* Returns whether {@code caseTree} is the default case of a switch statement. This includes
2201+
* {@code case null, default ->}.
2202+
*/
21882203
public static boolean isSwitchDefault(CaseTree caseTree) {
2189-
if (!caseTree.getExpressions().isEmpty()) {
2204+
List<? extends Tree> labels = caseTree.getLabels();
2205+
if (!caseTree.getExpressions().isEmpty() && labels.isEmpty()) {
21902206
return false;
21912207
}
2192-
List<? extends Tree> labels = caseTree.getLabels();
21932208
return labels.isEmpty()
2194-
|| (labels.size() == 1
2195-
// DEFAULT_CASE_LABEL is in Java 21, so we're stuck stringifying for now.
2196-
&& getOnlyElement(labels).getKind().name().equals("DEFAULT_CASE_LABEL"));
2209+
// DEFAULT_CASE_LABEL is in Java 21, so we're stuck stringifying for now.
2210+
|| labels.stream().anyMatch(label -> label.getKind().name().equals("DEFAULT_CASE_LABEL"));
21972211
}
21982212

21992213
private static final Supplier<Name> NULL_MARKED_NAME =

0 commit comments

Comments
 (0)