source: imaps-frontend/node_modules/eslint/lib/rules/object-curly-newline.js@ d565449

main
Last change on this file since d565449 was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 11.5 KB
Line 
1/**
2 * @fileoverview Rule to require or disallow line breaks inside braces.
3 * @author Toru Nagashima
4 * @deprecated in ESLint v8.53.0
5 */
6
7"use strict";
8
9//------------------------------------------------------------------------------
10// Requirements
11//------------------------------------------------------------------------------
12
13const astUtils = require("./utils/ast-utils");
14
15//------------------------------------------------------------------------------
16// Helpers
17//------------------------------------------------------------------------------
18
19// Schema objects.
20const OPTION_VALUE = {
21 oneOf: [
22 {
23 enum: ["always", "never"]
24 },
25 {
26 type: "object",
27 properties: {
28 multiline: {
29 type: "boolean"
30 },
31 minProperties: {
32 type: "integer",
33 minimum: 0
34 },
35 consistent: {
36 type: "boolean"
37 }
38 },
39 additionalProperties: false,
40 minProperties: 1
41 }
42 ]
43};
44
45/**
46 * Normalizes a given option value.
47 * @param {string|Object|undefined} value An option value to parse.
48 * @returns {{multiline: boolean, minProperties: number, consistent: boolean}} Normalized option object.
49 */
50function normalizeOptionValue(value) {
51 let multiline = false;
52 let minProperties = Number.POSITIVE_INFINITY;
53 let consistent = false;
54
55 if (value) {
56 if (value === "always") {
57 minProperties = 0;
58 } else if (value === "never") {
59 minProperties = Number.POSITIVE_INFINITY;
60 } else {
61 multiline = Boolean(value.multiline);
62 minProperties = value.minProperties || Number.POSITIVE_INFINITY;
63 consistent = Boolean(value.consistent);
64 }
65 } else {
66 consistent = true;
67 }
68
69 return { multiline, minProperties, consistent };
70}
71
72/**
73 * Checks if a value is an object.
74 * @param {any} value The value to check
75 * @returns {boolean} `true` if the value is an object, otherwise `false`
76 */
77function isObject(value) {
78 return typeof value === "object" && value !== null;
79}
80
81/**
82 * Checks if an option is a node-specific option
83 * @param {any} option The option to check
84 * @returns {boolean} `true` if the option is node-specific, otherwise `false`
85 */
86function isNodeSpecificOption(option) {
87 return isObject(option) || typeof option === "string";
88}
89
90/**
91 * Normalizes a given option value.
92 * @param {string|Object|undefined} options An option value to parse.
93 * @returns {{
94 * ObjectExpression: {multiline: boolean, minProperties: number, consistent: boolean},
95 * ObjectPattern: {multiline: boolean, minProperties: number, consistent: boolean},
96 * ImportDeclaration: {multiline: boolean, minProperties: number, consistent: boolean},
97 * ExportNamedDeclaration : {multiline: boolean, minProperties: number, consistent: boolean}
98 * }} Normalized option object.
99 */
100function normalizeOptions(options) {
101 if (isObject(options) && Object.values(options).some(isNodeSpecificOption)) {
102 return {
103 ObjectExpression: normalizeOptionValue(options.ObjectExpression),
104 ObjectPattern: normalizeOptionValue(options.ObjectPattern),
105 ImportDeclaration: normalizeOptionValue(options.ImportDeclaration),
106 ExportNamedDeclaration: normalizeOptionValue(options.ExportDeclaration)
107 };
108 }
109
110 const value = normalizeOptionValue(options);
111
112 return { ObjectExpression: value, ObjectPattern: value, ImportDeclaration: value, ExportNamedDeclaration: value };
113}
114
115/**
116 * Determines if ObjectExpression, ObjectPattern, ImportDeclaration or ExportNamedDeclaration
117 * node needs to be checked for missing line breaks
118 * @param {ASTNode} node Node under inspection
119 * @param {Object} options option specific to node type
120 * @param {Token} first First object property
121 * @param {Token} last Last object property
122 * @returns {boolean} `true` if node needs to be checked for missing line breaks
123 */
124function areLineBreaksRequired(node, options, first, last) {
125 let objectProperties;
126
127 if (node.type === "ObjectExpression" || node.type === "ObjectPattern") {
128 objectProperties = node.properties;
129 } else {
130
131 // is ImportDeclaration or ExportNamedDeclaration
132 objectProperties = node.specifiers
133 .filter(s => s.type === "ImportSpecifier" || s.type === "ExportSpecifier");
134 }
135
136 return objectProperties.length >= options.minProperties ||
137 (
138 options.multiline &&
139 objectProperties.length > 0 &&
140 first.loc.start.line !== last.loc.end.line
141 );
142}
143
144//------------------------------------------------------------------------------
145// Rule Definition
146//------------------------------------------------------------------------------
147
148/** @type {import('../shared/types').Rule} */
149module.exports = {
150 meta: {
151 deprecated: true,
152 replacedBy: [],
153 type: "layout",
154
155 docs: {
156 description: "Enforce consistent line breaks after opening and before closing braces",
157 recommended: false,
158 url: "https://eslint.org/docs/latest/rules/object-curly-newline"
159 },
160
161 fixable: "whitespace",
162
163 schema: [
164 {
165 oneOf: [
166 OPTION_VALUE,
167 {
168 type: "object",
169 properties: {
170 ObjectExpression: OPTION_VALUE,
171 ObjectPattern: OPTION_VALUE,
172 ImportDeclaration: OPTION_VALUE,
173 ExportDeclaration: OPTION_VALUE
174 },
175 additionalProperties: false,
176 minProperties: 1
177 }
178 ]
179 }
180 ],
181
182 messages: {
183 unexpectedLinebreakBeforeClosingBrace: "Unexpected line break before this closing brace.",
184 unexpectedLinebreakAfterOpeningBrace: "Unexpected line break after this opening brace.",
185 expectedLinebreakBeforeClosingBrace: "Expected a line break before this closing brace.",
186 expectedLinebreakAfterOpeningBrace: "Expected a line break after this opening brace."
187 }
188 },
189
190 create(context) {
191 const sourceCode = context.sourceCode;
192 const normalizedOptions = normalizeOptions(context.options[0]);
193
194 /**
195 * Reports a given node if it violated this rule.
196 * @param {ASTNode} node A node to check. This is an ObjectExpression, ObjectPattern, ImportDeclaration or ExportNamedDeclaration node.
197 * @returns {void}
198 */
199 function check(node) {
200 const options = normalizedOptions[node.type];
201
202 if (
203 (node.type === "ImportDeclaration" &&
204 !node.specifiers.some(specifier => specifier.type === "ImportSpecifier")) ||
205 (node.type === "ExportNamedDeclaration" &&
206 !node.specifiers.some(specifier => specifier.type === "ExportSpecifier"))
207 ) {
208 return;
209 }
210
211 const openBrace = sourceCode.getFirstToken(node, token => token.value === "{");
212
213 let closeBrace;
214
215 if (node.typeAnnotation) {
216 closeBrace = sourceCode.getTokenBefore(node.typeAnnotation);
217 } else {
218 closeBrace = sourceCode.getLastToken(node, token => token.value === "}");
219 }
220
221 let first = sourceCode.getTokenAfter(openBrace, { includeComments: true });
222 let last = sourceCode.getTokenBefore(closeBrace, { includeComments: true });
223
224 const needsLineBreaks = areLineBreaksRequired(node, options, first, last);
225
226 const hasCommentsFirstToken = astUtils.isCommentToken(first);
227 const hasCommentsLastToken = astUtils.isCommentToken(last);
228
229 /*
230 * Use tokens or comments to check multiline or not.
231 * But use only tokens to check whether line breaks are needed.
232 * This allows:
233 * var obj = { // eslint-disable-line foo
234 * a: 1
235 * }
236 */
237 first = sourceCode.getTokenAfter(openBrace);
238 last = sourceCode.getTokenBefore(closeBrace);
239
240 if (needsLineBreaks) {
241 if (astUtils.isTokenOnSameLine(openBrace, first)) {
242 context.report({
243 messageId: "expectedLinebreakAfterOpeningBrace",
244 node,
245 loc: openBrace.loc,
246 fix(fixer) {
247 if (hasCommentsFirstToken) {
248 return null;
249 }
250
251 return fixer.insertTextAfter(openBrace, "\n");
252 }
253 });
254 }
255 if (astUtils.isTokenOnSameLine(last, closeBrace)) {
256 context.report({
257 messageId: "expectedLinebreakBeforeClosingBrace",
258 node,
259 loc: closeBrace.loc,
260 fix(fixer) {
261 if (hasCommentsLastToken) {
262 return null;
263 }
264
265 return fixer.insertTextBefore(closeBrace, "\n");
266 }
267 });
268 }
269 } else {
270 const consistent = options.consistent;
271 const hasLineBreakBetweenOpenBraceAndFirst = !astUtils.isTokenOnSameLine(openBrace, first);
272 const hasLineBreakBetweenCloseBraceAndLast = !astUtils.isTokenOnSameLine(last, closeBrace);
273
274 if (
275 (!consistent && hasLineBreakBetweenOpenBraceAndFirst) ||
276 (consistent && hasLineBreakBetweenOpenBraceAndFirst && !hasLineBreakBetweenCloseBraceAndLast)
277 ) {
278 context.report({
279 messageId: "unexpectedLinebreakAfterOpeningBrace",
280 node,
281 loc: openBrace.loc,
282 fix(fixer) {
283 if (hasCommentsFirstToken) {
284 return null;
285 }
286
287 return fixer.removeRange([
288 openBrace.range[1],
289 first.range[0]
290 ]);
291 }
292 });
293 }
294 if (
295 (!consistent && hasLineBreakBetweenCloseBraceAndLast) ||
296 (consistent && !hasLineBreakBetweenOpenBraceAndFirst && hasLineBreakBetweenCloseBraceAndLast)
297 ) {
298 context.report({
299 messageId: "unexpectedLinebreakBeforeClosingBrace",
300 node,
301 loc: closeBrace.loc,
302 fix(fixer) {
303 if (hasCommentsLastToken) {
304 return null;
305 }
306
307 return fixer.removeRange([
308 last.range[1],
309 closeBrace.range[0]
310 ]);
311 }
312 });
313 }
314 }
315 }
316
317 return {
318 ObjectExpression: check,
319 ObjectPattern: check,
320 ImportDeclaration: check,
321 ExportNamedDeclaration: check
322 };
323 }
324};
Note: See TracBrowser for help on using the repository browser.