mirror of
https://github.com/jlengrand/error-prone-support.git
synced 2026-03-10 08:11:25 +00:00
Introduce Refaster rules for Sonar's java:S4635 rule (#1320)
As well as two related expressions that can be optimized.
See:
- https://sonarcloud.io/organizations/picnic-technologies/rules?open=java%3AS4635&rule_key=java%3AS4635
- 2615792731/java-checks/src/main/java/org/sonar/java/checks/StringOffsetMethodsCheck.java
This commit is contained in:
committed by
GitHub
parent
26da67d1f5
commit
3d5ee10d93
@@ -244,4 +244,105 @@ final class StringRules {
|
||||
return Utf8.encodedLength(str);
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link String#indexOf(int, int)} over less efficient alternatives. */
|
||||
static final class StringIndexOfChar {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("java:S4635" /* This violation will be rewritten. */)
|
||||
int before(String string, int ch, int fromIndex) {
|
||||
return string.substring(fromIndex).indexOf(ch);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
int after(String string, int ch, int fromIndex) {
|
||||
return Math.max(-1, string.indexOf(ch, fromIndex) - fromIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link String#indexOf(String, int)} over less efficient alternatives. */
|
||||
static final class StringIndexOfString {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("java:S4635" /* This violation will be rewritten. */)
|
||||
int before(String string, String substring, int fromIndex) {
|
||||
return string.substring(fromIndex).indexOf(substring);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
int after(String string, String substring, int fromIndex) {
|
||||
return Math.max(-1, string.indexOf(substring, fromIndex) - fromIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Once we compile Refaster templates with JDK 21 also suggest `String#indexOf(int, int,
|
||||
// int)` and `String#indexOf(String, int, int)`.
|
||||
|
||||
/** Prefer {@link String#lastIndexOf(int, int)} over less efficient alternatives. */
|
||||
static final class StringLastIndexOfChar {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("java:S4635" /* This violation will be rewritten. */)
|
||||
int before(String string, int ch, int fromIndex) {
|
||||
return string.substring(fromIndex).lastIndexOf(ch);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
int after(String string, int ch, int fromIndex) {
|
||||
return Math.max(-1, string.lastIndexOf(ch) - fromIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link String#lastIndexOf(String, int)} over less efficient alternatives. */
|
||||
static final class StringLastIndexOfString {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("java:S4635" /* This violation will be rewritten. */)
|
||||
int before(String string, String substring, int fromIndex) {
|
||||
return string.substring(fromIndex).lastIndexOf(substring);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
int after(String string, String substring, int fromIndex) {
|
||||
return Math.max(-1, string.lastIndexOf(substring) - fromIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link String#lastIndexOf(int, int)} over less efficient alternatives. */
|
||||
static final class StringLastIndexOfCharWithIndex {
|
||||
@BeforeTemplate
|
||||
int before(String string, int ch, int fromIndex) {
|
||||
return string.substring(0, fromIndex).lastIndexOf(ch);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
int after(String string, int ch, int fromIndex) {
|
||||
return string.lastIndexOf(ch, fromIndex - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link String#lastIndexOf(String, int)} over less efficient alternatives. */
|
||||
// XXX: The replacement expression isn't fully equivalent: in case `substring` is empty, then
|
||||
// the replacement yields `fromIndex - 1` rather than `fromIndex`.
|
||||
static final class StringLastIndexOfStringWithIndex {
|
||||
@BeforeTemplate
|
||||
int before(String string, String substring, int fromIndex) {
|
||||
return string.substring(0, fromIndex).lastIndexOf(substring);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
int after(String string, String substring, int fromIndex) {
|
||||
return string.lastIndexOf(substring, fromIndex - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link String#startsWith(String, int)} over less efficient alternatives. */
|
||||
static final class StringStartsWith {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("java:S4635" /* This violation will be rewritten. */)
|
||||
boolean before(String string, String prefix, int fromIndex) {
|
||||
return string.substring(fromIndex).startsWith(prefix);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
boolean after(String string, String prefix, int fromIndex) {
|
||||
return string.startsWith(prefix, fromIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,4 +96,32 @@ final class StringRulesTest implements RefasterRuleCollectionTestCase {
|
||||
int testUtf8EncodedLength() {
|
||||
return "foo".getBytes(UTF_8).length;
|
||||
}
|
||||
|
||||
int testStringIndexOfChar() {
|
||||
return "foo".substring(1).indexOf('a');
|
||||
}
|
||||
|
||||
int testStringIndexOfString() {
|
||||
return "foo".substring(1).indexOf("bar");
|
||||
}
|
||||
|
||||
int testStringLastIndexOfChar() {
|
||||
return "foo".substring(1).lastIndexOf('a');
|
||||
}
|
||||
|
||||
int testStringLastIndexOfString() {
|
||||
return "foo".substring(1).lastIndexOf("bar");
|
||||
}
|
||||
|
||||
int testStringLastIndexOfCharWithIndex() {
|
||||
return "foo".substring(0, 2).lastIndexOf('a');
|
||||
}
|
||||
|
||||
int testStringLastIndexOfStringWithIndex() {
|
||||
return "foo".substring(0, 2).lastIndexOf("bar");
|
||||
}
|
||||
|
||||
boolean testStringStartsWith() {
|
||||
return "foo".substring(1).startsWith("bar");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,4 +96,32 @@ final class StringRulesTest implements RefasterRuleCollectionTestCase {
|
||||
int testUtf8EncodedLength() {
|
||||
return Utf8.encodedLength("foo");
|
||||
}
|
||||
|
||||
int testStringIndexOfChar() {
|
||||
return Math.max(-1, "foo".indexOf('a', 1) - 1);
|
||||
}
|
||||
|
||||
int testStringIndexOfString() {
|
||||
return Math.max(-1, "foo".indexOf("bar", 1) - 1);
|
||||
}
|
||||
|
||||
int testStringLastIndexOfChar() {
|
||||
return Math.max(-1, "foo".lastIndexOf('a') - 1);
|
||||
}
|
||||
|
||||
int testStringLastIndexOfString() {
|
||||
return Math.max(-1, "foo".lastIndexOf("bar") - 1);
|
||||
}
|
||||
|
||||
int testStringLastIndexOfCharWithIndex() {
|
||||
return "foo".lastIndexOf('a', 2 - 1);
|
||||
}
|
||||
|
||||
int testStringLastIndexOfStringWithIndex() {
|
||||
return "foo".lastIndexOf("bar", 2 - 1);
|
||||
}
|
||||
|
||||
boolean testStringStartsWith() {
|
||||
return "foo".startsWith("bar", 1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user