Skip to content

Commit 354632a

Browse files
committed
Support space indentation option
Update the formatter and checkstyle rules to allow indentation with spaces rather than tabs. Closes gh-269
1 parent b831695 commit 354632a

File tree

56 files changed

+1087
-124
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1087
-124
lines changed

README.adoc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,20 @@ Spring Framework manually formats code, where as Spring Boot uses automatic form
227227

228228

229229

230+
=== Indenting With Spaces
231+
By default tabs are used for indenting formatted code.
232+
We strongly recommend that this default is not changed, especially for official Spring projects.
233+
If, however, you feel that you can't live with tabs then switching to spaces is the one configuration option that we do support.
234+
235+
To use spaces rather than tabs, add a file called `.springjavaformatconfig` to the root of your project with the following content:
236+
237+
[source,properties]
238+
----
239+
indentation-style=spaces
240+
----
241+
242+
243+
230244
=== Tips
231245
Formatting and Checkstyle alone are not enough to produce truly consistent code.
232246
Here are some tips that we've found useful when developing Spring Boot.

spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/src/io/spring/javaformat/eclipse/projectsettings/ProjectPropertiesTests.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2021 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.
@@ -30,6 +30,8 @@
3030
import org.junit.Test;
3131
import org.junit.rules.TemporaryFolder;
3232

33+
import io.spring.javaformat.config.JavaFormatConfig;
34+
3335
import static org.assertj.core.api.Assertions.assertThat;
3436

