diff --git a/rewrite-core/src/main/java/org/openrewrite/internal/NamingService.java b/rewrite-core/src/main/java/org/openrewrite/internal/NamingService.java new file mode 100644 index 00000000000..c8a1ddfb512 --- /dev/null +++ b/rewrite-core/src/main/java/org/openrewrite/internal/NamingService.java @@ -0,0 +1,22 @@ +/* + * Copyright 2024 the original author or authors. + *
+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *
+ * https://www.apache.org/licenses/LICENSE-2.0 + *
+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.internal; + +public interface NamingService { + + String standardizeMethodName(String oldMethodName); + +} diff --git a/rewrite-java/src/main/java/org/openrewrite/java/service/JavaNamingService.java b/rewrite-java/src/main/java/org/openrewrite/java/service/JavaNamingService.java new file mode 100644 index 00000000000..5f2e84e9c04 --- /dev/null +++ b/rewrite-java/src/main/java/org/openrewrite/java/service/JavaNamingService.java @@ -0,0 +1,67 @@ +/* + * Copyright 2023 the original author or authors. + *
+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *
+ * https://www.apache.org/licenses/LICENSE-2.0 + *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.openrewrite.java.service;
+
+import org.openrewrite.internal.NameCaseConvention;
+import org.openrewrite.internal.NamingService;
+
+import java.util.regex.Pattern;
+
+public class JavaNamingService implements NamingService {
+
+ private static final Pattern STANDARD_METHOD_NAME = Pattern.compile("^[a-z][a-zA-Z0-9]*$");
+ private static final Pattern SNAKE_CASE = Pattern.compile("^[a-zA-Z0-9]+_\\w+$");
+
+ @Override
+ public String standardizeMethodName(String oldMethodName) {
+ if (!oldMethodName.startsWith("_") &&
+ !STANDARD_METHOD_NAME.matcher(oldMethodName).matches()) {
+ StringBuilder result = new StringBuilder();
+ if (SNAKE_CASE.matcher(oldMethodName).matches()) {
+ result.append(NameCaseConvention.format(NameCaseConvention.LOWER_CAMEL, oldMethodName));
+ } else {
+ int nameLength = oldMethodName.length();
+ for (int i = 0; i < nameLength; i++) {
+ char c = oldMethodName.charAt(i);
+ if (i == 0) {
+ // the java specification requires identifiers to start with [a-zA-Z$_]
+ if (c != '$' && c != '_') {
+ result.append(Character.toLowerCase(c));
+ }
+ } else {
+ if (!Character.isLetterOrDigit(c)) {
+ while ((!Character.isLetterOrDigit(c) || c > 'z')) {
+ i++;
+ if (i < nameLength) {
+ c = oldMethodName.charAt(i);
+ } else {
+ break;
+ }
+ }
+ if (i < nameLength) {
+ result.append(Character.toUpperCase(c));
+ }
+ } else {
+ result.append(c);
+ }
+ }
+ }
+ }
+ return result.toString();
+ }
+ return oldMethodName;
+ }
+}
diff --git a/rewrite-java/src/main/java/org/openrewrite/java/tree/JavaSourceFile.java b/rewrite-java/src/main/java/org/openrewrite/java/tree/JavaSourceFile.java
index 97f3551c473..d705a710f64 100644
--- a/rewrite-java/src/main/java/org/openrewrite/java/tree/JavaSourceFile.java
+++ b/rewrite-java/src/main/java/org/openrewrite/java/tree/JavaSourceFile.java
@@ -18,12 +18,14 @@
import org.jspecify.annotations.Nullable;
import org.openrewrite.Incubating;
import org.openrewrite.SourceFile;
+import org.openrewrite.internal.NamingService;
import org.openrewrite.internal.WhitespaceValidationService;
import org.openrewrite.java.internal.JavaWhitespaceValidationService;
import org.openrewrite.java.internal.TypesInUse;
import org.openrewrite.java.service.AnnotationService;
import org.openrewrite.java.service.AutoFormatService;
import org.openrewrite.java.service.ImportService;
+import org.openrewrite.java.service.JavaNamingService;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Path;
@@ -75,6 +77,8 @@ default T service(Class service) {
} else if (WhitespaceValidationService.class.getName().equals(service.getName())) {
// Only unit tests should need to use this service, so no classloading concerns
return (T) new JavaWhitespaceValidationService();
+ } else if (NamingService.class.getName().equals(service.getName())) {
+ return (T) new JavaNamingService();
} else {
throw new UnsupportedOperationException("Service " + service + " not supported");
}
diff --git a/rewrite-java/src/test/java/org/openrewrite/java/service/JavaNamingServiceTest.java b/rewrite-java/src/test/java/org/openrewrite/java/service/JavaNamingServiceTest.java
new file mode 100644
index 00000000000..8a28a65d1ba
--- /dev/null
+++ b/rewrite-java/src/test/java/org/openrewrite/java/service/JavaNamingServiceTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *
+ * https://www.apache.org/licenses/LICENSE-2.0 + *
+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.java.service; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.assertj.core.api.Assertions.assertThat; + +class JavaNamingServiceTest { + + @ParameterizedTest + @CsvSource(textBlock = """ + foo_bar,fooBar + foo$bar,fooBar + foo_bar$,fooBar + foo$bar$,fooBar + """) + void changeMethodName(String before, String after) { + String actual = new JavaNamingService().standardizeMethodName(before); + assertThat(actual).isEqualTo(after); + } +}