tech.picnic.errorprone.refasterrules.StringRulesRecipes Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of error-prone-contrib Show documentation
Show all versions of error-prone-contrib Show documentation
Extra Error Prone plugins by Picnic.
package tech.picnic.errorprone.refasterrules;
import org.openrewrite.ExecutionContext;
import org.openrewrite.Preconditions;
import org.openrewrite.Recipe;
import org.openrewrite.TreeVisitor;
import org.openrewrite.internal.lang.NonNullApi;
import org.openrewrite.java.JavaParser;
import org.openrewrite.java.JavaTemplate;
import org.openrewrite.java.JavaVisitor;
import org.openrewrite.java.search.*;
import org.openrewrite.java.template.Primitive;
import org.openrewrite.java.template.function.*;
import org.openrewrite.java.template.internal.AbstractRefasterJavaVisitor;
import org.openrewrite.java.tree.*;
import javax.annotation.Generated;
import java.util.*;
import static org.openrewrite.java.template.internal.AbstractRefasterJavaVisitor.EmbeddingOption.*;
/**
* OpenRewrite recipes created for Refaster template {@code tech.picnic.errorprone.refasterrules.StringRules}.
*/
@SuppressWarnings("all")
@Generated("org.openrewrite.java.template.processor.RefasterTemplateProcessor")
public class StringRulesRecipes extends Recipe {
/**
* Instantiates a new instance.
*/
public StringRulesRecipes() {}
@Override
public String getDisplayName() {
return "Refaster rules related to expressions dealing with `String`s";
}
@Override
public String getDescription() {
return "Refaster template recipes for `tech.picnic.errorprone.refasterrules.StringRules`. [Source](https://error-prone.picnic.tech/refasterrules/StringRules).";
}
@Override
public List getRecipeList() {
return Arrays.asList(
new StringIsEmptyRecipe(),
new StringIsNullOrEmptyRecipe(),
new OptionalNonEmptyStringRecipe(),
new FilterEmptyStringRecipe(),
new JoinStringsRecipe(),
new StringValueOfRecipe(),
new NewStringFromCharArraySubSequenceRecipe(),
new NewStringFromCharArrayRecipe(),
new SubstringRemainderRecipe(),
new Utf8EncodedLengthRecipe()
);
}
/**
* OpenRewrite recipe created for Refaster template {@code StringRules.StringIsEmpty}.
*/
@SuppressWarnings("all")
@NonNullApi
@Generated("org.openrewrite.java.template.processor.RefasterTemplateProcessor")
public static class StringIsEmptyRecipe extends Recipe {
/**
* Instantiates a new instance.
*/
public StringIsEmptyRecipe() {}
@Override
public String getDisplayName() {
return "Prefer `String#isEmpty()` over alternatives that consult the string's length";
}
@Override
public String getDescription() {
return "Recipe created for the following Refaster template:\n```java\nstatic final class StringIsEmpty {\n \n @BeforeTemplate\n boolean before(String str) {\n return Refaster.anyOf(str.length() == 0, str.length() <= 0, str.length() < 1);\n }\n \n @AfterTemplate\n @AlsoNegation\n boolean after(String str) {\n return str.isEmpty();\n }\n}\n```\n.";
}
@Override
public TreeVisitor, ExecutionContext> getVisitor() {
JavaVisitor javaVisitor = new AbstractRefasterJavaVisitor() {
final JavaTemplate before$0 = JavaTemplate
.builder("#{str:any(java.lang.String)}.length() == 0")
.build();
final JavaTemplate before$1 = JavaTemplate
.builder("#{str:any(java.lang.String)}.length() <= 0")
.build();
final JavaTemplate before$2 = JavaTemplate
.builder("#{str:any(java.lang.String)}.length() < 1")
.build();
final JavaTemplate after = JavaTemplate
.builder("#{str:any(java.lang.String)}.isEmpty()")
.build();
@Override
public J visitMethodInvocation(J.MethodInvocation elem, ExecutionContext ctx) {
JavaTemplate.Matcher matcher;
if ((matcher = before$0.matcher(getCursor())).find()) {
return embed(
after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0)),
getCursor(),
ctx,
SHORTEN_NAMES, SIMPLIFY_BOOLEANS
);
}
if ((matcher = before$1.matcher(getCursor())).find()) {
return embed(
after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0)),
getCursor(),
ctx,
SHORTEN_NAMES, SIMPLIFY_BOOLEANS
);
}
if ((matcher = before$2.matcher(getCursor())).find()) {
return embed(
after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0)),
getCursor(),
ctx,
SHORTEN_NAMES, SIMPLIFY_BOOLEANS
);
}
return super.visitMethodInvocation(elem, ctx);
}
};
return Preconditions.check(
new UsesMethod<>("java.lang.String length(..)"),
javaVisitor
);
}
}
/**
* OpenRewrite recipe created for Refaster template {@code StringRules.StringIsNullOrEmpty}.
*/
@SuppressWarnings("all")
@NonNullApi
@Generated("org.openrewrite.java.template.processor.RefasterTemplateProcessor")
public static class StringIsNullOrEmptyRecipe extends Recipe {
/**
* Instantiates a new instance.
*/
public StringIsNullOrEmptyRecipe() {}
@Override
public String getDisplayName() {
return "Prefer `Strings#isNullOrEmpty(String)` over the more verbose alternative";
}
@Override
public String getDescription() {
return "Recipe created for the following Refaster template:\n```java\nstatic final class StringIsNullOrEmpty {\n \n @BeforeTemplate\n boolean before(@Nullable\n String str) {\n return str == null || str.isEmpty();\n }\n \n @AfterTemplate\n @AlsoNegation\n boolean after(String str) {\n return Strings.isNullOrEmpty(str);\n }\n}\n```\n.";
}
@Override
public TreeVisitor, ExecutionContext> getVisitor() {
JavaVisitor javaVisitor = new AbstractRefasterJavaVisitor() {
final JavaTemplate before = JavaTemplate
.builder("#{str:any([email protected] String)} == null || #{str}.isEmpty()")
.build();
final JavaTemplate after = JavaTemplate
.builder("com.google.common.base.Strings.isNullOrEmpty(#{str:any(java.lang.String)})")
.javaParser(JavaParser.fromJavaVersion().classpath(JavaParser.runtimeClasspath()))
.build();
@Override
public J visitBinary(J.Binary elem, ExecutionContext ctx) {
JavaTemplate.Matcher matcher;
if ((matcher = before.matcher(getCursor())).find()) {
return embed(
after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0)),
getCursor(),
ctx,
SHORTEN_NAMES, SIMPLIFY_BOOLEANS
);
}
return super.visitBinary(elem, ctx);
}
};
return Preconditions.check(
new UsesMethod<>("java.lang.String isEmpty(..)"),
javaVisitor
);
}
}
/**
* OpenRewrite recipe created for Refaster template {@code StringRules.OptionalNonEmptyString}.
*/
@SuppressWarnings("all")
@NonNullApi
@Generated("org.openrewrite.java.template.processor.RefasterTemplateProcessor")
public static class OptionalNonEmptyStringRecipe extends Recipe {
/**
* Instantiates a new instance.
*/
public OptionalNonEmptyStringRecipe() {}
@Override
public String getDisplayName() {
return "Don't use the ternary operator to create an optionally-absent string";
}
@Override
public String getDescription() {
return "Recipe created for the following Refaster template:\n```java\nstatic final class OptionalNonEmptyString {\n \n @BeforeTemplate\n Optional before(String str) {\n return Strings.isNullOrEmpty(str) ? Optional.empty() : Refaster.anyOf(Optional.of(str), Optional.ofNullable(str));\n }\n \n @AfterTemplate\n Optional after(String str) {\n return Optional.ofNullable(str).filter(not(String::isEmpty));\n }\n}\n```\n.";
}
@Override
public TreeVisitor, ExecutionContext> getVisitor() {
JavaVisitor javaVisitor = new AbstractRefasterJavaVisitor() {
final JavaTemplate before$0 = JavaTemplate
.builder("Strings.isNullOrEmpty(str) ? Optional.empty() : java.util.Optional.of(#{str:any(java.lang.String)})")
.build();
final JavaTemplate before$1 = JavaTemplate
.builder("Strings.isNullOrEmpty(str) ? Optional.empty() : java.util.Optional.ofNullable(#{str:any(java.lang.String)})")
.build();
final JavaTemplate after = JavaTemplate
.builder("java.util.Optional.ofNullable(#{str:any(java.lang.String)}).filter(java.util.function.Predicate.not(String::isEmpty))")
.build();
@Override
public J visitTernary(J.Ternary elem, ExecutionContext ctx) {
JavaTemplate.Matcher matcher;
if ((matcher = before$0.matcher(getCursor())).find()) {
maybeRemoveImport("com.google.common.base.Strings");
return embed(
after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0)),
getCursor(),
ctx,
SHORTEN_NAMES
);
}
if ((matcher = before$1.matcher(getCursor())).find()) {
maybeRemoveImport("com.google.common.base.Strings");
return embed(
after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0)),
getCursor(),
ctx,
SHORTEN_NAMES
);
}
return super.visitTernary(elem, ctx);
}
};
return Preconditions.check(
Preconditions.and(
new UsesType<>("com.google.common.base.Strings", true),
new UsesType<>("java.util.Optional", true),
new UsesMethod<>("com.google.common.base.Strings isNullOrEmpty(..)"),
new UsesMethod<>("java.util.Optional empty(..)"),
Preconditions.or(
new UsesMethod<>("java.util.Optional of(..)"),
new UsesMethod<>("java.util.Optional ofNullable(..)")
)
),
javaVisitor
);
}
}
/**
* OpenRewrite recipe created for Refaster template {@code StringRules.FilterEmptyString}.
*/
@SuppressWarnings("all")
@NonNullApi
@Generated("org.openrewrite.java.template.processor.RefasterTemplateProcessor")
public static class FilterEmptyStringRecipe extends Recipe {
/**
* Instantiates a new instance.
*/
public FilterEmptyStringRecipe() {}
@Override
public String getDisplayName() {
return "Refaster template `StringRules.FilterEmptyString`";
}
@Override
public String getDescription() {
return "Recipe created for the following Refaster template:\n```java\nstatic final class FilterEmptyString {\n \n @BeforeTemplate\n Optional before(Optional optional) {\n return optional.map(Strings::emptyToNull);\n }\n \n @AfterTemplate\n @UseImportPolicy(value = STATIC_IMPORT_ALWAYS)\n Optional after(Optional optional) {\n return optional.filter(not(String::isEmpty));\n }\n}\n```\n.";
}
@Override
public TreeVisitor, ExecutionContext> getVisitor() {
JavaVisitor javaVisitor = new AbstractRefasterJavaVisitor() {
final JavaTemplate before = JavaTemplate
.builder("#{optional:any(java.util.Optional)}.map(com.google.common.base.Strings::emptyToNull)")
.javaParser(JavaParser.fromJavaVersion().classpath(JavaParser.runtimeClasspath()))
.build();
final JavaTemplate after = JavaTemplate
.builder("#{optional:any(java.util.Optional)}.filter(java.util.function.Predicate.not(String::isEmpty))")
.build();
@Override
public J visitMethodInvocation(J.MethodInvocation elem, ExecutionContext ctx) {
JavaTemplate.Matcher matcher;
if ((matcher = before.matcher(getCursor())).find()) {
maybeRemoveImport("com.google.common.base.Strings");
return embed(
after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0)),
getCursor(),
ctx,
SHORTEN_NAMES
);
}
return super.visitMethodInvocation(elem, ctx);
}
};
return Preconditions.check(
Preconditions.and(
new UsesType<>("com.google.common.base.Strings", true),
new UsesType<>("java.util.Optional", true),
new UsesMethod<>("java.util.Optional map(..)")
),
javaVisitor
);
}
}
/**
* OpenRewrite recipe created for Refaster template {@code StringRules.JoinStrings}.
*/
@SuppressWarnings("all")
@NonNullApi
@Generated("org.openrewrite.java.template.processor.RefasterTemplateProcessor")
public static class JoinStringsRecipe extends Recipe {
/**
* Instantiates a new instance.
*/
public JoinStringsRecipe() {}
@Override
public String getDisplayName() {
return "Prefer `String#join(CharSequence, Iterable)` and variants over the Guava alternative";
}
@Override
public String getDescription() {
return "Recipe created for the following Refaster template:\n```java\nstatic final class JoinStrings {\n \n @BeforeTemplate\n String before(String delimiter, CharSequence[] elements) {\n return Refaster.anyOf(Joiner.on(delimiter).join(elements), Arrays.stream(elements).collect(joining(delimiter)));\n }\n \n @BeforeTemplate\n String before(String delimiter, Iterable extends CharSequence> elements) {\n return Refaster.anyOf(Joiner.on(delimiter).join(elements), Streams.stream(elements).collect(joining(delimiter)));\n }\n \n @BeforeTemplate\n String before(CharSequence delimiter, Collection extends CharSequence> elements) {\n return elements.stream().collect(joining(delimiter));\n }\n \n @AfterTemplate\n String after(CharSequence delimiter, Iterable extends CharSequence> elements) {\n return String.join(delimiter, elements);\n }\n}\n```\n.";
}
@Override
public TreeVisitor, ExecutionContext> getVisitor() {
JavaVisitor javaVisitor = new AbstractRefasterJavaVisitor() {
final JavaTemplate before$0 = JavaTemplate
.builder("com.google.common.base.Joiner.on(#{delimiter:any(java.lang.String)}).join(#{elements:anyArray(java.lang.CharSequence)})")
.javaParser(JavaParser.fromJavaVersion().classpath(JavaParser.runtimeClasspath()))
.build();
final JavaTemplate before$1 = JavaTemplate
.builder("java.util.Arrays.stream(#{elements:anyArray(java.lang.CharSequence)}).collect(java.util.stream.Collectors.joining(#{delimiter:any(java.lang.String)}))")
.build();
final JavaTemplate before0$0 = JavaTemplate
.builder("com.google.common.base.Joiner.on(#{delimiter:any(java.lang.String)}).join(#{elements:any(java.lang.Iterable extends java.lang.CharSequence>)})")
.javaParser(JavaParser.fromJavaVersion().classpath(JavaParser.runtimeClasspath()))
.build();
final JavaTemplate before0$1 = JavaTemplate
.builder("com.google.common.collect.Streams.stream(#{elements:any(java.lang.Iterable extends java.lang.CharSequence>)}).collect(java.util.stream.Collectors.joining(#{delimiter:any(java.lang.String)}))")
.javaParser(JavaParser.fromJavaVersion().classpath(JavaParser.runtimeClasspath()))
.build();
final JavaTemplate before1 = JavaTemplate
.builder("#{elements:any(java.util.Collection extends java.lang.CharSequence>)}.stream().collect(java.util.stream.Collectors.joining(#{delimiter:any(java.lang.CharSequence)}))")
.build();
final JavaTemplate after = JavaTemplate
.builder("String.join(#{delimiter:any(java.lang.CharSequence)}, #{elements:any(java.lang.Iterable extends java.lang.CharSequence>)})")
.build();
@Override
public J visitMethodInvocation(J.MethodInvocation elem, ExecutionContext ctx) {
JavaTemplate.Matcher matcher;
if ((matcher = before$0.matcher(getCursor())).find()) {
maybeRemoveImport("com.google.common.base.Joiner");
return embed(
after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0), matcher.parameter(1)),
getCursor(),
ctx,
SHORTEN_NAMES
);
}
if ((matcher = before$1.matcher(getCursor())).find()) {
maybeRemoveImport("java.util.Arrays");
maybeRemoveImport("java.util.stream.Collectors.joining");
return embed(
after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0), matcher.parameter(1)),
getCursor(),
ctx,
SHORTEN_NAMES
);
}
if ((matcher = before0$0.matcher(getCursor())).find()) {
maybeRemoveImport("com.google.common.base.Joiner");
return embed(
after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0), matcher.parameter(1)),
getCursor(),
ctx,
SHORTEN_NAMES
);
}
if ((matcher = before0$1.matcher(getCursor())).find()) {
maybeRemoveImport("com.google.common.collect.Streams");
maybeRemoveImport("java.util.stream.Collectors.joining");
return embed(
after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0), matcher.parameter(1)),
getCursor(),
ctx,
SHORTEN_NAMES
);
}
if ((matcher = before1.matcher(getCursor())).find()) {
maybeRemoveImport("java.util.Collection");
maybeRemoveImport("java.util.stream.Collectors.joining");
return embed(
after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(1), matcher.parameter(0)),
getCursor(),
ctx,
SHORTEN_NAMES
);
}
return super.visitMethodInvocation(elem, ctx);
}
};
return Preconditions.check(
Preconditions.or(
Preconditions.and(
new UsesType<>("com.google.common.base.Joiner", true),
new UsesMethod<>("com.google.common.base.Joiner join(..)"),
new UsesMethod<>("com.google.common.base.Joiner on(..)")
),
Preconditions.and(
new UsesType<>("com.google.common.collect.Streams", true),
new UsesMethod<>("java.util.stream.Stream collect(..)"),
new UsesMethod<>("com.google.common.collect.Streams stream(..)"),
new UsesMethod<>("java.util.stream.Collectors joining(..)")
),
Preconditions.and(
new UsesType<>("java.util.Collection", true),
new UsesMethod<>("java.util.stream.Stream collect(..)"),
new UsesMethod<>("java.util.Collection stream(..)"),
new UsesMethod<>("java.util.stream.Collectors joining(..)")
)
),
javaVisitor
);
}
}
/**
* OpenRewrite recipe created for Refaster template {@code StringRules.StringValueOf}.
*/
@SuppressWarnings("all")
@NonNullApi
@Generated("org.openrewrite.java.template.processor.RefasterTemplateProcessor")
public static class StringValueOfRecipe extends Recipe {
/**
* Instantiates a new instance.
*/
public StringValueOfRecipe() {}
@Override
public String getDisplayName() {
return "Prefer direct invocation of `String#valueOf(Object)` over the indirection introduced by `Objects#toString(Object)`";
}
@Override
public String getDescription() {
return "Recipe created for the following Refaster template:\n```java\nstatic final class StringValueOf {\n \n @BeforeTemplate\n String before(Object object) {\n return Objects.toString(object);\n }\n \n @AfterTemplate\n String after(Object object) {\n return String.valueOf(object);\n }\n}\n```\n.";
}
@Override
public TreeVisitor, ExecutionContext> getVisitor() {
JavaVisitor javaVisitor = new AbstractRefasterJavaVisitor() {
final JavaTemplate before = JavaTemplate
.builder("java.util.Objects.toString(#{object:any(java.lang.Object)})")
.build();
final JavaTemplate after = JavaTemplate
.builder("String.valueOf(#{object:any(java.lang.Object)})")
.build();
@Override
public J visitMethodInvocation(J.MethodInvocation elem, ExecutionContext ctx) {
JavaTemplate.Matcher matcher;
if ((matcher = before.matcher(getCursor())).find()) {
maybeRemoveImport("java.util.Objects");
return embed(
after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0)),
getCursor(),
ctx,
SHORTEN_NAMES
);
}
return super.visitMethodInvocation(elem, ctx);
}
};
return Preconditions.check(
Preconditions.and(
new UsesType<>("java.util.Objects", true),
new UsesMethod<>("java.util.Objects toString(..)")
),
javaVisitor
);
}
}
/**
* OpenRewrite recipe created for Refaster template {@code StringRules.NewStringFromCharArraySubSequence}.
*/
@SuppressWarnings("all")
@NonNullApi
@Generated("org.openrewrite.java.template.processor.RefasterTemplateProcessor")
public static class NewStringFromCharArraySubSequenceRecipe extends Recipe {
/**
* Instantiates a new instance.
*/
public NewStringFromCharArraySubSequenceRecipe() {}
@Override
public String getDisplayName() {
return "Prefer direct invocation of `String#String(char[], int, int)` over the indirection introduced by alternatives";
}
@Override
public String getDescription() {
return "Recipe created for the following Refaster template:\n```java\nstatic final class NewStringFromCharArraySubSequence {\n \n @BeforeTemplate\n String before(char[] data, int offset, int count) {\n return Refaster.anyOf(String.valueOf(data, offset, count), String.copyValueOf(data, offset, count));\n }\n \n @AfterTemplate\n String after(char[] data, int offset, int count) {\n return new String(data, offset, count);\n }\n}\n```\n.";
}
@Override
public TreeVisitor, ExecutionContext> getVisitor() {
JavaVisitor javaVisitor = new AbstractRefasterJavaVisitor() {
final JavaTemplate before$0 = JavaTemplate
.builder("String.valueOf(#{data:anyArray(char)}, #{offset:any(int)}, #{count:any(int)})")
.build();
final JavaTemplate before$1 = JavaTemplate
.builder("String.copyValueOf(#{data:anyArray(char)}, #{offset:any(int)}, #{count:any(int)})")
.build();
final JavaTemplate after = JavaTemplate
.builder("new String(#{data:anyArray(char)}, #{offset:any(int)}, #{count:any(int)})")
.build();
@Override
public J visitMethodInvocation(J.MethodInvocation elem, ExecutionContext ctx) {
JavaTemplate.Matcher matcher;
if ((matcher = before$0.matcher(getCursor())).find()) {
return embed(
after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0), matcher.parameter(1), matcher.parameter(2)),
getCursor(),
ctx,
SHORTEN_NAMES
);
}
if ((matcher = before$1.matcher(getCursor())).find()) {
return embed(
after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0), matcher.parameter(1), matcher.parameter(2)),
getCursor(),
ctx,
SHORTEN_NAMES
);
}
return super.visitMethodInvocation(elem, ctx);
}
};
return Preconditions.check(
Preconditions.or(
new UsesMethod<>("java.lang.String valueOf(..)"),
new UsesMethod<>("java.lang.String copyValueOf(..)")
),
javaVisitor
);
}
}
/**
* OpenRewrite recipe created for Refaster template {@code StringRules.NewStringFromCharArray}.
*/
@SuppressWarnings("all")
@NonNullApi
@Generated("org.openrewrite.java.template.processor.RefasterTemplateProcessor")
public static class NewStringFromCharArrayRecipe extends Recipe {
/**
* Instantiates a new instance.
*/
public NewStringFromCharArrayRecipe() {}
@Override
public String getDisplayName() {
return "Prefer direct invocation of `String#String(char[])` over the indirection introduced by alternatives";
}
@Override
public String getDescription() {
return "Recipe created for the following Refaster template:\n```java\nstatic final class NewStringFromCharArray {\n \n @BeforeTemplate\n String before(char[] data) {\n return Refaster.anyOf(String.valueOf(data), new String(data, 0, data.length));\n }\n \n @AfterTemplate\n String after(char[] data) {\n return new String(data);\n }\n}\n```\n.";
}
@Override
public TreeVisitor, ExecutionContext> getVisitor() {
JavaVisitor javaVisitor = new AbstractRefasterJavaVisitor() {
final JavaTemplate before$0 = JavaTemplate
.builder("String.valueOf(#{data:anyArray(char)})")
.build();
final JavaTemplate before$1 = JavaTemplate
.builder("new String(#{data:anyArray(char)}, 0, #{data}.length)")
.build();
final JavaTemplate after = JavaTemplate
.builder("new String(#{data:anyArray(char)})")
.build();
@Override
public J visitMethodInvocation(J.MethodInvocation elem, ExecutionContext ctx) {
JavaTemplate.Matcher matcher;
if ((matcher = before$0.matcher(getCursor())).find()) {
return embed(
after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0)),
getCursor(),
ctx,
SHORTEN_NAMES
);
}
if ((matcher = before$1.matcher(getCursor())).find()) {
return embed(
after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0)),
getCursor(),
ctx,
SHORTEN_NAMES
);
}
return super.visitMethodInvocation(elem, ctx);
}
};
return Preconditions.check(
Preconditions.or(
new UsesMethod<>("java.lang.String valueOf(..)"),
new UsesMethod<>("java.lang.String (..)")
),
javaVisitor
);
}
}
/**
* OpenRewrite recipe created for Refaster template {@code StringRules.SubstringRemainder}.
*/
@SuppressWarnings("all")
@NonNullApi
@Generated("org.openrewrite.java.template.processor.RefasterTemplateProcessor")
public static class SubstringRemainderRecipe extends Recipe {
/**
* Instantiates a new instance.
*/
public SubstringRemainderRecipe() {}
@Override
public String getDisplayName() {
return "Don't unnecessarily use the two-argument `String#substring(int, int)`";
}
@Override
public String getDescription() {
return "Recipe created for the following Refaster template:\n```java\nstatic final class SubstringRemainder {\n \n @BeforeTemplate\n String before(String str, int index) {\n return str.substring(index, str.length());\n }\n \n @AfterTemplate\n String after(String str, int index) {\n return str.substring(index);\n }\n}\n```\n.";
}
@Override
public TreeVisitor, ExecutionContext> getVisitor() {
JavaVisitor javaVisitor = new AbstractRefasterJavaVisitor() {
final JavaTemplate before = JavaTemplate
.builder("#{str:any(java.lang.String)}.substring(#{index:any(int)}, #{str}.length())")
.build();
final JavaTemplate after = JavaTemplate
.builder("#{str:any(java.lang.String)}.substring(#{index:any(int)})")
.build();
@Override
public J visitMethodInvocation(J.MethodInvocation elem, ExecutionContext ctx) {
JavaTemplate.Matcher matcher;
if ((matcher = before.matcher(getCursor())).find()) {
return embed(
after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0), matcher.parameter(1)),
getCursor(),
ctx,
SHORTEN_NAMES
);
}
return super.visitMethodInvocation(elem, ctx);
}
};
return Preconditions.check(
Preconditions.and(
new UsesMethod<>("java.lang.String substring(..)"),
new UsesMethod<>("java.lang.String length(..)")
),
javaVisitor
);
}
}
/**
* OpenRewrite recipe created for Refaster template {@code StringRules.Utf8EncodedLength}.
*/
@SuppressWarnings("all")
@NonNullApi
@Generated("org.openrewrite.java.template.processor.RefasterTemplateProcessor")
public static class Utf8EncodedLengthRecipe extends Recipe {
/**
* Instantiates a new instance.
*/
public Utf8EncodedLengthRecipe() {}
@Override
public String getDisplayName() {
return "Prefer `Utf8#encodedLength(CharSequence)` over less efficient alternatives";
}
@Override
public String getDescription() {
return "Recipe created for the following Refaster template:\n```java\nstatic final class Utf8EncodedLength {\n \n @BeforeTemplate\n int before(String str) {\n return str.getBytes(UTF_8).length;\n }\n \n @AfterTemplate\n int after(String str) {\n return Utf8.encodedLength(str);\n }\n}\n```\n.";
}
@Override
public TreeVisitor, ExecutionContext> getVisitor() {
JavaVisitor javaVisitor = new AbstractRefasterJavaVisitor() {
final JavaTemplate before = JavaTemplate
.builder("#{str:any(java.lang.String)}.getBytes(java.nio.charset.StandardCharsets.UTF_8).length")
.build();
final JavaTemplate after = JavaTemplate
.builder("com.google.common.base.Utf8.encodedLength(#{str:any(java.lang.String)})")
.javaParser(JavaParser.fromJavaVersion().classpath(JavaParser.runtimeClasspath()))
.build();
@Override
public J visitFieldAccess(J.FieldAccess elem, ExecutionContext ctx) {
JavaTemplate.Matcher matcher;
if ((matcher = before.matcher(getCursor())).find()) {
maybeRemoveImport("java.nio.charset.StandardCharsets.UTF_8");
return embed(
after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0)),
getCursor(),
ctx,
SHORTEN_NAMES
);
}
return super.visitFieldAccess(elem, ctx);
}
@Override
public J visitIdentifier(J.Identifier elem, ExecutionContext ctx) {
JavaTemplate.Matcher matcher;
if ((matcher = before.matcher(getCursor())).find()) {
maybeRemoveImport("java.nio.charset.StandardCharsets.UTF_8");
return embed(
after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0)),
getCursor(),
ctx,
SHORTEN_NAMES
);
}
return super.visitIdentifier(elem, ctx);
}
};
return Preconditions.check(
new UsesMethod<>("java.lang.String getBytes(..)"),
javaVisitor
);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy