Skip to content

Commit ff5c2a2

Browse files
committed
Improve javadoc cleanup to remove duplicate spaces
Improve `TypeUtils` so that repeated space chars are removed. Fixes gh-40593
1 parent 72925e7 commit ff5c2a2

File tree

4 files changed

+94
-9
lines changed

4 files changed

+94
-9
lines changed

spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/TypeUtils.java

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -67,8 +67,6 @@ class TypeUtils {
6767

6868
private static final Map<String, TypeKind> WRAPPER_TO_PRIMITIVE;
6969

70-
private static final Pattern NEW_LINE_PATTERN = Pattern.compile("[\r\n]+");
71-
7270
static {
7371
Map<String, TypeKind> primitives = new HashMap<>();
7472
PRIMITIVE_WRAPPERS.forEach((kind, wrapperClass) -> primitives.put(wrapperClass.getName(), kind));
@@ -183,9 +181,7 @@ String getJavaDoc(Element element) {
183181
return getJavaDoc((RecordComponentElement) element);
184182
}
185183
String javadoc = (element != null) ? this.env.getElementUtils().getDocComment(element) : null;
186-
if (javadoc != null) {
187-
javadoc = NEW_LINE_PATTERN.matcher(javadoc).replaceAll("").trim();
188-
}
184+
javadoc = (javadoc != null) ? cleanupJavaDoc(javadoc) : null;
189185
return (javadoc == null || javadoc.isEmpty()) ? null : javadoc;
190186
}
191187

@@ -259,7 +255,7 @@ private String getJavaDoc(RecordComponentElement recordComponent) {
259255
Pattern paramJavadocPattern = paramJavadocPattern(recordComponent.getSimpleName().toString());
260256
Matcher paramJavadocMatcher = paramJavadocPattern.matcher(recordJavadoc);
261257
if (paramJavadocMatcher.find()) {
262-
String paramJavadoc = NEW_LINE_PATTERN.matcher(paramJavadocMatcher.group()).replaceAll("").trim();
258+
String paramJavadoc = cleanupJavaDoc(paramJavadocMatcher.group());
263259
return paramJavadoc.isEmpty() ? null : paramJavadoc;
264260
}
265261
}
@@ -271,6 +267,20 @@ private Pattern paramJavadocPattern(String paramName) {
271267
return Pattern.compile(pattern, Pattern.DOTALL);
272268
}
273269

270+
private String cleanupJavaDoc(String javadoc) {
271+
StringBuilder result = new StringBuilder(javadoc.length());
272+
char lastChar = '.';
273+
for (int i = 0; i < javadoc.length(); i++) {
274+
char ch = javadoc.charAt(i);
275+
boolean repeatedSpace = ch == ' ' && lastChar == ' ';
276+
if (ch != '\r' && ch != '\n' && !repeatedSpace) {
277+
result.append(ch);
278+
lastChar = ch;
279+
}
280+
}
281+
return result.toString().trim();
282+
}
283+
274284
/**
275285
* A visitor that extracts the fully qualified name of a type, including generic
276286
* information.

spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,7 @@ void shouldNotMarkDbcp2UsernameOrPasswordAsDeprecated() {
521521
void recordPropertiesWithDescriptions() {
522522
ConfigurationMetadata metadata = compile(ExampleRecord.class);
523523
assertThat(metadata).has(Metadata.withProperty("record.descriptions.some-string", String.class)
524-
.withDescription("very long description that doesn't fit single line"));
524+
.withDescription("very long description that doesn't fit single line and is indented"));
525525
assertThat(metadata).has(Metadata.withProperty("record.descriptions.some-integer", Integer.class)
526526
.withDescription("description with @param and @ pitfalls"));
527527
assertThat(metadata).has(Metadata.withProperty("record.descriptions.some-boolean", Boolean.class)

spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/record/ExampleRecord.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@
1616

1717
package org.springframework.boot.configurationsample.record;
1818

19+
// @formatter:off
20+
1921
/**
2022
* Example Record Javadoc sample
2123
*
22-
* @param someString very long description that doesn't fit single line
24+
* @param someString very long description that
25+
* doesn't fit single line and is indented
2326
* @param someInteger description with @param and @ pitfalls
2427
* @param someBoolean description with extra spaces
2528
* @param someLong description without space after asterisk
@@ -30,3 +33,5 @@
3033
@org.springframework.boot.configurationsample.ConfigurationProperties("record.descriptions")
3134
public record ExampleRecord(String someString, Integer someInteger, Boolean someBoolean, Long someLong, Byte someByte) {
3235
}
36+
37+
//@formatter:on
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2012-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.context.properties;
18+
19+
/**
20+
* @author pwebb
21+
*/
22+
23+
import org.junit.jupiter.api.Test;
24+
25+
import org.springframework.boot.context.properties.bind.DefaultValue;
26+
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
27+
import org.springframework.context.annotation.Configuration;
28+
import org.springframework.test.context.support.TestPropertySourceUtils;
29+
30+
public class TempTests {
31+
32+
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
33+
34+
@Test
35+
void testName() {
36+
load(MyConfig.class, "foo.bar.baz=hello");
37+
System.out.println(this.context.getBean(Foo.class));
38+
}
39+
40+
@Test
41+
void testName2() {
42+
load(MyConfig.class);
43+
System.out.println(this.context.getBean(Foo.class));
44+
}
45+
46+
private AnnotationConfigApplicationContext load(Class<?> configuration, String... inlinedProperties) {
47+
return load(new Class<?>[] { configuration }, inlinedProperties);
48+
}
49+
50+
private AnnotationConfigApplicationContext load(Class<?>[] configuration, String... inlinedProperties) {
51+
this.context.register(configuration);
52+
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context, inlinedProperties);
53+
this.context.refresh();
54+
return this.context;
55+
}
56+
57+
@Configuration
58+
@EnableConfigurationProperties(Foo.class)
59+
static class MyConfig {
60+
61+
}
62+
63+
@ConfigurationProperties("foo")
64+
record Foo(@DefaultValue Bar bar) {
65+
}
66+
67+
record Bar(@DefaultValue("hello") String baz) {
68+
}
69+
70+
}

0 commit comments

Comments
 (0)