Skip to content

System-default line separators are implicitly enforced despite lax configurations #280

Closed as not planned
@ParkerM

Description

@ParkerM

Context: I'm a Windows user that often builds Spring projects from source. My global .gitconfig sets core.autocrlf=input because I want to avoid CRLF line endings by any means necessary. This clashes specifically with spring-javaformat, and makes it a huge pain to build any Spring project.

Example output with spring-projects/spring-boot
$ git config --get core.autocrlf
input

$ ./gradlew build

> Task :spring-boot-project:spring-boot-tools:spring-boot-antlib:integrationTest  
Trying to override old definition of task fail
Trying to override old definition of datatype resources
Trying to override old definition of task buildnumber

> Task :spring-boot-project:spring-boot-tools:spring-boot-maven-plugin:checkFormatMain FAILED

> Task :spring-boot-project:spring-boot:compileJava
Note: Processing Log4j annotations
...

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':spring-boot-project:spring-boot-tools:spring-boot-maven-plugin:checkFormatMain'.
> Formatting violations found in the following files:
   * src\main\java\org\springframework\boot\maven\AbstractDependencyFilterMojo.java
   * src\main\java\org\springframework\boot\maven\AbstractPackagerMojo.java
   * src\main\java\org\springframework\boot\maven\AbstractRunMojo.java
   * src\main\java\org\springframework\boot\maven\ArtifactsLibraries.java
   * src\main\java\org\springframework\boot\maven\BuildImageMojo.java
   * src\main\java\org\springframework\boot\maven\BuildInfoMojo.java
   * src\main\java\org\springframework\boot\maven\CustomLayersProvider.java
...

  Run `format` to fix.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 40s
846 actionable tasks: 552 executed, 287 from cache, 7 up-to-date

A build scan was not published as you have not authenticated with server 'ge.spring.io'.

# let's run format
$ ./gradlew format

BUILD SUCCESSFUL in 10s
224 actionable tasks: 224 executed

A build scan was not published as you have not authenticated with server 'ge.spring.io'.

# it just converts all my line-endings to CRLF
$ git st | wc -l
5986

$ git diff
warning: CRLF will be replaced by LF in spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/OnEndpointElementCondition.java.
The file will have its original line endings in your working directory
warning: CRLF will be replaced by LF in spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/amqp/RabbitHealthContributorAutoConfiguration.java.
...

I first assumed this had something to do with Checkstyle, but I do not believe this is the case, especially since the default NewlineAtEndOfFileCheck was relaxed to accept any trailing newline in 0b36c1c.

Another contributor touched on the crux of the problem here:

Anyways what I have found is, when sources are checked out with LF and formatter runs on Windows reformatted code has line endings that comes from org.eclipse.jdt.internal.compiler.util.Util#LINE_SEPARATOR constant.
I think that this glitch should be documented somehow (maybe here or at spring-cloud docs). What do you think?
Thank you

It seems the discussion fell short once the issue was closed as fixed, but the fix only supports the "Windows user with CRLF line endings" case.

From what I've gathered, whenever a line separator is not explicitly specified, it is passed down as null to the internals of the Eclipse TextEdit stuff that occurs during the validate/format phases, wherein the default line separator null turns into System.lineSeparator() (which does not abide my git config).


My proposal is to attempt to detect and pass along the line endings of each file before it is submitted to the whims of the Eclipse formatter. Essentially:

  • If io.spring.javaformat.formatter.Formatter#format is called with lineSeparator = null
    • Try to naively determine the configured line separator for the given source by checking each line separator.
    • Iff every line separator is the same, then pass it as an arg to this.delegate.format.
    • Otherwise, fallback to the existing behavior of passing a null line separator to this.delegate.format by default.

Here's a clumsy and un-tested whack at the impl I'm describing: ParkerM@92579ca


I'd be happy to create some repros via various CI runners and git configs, but will hold off until it's deemed necessary.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions