diff --git a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/StringRules.java b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/StringRules.java index 2db97dc02c..94b972bd68 100644 --- a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/StringRules.java +++ b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/StringRules.java @@ -309,7 +309,7 @@ int after(String str) { } /** Prefer {@link String#indexOf(int, int)} over less efficient alternatives. */ - static final class StringIndexOfChar { + static final class StringIndexOfCharFromIndex { @BeforeTemplate @SuppressWarnings("java:S4635" /* This violation will be rewritten. */) int before(String string, int ch, int fromIndex) { @@ -322,8 +322,21 @@ int after(String string, int ch, int fromIndex) { } } + /** Prefer {@link String#indexOf(int, int, int)} over less efficient alternatives. */ + static final class StringIndexOfCharBetweenIndices { + @BeforeTemplate + int before(String string, int ch, int beginIndex, int endIndex) { + return string.substring(beginIndex, endIndex).indexOf(ch); + } + + @AfterTemplate + int after(String string, int ch, int beginIndex, int endIndex) { + return Math.max(-1, string.indexOf(ch, beginIndex, endIndex) - beginIndex); + } + } + /** Prefer {@link String#indexOf(String, int)} over less efficient alternatives. */ - static final class StringIndexOfString { + static final class StringIndexOfStringFromIndex { @BeforeTemplate @SuppressWarnings("java:S4635" /* This violation will be rewritten. */) int before(String string, String substring, int fromIndex) { @@ -336,8 +349,18 @@ int after(String string, String substring, int 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#indexOf(String, int)} over less efficient alternatives. */ + static final class StringIndexOfStringBetweenIndices { + @BeforeTemplate + int before(String string, String substring, int beginIndex, int endIndex) { + return string.substring(beginIndex, endIndex).indexOf(substring); + } + + @AfterTemplate + int after(String string, String substring, int beginIndex, int endIndex) { + return Math.max(-1, string.indexOf(substring, beginIndex, endIndex) - beginIndex); + } + } /** Prefer {@link String#lastIndexOf(int, int)} over less efficient alternatives. */ static final class StringLastIndexOfChar { diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/StringRulesTestInput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/StringRulesTestInput.java index 6ef65d578c..3e538fca34 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/StringRulesTestInput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/StringRulesTestInput.java @@ -114,14 +114,22 @@ int testUtf8EncodedLength() { return "foo".getBytes(UTF_8).length; } - int testStringIndexOfChar() { + int testStringIndexOfCharFromIndex() { return "foo".substring(1).indexOf('a'); } - int testStringIndexOfString() { + int testStringIndexOfCharBetweenIndices() { + return "foo".substring(1, 2).indexOf('a'); + } + + int testStringIndexOfStringFromIndex() { return "foo".substring(1).indexOf("bar"); } + int testStringIndexOfStringBetweenIndices() { + return "foo".substring(1, 2).indexOf("bar"); + } + int testStringLastIndexOfChar() { return "foo".substring(1).lastIndexOf('a'); } diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/StringRulesTestOutput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/StringRulesTestOutput.java index 5841e928e3..264a33472e 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/StringRulesTestOutput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/StringRulesTestOutput.java @@ -109,14 +109,22 @@ int testUtf8EncodedLength() { return Utf8.encodedLength("foo"); } - int testStringIndexOfChar() { + int testStringIndexOfCharFromIndex() { return Math.max(-1, "foo".indexOf('a', 1) - 1); } - int testStringIndexOfString() { + int testStringIndexOfCharBetweenIndices() { + return Math.max(-1, "foo".indexOf('a', 1, 2) - 1); + } + + int testStringIndexOfStringFromIndex() { return Math.max(-1, "foo".indexOf("bar", 1) - 1); } + int testStringIndexOfStringBetweenIndices() { + return Math.max(-1, "foo".indexOf("bar", 1, 2) - 1); + } + int testStringLastIndexOfChar() { return Math.max(-1, "foo".lastIndexOf('a') - 1); }