diff --git a/README.md b/README.md index 274998e9d2..22b2372ac4 100644 --- a/README.md +++ b/README.md @@ -156,20 +156,23 @@ spotless { // when writing a custom step, it will be helpful to know // how the formatting process works, which is as follows: - // 1) Load each target file, and convert it to unix-style line endings ('\n') + // 1) Load each target file // 2) Pass its content through a series of steps, feeding the output of each step to the next - // 3) Put the correct line endings back on, then either check or apply + // 3) Then either check or apply // each step receives a string as input, and should output - // a formatted string as output. Each step can trust that its - // input will have unix newlines, and it must promise to output - // only unix newlines. Other than that, anything is fair game! + // a formatted string as output. } + + // If you don't specify a format specific line ending, the spotless-global setting will be used. + lineEndings = 'UNIX' } // If you'd like to specify that files should always have a certain line ending, you can, - // but the default value of PLATFORM_NATIVE is *highly* recommended - lineEndings = PLATFORM_NATIVE // can be WINDOWS, UNIX, or PLATFORM_NATIVE + // but the default value of PLATFORM_NATIVE is *highly* recommended. + // DERIVED means the line ending is derived for each file based on the first line ending + // in its content. If none is found PLATFORM_NATIVE is used. + lineEndings = 'PLATFORM_NATIVE' // can be WINDOWS, UNIX, PLATFORM_NATIVE or DERIVED } ``` diff --git a/build.gradle b/build.gradle index 6169af13d3..cfca739391 100644 --- a/build.gradle +++ b/build.gradle @@ -83,8 +83,12 @@ dependencies { // UNCOMMENT TO DOWNLOAD SOURCE JARS //embeddedJars "p2:${name}.source:${ver}" } - + configurations.compile.extendsFrom(configurations.embeddedJars) + + testCompile 'org.mockito:mockito-core:1.10.19', { + exclude group:'org.hamcrest', module: 'hamcrest-core' + } } jar { diff --git a/src/main/java/com/diffplug/gradle/spotless/FileEndingStep.java b/src/main/java/com/diffplug/gradle/spotless/FileEndingStep.java new file mode 100644 index 0000000000..1b395370bb --- /dev/null +++ b/src/main/java/com/diffplug/gradle/spotless/FileEndingStep.java @@ -0,0 +1,59 @@ +/* + * Copyright 2016 DiffPlug + * + * 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 + * + * http://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 com.diffplug.gradle.spotless; + +public class FileEndingStep { + private LineEnding lineEnding; + private LineEndingService lineEndingService; + private boolean clobber = true; + + public FileEndingStep(LineEnding lineEnding) { + this(lineEnding, new LineEndingService()); + } + + FileEndingStep(LineEnding lineEnding, LineEndingService lineEndingService) { + this.lineEnding = lineEnding; + this.lineEndingService = lineEndingService; + } + + public void disableClobber() { + this.clobber = false; + } + + public String format(String input) { + return clobber ? formatWithClobber(input) : formatWithoutClobber(input); + } + + public String formatWithClobber(String input) { + String lineSeparator = lineEndingService.getLineSeparatorOrDefault(lineEnding, input); + int indexOfLastNonWhitespaceCharacter = lineEndingService.indexOfLastNonWhitespaceCharacter(input); + + if (indexOfLastNonWhitespaceCharacter == -1) { + return lineSeparator; + } + + StringBuilder builder = new StringBuilder(indexOfLastNonWhitespaceCharacter + 2); + builder.append(input, 0, indexOfLastNonWhitespaceCharacter + 1); + builder.append(lineSeparator); + return builder.toString(); + } + + public String formatWithoutClobber(String input) { + String lineSeparator = lineEndingService.getLineSeparatorOrDefault(lineEnding, input); + return input.endsWith(lineSeparator) ? input : input + lineSeparator; + } + +} diff --git a/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java b/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java index 5b7b0ee0f4..6e133e28b7 100644 --- a/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java +++ b/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java @@ -20,6 +20,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.regex.Pattern; import org.gradle.api.GradleException; @@ -35,20 +36,25 @@ public class FormatExtension { protected final String name; protected final SpotlessExtension root; + /** The steps that need to be added. */ + protected List steps = new ArrayList<>(); + + /** The files that need to be formatted. */ + protected FileCollection target; + + private Optional lineEndings = Optional.empty(); + public FormatExtension(String name, SpotlessExtension root) { this.name = name; this.root = root; root.addFormatExtension(this); - } - /** The files that need to be formatted. */ - protected FileCollection target; + // Adding LineEndingStep by default in order to be compatible to v1.3.3 + customLazy("defaultLineEnding", () -> new LineEndingStep(root.getLineEndings())::format); + } /** - * FileCollections pass through raw. - * Strings are treated as the 'include' arg to fileTree, with project.rootDir as the dir. - * List are treates as the 'includes' arg to fileTree, with project.rootDir as the dir. - * Anything else gets passed to getProject().files(). + * FileCollections pass through raw. Strings are treated as the 'include' arg to fileTree, with project.rootDir as the dir. List are treates as the 'includes' arg to fileTree, with project.rootDir as the dir. Anything else gets passed to getProject().files(). */ public void target(Object... targets) { if (targets.length == 0) { @@ -87,13 +93,18 @@ protected FileCollection parseTarget(Object target) { } } - /** The steps that need to be added. */ - protected List steps = new ArrayList<>(); + public LineEnding getLineEndings() { + return lineEndings.orElse(root.getLineEndings()); + } + + public void setLineEndings(LineEnding lineEndings) { + this.lineEndings = Optional.of(lineEndings); + dontDoDefaultLineEndingNormalization(); + customLazy("lineEnding", () -> new LineEndingStep(lineEndings)::format); + } /** * Adds the given custom step, which is constructed lazily for performance reasons. - * - * The resulting function will receive a string with unix-newlines, and it must return a string unix newlines. */ public void customLazy(String name, Throwing.Supplier> formatterSupplier) { for (FormatterStep step : steps) { @@ -104,12 +115,12 @@ public void customLazy(String name, Throwing.Supplier formatter) { custom(name, formatter::call); } - /** Adds a custom step. Receives a string with unix-newlines, must return a string with unix newlines. */ + /** Adds a custom step. */ public void custom(String name, Throwing.Function formatter) { customLazy(name, () -> formatter); } @@ -122,7 +133,7 @@ public void customReplace(String name, CharSequence original, CharSequence after /** Highly efficient find-replace regex. */ public void customReplaceRegex(String name, String regex, String replacement) { customLazy(name, () -> { - Pattern pattern = Pattern.compile(regex, Pattern.UNIX_LINES | Pattern.MULTILINE); + Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE); return raw -> pattern.matcher(raw).replaceAll(replacement); }); } @@ -134,36 +145,7 @@ public void trimTrailingWhitespace() { /** Ensures that files end with a single newline. */ public void endWithNewline() { - custom("endWithNewline", raw -> { - // simplifies the logic below if we can assume length > 0 - if (raw.isEmpty()) { - return "\n"; - } - - // find the last character which has real content - int lastContentCharacter = raw.length() - 1; - char c; - while (lastContentCharacter >= 0) { - c = raw.charAt(lastContentCharacter); - if (c == '\n' || c == '\t' || c == ' ') { - --lastContentCharacter; - } else { - break; - } - } - - // if it's already clean, no need to create another string - if (lastContentCharacter == -1) { - return "\n"; - } else if (lastContentCharacter == raw.length() - 2 && raw.charAt(raw.length() - 1) == '\n') { - return raw; - } else { - StringBuilder builder = new StringBuilder(lastContentCharacter + 2); - builder.append(raw, 0, lastContentCharacter + 1); - builder.append('\n'); - return builder.toString(); - } - }); + customLazy("endWithNewline", () -> new FileEndingStep(getLineEndings())::format); } /** Ensures that the files are indented using spaces. */ @@ -187,19 +169,23 @@ public void indentWithTabs() { } /** - * @param licenseHeader Content that should be at the top of every file - * @param delimiter Spotless will look for a line that starts with this to know what the "top" is. + * @param licenseHeader + * Content that should be at the top of every file + * @param delimiter + * Spotless will look for a line that starts with this to know what the "top" is. */ public void licenseHeader(String licenseHeader, String delimiter) { - customLazy(LicenseHeaderStep.NAME, () -> new LicenseHeaderStep(licenseHeader, delimiter)::format); + customLazy(LicenseHeaderStep.NAME, () -> new LicenseHeaderStep(licenseHeader, delimiter, getLineEndings())::format); } /** - * @param licenseHeaderFile Content that should be at the top of every file - * @param delimiter Spotless will look for a line that starts with this to know what the "top" is. + * @param licenseHeaderFile + * Content that should be at the top of every file + * @param delimiter + * Spotless will look for a line that starts with this to know what the "top" is. */ public void licenseHeaderFile(Object licenseHeaderFile, String delimiter) { - customLazy(LicenseHeaderStep.NAME, () -> new LicenseHeaderStep(getProject().file(licenseHeaderFile), delimiter)::format); + customLazy(LicenseHeaderStep.NAME, () -> new LicenseHeaderStep(getProject().file(licenseHeaderFile), delimiter, getLineEndings())::format); } /** Sets up a FormatTask according to the values in this extension. */ @@ -212,4 +198,14 @@ protected void setupTask(FormatTask task) throws Exception { protected Project getProject() { return root.project; } + + // As long defaultLineEnding is active by default, we need to be able to disable the + // eol normalization for the tests. + protected void dontDoDefaultLineEndingNormalization() { + Optional lineEndingStep = steps.stream() + .filter(step -> "defaultLineEnding".equals(step.getName())) + .findFirst(); + + lineEndingStep.ifPresent(steps::remove); + } } diff --git a/src/main/java/com/diffplug/gradle/spotless/FormatTask.java b/src/main/java/com/diffplug/gradle/spotless/FormatTask.java index 8d4b98dd29..3000496d5e 100644 --- a/src/main/java/com/diffplug/gradle/spotless/FormatTask.java +++ b/src/main/java/com/diffplug/gradle/spotless/FormatTask.java @@ -34,8 +34,6 @@ public class FormatTask extends DefaultTask { @Input public boolean check = false; @Input - public LineEnding lineEndings = LineEnding.PLATFORM_NATIVE; - @Input public List steps = new ArrayList<>(); @TaskAction @@ -44,7 +42,7 @@ public void format() throws Exception { throw new GradleException("You must specify 'Iterable toFormat'"); } // combine them into the master formatter - Formatter formatter = new Formatter(lineEndings, getProject().getProjectDir().toPath(), steps); + Formatter formatter = new Formatter(getProject().getProjectDir().toPath(), steps); // perform the check if (check) { diff --git a/src/main/java/com/diffplug/gradle/spotless/Formatter.java b/src/main/java/com/diffplug/gradle/spotless/Formatter.java index 322e6c01c5..0616ddc0ca 100644 --- a/src/main/java/com/diffplug/gradle/spotless/Formatter.java +++ b/src/main/java/com/diffplug/gradle/spotless/Formatter.java @@ -29,13 +29,11 @@ /** Formatter which performs the full formatting. */ public class Formatter { - private final LineEnding lineEnding; private final Path projectDirectory; private final List steps; private final Logger logger = Logging.getLogger(Formatter.class); - public Formatter(LineEnding lineEnding, Path projectDirectory, List steps) { - this.lineEnding = lineEnding; + public Formatter(Path projectDirectory, List steps) { this.projectDirectory = projectDirectory; this.steps = new ArrayList<>(steps); } @@ -43,55 +41,35 @@ public Formatter(LineEnding lineEnding, Path projectDirectory, List val == '\n').count(); - int windowsNewLines = raw.length() - unix.length(); - if (lineEnding.isWin()) { - if (windowsNewLines != totalNewLines) { - return false; - } - } else { - if (windowsNewLines != 0) { - return false; - } - } // check the other formats - String formatted = applyAll(unix, file); + String formatted = applyAll(raw, file); - // return true iff the formatted string equals the unix one - return formatted.equals(unix); + // return true iff the formatted string equals raw + return formatted.equals(raw); } /** Applies formatting to the given file. */ public void applyFormat(File file) throws IOException { String raw = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8); - String unix = raw.replaceAll("\r", ""); // enforce the format - unix = applyAll(unix, file); - - // convert the line endings if necessary - if (!lineEnding.string.equals("\n")) { - unix = unix.replace("\n", lineEnding.string); - } + raw = applyAll(raw, file); // write out the file - Files.write(file.toPath(), unix.getBytes(StandardCharsets.UTF_8), StandardOpenOption.TRUNCATE_EXISTING); + Files.write(file.toPath(), raw.getBytes(StandardCharsets.UTF_8), StandardOpenOption.TRUNCATE_EXISTING); } /** Returns the result of calling all of the FormatterSteps. */ - String applyAll(String unix, File file) { + String applyAll(String raw, File file) { for (FormatterStep step : steps) { try { - unix = step.format(unix, file); + raw = step.format(raw, file); } catch (Throwable e) { logger.warn("Unable to apply step " + step.getName() + " to " + projectDirectory.relativize(file.toPath()) + ": " + e.getMessage()); logger.info("Exception is ", e); } } - return unix; + return raw; } } diff --git a/src/main/java/com/diffplug/gradle/spotless/FormatterStep.java b/src/main/java/com/diffplug/gradle/spotless/FormatterStep.java index 56d5a2f39b..30a50d1207 100644 --- a/src/main/java/com/diffplug/gradle/spotless/FormatterStep.java +++ b/src/main/java/com/diffplug/gradle/spotless/FormatterStep.java @@ -25,9 +25,6 @@ /** * An implementation of this class specifies a single step in a formatting process. - * - * The input is guaranteed to have unix-style newlines, and the output is required - * to not introduce any windows-style newlines as well. */ public interface FormatterStep { /** The name of the step, for debugging purposes. */ @@ -36,9 +33,9 @@ public interface FormatterStep { /** * Returns a formatted version of the given content. * - * @param raw File's content, guaranteed to have unix-style newlines ('\n') + * @param raw File's content * @param file the File which is being formatted - * @return The formatted content, guaranteed to only have unix-style newlines + * @return The formatted content * @throws Throwable */ String format(String raw, File file) throws Throwable; diff --git a/src/main/java/com/diffplug/gradle/spotless/IndentStep.java b/src/main/java/com/diffplug/gradle/spotless/IndentStep.java index 228fc95734..97c58685ad 100644 --- a/src/main/java/com/diffplug/gradle/spotless/IndentStep.java +++ b/src/main/java/com/diffplug/gradle/spotless/IndentStep.java @@ -72,6 +72,7 @@ public String format(String raw) { } // find the start of the next line + // this works even for lines ending with \r\n lineStart = raw.indexOf('\n', contentStart); if (lineStart == -1) { // if we're at the end, append all of it diff --git a/src/main/java/com/diffplug/gradle/spotless/LicenseHeaderStep.java b/src/main/java/com/diffplug/gradle/spotless/LicenseHeaderStep.java index 18c1bcd948..42b3a07204 100644 --- a/src/main/java/com/diffplug/gradle/spotless/LicenseHeaderStep.java +++ b/src/main/java/com/diffplug/gradle/spotless/LicenseHeaderStep.java @@ -32,22 +32,20 @@ public class LicenseHeaderStep { private final Pattern delimiterPattern; /** The license that we'd like enforced. */ - public LicenseHeaderStep(String license, String delimiter) { + public LicenseHeaderStep(String license, String delimiter, LineEnding lineEnding) { if (delimiter.contains("\n")) { throw new GradleException("The delimiter must not contain any newlines."); } - // sanitize the input license - license = license.replace("\r", ""); - if (!license.endsWith("\n")) { - license = license + "\n"; - } - this.license = license; - this.delimiterPattern = Pattern.compile('^' + delimiter, Pattern.UNIX_LINES | Pattern.MULTILINE); + FileEndingStep normalizer = new FileEndingStep(lineEnding); + normalizer.disableClobber(); + + this.license = normalizer.format(license); + this.delimiterPattern = Pattern.compile('^' + delimiter, Pattern.MULTILINE); } /** Reads the license file from the given file. */ - public LicenseHeaderStep(File licenseFile, String delimiter) throws IOException { - this(new String(Files.readAllBytes(licenseFile.toPath()), StandardCharsets.UTF_8), delimiter); + public LicenseHeaderStep(File licenseFile, String delimiter, LineEnding lineEnding) throws IOException { + this(new String(Files.readAllBytes(licenseFile.toPath()), StandardCharsets.UTF_8), delimiter, lineEnding); } /** Formats the given string. */ diff --git a/src/main/java/com/diffplug/gradle/spotless/LineEnding.java b/src/main/java/com/diffplug/gradle/spotless/LineEnding.java index 81c92f0af3..1e1b09cb4f 100644 --- a/src/main/java/com/diffplug/gradle/spotless/LineEnding.java +++ b/src/main/java/com/diffplug/gradle/spotless/LineEnding.java @@ -17,15 +17,11 @@ /** The line endings written by the tool. */ public enum LineEnding { - PLATFORM_NATIVE(System.getProperty("line.separator")), WINDOWS("\r\n"), UNIX("\n"); + PLATFORM_NATIVE, WINDOWS, UNIX, DERIVED, UNCERTAIN; - public final String string; + // Must not be set to UNCERTAIN + public static final LineEnding DEFAULT = PLATFORM_NATIVE; - private LineEnding(String ending) { - this.string = ending; - } - - public boolean isWin() { - return string.equals("\r\n"); - } + // Must not be set to DERIVED or UNCERTAIN + public static final LineEnding DERIVED_FALLBACK = PLATFORM_NATIVE; } diff --git a/src/main/java/com/diffplug/gradle/spotless/LineEndingService.java b/src/main/java/com/diffplug/gradle/spotless/LineEndingService.java new file mode 100644 index 0000000000..6b526adf95 --- /dev/null +++ b/src/main/java/com/diffplug/gradle/spotless/LineEndingService.java @@ -0,0 +1,115 @@ +/* + * Copyright 2016 DiffPlug + * + * 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 + * + * http://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 com.diffplug.gradle.spotless; + +import java.util.function.Supplier; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class LineEndingService { + private static final Pattern LAST_NON_WHITESPACE_PATTERN = Pattern.compile("[^\\s]\\s*$"); + + private Supplier lineSeparator = () -> System.lineSeparator(); + + void setLineSeparator(Supplier lineSeparator) { + this.lineSeparator = lineSeparator; + } + + public LineEnding determineLineEnding(String raw) { + return determineLineEnding(raw, LineEnding.UNCERTAIN); + } + + private LineEnding determineLineEnding(String raw, LineEnding fallback) { + int firstCR = raw.indexOf("\r"); + int firstLF = raw.indexOf("\n"); + + if (isWindows(firstCR, firstLF)) { + return LineEnding.WINDOWS; + } + + if (isUnix(firstCR, firstLF)) { + return LineEnding.UNIX; + } + + return fallback; + } + + public String getLineSeparatorOrDefault(LineEnding lineEnding, String rawForDerivedEnding) { + if (lineEnding == LineEnding.DERIVED) { + lineEnding = determineLineEnding(rawForDerivedEnding, LineEnding.DERIVED_FALLBACK); + } + + switch (lineEnding) { + case UNIX: + return "\n"; + case WINDOWS: + return "\r\n"; + case PLATFORM_NATIVE: + return getPlatformLineSeparator(); + default: + throw new IllegalStateException("No line separator available!"); + } + } + + private static boolean isWindows(int firstCR, int firstLF) { + if (firstCR == -1 && firstLF == -1) { + return false; + } + return firstCR + 1 == firstLF; + } + + private static boolean isUnix(int firstCR, int firstLF) { + if (firstLF == -1) { + return false; + } + if (firstCR == -1) { + return true; + } + return firstCR > firstLF; + } + + public LineEnding getPlatformLineEnding() { + String separator = getPlatformLineSeparator(); + + switch (separator) { + case "\r\n": + return LineEnding.WINDOWS; + case "\n": + return LineEnding.UNIX; + default: + throw new InternalError("Shouldn't happen."); + } + } + + String getPlatformLineSeparator() { + String separator = lineSeparator.get(); + + if ("\r\n".equals(separator) || "\n".equals(separator)) { + return separator; + } + + throw new UnsupportedOperationException("Determined native line separator is not supported!"); + } + + public int indexOfLastNonWhitespaceCharacter(String text) { + Matcher matcher = LAST_NON_WHITESPACE_PATTERN.matcher(text); + if (!matcher.find()) { + return -1; + } + return matcher.start(); + } + +} diff --git a/src/main/java/com/diffplug/gradle/spotless/LineEndingStep.java b/src/main/java/com/diffplug/gradle/spotless/LineEndingStep.java new file mode 100644 index 0000000000..f23c8fa1f7 --- /dev/null +++ b/src/main/java/com/diffplug/gradle/spotless/LineEndingStep.java @@ -0,0 +1,128 @@ +/* + * Copyright 2016 DiffPlug + * + * 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 + * + * http://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 com.diffplug.gradle.spotless; + +public class LineEndingStep { + + private final EOLNormalizer normalizer; + + public LineEndingStep(LineEnding lineEnding) { + this(lineEnding, new LineEndingService()); + } + + LineEndingStep(LineEnding lineEnding, LineEndingService lineEndingService) { + normalizer = forLineEnding(lineEnding, lineEndingService); + } + + private static EOLNormalizer forLineEnding(LineEnding lineEnding, LineEndingService lineEndingService) { + switch (lineEnding) { + case UNIX: + return new UnixEOLNormalizer(); + case WINDOWS: + return new WindowsEOLNormalizer(); + case PLATFORM_NATIVE: + return new PlatformNativeEOLNormalizer(lineEndingService); + case DERIVED: + return new DerivedEOLNormalizer(lineEndingService); + case UNCERTAIN: + return new NoEOLNormalizer(); + default: + throw new IllegalArgumentException("No EOLNormalizer specified for LineEnding"); + } + } + + public String format(String raw) { + return normalizer.format(raw); + } + + static interface EOLNormalizer { + String format(String input); + } + + static class UnixEOLNormalizer implements EOLNormalizer { + @Override + public String format(String input) { + return input.replace("\r\n", "\n"); + } + } + + static class WindowsEOLNormalizer implements EOLNormalizer { + @Override + public String format(String input) { + String unix = input.replace("\r\n", "\n"); + return unix.replace("\n", "\r\n"); + } + } + + static class NoEOLNormalizer implements EOLNormalizer { + @Override + public String format(String input) { + return input; + } + } + + static class DerivedEOLNormalizer implements EOLNormalizer { + private EOLNormalizer delegate; + private LineEndingService lineEndingService; + + public DerivedEOLNormalizer(LineEndingService lineEndingService) { + this.lineEndingService = lineEndingService; + } + + @Override + public String format(String input) { + LineEnding lineEnding = lineEndingService.determineLineEnding(input); + switch (lineEnding) { + case UNCERTAIN: + delegate = new NoEOLNormalizer(); + break; + case UNIX: + delegate = new UnixEOLNormalizer(); + break; + case WINDOWS: + delegate = new WindowsEOLNormalizer(); + break; + default: + throw new IllegalStateException("Unexpected result from LineEndingService"); + } + return delegate.format(input); + } + } + + static class PlatformNativeEOLNormalizer implements EOLNormalizer { + private EOLNormalizer delegate; + + public PlatformNativeEOLNormalizer(LineEndingService lineEndingService) { + LineEnding lineEnding = lineEndingService.getPlatformLineEnding(); + switch (lineEnding) { + case UNIX: + delegate = new UnixEOLNormalizer(); + break; + case WINDOWS: + delegate = new WindowsEOLNormalizer(); + break; + default: + throw new IllegalStateException("Unexpected result from LineEndingService"); + } + } + + @Override + public String format(String input) { + return delegate.format(input); + } + } + +} diff --git a/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java b/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java index 2c3466dfce..7160d1c4fc 100644 --- a/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java +++ b/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java @@ -29,12 +29,14 @@ public class SpotlessExtension { final Project project; + Map formats = new LinkedHashMap<>(); + public SpotlessExtension(Project project) { this.project = project; } /** Line endings (if any). */ - LineEnding lineEndings = LineEnding.PLATFORM_NATIVE; + LineEnding lineEndings = LineEnding.DEFAULT; public LineEnding getLineEndings() { return lineEndings; @@ -44,8 +46,6 @@ public void setLineEndings(LineEnding lineEndings) { this.lineEndings = lineEndings; } - Map formats = new LinkedHashMap<>(); - /** Configures the special java-specific extension. */ public void java(Closure closure) { JavaExtension java = new JavaExtension(this); diff --git a/src/main/java/com/diffplug/gradle/spotless/SpotlessPlugin.java b/src/main/java/com/diffplug/gradle/spotless/SpotlessPlugin.java index be9964626d..3b3ac0fbe3 100644 --- a/src/main/java/com/diffplug/gradle/spotless/SpotlessPlugin.java +++ b/src/main/java/com/diffplug/gradle/spotless/SpotlessPlugin.java @@ -67,7 +67,6 @@ void createTasks() throws Exception { FormatTask createTask(String name, FormatExtension subExtension, boolean check) throws Exception { FormatTask task = project.getTasks().create(EXTENSION + capitalize(name) + (check ? CHECK : APPLY), FormatTask.class); - task.lineEndings = extension.lineEndings; task.check = check; // sets toFormat and steps subExtension.setupTask(task); diff --git a/src/main/java/com/diffplug/gradle/spotless/java/EclipseFormatterStep.java b/src/main/java/com/diffplug/gradle/spotless/java/EclipseFormatterStep.java index 32cc9939da..ae6301795a 100644 --- a/src/main/java/com/diffplug/gradle/spotless/java/EclipseFormatterStep.java +++ b/src/main/java/com/diffplug/gradle/spotless/java/EclipseFormatterStep.java @@ -30,6 +30,7 @@ import org.gradle.api.logging.Logging; import com.diffplug.gradle.spotless.LineEnding; +import com.diffplug.gradle.spotless.LineEndingService; import groovy.util.Node; import groovy.util.NodeList; @@ -42,13 +43,17 @@ public class EclipseFormatterStep { private static final Logger logger = Logging.getLogger(EclipseFormatterStep.class); private CodeFormatter codeFormatter; + private LineEnding lineEnding; + private LineEndingService lineEndingService = new LineEndingService(); - private EclipseFormatterStep(Properties settings) { + private EclipseFormatterStep(Properties settings, LineEnding lineEnding) { this.codeFormatter = ToolFactory.createCodeFormatter(settings); + this.lineEnding = lineEnding; } public String format(String raw) throws Exception { - TextEdit edit = codeFormatter.format(CodeFormatter.K_COMPILATION_UNIT, raw, 0, raw.length(), 0, LineEnding.UNIX.string); + String lineSeparator = lineEndingService.getLineSeparatorOrDefault(lineEnding, raw); + TextEdit edit = codeFormatter.format(CodeFormatter.K_COMPILATION_UNIT, raw, 0, raw.length(), 0, lineSeparator); if (edit == null) { throw new IllegalArgumentException("Invalid java syntax for formatting."); } else { @@ -59,7 +64,7 @@ public String format(String raw) throws Exception { } /** Returns an EclipseFormatterStep from the given config file. */ - public static EclipseFormatterStep load(File file) throws Exception { + public static EclipseFormatterStep load(File file, LineEnding lineEnding) throws Exception { Properties settings = new Properties(); if (!file.exists()) { throw new GradleException("Eclipse formatter file '" + file + "' does not exist."); @@ -67,7 +72,7 @@ public static EclipseFormatterStep load(File file) throws Exception { try (InputStream input = new FileInputStream(file)) { settings.load(input); } - return new EclipseFormatterStep(settings); + return new EclipseFormatterStep(settings, lineEnding); } else if (file.getName().endsWith(".xml")) { Node xmlSettings = new XmlParser().parse(file); NodeList profiles = xmlSettings.getAt(new QName("profile")); @@ -84,7 +89,7 @@ public static EclipseFormatterStep load(File file) throws Exception { Node setting = (Node) xmlSettingsElements.get(i); settings.put(setting.attributes().get("id"), setting.attributes().get("value")); } - return new EclipseFormatterStep(settings); + return new EclipseFormatterStep(settings, lineEnding); } else { throw new GradleException("Eclipse formatter file must be .properties or .xml"); } diff --git a/src/main/java/com/diffplug/gradle/spotless/java/ImportSorterImpl.java b/src/main/java/com/diffplug/gradle/spotless/java/ImportSorterImpl.java index be70fe24b4..163c9458a6 100644 --- a/src/main/java/com/diffplug/gradle/spotless/java/ImportSorterImpl.java +++ b/src/main/java/com/diffplug/gradle/spotless/java/ImportSorterImpl.java @@ -21,6 +21,8 @@ /*not thread safe*/ class ImportSorterImpl { + private static final String RS = "\u001E"; + private List template = new ArrayList(); private Map> matchingImports = new HashMap>(); private ArrayList notMatching = new ArrayList(); @@ -131,7 +133,7 @@ private void mergeNotMatchingItems(boolean staticItems) { // no order is specified if (template.size() > 0 && (template.get(template.size() - 1).startsWith("static"))) { // insert N after last static import - template.add(ImportSorterStep.N); + template.add(RS); } template.add(notMatchingItem); } else { @@ -190,23 +192,23 @@ private void mergeMatchingItems() { // replace order item by matching import statements // this is a mess and it is only a luck that it works :-] template.remove(i); - if (i != 0 && !template.get(i - 1).equals(ImportSorterStep.N)) { - template.add(i, ImportSorterStep.N); + if (i != 0 && !template.get(i - 1).equals(RS)) { + template.add(i, RS); i++; } - if (i + 1 < template.size() && !template.get(i + 1).equals(ImportSorterStep.N) - && !template.get(i).equals(ImportSorterStep.N)) { - template.add(i, ImportSorterStep.N); + if (i + 1 < template.size() && !template.get(i + 1).equals(RS) + && !template.get(i).equals(RS)) { + template.add(i, RS); } template.addAll(i, matchingItems); - if (i != 0 && !template.get(i - 1).equals(ImportSorterStep.N)) { - template.add(i, ImportSorterStep.N); + if (i != 0 && !template.get(i - 1).equals(RS)) { + template.add(i, RS); } } } // if there is \n on the end, remove it - if (template.size() > 0 && template.get(template.size() - 1).equals(ImportSorterStep.N)) { + if (template.size() > 0 && template.get(template.size() - 1).equals(RS)) { template.remove(template.size() - 1); } } @@ -215,10 +217,10 @@ private List getResult() { ArrayList strings = new ArrayList(); for (String s : template) { - if (s.equals(ImportSorterStep.N)) { - strings.add(s); + if (s.equals(RS)) { + strings.add(""); } else { - strings.add("import " + s + ";" + ImportSorterStep.N); + strings.add("import " + s + ";"); } } return strings; diff --git a/src/main/java/com/diffplug/gradle/spotless/java/ImportSorterStep.java b/src/main/java/com/diffplug/gradle/spotless/java/ImportSorterStep.java index 0c423a8d73..8d9cc18b3b 100644 --- a/src/main/java/com/diffplug/gradle/spotless/java/ImportSorterStep.java +++ b/src/main/java/com/diffplug/gradle/spotless/java/ImportSorterStep.java @@ -26,6 +26,9 @@ import java.util.TreeMap; import java.util.stream.Collectors; +import com.diffplug.gradle.spotless.LineEnding; +import com.diffplug.gradle.spotless.LineEndingService; + /** * From https://github.com/krasa/EclipseCodeFormatter * @@ -35,15 +38,17 @@ public class ImportSorterStep { public static final String NAME = "ImportSorter"; public static final int START_INDEX_OF_IMPORTS_PACKAGE_DECLARATION = 7; - public static final String N = "\n"; private List importsOrder; + private LineEnding lineEnding; + private LineEndingService lineEndingService = new LineEndingService(); - public ImportSorterStep(List importsOrder) { + public ImportSorterStep(List importsOrder, LineEnding lineEnding) { this.importsOrder = new ArrayList(importsOrder); + this.lineEnding = lineEnding; } - public ImportSorterStep(File importsFile) throws IOException { + public ImportSorterStep(File importsFile, LineEnding lineEnding) throws IOException { Map orderToImport = Files.readAllLines(importsFile.toPath()).stream() // filter out comments .filter(line -> !line.startsWith("#")) @@ -57,10 +62,13 @@ public ImportSorterStep(File importsFile) throws IOException { // collect into map .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); // sort the entries by the key, save the values - importsOrder = new ArrayList<>(new TreeMap<>(orderToImport).values()); + this.importsOrder = new ArrayList<>(new TreeMap<>(orderToImport).values()); + this.lineEnding = lineEnding; } public String format(String raw) { + String lineSeparator = lineEndingService.getLineSeparatorOrDefault(lineEnding, raw); + // parse file Scanner scanner = new Scanner(raw); int firstImportLine = 0; @@ -90,10 +98,10 @@ public String format(String raw) { scanner.close(); List sortedImports = ImportSorterImpl.sort(imports, importsOrder); - return applyImportsToDocument(raw, firstImportLine, lastImportLine, sortedImports); + return applyImportsToDocument(raw, lineSeparator, firstImportLine, lastImportLine, sortedImports); } - private static String applyImportsToDocument(final String document, int firstImportLine, int lastImportLine, + private static String applyImportsToDocument(final String document, String lineSeparator, int firstImportLine, int lastImportLine, List strings) { boolean importsAlreadyAppended = false; Scanner scanner = new Scanner(document); @@ -108,12 +116,12 @@ private static String applyImportsToDocument(final String document, int firstImp if (curentLine >= firstImportLine && curentLine <= lastImportLine) { if (!importsAlreadyAppended) { for (String string : strings) { - sb.append(string); + append(sb, string, lineSeparator); } } importsAlreadyAppended = true; } else { - append(sb, next); + append(sb, next, lineSeparator); } } scanner.close(); @@ -123,9 +131,9 @@ private static String applyImportsToDocument(final String document, int firstImp return sb.toString(); } - private static void append(StringBuilder sb, String next) { + private static void append(StringBuilder sb, String next, String lineSeparator) { sb.append(next); - sb.append(N); + sb.append(lineSeparator); } private static boolean isNotValidImport(int i) { diff --git a/src/main/java/com/diffplug/gradle/spotless/java/JavaExtension.java b/src/main/java/com/diffplug/gradle/spotless/java/JavaExtension.java index b1e59fc8d3..3b49f2e902 100644 --- a/src/main/java/com/diffplug/gradle/spotless/java/JavaExtension.java +++ b/src/main/java/com/diffplug/gradle/spotless/java/JavaExtension.java @@ -45,15 +45,15 @@ public void licenseHeaderFile(Object licenseHeaderFile) { } public void importOrder(List importOrder) { - customLazy(ImportSorterStep.NAME, () -> new ImportSorterStep(importOrder)::format); + customLazy(ImportSorterStep.NAME, () -> new ImportSorterStep(importOrder, getLineEndings())::format); } public void importOrderFile(Object importOrderFile) { - customLazy(ImportSorterStep.NAME, () -> new ImportSorterStep(getProject().file(importOrderFile))::format); + customLazy(ImportSorterStep.NAME, () -> new ImportSorterStep(getProject().file(importOrderFile), getLineEndings())::format); } public void eclipseFormatFile(Object eclipseFormatFile) { - customLazy(EclipseFormatterStep.NAME, () -> EclipseFormatterStep.load(getProject().file(eclipseFormatFile))::format); + customLazy(EclipseFormatterStep.NAME, () -> EclipseFormatterStep.load(getProject().file(eclipseFormatFile), getLineEndings())::format); } /** If the user hasn't specified the files yet, we'll assume he/she means all of the java files. */ @@ -71,7 +71,7 @@ protected void setupTask(FormatTask task) throws Exception { target = union; } // LicenseHeaderStep completely blows apart package-info.java - this common-sense check ensures that - // it skips package-info.java. See https://github.com/diffplug/spotless/issues/1 + // it skips package-info.java. See https://github.com/diffplug/spotless/issues/1 steps.replaceAll(step -> { if (LicenseHeaderStep.NAME.equals(step.getName())) { return step.filterByFile(file -> !file.getName().equals("package-info.java")); diff --git a/src/test/java/com/diffplug/gradle/spotless/EndWithNewlineTest.java b/src/test/java/com/diffplug/gradle/spotless/EndWithNewlineTest.java index 89dcf6a25f..e56cfcdf96 100644 --- a/src/test/java/com/diffplug/gradle/spotless/EndWithNewlineTest.java +++ b/src/test/java/com/diffplug/gradle/spotless/EndWithNewlineTest.java @@ -17,7 +17,7 @@ import org.junit.Test; -public class EndWithNewlineTest extends ResourceTest { +public class EndWithNewlineTest extends FormatExtensionTest { @Test public void trimTrailingNewlines() throws Exception { endWithNewlineTest("", "\n"); @@ -34,6 +34,9 @@ private void endWithNewlineTest(String before) throws Exception { private void endWithNewlineTest(String before, String after) throws Exception { super.assertTask(test -> { + test.root.setLineEndings(LineEnding.UNIX); + test.dontDoDefaultLineEndingNormalization(); + test.endWithNewline(); }, before, after); } diff --git a/src/test/java/com/diffplug/gradle/spotless/FileEndingStepTest.java b/src/test/java/com/diffplug/gradle/spotless/FileEndingStepTest.java new file mode 100644 index 0000000000..c260f51253 --- /dev/null +++ b/src/test/java/com/diffplug/gradle/spotless/FileEndingStepTest.java @@ -0,0 +1,86 @@ +/* + * Copyright 2016 DiffPlug + * + * 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 + * + * http://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 com.diffplug.gradle.spotless; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import org.junit.Test; + +public class FileEndingStepTest { + @Test + public void testFormat_Windows() { + FileEndingStep classUnderTest = new FileEndingStep(LineEnding.WINDOWS); + endWithNewlineTest(classUnderTest, "", "\r\n"); + endWithNewlineTest(classUnderTest, "\n", "\r\n"); + endWithNewlineTest(classUnderTest, "\n\n\t\r\n\n", "\r\n"); + endWithNewlineTest(classUnderTest, "line", "line\r\n"); + endWithNewlineTest(classUnderTest, "line\n", "line\r\n"); + endWithNewlineTest(classUnderTest, "line\nline\n\n\n\n", "line\nline\r\n"); + endWithNewlineTest(classUnderTest, "line\nline\r\n\n\t\n\n", "line\nline\r\n"); + } + + @Test + public void testFormat_Unix() { + FileEndingStep classUnderTest = new FileEndingStep(LineEnding.UNIX); + endWithNewlineTest(classUnderTest, "", "\n"); + endWithNewlineTest(classUnderTest, "\n", "\n"); + endWithNewlineTest(classUnderTest, "\n\n\t\r\n\n", "\n"); + endWithNewlineTest(classUnderTest, "line", "line\n"); + endWithNewlineTest(classUnderTest, "line\n", "line\n"); + endWithNewlineTest(classUnderTest, "line\nline\n\n\n\n", "line\nline\n"); + endWithNewlineTest(classUnderTest, "line\nline\r\n\n\t\n\n", "line\nline\n"); + } + + @Test + public void testFormat_Derived() { + LineEndingService lineEndingService = new LineEndingService(); + lineEndingService.setLineSeparator(() -> "\r\n"); // platform native separator for the fallback + + FileEndingStep classUnderTest = new FileEndingStep(LineEnding.DERIVED, lineEndingService); + endWithNewlineTest(classUnderTest, "", "\r\n"); // Fallback is here in use + endWithNewlineTest(classUnderTest, "\n", "\r\n"); + endWithNewlineTest(classUnderTest, "\n\n\t\r\n\n", "\n"); + endWithNewlineTest(classUnderTest, "line", "line\r\n"); // and here + endWithNewlineTest(classUnderTest, "line\n", "line\n"); + endWithNewlineTest(classUnderTest, "line\nline\n\n\n\n", "line\nline\n"); + endWithNewlineTest(classUnderTest, "line\nline\r\n\n\t\n\n", "line\nline\n"); + } + + @Test + public void testFormat_ClobberDisabled() { + FileEndingStep classUnderTest = new FileEndingStep(LineEnding.UNIX); + classUnderTest.disableClobber(); + + endWithNewlineTest(classUnderTest, "", "\n"); + endWithNewlineTest(classUnderTest, "\n", "\n"); + endWithNewlineTest(classUnderTest, "\n\n\t\r\n\n", "\n\n\t\r\n\n"); + endWithNewlineTest(classUnderTest, "line", "line\n"); + endWithNewlineTest(classUnderTest, "line\n", "line\n"); + endWithNewlineTest(classUnderTest, "line\nline\n\n\n\n", "line\nline\n\n\n\n"); + endWithNewlineTest(classUnderTest, "line\nline\r\n\n\t\n\n", "line\nline\r\n\n\t\n\n"); + + classUnderTest = new FileEndingStep(LineEnding.WINDOWS); + classUnderTest.disableClobber(); + + endWithNewlineTest(classUnderTest, "line\nline\n\n\n\n", "line\nline\n\n\n\n\r\n"); + } + + private void endWithNewlineTest(FileEndingStep step, String before, String expectedAfter) { + String after = step.format(before); + assertThat(after, is(expectedAfter)); + } +} diff --git a/src/test/java/com/diffplug/gradle/spotless/FormatExtensionTest.java b/src/test/java/com/diffplug/gradle/spotless/FormatExtensionTest.java new file mode 100644 index 0000000000..5ff330252d --- /dev/null +++ b/src/test/java/com/diffplug/gradle/spotless/FormatExtensionTest.java @@ -0,0 +1,60 @@ +/* + * Copyright 2016 DiffPlug + * + * 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 + * + * http://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 com.diffplug.gradle.spotless; + +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; + +import org.gradle.api.Project; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.Assert; + +public abstract class FormatExtensionTest extends ResourceTest { + /** Tests that the formatExtension causes the given change. */ + protected void assertTask(Consumer test, String before, String afterExpected) throws Exception { + // create the task + FormatTask task = createTask(test); + // create the test file + File testFile = folder.newFile(); + Files.write(testFile.toPath(), before.getBytes(StandardCharsets.UTF_8)); + // set the task to use this test file + task.target = Collections.singleton(testFile); + // run the task + task.format(); + // check what the task did + String afterActual = new String(Files.readAllBytes(testFile.toPath()), StandardCharsets.UTF_8); + Assert.assertEquals(afterExpected, afterActual); + } + + /** Creates a FormatTask based on the given consumer. */ + private static FormatTask createTask(Consumer test) throws Exception { + Project project = ProjectBuilder.builder().build(); + SpotlessPlugin plugin = project.getPlugins().apply(SpotlessPlugin.class); + + AtomicReference ref = new AtomicReference<>(); + plugin.getExtension().format("underTest", ext -> { + ref.set(ext); + test.accept(ext); + }); + + boolean check = false; + return plugin.createTask("underTest", ref.get(), check); + } +} diff --git a/src/test/java/com/diffplug/gradle/spotless/FormatTaskTest.java b/src/test/java/com/diffplug/gradle/spotless/FormatTaskTest.java index bd6886eef7..d8c9a5eb03 100644 --- a/src/test/java/com/diffplug/gradle/spotless/FormatTaskTest.java +++ b/src/test/java/com/diffplug/gradle/spotless/FormatTaskTest.java @@ -23,6 +23,7 @@ import org.gradle.api.Project; import org.gradle.testfixtures.ProjectBuilder; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; public class FormatTaskTest extends ResourceTest { @@ -35,34 +36,6 @@ public void createTask() { task = (FormatTask) project.getTasks().create("underTest", FormatTask.class); } - @Test(expected = GradleException.class) - public void testLineEndingsCheckFail() throws IOException { - task.check = true; - task.lineEndings = LineEnding.UNIX; - task.target = Collections.singleton(createTestFile("testFile", "\r\n")); - task.execute(); - } - - @Test - public void testLineEndingsCheckPass() throws IOException { - task.check = true; - task.lineEndings = LineEnding.UNIX; - task.target = Collections.singleton(createTestFile("testFile", "\n")); - task.execute(); - } - - @Test - public void testLineEndingsApply() throws IOException { - File testFile = createTestFile("testFile", "\r\n"); - - task.check = false; - task.lineEndings = LineEnding.UNIX; - task.target = Collections.singleton(testFile); - task.execute(); - - assertFileContent("\n", testFile); - } - @Test(expected = GradleException.class) public void testStepCheckFail() throws IOException { File testFile = createTestFile("testFile", "apple"); diff --git a/src/test/java/com/diffplug/gradle/spotless/LicenseHeaderStepTest.java b/src/test/java/com/diffplug/gradle/spotless/LicenseHeaderStepTest.java index 2f3786e024..62f0b4f93e 100644 --- a/src/test/java/com/diffplug/gradle/spotless/LicenseHeaderStepTest.java +++ b/src/test/java/com/diffplug/gradle/spotless/LicenseHeaderStepTest.java @@ -28,19 +28,19 @@ public class LicenseHeaderStepTest extends ResourceTest { @Test public void fromString() throws Throwable { - LicenseHeaderStep step = new LicenseHeaderStep(getTestResource(KEY_LICENSE), JavaExtension.LICENSE_HEADER_DELIMITER); + LicenseHeaderStep step = new LicenseHeaderStep(getTestResource(KEY_LICENSE), JavaExtension.LICENSE_HEADER_DELIMITER, LineEnding.DERIVED); assertStep(step::format, KEY_FILE_NOTAPPLIED, KEY_FILE_APPLIED); } @Test public void fromFile() throws Throwable { - LicenseHeaderStep step = new LicenseHeaderStep(createTestFile(KEY_LICENSE), JavaExtension.LICENSE_HEADER_DELIMITER); + LicenseHeaderStep step = new LicenseHeaderStep(createTestFile(KEY_LICENSE), JavaExtension.LICENSE_HEADER_DELIMITER, LineEnding.DERIVED); assertStep(step::format, KEY_FILE_NOTAPPLIED, KEY_FILE_APPLIED); } @Test public void efficient() throws Throwable { - LicenseHeaderStep step = new LicenseHeaderStep("LicenseHeader\n", "contentstart"); + LicenseHeaderStep step = new LicenseHeaderStep("LicenseHeader\n", "contentstart", LineEnding.UNIX); String alreadyCorrect = "LicenseHeader\ncontentstart"; Assert.assertEquals(alreadyCorrect, step.format(alreadyCorrect)); // If no change is required, it should return the exact same string for efficiency reasons @@ -49,9 +49,9 @@ public void efficient() throws Throwable { @Test public void sanitized() throws Throwable { - // The sanitizer should add a \n - LicenseHeaderStep step = new LicenseHeaderStep("LicenseHeader", "contentstart"); - String alreadyCorrect = "LicenseHeader\ncontentstart"; + // The sanitizer should add the line separator for the LineEnding + LicenseHeaderStep step = new LicenseHeaderStep("LicenseHeader", "contentstart", LineEnding.WINDOWS); + String alreadyCorrect = "LicenseHeader\r\ncontentstart"; Assert.assertEquals(alreadyCorrect, step.format(alreadyCorrect)); Assert.assertTrue(alreadyCorrect == step.format(alreadyCorrect)); } @@ -59,7 +59,7 @@ public void sanitized() throws Throwable { @Test public void sanitizerDoesntGoTooFar() throws Throwable { // if the user wants extra lines after the header, we shouldn't clobber them - LicenseHeaderStep step = new LicenseHeaderStep("LicenseHeader\n\n", "contentstart"); + LicenseHeaderStep step = new LicenseHeaderStep("LicenseHeader\n\n", "contentstart", LineEnding.UNIX); String alreadyCorrect = "LicenseHeader\n\ncontentstart"; Assert.assertEquals(alreadyCorrect, step.format(alreadyCorrect)); Assert.assertTrue(alreadyCorrect == step.format(alreadyCorrect)); diff --git a/src/test/java/com/diffplug/gradle/spotless/LineEndingServiceTest.java b/src/test/java/com/diffplug/gradle/spotless/LineEndingServiceTest.java new file mode 100644 index 0000000000..cf9b845c8e --- /dev/null +++ b/src/test/java/com/diffplug/gradle/spotless/LineEndingServiceTest.java @@ -0,0 +1,118 @@ +/* + * Copyright 2016 DiffPlug + * + * 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 + * + * http://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 com.diffplug.gradle.spotless; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import org.junit.Test; + +public class LineEndingServiceTest { + + private LineEndingService classUnderTest = new LineEndingService(); + + @Test + public void testDetermineLineEnding() { + assertLineEndingDetermination("foobar\r\nhello world\r\n", LineEnding.WINDOWS); + assertLineEndingDetermination("foobar\r\nhello world\n", LineEnding.WINDOWS); + assertLineEndingDetermination("foobar\r\n", LineEnding.WINDOWS); + + assertLineEndingDetermination("foobar\nhello world\n", LineEnding.UNIX); + assertLineEndingDetermination("foobar\nhello world\r\n", LineEnding.UNIX); + assertLineEndingDetermination("foobar\n", LineEnding.UNIX); + + assertLineEndingDetermination("foobar", LineEnding.UNCERTAIN); + + // Don't care about legacy Mac EOL + assertLineEndingDetermination("foobar\r", LineEnding.UNCERTAIN); + } + + private void assertLineEndingDetermination(String raw, LineEnding expectedLineEnding) { + LineEnding lineEnding = classUnderTest.determineLineEnding(raw); + + assertThat(lineEnding, is(expectedLineEnding)); + } + + @Test + public void testGetLineSeparatorOrDefault() { + assertGetLineSeparatorOrDefault(LineEnding.UNIX, "", "\n"); + assertGetLineSeparatorOrDefault(LineEnding.WINDOWS, "", "\r\n"); + + assertGetLineSeparatorOrDefault(LineEnding.DERIVED, "foobar\n", "\n"); + assertGetLineSeparatorOrDefault(LineEnding.DERIVED, "foobar\r\n", "\r\n"); + + classUnderTest.setLineSeparator(() -> "\r\n"); + assertGetLineSeparatorOrDefault(LineEnding.PLATFORM_NATIVE, "", "\r\n"); + assertGetLineSeparatorOrDefault(LineEnding.DERIVED, "foobar", "\r\n"); + + classUnderTest.setLineSeparator(() -> "\n"); + assertGetLineSeparatorOrDefault(LineEnding.PLATFORM_NATIVE, "", "\n"); + assertGetLineSeparatorOrDefault(LineEnding.DERIVED, "foobar", "\n"); + } + + private void assertGetLineSeparatorOrDefault(LineEnding lineEnding, String rawForDerivedEnding, String expectedLineSeparator) { + String lineSeparator = classUnderTest.getLineSeparatorOrDefault(lineEnding, rawForDerivedEnding); + + assertThat(lineSeparator, is(expectedLineSeparator)); + } + + @Test + public void testGetPlatformLineSeparator_Unix() { + classUnderTest.setLineSeparator(() -> "\n"); + + String separator = classUnderTest.getPlatformLineSeparator(); + + assertThat(separator, is("\n")); + } + + @Test + public void testGetPlatformLineSeparator_Windows() { + classUnderTest.setLineSeparator(() -> "\r\n"); + + String separator = classUnderTest.getPlatformLineSeparator(); + + assertThat(separator, is("\r\n")); + } + + @Test(expected = UnsupportedOperationException.class) + public void testGetPlatformLineSeparator_dubious() { + classUnderTest.setLineSeparator(() -> "foo"); + + classUnderTest.getPlatformLineSeparator(); + } + + @Test + public void testIndexOfLastNonWhitespaceCharacter() { + assertIndexOfLastNonWhitespaceCharacter("", -1); + assertIndexOfLastNonWhitespaceCharacter(" ", -1); + assertIndexOfLastNonWhitespaceCharacter(" \n \t\t\n ", -1); + assertIndexOfLastNonWhitespaceCharacter("", -1); + + assertIndexOfLastNonWhitespaceCharacter("foobar", 5); + assertIndexOfLastNonWhitespaceCharacter("foobar ", 5); + assertIndexOfLastNonWhitespaceCharacter("foobar\t\n\n", 5); + + assertIndexOfLastNonWhitespaceCharacter("foo\nbar", 6); + assertIndexOfLastNonWhitespaceCharacter("foo\nbar ", 6); + assertIndexOfLastNonWhitespaceCharacter("foo\nbar\t\n\n", 6); + } + + private void assertIndexOfLastNonWhitespaceCharacter(String text, int expectedIndex) { + int indexOfLastNonWhitespaceCharacter = classUnderTest.indexOfLastNonWhitespaceCharacter(text); + + assertThat(indexOfLastNonWhitespaceCharacter, is(expectedIndex)); + } +} diff --git a/src/test/java/com/diffplug/gradle/spotless/LineEndingStepTest.java b/src/test/java/com/diffplug/gradle/spotless/LineEndingStepTest.java new file mode 100644 index 0000000000..3df4f8af3c --- /dev/null +++ b/src/test/java/com/diffplug/gradle/spotless/LineEndingStepTest.java @@ -0,0 +1,133 @@ +/* + * Copyright 2016 DiffPlug + * + * 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 + * + * http://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 com.diffplug.gradle.spotless; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import org.junit.Test; +import org.mockito.Mockito; + +import com.diffplug.gradle.spotless.LineEndingStep.EOLNormalizer; + +public class LineEndingStepTest extends ResourceTest { + @Test + public void normalizeToUnixFromFile() throws Throwable { + LineEndingStep eol = new LineEndingStep(LineEnding.UNIX); + assertStep(eol::format, "EOLWindows.test", "EOLUnix.test"); + assertStep(eol::format, "EOLMixed.test", "EOLUnix.test"); + assertStep(eol::format, "EOLUnix.test", "EOLUnix.test"); + } + + @Test + public void normalizeToWindowsFromFile() throws Throwable { + LineEndingStep eol = new LineEndingStep(LineEnding.WINDOWS); + assertStep(eol::format, "EOLWindows.test", "EOLWindows.test"); + assertStep(eol::format, "EOLMixed.test", "EOLWindows.test"); + assertStep(eol::format, "EOLUnix.test", "EOLWindows.test"); + } + + @Test + public void normalizeToDerivedEOLFromFile() throws Throwable { + LineEndingStep eol = new LineEndingStep(LineEnding.DERIVED); + assertStep(eol::format, "EOLWindows.test", "EOLWindows.test"); + assertStep(eol::format, "EOLMixed.test", "EOLWindows.test"); // first line contains '\r\n' + assertStep(eol::format, "EOLUnix.test", "EOLUnix.test"); + } + + @Test + public void normalizeToPlatformNativeFromFile_Windows() throws Throwable { + LineEndingService lineEndingServiceMock = Mockito.mock(LineEndingService.class); + Mockito.when(lineEndingServiceMock.getPlatformLineEnding()).thenReturn(LineEnding.WINDOWS); + + LineEndingStep eol = new LineEndingStep(LineEnding.PLATFORM_NATIVE, lineEndingServiceMock); + assertStep(eol::format, "EOLWindows.test", "EOLWindows.test"); + assertStep(eol::format, "EOLMixed.test", "EOLWindows.test"); + assertStep(eol::format, "EOLUnix.test", "EOLWindows.test"); + } + + @Test + public void normalizeToPlatformNativeFromFile_Unix() throws Throwable { + LineEndingService lineEndingServiceMock = Mockito.mock(LineEndingService.class); + Mockito.when(lineEndingServiceMock.getPlatformLineEnding()).thenReturn(LineEnding.UNIX); + + LineEndingStep eol = new LineEndingStep(LineEnding.PLATFORM_NATIVE, lineEndingServiceMock); + assertStep(eol::format, "EOLWindows.test", "EOLUnix.test"); + assertStep(eol::format, "EOLMixed.test", "EOLUnix.test"); + assertStep(eol::format, "EOLUnix.test", "EOLUnix.test"); + } + + @Test(expected = IllegalStateException.class) + public void normalizeToPlatformNativeFromFile_UnexpectedServiceResult() throws Throwable { + LineEndingService lineEndingServiceMock = Mockito.mock(LineEndingService.class); + Mockito.when(lineEndingServiceMock.getPlatformLineEnding()).thenReturn(LineEnding.UNCERTAIN); + + new LineEndingStep(LineEnding.PLATFORM_NATIVE, lineEndingServiceMock); + } + + @Test + public void normalizeToUnix() { + EOLNormalizer normalizer = new LineEndingStep.UnixEOLNormalizer(); + assertEOLnormalization(normalizer, "line 1\r\nline 2 \r\nline 3", "line 1\nline 2 \nline 3"); + assertEOLnormalization(normalizer, "line 1\r\nline 2 \nline 3", "line 1\nline 2 \nline 3"); + assertEOLnormalization(normalizer, "line 1\nline 2 \nline 3", "line 1\nline 2 \nline 3"); + } + + @Test + public void normalizeToWindows() { + EOLNormalizer normalizer = new LineEndingStep.WindowsEOLNormalizer(); + assertEOLnormalization(normalizer, "line 1\r\nline 2 \r\nline 3", "line 1\r\nline 2 \r\nline 3"); + assertEOLnormalization(normalizer, "line 1\r\nline 2 \nline 3", "line 1\r\nline 2 \r\nline 3"); + assertEOLnormalization(normalizer, "line 1\nline 2 \nline 3", "line 1\r\nline 2 \r\nline 3"); + } + + @Test + public void normalizeToDerivedEOL() { + EOLNormalizer normalizer = new LineEndingStep.DerivedEOLNormalizer(new LineEndingService()); + assertEOLnormalization(normalizer, "line 1\r\nline 2 \r\nline 3", "line 1\r\nline 2 \r\nline 3"); + assertEOLnormalization(normalizer, "line 1\r\nline 2 \nline 3", "line 1\r\nline 2 \r\nline 3"); + assertEOLnormalization(normalizer, "line 1\nline 2 \nline 3", "line 1\nline 2 \nline 3"); + } + + @Test + public void normalizeToPlatformNative() { + LineEndingService lineEndingServiceMock = Mockito.mock(LineEndingService.class); + Mockito.when(lineEndingServiceMock.getPlatformLineEnding()).thenReturn(LineEnding.UNIX); + EOLNormalizer normalizer = new LineEndingStep.PlatformNativeEOLNormalizer(lineEndingServiceMock); + assertEOLnormalization(normalizer, "line 1\r\nline 2 \r\nline 3", "line 1\nline 2 \nline 3"); + assertEOLnormalization(normalizer, "line 1\r\nline 2 \nline 3", "line 1\nline 2 \nline 3"); + assertEOLnormalization(normalizer, "line 1\nline 2 \nline 3", "line 1\nline 2 \nline 3"); + + lineEndingServiceMock = Mockito.mock(LineEndingService.class); + Mockito.when(lineEndingServiceMock.getPlatformLineEnding()).thenReturn(LineEnding.WINDOWS); + normalizer = new LineEndingStep.PlatformNativeEOLNormalizer(lineEndingServiceMock); + assertEOLnormalization(normalizer, "line 1\r\nline 2 \r\nline 3", "line 1\r\nline 2 \r\nline 3"); + assertEOLnormalization(normalizer, "line 1\r\nline 2 \nline 3", "line 1\r\nline 2 \r\nline 3"); + assertEOLnormalization(normalizer, "line 1\nline 2 \nline 3", "line 1\r\nline 2 \r\nline 3"); + } + + @Test(expected = IllegalStateException.class) + public void normalizeToPlatformNative_UnexpectedServiceResult() { + LineEndingService lineEndingServiceMock = Mockito.mock(LineEndingService.class); + Mockito.when(lineEndingServiceMock.getPlatformLineEnding()).thenReturn(LineEnding.UNCERTAIN); + new LineEndingStep.PlatformNativeEOLNormalizer(lineEndingServiceMock); + } + + private void assertEOLnormalization(LineEndingStep.EOLNormalizer normalizer, String before, String expectedAfter) { + String after = normalizer.format(before); + assertThat(after, is(expectedAfter)); + } +} diff --git a/src/test/java/com/diffplug/gradle/spotless/LineEndingTest.java b/src/test/java/com/diffplug/gradle/spotless/LineEndingTest.java new file mode 100644 index 0000000000..6689a4a497 --- /dev/null +++ b/src/test/java/com/diffplug/gradle/spotless/LineEndingTest.java @@ -0,0 +1,35 @@ +/* + * Copyright 2016 DiffPlug + * + * 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 + * + * http://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 com.diffplug.gradle.spotless; + +import org.junit.Test; + +public class LineEndingTest extends FormatExtensionTest { + @Test + public void lineEndingNormalizationIsActiveByDefault() throws Exception { + testNormalization(LineEnding.UNIX, "line\r\n", "line\n"); + testNormalization(LineEnding.UNIX, "line\n", "line\n"); + testNormalization(LineEnding.WINDOWS, "line\n", "line\r\n"); + testNormalization(LineEnding.WINDOWS, "line\r\n", "line\r\n"); + testNormalization(LineEnding.DERIVED, "line\r\nfoobar\n", "line\r\nfoobar\r\n"); + } + + private void testNormalization(LineEnding lineEnding, String before, String after) throws Exception { + super.assertTask(test -> { + test.root.setLineEndings(lineEnding); + }, before, after); + } +} diff --git a/src/test/java/com/diffplug/gradle/spotless/ResourceTest.java b/src/test/java/com/diffplug/gradle/spotless/ResourceTest.java index 8295f54880..24ae9e0767 100644 --- a/src/test/java/com/diffplug/gradle/spotless/ResourceTest.java +++ b/src/test/java/com/diffplug/gradle/spotless/ResourceTest.java @@ -33,7 +33,7 @@ import com.diffplug.common.base.Throwing; -public class ResourceTest { +public abstract class ResourceTest { @Rule public TemporaryFolder folder = new TemporaryFolder(); @@ -74,46 +74,12 @@ protected void assertFileContent(String expectedContent, File actual) throws IOE /** Reads the given resource from "before", applies the step, and makes sure the result is "after". */ protected void assertStep(Throwing.Function step, String unformattedPath, String expectedPath) throws Throwable { - String unformatted = getTestResource(unformattedPath).replace("\r", ""); // unix-ified input + String unformatted = getTestResource(unformattedPath); + String expected = getTestResource(expectedPath); + String formatted = step.apply(unformatted); - // no windows newlines - Assert.assertEquals(-1, formatted.indexOf('\r')); - // unix-ify the test resource output in case git screwed it up - String expected = getTestResource(expectedPath).replace("\r", ""); // unix-ified output Assert.assertEquals(expected, formatted); } - /** Creates a FormatTask based on the given consumer. */ - public static FormatTask createTask(Consumer test) throws Exception { - Project project = ProjectBuilder.builder().build(); - SpotlessPlugin plugin = project.getPlugins().apply(SpotlessPlugin.class); - - AtomicReference ref = new AtomicReference<>(); - plugin.getExtension().format("underTest", ext -> { - ref.set(ext); - test.accept(ext); - }); - - boolean check = false; - return plugin.createTask("underTest", ref.get(), check); - } - - /** Tests that the formatExtension causes the given change. */ - protected void assertTask(Consumer test, String before, String afterExpected) throws Exception { - // create the task - FormatTask task = createTask(test); - // force unix line endings, since we're passing in raw strings - task.lineEndings = LineEnding.UNIX; - // create the test file - File testFile = folder.newFile(); - Files.write(testFile.toPath(), before.getBytes(StandardCharsets.UTF_8)); - // set the task to use this test file - task.target = Collections.singleton(testFile); - // run the task - task.format(); - // check what the task did - String afterActual = new String(Files.readAllBytes(testFile.toPath()), StandardCharsets.UTF_8); - Assert.assertEquals(afterExpected, afterActual); - } } diff --git a/src/test/java/com/diffplug/gradle/spotless/TrimTrailingWhitespaceTest.java b/src/test/java/com/diffplug/gradle/spotless/TrimTrailingWhitespaceTest.java index 0458594f47..f2252c7810 100644 --- a/src/test/java/com/diffplug/gradle/spotless/TrimTrailingWhitespaceTest.java +++ b/src/test/java/com/diffplug/gradle/spotless/TrimTrailingWhitespaceTest.java @@ -17,7 +17,7 @@ import org.junit.Test; -public class TrimTrailingWhitespaceTest extends ResourceTest { +public class TrimTrailingWhitespaceTest extends FormatExtensionTest { @Test public void trimTrailingWhitespace() throws Exception { trimTrailingWhitespaceTestCase(""); @@ -41,6 +41,13 @@ public void trimTrailingWhitespace() throws Exception { trimTrailingWhitespaceTestCase("Line \nLine ", "Line\nLine"); trimTrailingWhitespaceTestCase(" Line \nLine ", " Line\nLine"); trimTrailingWhitespaceTestCase(" Line \n Line ", " Line\n Line"); + + trimTrailingWhitespaceTestCase("Line\r\nLine"); + trimTrailingWhitespaceTestCase("Line \r\nLine", "Line\r\nLine"); + trimTrailingWhitespaceTestCase("Line\r\nLine ", "Line\r\nLine"); + trimTrailingWhitespaceTestCase("Line \r\nLine ", "Line\r\nLine"); + trimTrailingWhitespaceTestCase(" Line \r\nLine ", " Line\r\nLine"); + trimTrailingWhitespaceTestCase(" Line \r\n Line ", " Line\r\n Line"); } private void trimTrailingWhitespaceTestCase(String before) throws Exception { @@ -49,6 +56,7 @@ private void trimTrailingWhitespaceTestCase(String before) throws Exception { private void trimTrailingWhitespaceTestCase(String before, String after) throws Exception { super.assertTask(test -> { + test.dontDoDefaultLineEndingNormalization(); test.trimTrailingWhitespace(); }, before, after); } diff --git a/src/test/java/com/diffplug/gradle/spotless/java/EclipseFormatterStepTest.java b/src/test/java/com/diffplug/gradle/spotless/java/EclipseFormatterStepTest.java index a14a19aca9..75c0953e85 100644 --- a/src/test/java/com/diffplug/gradle/spotless/java/EclipseFormatterStepTest.java +++ b/src/test/java/com/diffplug/gradle/spotless/java/EclipseFormatterStepTest.java @@ -20,25 +20,26 @@ import org.gradle.api.GradleException; import org.junit.Test; +import com.diffplug.gradle.spotless.LineEnding; import com.diffplug.gradle.spotless.ResourceTest; public class EclipseFormatterStepTest extends ResourceTest { @Test public void loadPropertiesSettings() throws Throwable { // setting for the formatter - EclipseFormatterStep step = EclipseFormatterStep.load(createTestFile("formatter.properties")); + EclipseFormatterStep step = EclipseFormatterStep.load(createTestFile("formatter.properties"), LineEnding.DERIVED); assertStep(step::format, "JavaCodeUnformatted.test", "JavaCodeFormatted.test"); } @Test public void loadXmlSettings() throws Throwable { // setting for the formatter - EclipseFormatterStep step = EclipseFormatterStep.load(createTestFile("formatter.xml")); + EclipseFormatterStep step = EclipseFormatterStep.load(createTestFile("formatter.xml"), LineEnding.DERIVED); assertStep(step::format, "JavaCodeUnformatted.test", "JavaCodeFormatted.test"); } @Test(expected = GradleException.class) public void loadUnknownSettings() throws Exception { - EclipseFormatterStep.load(new File("formatter.unknown")); + EclipseFormatterStep.load(new File("formatter.unknown"), LineEnding.DERIVED); } } diff --git a/src/test/java/com/diffplug/gradle/spotless/java/ImportSorterStepTest.java b/src/test/java/com/diffplug/gradle/spotless/java/ImportSorterStepTest.java index 94f51b33b0..b8bcd65aa5 100644 --- a/src/test/java/com/diffplug/gradle/spotless/java/ImportSorterStepTest.java +++ b/src/test/java/com/diffplug/gradle/spotless/java/ImportSorterStepTest.java @@ -19,24 +19,25 @@ import org.junit.Test; +import com.diffplug.gradle.spotless.LineEnding; import com.diffplug.gradle.spotless.ResourceTest; public class ImportSorterStepTest extends ResourceTest { @Test public void sortImportsFromArray() throws Throwable { - ImportSorterStep step = new ImportSorterStep(Arrays.asList("java", "javax", "org", "\\#com")); + ImportSorterStep step = new ImportSorterStep(Arrays.asList("java", "javax", "org", "\\#com"), LineEnding.DERIVED); assertStep(step::format, "JavaCodeUnsortedImports.test", "JavaCodeSortedImports.test"); } @Test public void sortImportsFromFile() throws Throwable { - ImportSorterStep step = new ImportSorterStep(createTestFile("import.properties")); + ImportSorterStep step = new ImportSorterStep(createTestFile("import.properties"), LineEnding.DERIVED); assertStep(step::format, "JavaCodeUnsortedImports.test", "JavaCodeSortedImports.test"); } @Test public void sortImportsUnmatched() throws Throwable { - ImportSorterStep step = new ImportSorterStep(createTestFile("import_unmatched.properties")); + ImportSorterStep step = new ImportSorterStep(createTestFile("import_unmatched.properties"), LineEnding.DERIVED); assertStep(step::format, "JavaCodeUnsortedImportsUnmatched.test", "JavaCodeSortedImportsUnmatched.test"); } } diff --git a/src/test/resources/.gitattributes b/src/test/resources/.gitattributes new file mode 100644 index 0000000000..8f3395ec0e --- /dev/null +++ b/src/test/resources/.gitattributes @@ -0,0 +1,3 @@ +EOLMixed.test -text +EOLUnix.test -text +EOLWindows.test -text diff --git a/src/test/resources/EOLMixed.test b/src/test/resources/EOLMixed.test new file mode 100644 index 0000000000..68b8d89e71 --- /dev/null +++ b/src/test/resources/EOLMixed.test @@ -0,0 +1,28 @@ +package com.github.youribonnaffe.gradle.format; + +import java.util.function.Function; + + +public class Java8Test { + public void doStuff() throws Exception { + Function example = Integer::parseInt; + example.andThen(val -> { + return val + 2; + } ); + SimpleEnum val = SimpleEnum.A; + switch (val) { + case A: + break; + case B: + break; + case C: + break; + default: + throw new Exception(); + } + } + + public enum SimpleEnum { + A, B, C; + } +} diff --git a/src/test/resources/EOLUnix.test b/src/test/resources/EOLUnix.test new file mode 100644 index 0000000000..38f9541b2c --- /dev/null +++ b/src/test/resources/EOLUnix.test @@ -0,0 +1,28 @@ +package com.github.youribonnaffe.gradle.format; + +import java.util.function.Function; + + +public class Java8Test { + public void doStuff() throws Exception { + Function example = Integer::parseInt; + example.andThen(val -> { + return val + 2; + } ); + SimpleEnum val = SimpleEnum.A; + switch (val) { + case A: + break; + case B: + break; + case C: + break; + default: + throw new Exception(); + } + } + + public enum SimpleEnum { + A, B, C; + } +} diff --git a/src/test/resources/EOLWindows.test b/src/test/resources/EOLWindows.test new file mode 100644 index 0000000000..acef6e1ea6 --- /dev/null +++ b/src/test/resources/EOLWindows.test @@ -0,0 +1,28 @@ +package com.github.youribonnaffe.gradle.format; + +import java.util.function.Function; + + +public class Java8Test { + public void doStuff() throws Exception { + Function example = Integer::parseInt; + example.andThen(val -> { + return val + 2; + } ); + SimpleEnum val = SimpleEnum.A; + switch (val) { + case A: + break; + case B: + break; + case C: + break; + default: + throw new Exception(); + } + } + + public enum SimpleEnum { + A, B, C; + } +}