]> git.proxmox.com Git - pve-eslint.git/blame - eslint/lib/rules/eol-last.js
import 8.23.1 source
[pve-eslint.git] / eslint / lib / rules / eol-last.js
CommitLineData
eb39fafa
DC
1/**
2 * @fileoverview Require or disallow newline at the end of files
3 * @author Nodeca Team <https://github.com/nodeca>
4 */
5"use strict";
6
eb39fafa
DC
7//------------------------------------------------------------------------------
8// Rule Definition
9//------------------------------------------------------------------------------
10
34eeec05 11/** @type {import('../shared/types').Rule} */
eb39fafa
DC
12module.exports = {
13 meta: {
14 type: "layout",
15
16 docs: {
8f9d1d4d 17 description: "Require or disallow newline at the end of files",
eb39fafa
DC
18 recommended: false,
19 url: "https://eslint.org/docs/rules/eol-last"
20 },
21
22 fixable: "whitespace",
23
24 schema: [
25 {
26 enum: ["always", "never", "unix", "windows"]
27 }
28 ],
29
30 messages: {
31 missing: "Newline required at end of file but not found.",
32 unexpected: "Newline not allowed at end of file."
33 }
34 },
35 create(context) {
36
37 //--------------------------------------------------------------------------
38 // Public
39 //--------------------------------------------------------------------------
40
41 return {
42 Program: function checkBadEOF(node) {
43 const sourceCode = context.getSourceCode(),
44 src = sourceCode.getText(),
5422a9cc 45 lastLine = sourceCode.lines[sourceCode.lines.length - 1],
eb39fafa 46 location = {
5422a9cc 47 column: lastLine.length,
eb39fafa
DC
48 line: sourceCode.lines.length
49 },
50 LF = "\n",
51 CRLF = `\r${LF}`,
5422a9cc 52 endsWithNewline = src.endsWith(LF);
eb39fafa
DC
53
54 /*
55 * Empty source is always valid: No content in file so we don't
56 * need to lint for a newline on the last line of content.
57 */
58 if (!src.length) {
59 return;
60 }
61
62 let mode = context.options[0] || "always",
63 appendCRLF = false;
64
65 if (mode === "unix") {
66
67 // `"unix"` should behave exactly as `"always"`
68 mode = "always";
69 }
70 if (mode === "windows") {
71
72 // `"windows"` should behave exactly as `"always"`, but append CRLF in the fixer for backwards compatibility
73 mode = "always";
74 appendCRLF = true;
75 }
76 if (mode === "always" && !endsWithNewline) {
77
78 // File is not newline-terminated, but should be
79 context.report({
80 node,
81 loc: location,
82 messageId: "missing",
83 fix(fixer) {
84 return fixer.insertTextAfterRange([0, src.length], appendCRLF ? CRLF : LF);
85 }
86 });
87 } else if (mode === "never" && endsWithNewline) {
88
609c276f
TL
89 const secondLastLine = sourceCode.lines[sourceCode.lines.length - 2];
90
eb39fafa
DC
91 // File is newline-terminated, but shouldn't be
92 context.report({
93 node,
609c276f
TL
94 loc: {
95 start: { line: sourceCode.lines.length - 1, column: secondLastLine.length },
96 end: { line: sourceCode.lines.length, column: 0 }
97 },
eb39fafa
DC
98 messageId: "unexpected",
99 fix(fixer) {
100 const finalEOLs = /(?:\r?\n)+$/u,
101 match = finalEOLs.exec(sourceCode.text),
102 start = match.index,
103 end = sourceCode.text.length;
104
105 return fixer.replaceTextRange([start, end], "");
106 }
107 });
108 }
109 }
110 };
111 }
112};