Skip to content

Commit 875e4a7

Browse files
committed
Add LineEnding.PRESERVE policy
WIP
1 parent 755c22f commit 875e4a7

File tree

2 files changed

+98
-2
lines changed

2 files changed

+98
-2
lines changed

lib/src/main/java/com/diffplug/spotless/LineEnding.java

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@
1616
package com.diffplug.spotless;
1717

1818
import java.io.File;
19+
import java.io.FileReader;
20+
import java.io.IOException;
21+
import java.io.Reader;
1922
import java.io.Serializable;
2023
import java.lang.reflect.Method;
24+
import java.nio.charset.StandardCharsets;
2125
import java.util.Objects;
2226
import java.util.function.Supplier;
2327

@@ -47,9 +51,11 @@ public Policy createPolicy() {
4751
/** {@code \r\n} */
4852
WINDOWS,
4953
/** {@code \n} */
50-
UNIX,
54+
UNIX,
5155
/** {@code \r} */
52-
MAC_CLASSIC;
56+
MAC_CLASSIC,
57+
/** preserve the line ending of the first line (no matter which format) */
58+
PRESERVE;
5359
// @formatter:on
5460

5561
/** Returns a {@link Policy} appropriate for files which are contained within the given rootFolder. */
@@ -81,6 +87,7 @@ public Policy createPolicy() {
8187
case WINDOWS: return WINDOWS_POLICY;
8288
case UNIX: return UNIX_POLICY;
8389
case MAC_CLASSIC: return MAC_CLASSIC_POLICY;
90+
case PRESERVE: return PRESERVE_POLICY;
8491
default: throw new UnsupportedOperationException(this + " is a path-specific line ending.");
8592
}
8693
}
@@ -100,9 +107,50 @@ public String getEndingFor(File file) {
100107
}
101108
}
102109

110+
static class PreserveLineEndingPolicy extends NoLambda.EqualityBasedOnSerialization implements Policy {
111+
private static final long serialVersionUID = 2L;
112+
113+
@Override
114+
public String getEndingFor(File file) {
115+
// assume US-ASCII encoding (only line ending characters need to be decoded anyways)
116+
try (Reader reader = new FileReader(file, StandardCharsets.US_ASCII)) {
117+
return getEndingFor(reader);
118+
} catch (IOException e) {
119+
throw new IllegalArgumentException("Could not determine line ending of file: " + file, e);
120+
}
121+
}
122+
123+
static String getEndingFor(Reader reader) throws IOException {
124+
char previousCharacter = 0;
125+
char currentCharacter = 0;
126+
int readResult;
127+
while ((readResult = reader.read()) != -1) {
128+
currentCharacter = (char)readResult;
129+
if (currentCharacter == '\n') {
130+
if (previousCharacter == '\r') {
131+
return WINDOWS.str();
132+
} else {
133+
return UNIX.str();
134+
}
135+
} else {
136+
if (previousCharacter == '\r') {
137+
return MAC_CLASSIC.str();
138+
}
139+
}
140+
previousCharacter = currentCharacter;
141+
}
142+
if (previousCharacter == '\r') {
143+
return MAC_CLASSIC.str();
144+
}
145+
// assume UNIX line endings if no line ending was found
146+
return UNIX.str();
147+
}
148+
}
149+
103150
private static final Policy WINDOWS_POLICY = new ConstantLineEndingPolicy(WINDOWS.str());
104151
private static final Policy UNIX_POLICY = new ConstantLineEndingPolicy(UNIX.str());
105152
private static final Policy MAC_CLASSIC_POLICY = new ConstantLineEndingPolicy(MAC_CLASSIC.str());
153+
private static final Policy PRESERVE_POLICY = new PreserveLineEndingPolicy();
106154
private static final String _platformNative = System.getProperty("line.separator");
107155
private static final Policy _platformNativePolicy = new ConstantLineEndingPolicy(_platformNative);
108156
private static final boolean nativeIsWin = _platformNative.equals(WINDOWS.str());
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
package com.diffplug.spotless;
15+
16+
import java.io.IOException;
17+
import java.io.Reader;
18+
import java.io.StringReader;
19+
20+
import org.junit.jupiter.api.Assertions;
21+
import org.junit.jupiter.api.Test;
22+
23+
class LineEndingTest {
24+
25+
@Test
26+
void testGetEndingFor() throws IOException {
27+
assertLineEnding("\r", "\r");
28+
assertLineEnding("\r", "Test\r");
29+
assertLineEnding("\r", "Test\rTest2\n");
30+
31+
assertLineEnding("\n", "Test");
32+
33+
assertLineEnding("\r\n", "\r\n");
34+
assertLineEnding("\r\n", "Test\r\n");
35+
assertLineEnding("\r\n", "Test\r\nTest2\n");
36+
37+
assertLineEnding("\n", "\n");
38+
assertLineEnding("\n", "Test\n");
39+
assertLineEnding("\n", "Test\nTest2\r");
40+
assertLineEnding("\n", "\n\t");
41+
}
42+
43+
static void assertLineEnding(String ending, String input) throws IOException {
44+
try (Reader reader = new StringReader(input)) {
45+
Assertions.assertEquals(ending, LineEnding.PreserveLineEndingPolicy.getEndingFor(reader));
46+
}
47+
}
48+
}

0 commit comments

Comments
 (0)