Skip to content

Conversation

holesch
Copy link
Contributor

@holesch holesch commented Jun 25, 2024

With insert_final_newline enabled, only a single final newline should be at the end of file. Add a check to fail, if there are multiple newlines.

This new validation logic doesn't fail with wrong line endings anymore, there's already another validator for that.

Fixes #341

@holesch holesch force-pushed the check-single-newline-at-eof branch 2 times, most recently from ff8d233 to d104b72 Compare June 25, 2024 16:10
With insert_final_newline enabled, only a single final newline should be
at the end of file. Add a check to fail, if there are multiple newlines.

This new validation logic doesn't fail with wrong line endings anymore,
there's already another validator for that.

Fixes editorconfig-checker#341
@holesch holesch force-pushed the check-single-newline-at-eof branch from d104b72 to 0eb9019 Compare June 25, 2024 21:57
Copy link
Member

@theoludwig theoludwig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for submitting this PR! @holesch

This mostly looks good, left a few comments, don't worry too much about CI, we have a problem on main, which make CI fails, we should resolve it ASAP (in a separated PR).


This new validation logic doesn't fail with wrong line endings anymore, there's already another validator for that.

Could you elaborate, on that please? Where is the other validator for this use case?


I would rather this PR focus only on the "multiple newlines" handling, and not editing current error messages or tests, this PR should only add new tests, but not edit existing ones, as the purpose of this PR is to add new errors when there are multiple newlines EOF.

That way, it will be easier to review and understand, why it is implemented the way it is.

Other changes, like improving error messages, or changing behavior in existing tests, should be done in separated PRs.

Comment on lines -22 to +24
{"x", "true", "lf", errors.New("Wrong line endings or no final newline")},
{"x", "true", "cr", errors.New("Wrong line endings or no final newline")},
{"x", "true", "crlf", errors.New("Wrong line endings or no final newline")},
{"x", "true", "lf", errors.New("Final newline expected")},
{"x", "true", "cr", errors.New("Final newline expected")},
{"x", "true", "crlf", errors.New("Final newline expected")},
Copy link
Member

@theoludwig theoludwig Jun 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea to be more explicit in error messages, so it is easier to fix. 👍

(but as said in my review comment, it should be done in a separated PR, as it introduces false error messages for other things, see my other comment)

Comment on lines -26 to +30
{"x\n", "true", "cr", errors.New("Wrong line endings or no final newline")},
{"x\n", "true", "crlf", errors.New("Wrong line endings or no final newline")},
{"x\n", "true", "cr", errors.New("Final newline expected")},
{"x\n", "true", "crlf", errors.New("Final newline expected")},

{"x\r", "true", "lf", errors.New("Wrong line endings or no final newline")},
{"x\r", "true", "crlf", errors.New("Wrong line endings or no final newline")},
{"x\r", "true", "lf", errors.New("Final newline expected")},
{"x\r", "true", "crlf", errors.New("Final newline expected")},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error messages here, if I understand correctly, should be "Wrong line endings".

For example line 26, with "x\n" with cr (\r) mode, it is because the final line ending should be \r and it is instead \n, but there is a final newline, it is just not the right one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I meant in the commit message: There's validators.LineEnding, that catches this error already:

$ printf 'x\r' > test
$ ./bin/ec -format gcc test
test:
        Final newline expected
        Not all lines have the correct end of line character

2 errors found

I found it more logical to not test it twice, but expect \r\n as final newline and \r\n is not here.

@holesch
Copy link
Contributor Author

holesch commented Jun 26, 2024

This new validation logic doesn't fail with wrong line endings anymore, there's already another validator for that.

Could you elaborate, on that please? Where is the other validator for this use case?

As written in the other comment, it's validators.LineEnding. I'll add the example to the commit message.

I would rather this PR focus only on the "multiple newlines" handling, and not editing current error messages or tests, this PR should only add new tests, but not edit existing ones, as the purpose of this PR is to add new errors when there are multiple newlines EOF.

That way, it will be easier to review and understand, why it is implemented the way it is.

Other changes, like improving error messages, or changing behavior in existing tests, should be done in separated PRs.

I found it easier to add this feature after removing the wrong line endings detection. What would you say if I split this in two commits? Do you agree with the line ending change or should I remove it completely?

@theoludwig
Copy link
Member

I found it easier to add this feature after removing the wrong line endings detection. What would you say if I split this in two commits? Do you agree with the line ending change or should I remove it completely?

It's fine like that, thanks for explaining, I didn't know, there was validators.LineEnding.

Looks good to me! 😄

@mstruebing
Copy link
Member

@holesch I did not check the PR but you should rebase so that CI passes. :)

Copy link

codecov bot commented Jul 2, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 85.50%. Comparing base (d6c17be) to head (476e14f).
Report is 22 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #350      +/-   ##
==========================================
+ Coverage   84.89%   85.50%   +0.61%     
==========================================
  Files           8        8              
  Lines         695      545     -150     
==========================================
- Hits          590      466     -124     
+ Misses         81       55      -26     
  Partials       24       24              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@theoludwig theoludwig merged commit 64b76e7 into editorconfig-checker:main Jul 2, 2024
@theoludwig theoludwig mentioned this pull request Jul 2, 2024
@andreineculau
Copy link

Presumably this is "just a fix" and aligning with editorconfig's specs, but in fact this is a breaking change for editorconfig-checker happening from 3.0.1 to 3.0.2 based on a clarification comment from March 1st 2023.

Please consider reverting this and queue this for the next major release.

@cfbao
Copy link

cfbao commented Jul 2, 2024

Agreed that this is a breaking change and should've been a major release.

@cfbao
Copy link

cfbao commented Jul 2, 2024

With insert_final_newline enabled, only a single final newline should be at the end of file.

The premise of this change seems flawed to me.

From https://editorconfig.org/:

insert_final_newline: set to true to ensure file ends with a newline when saving and false to ensure it doesn't.

From these discussions in the editorconfig repo:
editorconfig/editorconfig#475
editorconfig/editorconfig#111

Nothing suggests that insert_final_newline "should" enforce only a single final newline.
If anything, the language "'insert' final newline" suggests that it should only be concerned with adding a final newline when one isn't present, not to remove any.

@theoludwig
Copy link
Member

theoludwig commented Jul 2, 2024

@andreineculau @cfbao Determining which changes are breaking, is a difficult task and includes subjectivity. Because "Every change breaks someone's workflow", https://xkcd.com/1172/