3537
/**
@@ -75,15 +77,16 @@ public void addFromEmptyFolderUsesDefaults() throws IOException {
7577

7678
@Test
7779
public void getModifiedContentReplacesCopyrightYear() throws IOException {
80+
String year = "2016-2020";
7881
File folder = this.temp.newFolder();
7982
File file = new File(folder, "eclipse.properties");
80-
writeProperties(file, "2016-2020");
83+
writeProperties(file, year);
8184
ProjectProperties properties = new ProjectProperties();
8285
properties.addFromFolder(folder);
8386
ProjectSettingsFiles files = new ProjectSettingsFilesLocator().locateSettingsFiles();
8487
ProjectSettingsFile prefs = getFile(files, "org.eclipse.jdt.ui.prefs");
85-
String content = loadContent(properties.getModifiedContent(prefs));
86-
assertThat(content).contains("Copyright 2016-2020 the original author or authors");
88+
String content = loadContent(properties.getModifiedContent(prefs).getContent(JavaFormatConfig.DEFAULT));
89+
assertThat(content).contains("Copyright " + year + " the original author or authors");
8790

8891
}
8992

spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFileTests.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2019 the original author or authors.
2+
* Copyright 2017-2021 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.
@@ -25,6 +25,8 @@
2525
import org.junit.Test;
2626
import org.junit.rules.TemporaryFolder;
2727

28+
import io.spring.javaformat.config.JavaFormatConfig;
29+
2830
import static org.assertj.core.api.Assertions.assertThat;
2931

3032
/**
@@ -43,14 +45,16 @@ public void fromFileAdaptsFile() throws Exception {
4345
writeText(file, "test");
4446
ProjectSettingsFile projectSettingsFile = ProjectSettingsFile.fromFile(file);
4547
assertThat(projectSettingsFile.getName()).isEqualTo(file.getName());
46-
assertThat(projectSettingsFile.getContent()).hasSameContentAs(new ByteArrayInputStream("test".getBytes()));
48+
assertThat(projectSettingsFile.getContent(JavaFormatConfig.DEFAULT))
49+
.hasSameContentAs(new ByteArrayInputStream("test".getBytes()));
4750
}
4851

4952
@Test
5053
public void fromClasspathResourceAdaptsResource() throws Exception {
5154
ProjectSettingsFile projectSettingsFile = ProjectSettingsFile.fromClasspath(getClass(), "test.txt");
5255
assertThat(projectSettingsFile.getName()).isEqualTo("test.txt");
53-
assertThat(projectSettingsFile.getContent()).hasSameContentAs(new ByteArrayInputStream("test".getBytes()));
56+
assertThat(projectSettingsFile.getContent(JavaFormatConfig.DEFAULT))
57+
.hasSameContentAs(new ByteArrayInputStream("test".getBytes()));
5458
}
5559

5660
private void writeText(File file, String s) throws FileNotFoundException {

spring-javaformat-eclipse/io.spring.javaformat.eclipse.tests/src/io/spring/javaformat/eclipse/projectsettings/ProjectSettingsFilesLocatorTests.java

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2019 the original author or authors.
2+
* Copyright 2017-2021 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.
@@ -19,14 +19,18 @@
1919
import java.io.ByteArrayInputStream;
2020
import java.io.File;
2121
import java.io.IOException;
22+
import java.io.InputStream;
2223
import java.io.PrintWriter;
2324
import java.util.LinkedHashMap;
2425
import java.util.Map;
26+
import java.util.Properties;
2527

2628
import org.junit.Rule;
2729
import org.junit.Test;
2830
import org.junit.rules.TemporaryFolder;
2931

32+
import io.spring.javaformat.config.JavaFormatConfig;
33+
3034
import static org.assertj.core.api.Assertions.assertThat;
3135

3236
/**
@@ -66,11 +70,45 @@ public void locateSettingsFilesWhenMultipleFoldersFindsInEarliest() throws Excep
6670
ProjectSettingsFiles files = new ProjectSettingsFilesLocator(folder1, folder2).locateSettingsFiles();
6771
Map<String, ProjectSettingsFile> found = new LinkedHashMap<>();
6872
files.iterator().forEachRemaining((f) -> found.put(f.getName(), f));
69-
assertThat(found.get("foo.prefs").getContent()).hasSameContentAs(new ByteArrayInputStream("foo1".getBytes()));
70-
assertThat(found.get("org.eclipse.jdt.core.prefs").getContent())
73+
assertThat(found.get("foo.prefs").getContent(JavaFormatConfig.DEFAULT))
74+
.hasSameContentAs(new ByteArrayInputStream("foo1".getBytes()));
75+
assertThat(found.get("org.eclipse.jdt.core.prefs").getContent(JavaFormatConfig.DEFAULT))
7176
.hasSameContentAs(new ByteArrayInputStream("core2".getBytes()));
7277
}
7378

79+
@Test
80+
public void jdtCorePrefsFormatterWhenDefaultShouldUseTabs() throws IOException {
81+
ProjectSettingsFiles files = new ProjectSettingsFilesLocator().locateSettingsFiles();
82+
ProjectSettingsFile file = get(files, "org.eclipse.jdt.core.prefs");
83+
try (InputStream content = file.getContent(JavaFormatConfig.DEFAULT)) {
84+
Properties properties = new Properties();
85+
properties.load(content);
86+
assertThat(properties.get("org.eclipse.jdt.core.javaFormatter"))
87+
.isEqualTo("io.spring.javaformat.eclipse.formatter");
88+
}
89+
}
90+
91+
@Test
92+
public void jdtCorePrefsFormatterWhenSpacesShouldUseSpaces() throws IOException {
93+
ProjectSettingsFiles files = new ProjectSettingsFilesLocator().locateSettingsFiles();
94+
ProjectSettingsFile file = get(files, "org.eclipse.jdt.core.prefs");
95+
try (InputStream content = file.getContent(JavaFormatConfig.SPACES)) {
96+
Properties properties = new Properties();
97+
properties.load(content);
98+
assertThat(properties.get("org.eclipse.jdt.core.javaFormatter"))
99+
.isEqualTo("io.spring.javaformat.eclipse.formatter.spaces");
100+
}
101+
}
102+
103+
private ProjectSettingsFile get(ProjectSettingsFiles files, String name) {
104+
for (ProjectSettingsFile file : files) {
105+
if (file.getName().equals(name)) {
106+
return file;
107+
}
108+
}
109+
return null;
110+
}
111+
74112
private void writeFile(File folder, String name) throws IOException {
75113
writeFile(folder, name, name);
76114
}

spring-javaformat-eclipse/io.spring.javaformat.eclipse/META-INF/MANIFEST.MF

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Require-Bundle: org.eclipse.ui,
2020
net.sf.eclipsecs.core;resolution:=optional
2121
Bundle-ClassPath: .,
2222
lib/spring-javaformat-formatter-eclipse.jar,
23+
lib/spring-javaformat-config.jar,
2324
lib/spring-javaformat-formatter.jar,
2425
lib/spring-javaformat-checkstyle.jar
2526
Bundle-ActivationPolicy: lazy

spring-javaformat-eclipse/io.spring.javaformat.eclipse/build.properties

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ bin.includes = META-INF/,\
33
.,\
44
plugin.xml,\
55
lifecycle-mapping-metadata.xml,\
6-
lib/spring-javaformat-formatter-eclipse.jar,\
6+
lib/spring-javaformat-checkstyle.jar,\
7+
lib/spring-javaformat-config.jar,\
78
lib/spring-javaformat-formatter.jar,\
8-
lib/spring-javaformat-checkstyle.jar
9-
9+
lib/spring-javaformat-formatter-eclipse.jar

spring-javaformat-eclipse/io.spring.javaformat.eclipse/plugin.xml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,14 @@
33
<plugin>
44
<extension point="org.eclipse.jdt.core.javaFormatter">
55
<javaFormatter
6-
class="io.spring.javaformat.eclipse.formatter.SpringCodeFormatter"
6+
class="io.spring.javaformat.eclipse.formatter.SpringCodeFormatterTabs"
77
id="io.spring.javaformat.eclipse.formatter"
8-
name="Spring">
8+
name="Spring (tab indented)">
9+
</javaFormatter>
10+
<javaFormatter
11+
class="io.spring.javaformat.eclipse.formatter.SpringCodeFormatterSpaces"
12+
id="io.spring.javaformat.eclipse.formatter.spaces"
13+
name="Spring (space indented)">
914
</javaFormatter>
1015
</extension>
1116
<extension point="org.eclipse.m2e.core.projectConfigurators">

spring-javaformat-eclipse/io.spring.javaformat.eclipse/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@
1616
</properties>
1717
<dependencies>
1818
<!-- Runtime -->
19+
<dependency>
20+
<groupId>io.spring.javaformat</groupId>
21+
<artifactId>spring-javaformat-config</artifactId>
22+
<scope>runtime</scope>
23+
<version>${project.version}</version>
24+
</dependency>
1925
<dependency>
2026
<groupId>io.spring.javaformat</groupId>
2127
<artifactId>spring-javaformat-formatter</artifactId>

spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/formatter/SpringCodeFormatter.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2019 the original author or authors.
2+
* Copyright 2017-2021 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.
@@ -22,16 +22,21 @@
2222
import org.eclipse.jface.text.IRegion;
2323
import org.eclipse.text.edits.TextEdit;
2424

25+
import io.spring.javaformat.config.JavaFormatConfig;
2526
import io.spring.javaformat.formatter.Formatter;
2627

2728
/**
28-
* Eclipse {@link CodeFormatter} for Spring formatting.
29+
* Eclipse {@link CodeFormatter} base class for Spring formatting.
2930
*
3031
* @author Phillip Webb
3132
*/
32-
public class SpringCodeFormatter extends CodeFormatter {
33+
public abstract class SpringCodeFormatter extends CodeFormatter {
3334

34-
private Formatter delegate = new Formatter();
35+
private final Formatter delegate;
36+
37+
public SpringCodeFormatter(JavaFormatConfig javaFormatConfig) {
38+
this.delegate = new Formatter(javaFormatConfig);
39+
}
3540

3641
@Override
3742
public TextEdit format(int kind, String source, int offset, int length, int indentationLevel,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2017-2021 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 io.spring.javaformat.eclipse.formatter;
18+
19+
import org.eclipse.jdt.core.formatter.CodeFormatter;
20+
21+
import io.spring.javaformat.config.JavaFormatConfig;
22+
23+
/**
24+
* Eclipse {@link CodeFormatter} for Spring formatting with spaces.
25+
*
26+
* @author Phillip Webb
27+
*/
28+
public class SpringCodeFormatterSpaces extends SpringCodeFormatter {
29+
30+
public SpringCodeFormatterSpaces() {
31+
super(JavaFormatConfig.SPACES);
32+
}
33+
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2017-2021 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 io.spring.javaformat.eclipse.formatter;
18+
19+
import org.eclipse.jdt.core.formatter.CodeFormatter;
20+
21+
import io.spring.javaformat.config.JavaFormatConfig;
22+
23+
/**
24+
* Eclipse {@link CodeFormatter} for Spring formatting with tabs.
25+
*
26+
* @author Phillip Webb
27+
*/
28+
public class SpringCodeFormatterTabs extends SpringCodeFormatter {
29+
30+
public SpringCodeFormatterTabs() {
31+
super(JavaFormatConfig.DEFAULT);
32+
}
33+
34+
}

spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/gradle/GradleProjectSettingsConfigurator.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2020 the original author or authors.
2+
* Copyright 2017-2021 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.
@@ -88,8 +88,8 @@ private void configureProject(IProject project, IProgressMonitor monitor) throws
8888

8989
@SuppressWarnings("unchecked")
9090
private Collection<EclipseProject> getRootProjects(IProgressMonitor monitor, ModelProvider modelProvider) {
91-
Object models = modelProvider.fetchModels(EclipseProject.class,
92-
FetchStrategy.FORCE_RELOAD, this.tokenSource, monitor);
91+
Object models = modelProvider.fetchModels(EclipseProject.class, FetchStrategy.FORCE_RELOAD, this.tokenSource,
92+
monitor);
9393
return (Collection<EclipseProject>) ((models instanceof Map) ? ((Map<?, ?>) models).values() : models);
9494
}
9595

spring-javaformat-eclipse/io.spring.javaformat.eclipse/src/io/spring/javaformat/eclipse/projectsettings/ProjectProperties.java

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2021 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.
@@ -16,15 +16,9 @@
1616

1717
package io.spring.javaformat.eclipse.projectsettings;
1818

19-
import java.io.BufferedReader;
20-
import java.io.ByteArrayInputStream;
2119
import java.io.File;
2220
import java.io.FileInputStream;
2321
import java.io.IOException;
24-
import java.io.InputStream;
25-
import java.io.InputStreamReader;
26-
import java.io.StringWriter;
27-
import java.nio.charset.StandardCharsets;
2822
import java.time.LocalDateTime;
2923
import java.time.format.DateTimeFormatter;
3024
import java.util.Collections;
@@ -74,26 +68,13 @@ private void addFromProperties(Properties properties) {
7468
});
7569
}
7670

77-
public InputStream getModifiedContent(ProjectSettingsFile file) throws IOException {
71+
public ProjectSettingsFile getModifiedContent(ProjectSettingsFile file) throws IOException {
7872
if (file.getName().equals("org.eclipse.jdt.ui.prefs")) {
79-
String content = loadContent(file);
80-
content = content.replace("Copyright the original author or authors",
81-
"Copyright " + get(COPYRIGHT_YEAR) + " the original author or authors");
82-
return new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
83-
}
84-
return file.getContent();
85-
}
86-
87-
private String loadContent(ProjectSettingsFile file) throws IOException {
88-
try (BufferedReader reader = new BufferedReader(new InputStreamReader(file.getContent()))) {
89-
StringWriter writer = new StringWriter();
90-
char[] buffer = new char[4096];
91-
int read = 0;
92-
while ((read = reader.read(buffer)) >= 0) {
93-
writer.write(buffer, 0, read);
94-
}
95-
return writer.toString();
73+
return file.withUpdatedContent(
74+
(javaFormatConfig, content) -> content.replace("Copyright the original author or authors",
75+
"Copyright " + get(COPYRIGHT_YEAR) + " the original author or authors"));
9676
}
77+
return file;
9778
}
9879

9980
String get(String name) {

0 commit comments

Comments
 (0)