Skip to content
Permalink
Browse files

Update: Add `always`/`never` option to `eol-last` (fixes #6938) (#6952)

  • Loading branch information...
kdex authored and kaicataldo committed Sep 13, 2016
1 parent 0ca26d9 commit bcfa3e56a7dd20d0c7e8827fde5125f325cb3793
Showing with 132 additions and 25 deletions.
  1. +10 −6 docs/rules/eol-last.md
  2. +49 −17 lib/rules/eol-last.js
  3. +73 −2 tests/lib/rules/eol-last.js
@@ -1,4 +1,4 @@
# Require file to end with single newline (eol-last)
# require or disallow newline at the end of files (eol-last)

(fixable) The `--fix` option on the [command line](../user-guide/command-line-interface#fix) automatically fixes problems reported by this rule.

@@ -8,7 +8,8 @@ as output files to the terminal without interfering with shell prompts.

## Rule Details

This rule requires at least one newline at the end of non-empty files.
This rule enforces at least one newline (or absence thereof) at the end
of non-empty files.

Prior to v0.16.0 this rule also enforced that there was only a single line at
the end of the file. If you still want this behaviour, consider enabling
@@ -32,13 +33,16 @@ Examples of **correct** code for this rule:
function doSmth() {
var foo = 2;
}
}\n
```

## Options

This rule has a string option:

* `"unix"` (default) enforces line feed (LF) as newline
* `"windows"` enforces carriage return line feed (CRLF) as newline
* `"always"` (default) enforces that files end with a newline (LF)
* `"never"` enforces that files do not end with a newline
* `"unix"` (deprecated) is identical to "always"
* `"windows"` (deprecated) is identical to "always", but will use a CRLF character when autofixing

**Deprecated:** The options `"unix"` and `"windows"` are deprecated. If you need to enforce a specific linebreak style, use this rule in conjunction with `linebreak-style`.
@@ -1,62 +1,94 @@
/**
* @fileoverview Require file to end with single newline.
* @fileoverview Require or disallow newline at the end of files
* @author Nodeca Team <https://github.com/nodeca>
*/
"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

const lodash = require("lodash");

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

module.exports = {
meta: {
docs: {
description: "enforce at least one newline at the end of files",
description: "require or disallow newline at the end of files",
category: "Stylistic Issues",
recommended: false
},

fixable: "whitespace",

schema: [
{
enum: ["unix", "windows"]
enum: ["always", "never", "unix", "windows"]
}
]
},

create(context) {

//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------

return {

Program: function checkBadEOF(node) {

const sourceCode = context.getSourceCode(),
src = sourceCode.getText(),
location = {column: 1},
linebreakStyle = context.options[0] || "unix",
linebreak = linebreakStyle === "unix" ? "\n" : "\r\n";
location = {
column: 1,
line: sourceCode.lines.length
},
LF = "\n",
CRLF = "\r" + LF,
endsWithNewline = lodash.endsWith(src, LF);

let mode = context.options[0] || "always",
appendCRLF = false;

if (mode === "unix") {

// `"unix"` should behave exactly as `"always"`
mode = "always";
}
if (mode === "windows") {

if (src[src.length - 1] !== "\n") {
// `"windows"` should behave exactly as `"always"`, but append CRLF in the fixer for backwards compatibility
mode = "always";
appendCRLF = true;
}
if (mode === "always" && !endsWithNewline) {

// file is not newline-terminated
location.line = src.split(/\n/g).length;
// File is not newline-terminated, but should be
context.report({
node,
loc: location,
message: "Newline required at end of file but not found.",
fix(fixer) {
return fixer.insertTextAfterRange([0, src.length], linebreak);
return fixer.insertTextAfterRange([0, src.length], appendCRLF ? CRLF : LF);
}
});
} else if (mode === "never" && endsWithNewline) {

// File is newline-terminated, but shouldn't be
context.report({
node,
loc: location,
message: "Newline not allowed at end of file.",
fix(fixer) {
const finalEOLs = /(?:\r?\n)+$/,
match = finalEOLs.exec(sourceCode.text),
start = match.index,
end = sourceCode.text.length;

return fixer.replaceTextRange([start, end], "");
}
});
}
}

};

}
};
@@ -1,5 +1,5 @@
/**
* @fileoverview Check, that file is ended with newline, and there are no multiple empty lines at the end.
* @fileoverview Tests for eol-last rule.
* @author Nodeca Team <https://github.com/nodeca>
*/
"use strict";
@@ -29,7 +29,26 @@ ruleTester.run("eol-last", rule, {
"\r\n",
"var a = 123;\r\n",
"var a = 123;\r\n\r\n",
"var a = 123;\r\n \r\n"
"var a = 123;\r\n \r\n",

{ code: "var a = 123;", options: ["never"] },
{ code: "var a = 123;\nvar b = 456;", options: ["never"] },
{ code: "var a = 123;\r\nvar b = 456;", options: ["never"] },

// Deprecated: `"unix"` parameter
{ code: "", options: ["unix"] },
{ code: "\n", options: ["unix"] },
{ code: "var a = 123;\n", options: ["unix"] },
{ code: "var a = 123;\n\n", options: ["unix"] },
{ code: "var a = 123;\n \n", options: ["unix"] },

// Deprecated: `"windows"` parameter
{ code: "", options: ["windows"] },
{ code: "\n", options: ["windows"] },
{ code: "\r\n", options: ["windows"] },
{ code: "var a = 123;\r\n", options: ["windows"] },
{ code: "var a = 123;\r\n\r\n", options: ["windows"] },
{ code: "var a = 123;\r\n \r\n", options: ["windows"] }
],

invalid: [
@@ -43,6 +62,58 @@ ruleTester.run("eol-last", rule, {
errors: [{ message: "Newline required at end of file but not found.", type: "Program" }],
output: "var a = 123;\n \n"
},
{
code: "var a = 123;\n",
options: ["never"],
errors: [{ message: "Newline not allowed at end of file.", type: "Program" }],
output: "var a = 123;"
},
{
code: "var a = 123;\r\n",
options: ["never"],
errors: [{ message: "Newline not allowed at end of file.", type: "Program" }],
output: "var a = 123;"
},
{
code: "var a = 123;\r\n\r\n",
options: ["never"],
errors: [{ message: "Newline not allowed at end of file.", type: "Program" }],
output: "var a = 123;"
},
{
code: "var a = 123;\nvar b = 456;\n",
options: ["never"],
errors: [{ message: "Newline not allowed at end of file.", type: "Program" }],
output: "var a = 123;\nvar b = 456;"
},
{
code: "var a = 123;\r\nvar b = 456;\r\n",
options: ["never"],
errors: [{ message: "Newline not allowed at end of file.", type: "Program" }],
output: "var a = 123;\r\nvar b = 456;"
},
{
code: "var a = 123;\n\n",
options: ["never"],
errors: [{ message: "Newline not allowed at end of file.", type: "Program" }],
output: "var a = 123;"
},

// Deprecated: `"unix"` parameter
{
code: "var a = 123;",
options: ["unix"],
errors: [{ message: "Newline required at end of file but not found.", type: "Program" }],
output: "var a = 123;\n"
},
{
code: "var a = 123;\n ",
options: ["unix"],
errors: [{ message: "Newline required at end of file but not found.", type: "Program" }],
output: "var a = 123;\n \n"
},

// Deprecated: `"windows"` parameter
{
code: "var a = 123;",
options: ["windows"],

0 comments on commit bcfa3e5

Please sign in to comment.
You can’t perform that action at this time.