Skip to content

Commit 2a1f203

Browse files
committed
Add StreamsFormatter
Add a new `StreamsFormatter` class which is similar to `FileFormatter` but designed to work with `java.io` streams. Closes gh-361
1 parent 5b2036f commit 2a1f203

File tree

7 files changed

+455
-37
lines changed

7 files changed

+455
-37
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/*
2+
* Copyright 2017-2023 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.formatter;
18+
19+
import java.io.ByteArrayOutputStream;
20+
import java.io.File;
21+
import java.io.IOException;
22+
import java.nio.charset.Charset;
23+
import java.nio.charset.StandardCharsets;
24+
import java.nio.file.Files;
25+
import java.nio.file.StandardCopyOption;
26+
27+
import org.eclipse.text.edits.TextEdit;
28+
import org.junit.jupiter.api.BeforeEach;
29+
import org.junit.jupiter.api.Test;
30+
import org.junit.jupiter.api.io.TempDir;
31+
32+
import static org.assertj.core.api.Assertions.assertThat;
33+
34+
/**
35+
* Tests for {@link StreamsEdit}.
36+
*
37+
* @author Phillip Webb
38+
*/
39+
public class StreamsEditTests {
40+
41+
private static final Charset UTF_8 = StandardCharsets.UTF_8;
42+
43+
@TempDir
44+
public File temp;
45+
46+
private File source;
47+
48+
private File expected;
49+
50+
private TextEdit textEdit;
51+
52+
private StreamsEdit streamsEdit;
53+
54+
@BeforeEach
55+
void setup() throws IOException {
56+
this.source = new File(this.temp, "source.txt");
57+
this.expected = new File(this.temp, "expected.txt");
58+
Files.copy(new File("src/test/resources/source/javadoc-top.txt").toPath(), this.source.toPath(),
59+
StandardCopyOption.REPLACE_EXISTING);
60+
Files.copy(new File("src/test/resources/expected/javadoc-top.txt").toPath(), this.expected.toPath(),
61+
StandardCopyOption.REPLACE_EXISTING);
62+
String content = read(this.source);
63+
this.textEdit = new Formatter().format(content);
64+
this.streamsEdit = new StreamsEdit(content, this.textEdit);
65+
}
66+
67+
@Test
68+
void hasEditsWhenHasEditsReturnsTrue() throws Exception {
69+
assertThat(this.streamsEdit.hasEdits()).isTrue();
70+
}
71+
72+
@Test
73+
void hasEditsWhenHasNoEditsReturnsFalse() throws Exception {
74+
String content = read(this.expected);
75+
this.textEdit = new Formatter().format(content);
76+
this.streamsEdit = new StreamsEdit(content, this.textEdit);
77+
assertThat(this.streamsEdit.hasEdits()).isFalse();
78+
}
79+
80+
@Test
81+
void writeToOutputStreamWritesContent() throws Exception {
82+
String expected = read(this.expected);
83+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
84+
this.streamsEdit.writeTo(outputStream);
85+
assertThat(outputStream.toByteArray()).isEqualTo(expected.getBytes(UTF_8));
86+
}
87+
88+
@Test
89+
void writeToOutputStreamWithCharsetWritesContent() throws IOException {
90+
String expected = read(this.expected);
91+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
92+
this.streamsEdit.writeTo(outputStream, UTF_8);
93+
assertThat(outputStream.toByteArray()).isEqualTo(expected.getBytes(UTF_8));
94+
}
95+
96+
@Test
97+
void writeToAppendableWritesContent() throws IOException {
98+
String expected = read(this.expected);
99+
StringBuilder output = new StringBuilder();
100+
this.streamsEdit.writeTo(output);
101+
assertThat(output.toString()).isEqualTo(expected);
102+
}
103+
104+
@Test
105+
void getFormattedContentReturnsFormattedContent() throws Exception {
106+
String expected = read(this.expected);
107+
assertThat(this.streamsEdit.getFormattedContent()).isEqualTo(expected);
108+
}
109+
110+
private String read(File file) throws IOException {
111+
return new String(Files.readAllBytes(file.toPath()), UTF_8);
112+
}
113+
114+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright 2017-2023 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.formatter;
18+
19+
import java.io.FileInputStream;
20+
import java.io.InputStream;
21+
import java.io.InputStreamReader;
22+
import java.io.Reader;
23+
import java.nio.charset.StandardCharsets;
24+
25+
import org.junit.jupiter.params.ParameterizedTest;
26+
import org.junit.jupiter.params.provider.MethodSource;
27+
28+
import static org.assertj.core.api.Assertions.assertThat;
29+
30+
/**
31+
* Tests for {@link StreamsFormatter}.
32+
*
33+
* @author Phillip Webb
34+
*/
35+
public class StreamsFormatterTests extends AbstractFormatterTests {
36+
37+
@ParameterizedTest
38+
@MethodSource("items")
39+
void formatInputStreamFormatsFile(Item item) throws Exception {
40+
try (InputStream inputStream = new FileInputStream(item.getSource())) {
41+
StreamsEdit edit = new StreamsFormatter(item.getConfig()).format(inputStream);
42+
assertThat(edit.getFormattedContent()).isEqualTo(read(item.getExpected()));
43+
}
44+
}
45+
46+
@ParameterizedTest
47+
@MethodSource("items")
48+
void formatInputStreamWithCharsetFormatsFile(Item item) throws Exception {
49+
try (InputStream inputStream = new FileInputStream(item.getSource())) {
50+
StreamsEdit edit = new StreamsFormatter(item.getConfig()).format(inputStream, StandardCharsets.UTF_8);
51+
assertThat(edit.getFormattedContent()).isEqualTo(read(item.getExpected()));
52+
}
53+
}
54+
55+
@ParameterizedTest
56+
@MethodSource("items")
57+
void formatReaderFormatsFile(Item item) throws Exception {
58+
try (Reader reader = new InputStreamReader(new FileInputStream(item.getSource()))) {
59+
StreamsEdit edit = new StreamsFormatter(item.getConfig()).format(reader);
60+
assertThat(edit.getFormattedContent()).isEqualTo(read(item.getExpected()));
61+
}
62+
}
63+
64+
static Item[] items() {
65+
return items(null);
66+
}
67+
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright 2017-2023 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.formatter;
18+
19+
import java.util.regex.Pattern;
20+
21+
import org.eclipse.jface.text.Document;
22+
import org.eclipse.jface.text.IDocument;
23+
import org.eclipse.text.edits.TextEdit;
24+
25+
/**
26+
* Base class for edits that can be applied to content.
27+
*
28+
* @author Phillip Webb
29+
*/
30+
public abstract class Edit {
31+
32+
private static final Pattern TRAILING_WHITESPACE = Pattern.compile(" +$", Pattern.MULTILINE);
33+
34+
private final String originalContent;
35+
36+
private final TextEdit textEdit;
37+
38+
protected Edit(String originalContent, TextEdit textEdit) {
39+
super();
40+
this.originalContent = originalContent;
41+
this.textEdit = textEdit;
42+
}
43+
44+
public boolean hasEdits() {
45+
return (this.textEdit.hasChildren() || this.textEdit.getLength() > 0);
46+
}
47+
48+
protected String getFormattedContent() throws Exception {
49+
IDocument document = new Document(this.originalContent);
50+
this.textEdit.apply(document);
51+
String formattedContent = document.get();
52+
return trimTrailingWhitespace(formattedContent);
53+
}
54+
55+
private String trimTrailingWhitespace(String content) {
56+
return TRAILING_WHITESPACE.matcher(content).replaceAll("");
57+
}
58+
59+
}
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-2023 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.
@@ -20,44 +20,30 @@
2020
import java.nio.charset.Charset;
2121
import java.nio.file.Files;
2222
import java.nio.file.StandardOpenOption;
23-
import java.util.regex.Pattern;
2423

25-
import org.eclipse.jface.text.Document;
26-
import org.eclipse.jface.text.IDocument;
2724
import org.eclipse.text.edits.TextEdit;
2825

2926
/**
30-
* An Edit that can be applied to a File.
27+
* An {@link Edit} that can be applied to a {@link File}.
3128
*
3229
* @author Phillip Webb
3330
*/
34-
public class FileEdit {
35-
36-
private static final Pattern TRAILING_WHITESPACE = Pattern.compile(" +$", Pattern.MULTILINE);
31+
public class FileEdit extends Edit {
3732

3833
private final File file;
3934

4035
private final Charset encoding;
4136

42-
private final String originalContent;
43-
44-
private final TextEdit edit;
45-
46-
FileEdit(File file, Charset encoding, String originalContent, TextEdit edit) {
37+
FileEdit(File file, Charset encoding, String originalContent, TextEdit textEdit) {
38+
super(originalContent, textEdit);
4739
this.file = file;
4840
this.encoding = encoding;
49-
this.originalContent = originalContent;
50-
this.edit = edit;
5141
}
5242

5343
public File getFile() {
5444
return this.file;
5545
}
5646

57-
public boolean hasEdits() {
58-
return (this.edit.hasChildren() || this.edit.getLength() > 0);
59-
}
60-
6147
public void save() {
6248
try {
6349
String formattedContent = getFormattedContent();
@@ -69,20 +55,14 @@ public void save() {
6955
}
7056
}
7157

72-
public String getFormattedContent() throws Exception {
58+
@Override
59+
protected String getFormattedContent() throws Exception {
7360
try {
74-
IDocument document = new Document(this.originalContent);
75-
this.edit.apply(document);
76-
String formattedContent = document.get();
77-
return trimTrailingWhitespace(formattedContent);
61+
return super.getFormattedContent();
7862
}
7963
catch (Exception ex) {
8064
throw FileFormatterException.wrap(this.file, ex);
8165
}
8266
}
8367

84-
private String trimTrailingWhitespace(String content) {
85-
return TRAILING_WHITESPACE.matcher(content).replaceAll("");
86-
}
87-
8868
}

Diff for: spring-javaformat/spring-javaformat-formatter/src/main/java/io/spring/javaformat/formatter/FileFormatter.java

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2021 the original author or authors.
2+
* Copyright 2017-2023 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.
@@ -55,7 +55,7 @@ public FileFormatter(Formatter formatter) {
5555
* instances.
5656
* @param files the files to format
5757
* @param encoding the source encoding
58-
* @return a stream of formatted files that have edits
58+
* @return a stream of file edits
5959
*/
6060
public Stream<FileEdit> formatFiles(Iterable<File> files, Charset encoding) {
6161
return formatFiles(files, encoding, Formatter.DEFAULT_LINE_SEPARATOR);
@@ -67,7 +67,7 @@ public Stream<FileEdit> formatFiles(Iterable<File> files, Charset encoding) {
6767
* @param files the files to format
6868
* @param encoding the source encoding
6969
* @param lineSeparator the line separator
70-
* @return a stream of formatted files that have edits
70+
* @return a stream of file edits
7171
*/
7272
public Stream<FileEdit> formatFiles(Iterable<File> files, Charset encoding, String lineSeparator) {
7373
return formatFiles(StreamSupport.stream(files.spliterator(), false), encoding, lineSeparator);
@@ -78,7 +78,7 @@ public Stream<FileEdit> formatFiles(Iterable<File> files, Charset encoding, Stri
7878
* instances.
7979
* @param files the files to format
8080
* @param encoding the source encoding
81-
* @return a stream of formatted files that have edits
81+
* @return a stream of file edits
8282
*/
8383
public Stream<FileEdit> formatFiles(Stream<File> files, Charset encoding) {
8484
return formatFiles(files, encoding, Formatter.DEFAULT_LINE_SEPARATOR);
@@ -90,28 +90,28 @@ public Stream<FileEdit> formatFiles(Stream<File> files, Charset encoding) {
9090
* @param files the files to format
9191
* @param encoding the source encoding
9292
* @param lineSeparator the line separator
93-
* @return a stream of formatted files that have edits
93+
* @return a stream of file edits
9494
*/
9595
public Stream<FileEdit> formatFiles(Stream<File> files, Charset encoding, String lineSeparator) {
9696
return files.map((file) -> formatFile(file, encoding, lineSeparator));
9797
}
9898

9999
/**
100-
* Format the the given source file and return a {@link FileEdit} instance.
100+
* Format the given source file and return a {@link FileEdit} instance.
101101
* @param file the file to format
102102
* @param encoding the source encoding
103-
* @return a formatted file
103+
* @return a file edit
104104
*/
105105
public FileEdit formatFile(File file, Charset encoding) {
106106
return formatFile(file, encoding, Formatter.DEFAULT_LINE_SEPARATOR);
107107
}
108108

109109
/**
110-
* Format the the given source file and return a {@link FileEdit} instance.
110+
* Format the given source file and return a {@link FileEdit} instance.
111111
* @param file the file to format
112112
* @param encoding the source encoding
113113
* @param lineSeparator the line separator
114-
* @return a formatted file
114+
* @return a file edit
115115
*/
116116
public FileEdit formatFile(File file, Charset encoding, String lineSeparator) {
117117
try {

0 commit comments

Comments
 (0)