Skip to content

Commit 417ad81

Browse files
committed
Use config-file to define errorprone rule
Also enabled a couple more simple rules, and adding suppressions/fixes for/to the code. The two rules `EqualsGetClass` and `UnusedMethod`, which I think are useful, are not enabled yet, because that would mean actual code changes, which I do not want to do in this PR. The rule `PatternMatchingInstanceof`, introduced in apache#393, is disabled in this PR. It does not work before errorrpone 2.37.0 (via apache#1213) - requires additional changes to enable the rule (see apache#1215).
1 parent 1cf9e08 commit 417ad81

File tree

10 files changed

+324
-25
lines changed

10 files changed

+324
-25
lines changed

build-logic/src/main/kotlin/polaris-java.gradle.kts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
* under the License.
1818
*/
1919

20+
import java.util.Properties
21+
import net.ltgt.gradle.errorprone.CheckSeverity
2022
import net.ltgt.gradle.errorprone.errorprone
2123
import org.gradle.api.tasks.compile.JavaCompile
2224
import org.gradle.api.tasks.testing.Test
@@ -41,18 +43,23 @@ tasks.withType(JavaCompile::class.java).configureEach {
4143
options.errorprone.disableWarningsInGeneratedCode = true
4244
options.errorprone.excludedPaths =
4345
".*/${project.layout.buildDirectory.get().asFile.relativeTo(projectDir)}/generated/.*"
44-
options.errorprone.error(
45-
"DefaultCharset",
46-
"FallThrough",
47-
"MissingCasesInEnumSwitch",
48-
"MissingOverride",
49-
"ModifiedButNotUsed",
50-
"OrphanedFormatString",
51-
"PatternMatchingInstanceof",
52-
"StringCaseLocaleUsage",
53-
)
46+
val errorproneRules = rootProject.projectDir.resolve("codestyle/errorprone-rules.properties")
47+
inputs.file(errorproneRules).withPathSensitivity(PathSensitivity.RELATIVE)
48+
options.errorprone.checks.putAll(provider { memoizedErrorproneRules(errorproneRules) })
5449
}
5550

51+
private fun memoizedErrorproneRules(rulesFile: File): Map<String, CheckSeverity> =
52+
rulesFile.reader().use {
53+
val rules = Properties()
54+
rules.load(it)
55+
rules
56+
.mapKeys { e -> (e.key as String).trim() }
57+
.mapValues { e -> (e.value as String).trim() }
58+
.filter { e -> e.key.isNotEmpty() && e.value.isNotEmpty() }
59+
.mapValues { e -> CheckSeverity.valueOf(e.value) }
60+
.toMap()
61+
}
62+
5663
tasks.register("compileAll").configure {
5764
group = "build"
5865
description = "Runs all compilation and jar tasks"

codestyle/errorprone-rules.properties

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
#
2+
# Licensed to the Apache Software Foundation (ASF) under one
3+
# or more contributor license agreements. See the NOTICE file
4+
# distributed with this work for additional information
5+
# regarding copyright ownership. The ASF licenses this file
6+
# to you under the Apache License, Version 2.0 (the
7+
# "License"); you may not use this file except in compliance
8+
# with the License. You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing,
13+
# software distributed under the License is distributed on an
14+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
# KIND, either express or implied. See the License for the
16+
# specific language governing permissions and limitations
17+
# under the License.
18+
#
19+
20+
####################################################################################################
21+
# On by default : ERROR
22+
# See https://errorprone.info/bugpatterns
23+
####################################################################################################
24+
25+
####################################################################################################
26+
# On by default : WARNING
27+
# See https://errorprone.info/bugpatterns
28+
####################################################################################################
29+
30+
AnnotateFormatMethod=ERROR
31+
# This method passes a pair of parameters through to String.format, but the enclosing method wasn't annotated @FormatMethod. Doing so gives compile-time rather than run-time protection against malformed format strings.
32+
33+
ArrayAsKeyOfSetOrMap=ERROR
34+
# Arrays do not override equals() or hashCode, so comparisons will be done on reference equality only. If neither deduplication nor lookup are needed, consider using a List instead. Otherwise, use IdentityHashMap/Set, a Map from a library that handles object arrays, or an Iterable/List of pairs.
35+
36+
AssertEqualsArgumentOrderChecker=ERROR
37+
# Arguments are swapped in assertEquals-like call
38+
39+
AssertThrowsMultipleStatements=ERROR
40+
# The lambda passed to assertThrows should contain exactly one statement
41+
42+
AssertionFailureIgnored=ERROR
43+
# This assertion throws an AssertionError if it fails, which will be caught by an enclosing try block.
44+
45+
BadImport=ERROR
46+
# Importing nested classes/static methods/static fields with commonly-used names can make code harder to read, because it may not be clear from the context exactly which type is being referred to. Qualifying the name with that of the containing class can make the code clearer.
47+
48+
BadInstanceof=ERROR
49+
# instanceof used in a way that is equivalent to a null check.
50+
51+
BareDotMetacharacter=ERROR
52+
# "." is rarely useful as a regex, as it matches any character. To match a literal '.' character, instead write "\.".
53+
54+
BigDecimalEquals=ERROR
55+
# BigDecimal#equals has surprising behavior: it also compares scale.
56+
57+
BigDecimalLiteralDouble=ERROR
58+
# new BigDecimal(double) loses precision in this case.
59+
60+
BoxedPrimitiveConstructor=ERROR
61+
# valueOf or autoboxing provides better time and space performance
62+
63+
ByteBufferBackingArray=ERROR
64+
# ByteBuffer.array() shouldn't be called unless ByteBuffer.arrayOffset() is used or if the ByteBuffer was initialized using ByteBuffer.wrap() or ByteBuffer.allocate().
65+
66+
CanIgnoreReturnValueSuggester=OFF
67+
# Methods that always 'return this' should be annotated with @CanIgnoreReturnValue
68+
69+
CatchAndPrintStackTrace=ERROR
70+
# Logging or rethrowing exceptions should usually be preferred to catching and calling printStackTrace
71+
72+
ClassCanBeStatic=ERROR
73+
# Inner class is non-static but does not reference enclosing class
74+
75+
ClassNewInstance=ERROR
76+
# Class.newInstance() bypasses exception checking; prefer getDeclaredConstructor().newInstance()
77+
78+
DateFormatConstant=ERROR
79+
# DateFormat is not thread-safe, and should not be used as a constant field.
80+
81+
DefaultCharset=ERROR
82+
# Implicit use of the platform default charset, which can result in differing behaviour between JVM executions or incorrect behavior if the encoding of the data source doesn't match expectations.
83+
84+
DistinctVarargsChecker=ERROR
85+
# Method expects distinct arguments at some/all positions
86+
87+
DoubleCheckedLocking=ERROR
88+
# Double-checked locking on non-volatile fields is unsafe
89+
90+
# TODO enable: EqualsGetClass=ERROR
91+
# Prefer instanceof to getClass when implementing Object#equals.
92+
93+
EqualsIncompatibleType=ERROR
94+
# An equality test between objects with incompatible types always returns false
95+
96+
EqualsUnsafeCast=ERROR
97+
# The contract of #equals states that it should return false for incompatible types, while this implementation may throw ClassCastException.
98+
99+
EqualsUsingHashCode=ERROR
100+
# Implementing #equals by just comparing hashCodes is fragile. Hashes collide frequently, and this will lead to false positives in #equals.
101+
102+
ErroneousBitwiseExpression=ERROR
103+
# This expression evaluates to 0. If this isn't an error, consider expressing it as a literal 0.
104+
105+
ErroneousThreadPoolConstructorChecker=ERROR
106+
# Thread pool size will never go beyond corePoolSize if an unbounded queue is used
107+
108+
EscapedEntity=ERROR
109+
# HTML entities in @code/@literal tags will appear literally in the rendered javadoc.
110+
111+
FallThrough=ERROR
112+
# Switch case may fall through
113+
114+
FloatCast=ERROR
115+
# Use parentheses to make the precedence explicit
116+
117+
FloatingPointAssertionWithinEpsilon=ERROR
118+
# This fuzzy equality check is using a tolerance less than the gap to the next number. You may want a less restrictive tolerance, or to assert equality.
119+
120+
FloatingPointLiteralPrecision=ERROR
121+
# Floating point literal loses precision
122+
123+
FutureReturnValueIgnored=ERROR
124+
# Return value of methods returning Future must be checked. Ignoring returned Futures suppresses exceptions thrown from the code that completes the Future.
125+
126+
GetClassOnEnum=ERROR
127+
# Calling getClass() on an enum may return a subclass of the enum type
128+
129+
InconsistentHashCode=ERROR
130+
# Including fields in hashCode which are not compared in equals violates the contract of hashCode.
131+
132+
IntLongMath=ERROR
133+
# Expression of type int may overflow before being assigned to a long
134+
135+
JavaLangClash=ERROR
136+
# Never reuse class names from java.lang
137+
138+
JdkObsolete=ERROR
139+
# Suggests alternatives to obsolete JDK classes.
140+
141+
LockNotBeforeTry=ERROR
142+
# Calls to Lock#lock should be immediately followed by a try block which releases the lock.
143+
144+
LongDoubleConversion=ERROR
145+
# Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
146+
147+
LongFloatConversion=ERROR
148+
# Conversion from long to float may lose precision; use an explicit cast to float if this was intentional
149+
150+
MissingCasesInEnumSwitch=ERROR
151+
# Switches on enum types should either handle all values, or have a default case.
152+
153+
MissingOverride=ERROR
154+
# method overrides method in supertype; expected @Override
155+
156+
ModifiedButNotUsed=ERROR
157+
# A collection or proto builder was created, but its values were never accessed.
158+
159+
MockNotUsedInProduction=ERROR
160+
# This mock is instantiated and configured, but is never passed to production code. It should be
161+
# either removed or used.
162+
163+
NonAtomicVolatileUpdate=ERROR
164+
# This update of a volatile variable is non-atomic
165+
166+
NonCanonicalType=ERROR
167+
# This type is referred to by a non-canonical name, which may be misleading.
168+
169+
NotJavadoc=ERROR
170+
# Avoid using /** for comments which aren't actually Javadoc.
171+
172+
NullOptional=ERROR
173+
# Passing a literal null to an Optional parameter is almost certainly a mistake. Did you mean to provide an empty Optional?
174+
175+
ObjectEqualsForPrimitives=ERROR
176+
# Avoid unnecessary boxing by using plain == for primitive types.
177+
178+
OperatorPrecedence=ERROR
179+
# Use grouping parenthesis to make the operator precedence explicit
180+
181+
OrphanedFormatString=ERROR
182+
# String literal contains format specifiers, but is not passed to a format method
183+
184+
Overrides=ERROR
185+
# Varargs doesn't agree for overridden method
186+
187+
# TODO PatternMatchingInstanceof=ERROR
188+
# This code can be simplified to use a pattern-matching instanceof.
189+
190+
StreamToIterable=ERROR
191+
# Using stream::iterator creates a one-shot Iterable, which may cause surprising failures.
192+
193+
SynchronizeOnNonFinalField=ERROR
194+
# Synchronizing on non-final fields is not safe: if the field is ever updated, different threads may end up locking on different objects.
195+
196+
ThreadLocalUsage=ERROR
197+
# ThreadLocals should be stored in static fields
198+
199+
URLEqualsHashCode=ERROR
200+
# Avoid hash-based containers of java.net.URL–the containers rely on equals() and hashCode(), which cause java.net.URL to make blocking internet connections.
201+
202+
UnnecessaryLambda=ERROR
203+
# Returning a lambda from a helper method or saving it in a constant is unnecessary; prefer to implement the functional interface method directly and use a method reference instead.
204+
205+
# TODO enable: UnusedMethod=ERROR
206+
# Unused.
207+
208+
UnusedNestedClass=ERROR
209+
# This nested class is unused, and can be removed.
210+
211+
UnusedTypeParameter=ERROR
212+
# This type parameter is unused and can be removed.
213+
214+
UseCorrectAssertInTests=ERROR
215+
# Java assert is used in test. For testing purposes Assert.* matchers should be used.
216+
217+
####################################################################################################
218+
# Experimental : ERROR
219+
# See https://errorprone.info/bugpatterns
220+
####################################################################################################
221+
222+
####################################################################################################
223+
# Experimental : WARNING
224+
# See https://errorprone.info/bugpatterns
225+
####################################################################################################
226+
227+
ConstantPatternCompile=ERROR
228+
# Variables initialized with Pattern#compile calls on constants can be constants
229+
230+
PrimitiveArrayPassedToVarargsMethod=ERROR
231+
# Passing a primitive array to a varargs method is usually wrong
232+
233+
RedundantOverride=ERROR
234+
# This overriding method is redundant, and can be removed.
235+
236+
RedundantThrows=ERROR
237+
# Thrown exception is a subtype of another
238+
239+
StringCaseLocaleUsage=ERROR
240+
# Specify a `Locale` when calling `String#to{Lower,Upper}Case`. (Note: there are multiple suggested fixes; the third may be most appropriate if you're dealing with ASCII Strings.)
241+
242+
StronglyTypeByteString=WARN
243+
# This primitive byte array is only used to construct ByteStrings. It would be clearer to strongly type the field instead.
244+
245+
StronglyTypeTime=ERROR
246+
# This primitive integral type is only used to construct time types. It would be clearer to strongly type the field instead.
247+
248+
TestExceptionChecker=ERROR
249+
# Using @Test(expected=…) is discouraged, since the test will pass if any statement in the test method throws the expected exception
250+
251+
TransientMisuse=ERROR
252+
# Static fields are implicitly transient, so the explicit modifier is unnecessary
253+
254+
UrlInSee=ERROR
255+
# URLs should not be used in @see tags; they are designed for Java elements which could be used with @link.
256+
257+
####################################################################################################
258+
# Experimental : SUGGESTION
259+
# See https://errorprone.info/bugpatterns
260+
####################################################################################################
261+
262+
FieldCanBeStatic=ERROR
263+
# A final field initialized at compile-time with an instance of an immutable type can be static.
264+
265+
ForEachIterable=ERROR
266+
# This loop can be replaced with an enhanced for loop.
267+
268+
MixedArrayDimensions=ERROR
269+
# C-style array declarations should not be used
270+
271+
PackageLocation=ERROR
272+
# Package names should match the directory they are declared in
273+
274+
TryFailRefactoring=ERROR
275+
# Prefer assertThrows to try/fail
276+
277+
UnnecessaryBoxedAssignment=WARN
278+
# This expression can be implicitly boxed.
279+
280+
UnnecessaryBoxedVariable=ERROR
281+
# It is unnecessary for this variable to be boxed. Use the primitive instead.
282+
283+
UseEnumSwitch=ERROR
284+
# Prefer using a switch instead of a chained if-else for enums

extension/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisEclipseLinkMetaStoreSessionImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,12 @@ public class PolarisEclipseLinkMetaStoreSessionImpl extends AbstractTransactiona
7777
private static final ConcurrentHashMap<String, EntityManagerFactory> realmFactories =
7878
new ConcurrentHashMap<>();
7979
private final EntityManagerFactory emf;
80+
81+
// TODO this has to be refactored, see https://github.com/apache/polaris/issues/463 and
82+
// https://errorprone.info/bugpattern/ThreadLocalUsage
83+
@SuppressWarnings("ThreadLocalUsage")
8084
private final ThreadLocal<EntityManager> localSession = new ThreadLocal<>();
85+
8186
private final PolarisEclipseLinkStore store;
8287
private final PolarisStorageIntegrationProvider storageIntegrationProvider;
8388
private final PrincipalSecretsGenerator secretsGenerator;

polaris-core/src/main/java/org/apache/polaris/core/config/ProductionReadinessCheck.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ default boolean ready() {
4040
List<Error> getErrors();
4141

4242
@PolarisImmutable
43+
@SuppressWarnings("JavaLangClash")
4344
interface Error {
4445

4546
static Error of(String message, String offendingProperty) {

polaris-core/src/main/java/org/apache/polaris/core/storage/aws/AwsStorageConfigurationInfo.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ public class AwsStorageConfigurationInfo extends PolarisStorageConfigurationInfo
3636
@JsonIgnore
3737
public static final String ROLE_ARN_PATTERN = "^arn:(aws|aws-us-gov):iam::(\\d{12}):role/.+$";
3838

39+
private static final Pattern ROLE_ARN_PATTERN_COMPILED = Pattern.compile(ROLE_ARN_PATTERN);
40+
3941
// AWS role to be assumed
4042
private final @Nonnull String roleARN;
4143

@@ -131,8 +133,7 @@ public String getAwsPartition() {
131133

132134
private static String parseAwsAccountId(String arn) {
133135
validateArn(arn);
134-
Pattern pattern = Pattern.compile(ROLE_ARN_PATTERN);
135-
Matcher matcher = pattern.matcher(arn);
136+
Matcher matcher = ROLE_ARN_PATTERN_COMPILED.matcher(arn);
136137
if (matcher.matches()) {
137138
return matcher.group(2);
138139
} else {
@@ -142,8 +143,7 @@ private static String parseAwsAccountId(String arn) {
142143

143144
private static String parseAwsPartition(String arn) {
144145
validateArn(arn);
145-
Pattern pattern = Pattern.compile(ROLE_ARN_PATTERN);
146-
Matcher matcher = pattern.matcher(arn);
146+
Matcher matcher = ROLE_ARN_PATTERN_COMPILED.matcher(arn);
147147
if (matcher.matches()) {
148148
return matcher.group(1);
149149
} else {

quarkus/service/src/test/java/org/apache/polaris/service/quarkus/ratelimiter/TokenBucketTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ void testBasic() {
5757
* only allow "maxTokens" requests
5858
*/
5959
@Test
60+
@SuppressWarnings("FutureReturnValueIgnored") // implementation looks okay
6061
void testConcurrent() throws InterruptedException {
6162
int maxTokens = 100;
6263
int numTasks = 50000;

service/common/src/main/java/org/apache/polaris/service/auth/OAuthTokenErrorResponse.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
/** An OAuth Error Token Response as defined by the Iceberg REST API OpenAPI Spec. */
2424
public class OAuthTokenErrorResponse {
2525

26+
@SuppressWarnings("JavaLangClash")
2627
public enum Error {
2728
invalid_request("The request is invalid"),
2829
invalid_client("The Client is invalid"),

0 commit comments

Comments
 (0)