Another famous linting tool, for example in the JavaScript ecosystem, ESLint, considers bug fixes that results in reporting more linting errors, is not considered breaking but a minor version, while they don't consider it a "simple" patch version, it's not considered major. (https://github.com/eslint/eslint?tab=readme-ov-file#semantic-versioning-policy)

Now we might need to do the same as ESLint, add documentation about how we handle semantic versioning for editorconfig-checker.

I'm not saying, we should not consider that kind of changes breaking, but that's another issue in itself that can probably be discussed separately.

Please consider reverting this and queue this for the next major release.

Is that worth it, to release v3.0.3, which revert these changes, and directly after, release v4.0.0? Don't think so, as if these changes are considered "right"/correct, it's probably easier for users to have editorconfig-checker updated to the latest version, and without false positives.


Coming back to the real "issue"/bug fix, another famous implementation of editorconfig, e.g: https://github.com/editorconfig/editorconfig-vscode, removes extra end of lines, when insert_final_newline = true is set.

IMO that's the expected behavior, I might miss something, but what are the use cases to include multiple end of lines at the end of a file, one is enough?
If you want multiple and do not want editorconfig-checker to report errors, you can set insert_final_newline = unset.

@cfbao
Copy link

cfbao commented Jul 2, 2024

I can appreciate the nuance and difficulty in versioning. Have experienced multiple times myself.
I'd consider it fair break if it's indeed a bug fix, but I disagree with this premise.

Coming back to the real "issue"/bug fix, another famous implementation of editorconfig, e.g: https://github.com/editorconfig/editorconfig-vscode, removes extra end of lines, when insert_final_newline = true is set.

This isn't true in my experience.
I have used https://github.com/editorconfig/editorconfig-vscode for a long time and it never does that. Maybe you have another formatter that's removing multiple blank lines?
Maybe try using it on a plaintext file and see what happens?

I do want a final new line in all files. I also do not want EC checker to remove multiple new lines. So unset isn't viable.

One example where having two empty lines at the end helps is in a markdown template like this:

### section


People using the template should fill it out like

### section

this is my content

not

### section
this is my content

Not having two line endings can easily lead to the second less desirable outcome.
I know it's niche and nitpicky, but it is a valid use case for multiple new lines at the end.
Plus, it doesn't violate insert_final_newline=true according the spec's definition.

@andreineculau
Copy link

+1 for the subjectivity of semver compat. The highlight in "Please consider" is on please 🤝

I do want a final new line in all files. I also do not want EC checker to remove multiple new lines. So unset isn't viable.

Also in the same camp. "unset" is no go

Don't think it's useful to talk concrete examples but fwiw our case is sqlfmt which "fixes" some files by introducing an empty trailing line.

It's worth the comparison with the vscode extension: the difference is in plugin vs standalone. In vscode the editorconfig extension will format the file (so maybe it removes the trailing empty lines) but the sqlfmt extension has precedence and wins (adds the empty line).

So while it's great to try to align, aligning for the sake of aligning would only work if the premise is the same. It isn't.

PS: I haven't checked vscode behavior but I incline to agree with @cfbao as the extension's source code doesn't mention any line removal https://github.com/editorconfig/editorconfig-vscode/blob/main/src/transformations/InsertFinalNewline.ts . Maybe we're seeing a side-effect of the built-in file.trimTrailingWhitespace setting set to true?!

PPS: I also read the other editorconfig threads and I agree with @cfbao - the premise seems false. insert_new_line should make sure there is a (i.e. at least one) new line. Otherwise we agree we increase cognitive load by needing to read the fine print as "insert" is not anymore the English "insert"

@holesch
Copy link
Contributor Author

holesch commented Jul 2, 2024

Hi, sorry for breaking things, didn't think this would be so controversial, but the relevant xkcd was already linked :).

So IMO the vast majority of files would benefit from this fix/change. There are always edge-cases, where this is unwanted, but couldn't you exclude only those special files with a narrow match? For example:

[*]
insert_final_newline = true

[docs/templates/*.md]
insert_final_newline = unset

Regarding major bump or not, I just saw the "bug" label in #341 and assumed "fix" would be appropriate.

@cfbao
Copy link

cfbao commented Jul 2, 2024

IMO the vast majority of files would benefit from this fix/change

IMO the vast majority of files gain nothing from this change.
Some edge cases would benefit, some edge cases would be worse, a non-negligible minority would see confusing breaking changes, and have to be investigated and "fixed" one way or another (e.g. pinning EC-checker version and not updating).

I'm seeing multiple unrelated repos across multiple teams in our org encountering this problem right now.

but couldn't you exclude only those special files with a narrow match?

No. That'd mean we're allowing files without an trailing newline in the matched file pattern, which is false.

@theoludwig
Copy link
Member

@cfbao

This isn't true in my experience.
I have used editorconfig/editorconfig-vscode for a long time and it never does that. Maybe you have another formatter that's removing multiple blank lines?
Maybe try using it on a plaintext file and see what happens?

@andreineculau

I haven't checked vscode behavior but I incline to agree with @cfbao as the extension's source code doesn't mention any line removal editorconfig/editorconfig-vscode@main/src/transformations/InsertFinalNewline.ts . Maybe we're seeing a side-effect of the built-in file.trimTrailingWhitespace setting set to true?!

My bad, you are right, I always thought it was the editorconfig-vscode extension that removed the extra lines, because it was done nearly on all the files, but it was because of other tooling/formatters.
Some examples includes: Prettier, shfmt (which can also format .gitignore files, which I thought I haven't configured a formatter for this kind of file, and it still removed extra lines, that's why, I really believed it was editorconfig-vscode), clang-format, autopep8, and probably many more.

Basically nearly all the files, I'm used to edit inside VSCode, are formatted on save, and remove the extra lines.
But for .txt files, I don't have a formatter, I tested, and you are right, the extra lines are kept.


While searching on the editorconfig repo, I found this issue: editorconfig/editorconfig#269
It is a feature request to add a new option, to remove extra lines.

While, to me, it still doesn't make sense to have files with multiple final new lines (and as demonstrated above, many famous formatters/tools already remove those extra lines), and would like to keep the current behavior as of v3.0.2, the best option, would be to wait until it is officially an option in editorconfig to remove extra lines.

Meanwhile, I think, we can revert this PR, as editorconfig-checker should follow the editorconfig spec, not creating "new rules".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

insert_final_newline should ensure a single newline character at the end of the file
5 participants