Ok, I have 2 tests here, one is using the advice of error prone, but fails, and the other passes if I turn the error prone error into a warning.
For a compile error (of course this and the rest of the output says warning that's because I switched it to test ) I get
warning: [InvalidPatternSyntax] Invalid syntax used for a regular expression: "." is a valid but useless regex
return password.replaceAll( ".", "*" );
^
(see https://errorprone.info/bugpattern/InvalidPatternSyntax)
Did you mean 'return password.replaceAll( "\\.", "*" );'?
1 warning
This seems overly strict, or like a false positive, as error prone even agree's it's valid, and in this case it seems to be doing exactly what I want, nothing else I tried does. Maybe my regex is too rusty (I had a problem, I used a regex, now I have 2) but this seems to be functioning correctly.
Here's the tests
package com.xenoterracide.ppm.authn;
import org.junit.jupiter.api.Test;
import org.springframework.lang.NonNull;
import static org.assertj.core.api.Assertions.assertThat;
public class AsteriskTest {
@NonNull
public static String replaceWithAsterisk( @NonNull String password ) {
return password.replaceAll( ".", "*" );
}
@Test
public void testReplaceWithAsterisk() {
assertThat( replaceWithAsterisk( "" ) ).isEqualTo( "" );
assertThat( replaceWithAsterisk( "hello" ) ).isEqualTo( "*****" );
assertThat( replaceWithAsterisk( "To*day!" ) ).isEqualTo( "*******" );
}
}
package com.xenoterracide.ppm.authn;
import org.junit.jupiter.api.Test;
import org.springframework.lang.NonNull;
import static org.assertj.core.api.Assertions.assertThat;
public class Asterisk2Test {
@NonNull
public static String replaceWithAsterisk( @NonNull String password ) {
return password.replaceAll( "\\.", "*" );
}
@Test
public void testReplaceWithAsterisk() {
assertThat( replaceWithAsterisk( "" ) ).isEqualTo( "" );
assertThat( replaceWithAsterisk( "hello" ) ).isEqualTo( "*****" );
assertThat( replaceWithAsterisk( "To*day!" ) ).isEqualTo( "*******" );
}
}
Here's what I believe to be the relevant part of the gradle config
import net.ltgt.gradle.errorprone.CheckSeverity
import net.ltgt.gradle.errorprone.errorprone
import net.ltgt.gradle.nullaway.nullaway
plugins {
`java-library`
id("net.ltgt.errorprone")
id("net.ltgt.nullaway")
}
dependencies {
errorprone("com.google.errorprone:error_prone_core:2.4.+")
errorprone("com.uber.nullaway:nullaway:0.8.+")
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(11))
}
}
nullaway {
annotatedPackages.add("com.xenoterracide")
}
tasks.withType<JavaCompile>().configureEach {
options.errorprone {
nullaway {
severity.set(CheckSeverity.ERROR)
acknowledgeRestrictiveAnnotations.set(true)
handleTestAssertionLibraries.set(true)
}
disableWarningsInGeneratedCode.set(true)
warn("InvalidPatternSyntax")
Received 27 file system events since last build while watching 1 hierarchies
Virtual file system retained information about 3547 files, 254 directories and 5 missing files since last build
> Task :buildSrc:extractPrecompiledScriptPluginPlugins UP-TO-DATE
> Task :buildSrc:generateExternalPluginSpecBuilders UP-TO-DATE
> Task :buildSrc:compilePluginsBlocks UP-TO-DATE
> Task :buildSrc:generatePrecompiledScriptPluginAccessors UP-TO-DATE
> Task :buildSrc:configurePrecompiledScriptDependenciesResolver
> Task :buildSrc:generateScriptPluginAdapters UP-TO-DATE
> Task :buildSrc:compileKotlin UP-TO-DATE
> Task :buildSrc:compileJava NO-SOURCE
> Task :buildSrc:compileGroovy NO-SOURCE
> Task :buildSrc:pluginDescriptors UP-TO-DATE
> Task :buildSrc:processResources UP-TO-DATE
> Task :buildSrc:classes UP-TO-DATE
> Task :buildSrc:inspectClassesForKotlinIC UP-TO-DATE
> Task :buildSrc:jar UP-TO-DATE
> Task :buildSrc:assemble UP-TO-DATE
> Task :buildSrc:compileTestKotlin NO-SOURCE
> Task :buildSrc:pluginUnderTestMetadata UP-TO-DATE
> Task :buildSrc:compileTestJava NO-SOURCE
> Task :buildSrc:compileTestGroovy NO-SOURCE
> Task :buildSrc:processTestResources NO-SOURCE
> Task :buildSrc:testClasses UP-TO-DATE
> Task :buildSrc:test NO-SOURCE
> Task :buildSrc:validatePlugins UP-TO-DATE
> Task :buildSrc:check UP-TO-DATE
> Task :buildSrc:build UP-TO-DATE
> Task :authn:compileJava NO-SOURCE
> Task :authn:processResources NO-SOURCE
> Task :authn:classes UP-TO-DATE
> Task :authn:compileTestJava
/home/xeno/IdeaProjects/PPM/api/authn/src/test/java/com/xenoterracide/ppm/authn/AsteriskTest.java:12: warning: [InvalidPatternSyntax] Invalid syntax used for a regular expression: "." is a valid but useless regex
return password.replaceAll( ".", "*" );
^
(see https://errorprone.info/bugpattern/InvalidPatternSyntax)
Did you mean 'return password.replaceAll( "\\.", "*" );'?
1 warning
> Task :authn:processTestResources UP-TO-DATE
> Task :authn:testClasses
Connected to the target VM, address: 'localhost:37911', transport: 'socket'
Disconnected from the target VM, address: 'localhost:37911', transport: 'socket'
> Task :authn:test FAILED
Expecting:
<"hello">
to be equal to:
<"*****">
but was not.
org.opentest4j.AssertionFailedError:
Expecting:
<"hello">
to be equal to:
<"*****">
but was not.
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at com.xenoterracide.ppm.authn.Asterisk2Test.testReplaceWithAsterisk(Asterisk2Test.java:18)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:210)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:206)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:131)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:65)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:248)
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$5(DefaultLauncher.java:211)
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:226)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:199)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:132)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at com.sun.proxy.$Proxy2.stop(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:133)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:414)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
at java.base/java.lang.Thread.run(Thread.java:834)
Asterisk2Test > testReplaceWithAsterisk() STARTED
Asterisk2Test > testReplaceWithAsterisk() FAILED
org.opentest4j.AssertionFailedError at Asterisk2Test.java:18
1 test completed, 1 failed
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':authn:test'.
> There were failing tests. See the results at: file:///home/xeno/IdeaProjects/PPM/api/authn/build/test-results/test/
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 6s
3 actionable tasks: 2 executed, 1 up-to-date
Received 0 file system events during the current build while watching 1 hierarchies
Virtual file system retains information about 3557 files, 261 directories and 5 missing files until next build
here's the resolved versions
❯ ./gradlew dependencies | grep errorprone | uniq # api -> master + ! $
+--- com.google.errorprone:error_prone_core:2.4.+ -> 2.4.0
| +--- com.google.errorprone:error_prone_annotation:2.4.0
| | +--- com.google.errorprone:error_prone_annotations:2.2.0 -> 2.4.0
| +--- com.google.errorprone:error_prone_type_annotations:2.4.0
| +--- com.google.errorprone:error_prone_check_api:2.4.0
| | +--- com.google.errorprone:error_prone_annotation:2.4.0 (*)
| | +--- com.google.errorprone:error_prone_annotations:2.4.0
| | \--- com.google.errorprone:error_prone_annotations:2.3.3 -> 2.4.0
| +--- com.google.errorprone:error_prone_annotations:2.4.0
| +--- com.google.errorprone:error_prone_annotations:2.3.4
errorprone - Error Prone dependencies, will be extended by all source sets' annotationProcessor configurations
+--- com.google.errorprone:error_prone_core:2.4.+ -> 2.4.0
| +--- com.google.errorprone:error_prone_annotation:2.4.0
| | +--- com.google.errorprone:error_prone_annotations:2.2.0 -> 2.4.0
| +--- com.google.errorprone:error_prone_type_annotations:2.4.0
| +--- com.google.errorprone:error_prone_check_api:2.4.0
| | +--- com.google.errorprone:error_prone_annotation:2.4.0 (*)
| | +--- com.google.errorprone:error_prone_annotations:2.4.0
| | \--- com.google.errorprone:error_prone_annotations:2.3.3 -> 2.4.0
| +--- com.google.errorprone:error_prone_annotations:2.4.0
errorproneJavac - Error Prone Javac dependencies, will only be used when using JDK 8 (i.e. not JDK 9 or superior)
+--- com.google.errorprone:error_prone_core:2.4.+ -> 2.4.0
| +--- com.google.errorprone:error_prone_annotation:2.4.0
| | +--- com.google.errorprone:error_prone_annotations:2.2.0 -> 2.4.0
| +--- com.google.errorprone:error_prone_type_annotations:2.4.0
| +--- com.google.errorprone:error_prone_check_api:2.4.0
| | +--- com.google.errorprone:error_prone_annotation:2.4.0 (*)
| | +--- com.google.errorprone:error_prone_annotations:2.4.0
| | \--- com.google.errorprone:error_prone_annotations:2.3.3 -> 2.4.0
| +--- com.google.errorprone:error_prone_annotations:2.4.0
+--- com.google.errorprone:error_prone_core:2.4.+ -> 2.4.0
| +--- com.google.errorprone:error_prone_annotation:2.4.0
| | +--- com.google.errorprone:error_prone_annotations:2.2.0 -> 2.4.0
| +--- com.google.errorprone:error_prone_type_annotations:2.4.0
| +--- com.google.errorprone:error_prone_check_api:2.4.0
| | +--- com.google.errorprone:error_prone_annotation:2.4.0 (*)
| | +--- com.google.errorprone:error_prone_annotations:2.4.0
| | \--- com.google.errorprone:error_prone_annotations:2.3.3 -> 2.4.0
| +--- com.google.errorprone:error_prone_annotations:2.4.0
+--- com.google.errorprone:error_prone_core:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_annotation:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_type_annotations:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_check_api:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_annotations:{strictly 2.4.0} -> 2.4.0 (c)
| | +--- com.google.errorprone:error_prone_annotations:2.3.4
+--- com.google.errorprone:error_prone_annotations:{strictly 2.3.4} -> 2.3.4 (c)
errorprone - Error Prone dependencies, will be extended by all source sets' annotationProcessor configurations
+--- com.google.errorprone:error_prone_core:2.4.+ -> 2.4.0
| +--- com.google.errorprone:error_prone_annotation:2.4.0
| | +--- com.google.errorprone:error_prone_annotations:2.2.0 -> 2.4.0
| +--- com.google.errorprone:error_prone_type_annotations:2.4.0
| +--- com.google.errorprone:error_prone_check_api:2.4.0
| | +--- com.google.errorprone:error_prone_annotation:2.4.0 (*)
| | +--- com.google.errorprone:error_prone_annotations:2.4.0
| | \--- com.google.errorprone:error_prone_annotations:2.3.3 -> 2.4.0
| +--- com.google.errorprone:error_prone_annotations:2.4.0
+--- com.google.errorprone:error_prone_core:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_annotation:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_type_annotations:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_check_api:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_annotations:{strictly 2.4.0} -> 2.4.0 (c)
errorproneJavac - Error Prone Javac dependencies, will only be used when using JDK 8 (i.e. not JDK 9 or superior)
+--- com.google.errorprone:error_prone_core:2.4.+ -> 2.4.0
| +--- com.google.errorprone:error_prone_annotation:2.4.0
| | +--- com.google.errorprone:error_prone_annotations:2.2.0 -> 2.4.0
| +--- com.google.errorprone:error_prone_type_annotations:2.4.0
| +--- com.google.errorprone:error_prone_check_api:2.4.0
| | +--- com.google.errorprone:error_prone_annotation:2.4.0 (*)
| | +--- com.google.errorprone:error_prone_annotations:2.4.0
| | \--- com.google.errorprone:error_prone_annotations:2.3.3 -> 2.4.0
| +--- com.google.errorprone:error_prone_annotations:2.4.0
+--- com.google.errorprone:error_prone_core:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_annotation:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_type_annotations:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_check_api:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_annotations:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_core:2.4.+ -> 2.4.0
| +--- com.google.errorprone:error_prone_annotation:2.4.0
| | +--- com.google.errorprone:error_prone_annotations:2.2.0 -> 2.4.0
| +--- com.google.errorprone:error_prone_type_annotations:2.4.0
| +--- com.google.errorprone:error_prone_check_api:2.4.0
| | +--- com.google.errorprone:error_prone_annotation:2.4.0 (*)
| | +--- com.google.errorprone:error_prone_annotations:2.4.0
| | \--- com.google.errorprone:error_prone_annotations:2.3.3 -> 2.4.0
| +--- com.google.errorprone:error_prone_annotations:2.4.0
+--- com.google.errorprone:error_prone_core:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_annotation:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_type_annotations:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_check_api:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_annotations:{strictly 2.4.0} -> 2.4.0 (c)
| | +--- com.google.errorprone:error_prone_annotations:2.3.4
+--- com.google.errorprone:error_prone_annotations:{strictly 2.3.4} -> 2.3.4 (c)
errorprone - Error Prone dependencies, will be extended by all source sets' annotationProcessor configurations
+--- com.google.errorprone:error_prone_core:2.4.+ -> 2.4.0
| +--- com.google.errorprone:error_prone_annotation:2.4.0
| | +--- com.google.errorprone:error_prone_annotations:2.2.0 -> 2.4.0
| +--- com.google.errorprone:error_prone_type_annotations:2.4.0
| +--- com.google.errorprone:error_prone_check_api:2.4.0
| | +--- com.google.errorprone:error_prone_annotation:2.4.0 (*)
| | +--- com.google.errorprone:error_prone_annotations:2.4.0
| | \--- com.google.errorprone:error_prone_annotations:2.3.3 -> 2.4.0
| +--- com.google.errorprone:error_prone_annotations:2.4.0
+--- com.google.errorprone:error_prone_core:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_annotation:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_type_annotations:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_check_api:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_annotations:{strictly 2.4.0} -> 2.4.0 (c)
errorproneJavac - Error Prone Javac dependencies, will only be used when using JDK 8 (i.e. not JDK 9 or superior)
+--- com.google.errorprone:error_prone_core:2.4.+ -> 2.4.0
| +--- com.google.errorprone:error_prone_annotation:2.4.0
| | +--- com.google.errorprone:error_prone_annotations:2.2.0 -> 2.4.0
| +--- com.google.errorprone:error_prone_type_annotations:2.4.0
| +--- com.google.errorprone:error_prone_check_api:2.4.0
| | +--- com.google.errorprone:error_prone_annotation:2.4.0 (*)
| | +--- com.google.errorprone:error_prone_annotations:2.4.0
| | \--- com.google.errorprone:error_prone_annotations:2.3.3 -> 2.4.0
| +--- com.google.errorprone:error_prone_annotations:2.4.0
+--- com.google.errorprone:error_prone_core:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_annotation:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_type_annotations:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_check_api:{strictly 2.4.0} -> 2.4.0 (c)
+--- com.google.errorprone:error_prone_annotations:{strictly 2.4.0} -> 2.4.0 (c)
❯ # api -> master + ! $
❯ ./gradlew --version # api -> master + ! $
------------------------------------------------------------
Gradle 6.7
------------------------------------------------------------
Build time: 2020-10-14 16:13:12 UTC
Revision: 312ba9e0f4f8a02d01854d1ed743b79ed996dfd3
Kotlin: 1.3.72
Groovy: 2.5.12
Ant: Apache Ant(TM) version 1.10.8 compiled on May 10 2020
JVM: 11.0.9.1 (AdoptOpenJDK 11.0.9.1+1)
OS: Linux 5.10.7-3-MANJARO amd64
Note that, assuming the input to replaceWithAsterisk does not contain new lines, it could be implemented as:
@NonNull
public static String replaceWithAsterisk( @NonNull String password ) {
return "*".repeat(password.codePointCount(0, password.length));
}
or even "*".repeat(password.length) if you don't really care about Unicode surrogate pairs.
IMO, there are greater chances that people are using "." trying to match dots/periods than trying to match "everything but new lines" (which could also be expressed as "[^\\r\\n\\u0085\\u2028\\u2029]", see https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/regex/Pattern.html#lt and https://www.regular-expressions.info/dot.html), so I wouldn't personally change the check.
sure, but the many ways this function could be implemented isn't why I brought this up, obviously, and it's not actually a "real" implementation for the problem. If it was a real function I wouldn't match the count, as that reveals too much. This might as well be fizzbuzz if you get my drift.
Just my opinion that it doesn't seem like InvalidPatternSyntax, I could see a separate check for IllAdvisedPatternSyntax that's set to warn (by default).
Yet, my point was that there will always be alternative implementations to using a "." regex that will undoubtedly be more performant and/or better express the intent, and that using "." has good chances to be a mistake for "\\.".
| flagged | alternative |
|-----|-----|
| str.matches(".") | str.length == 1, str.codePoints().limit(2).count() == 1, str.matches("[^\\r\\n\\u0085\\u2028\\u2029]"), etc.
| str.split(".") or str.split(".", limit) | :thinking:
| str.replaceFirst(".", r) | r + str.substring(1), str.isEmpty() ? "" : r + str.substring(1), r + str.substring(Character.charCount(str.codePointAt(0))), str.replaceFirst("[^\\r\\n\\u0085\\u2028\\u2029]", r), etc.
| str.replaceAll(".", r) | r.repeat(str.length), r.repeat(str.codePointCount(0, str.length)), str.replaceAll("[^\\r\\n\\u0085\\u2028\\u2029]", r), etc.
| Pattern.matches(".", str) | see str.matches(".")
| Splitter.onPattern(".") | :thinking:
I added a note about this in 6519ed5cf7297af17dd70c61a0717b95803fdbdd. I agree that calling "." "invalid" isn't technically correct, but discouraging this was a deliberate decision to encourage people to use clearer alternatives like the ones @tbroyer mentioned.
Most helpful comment
Note that, assuming the input to
replaceWithAsteriskdoes not contain new lines, it could be implemented as:or even
"*".repeat(password.length)if you don't really care about Unicode surrogate pairs.IMO, there are greater chances that people are using
"."trying to match dots/periods than trying to match "everything but new lines" (which could also be expressed as"[^\\r\\n\\u0085\\u2028\\u2029]", see https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/regex/Pattern.html#lt and https://www.regular-expressions.info/dot.html), so I wouldn't personally change the check.