205 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			205 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | ||
|  * @fileoverview A rule to ensure whitespace before blocks.
 | ||
|  * @author Mathias Schreck <https://github.com/lo1tuma>
 | ||
|  * @deprecated in ESLint v8.53.0
 | ||
|  */
 | ||
| 
 | ||
| "use strict";
 | ||
| 
 | ||
| //------------------------------------------------------------------------------
 | ||
| // Requirements
 | ||
| //------------------------------------------------------------------------------
 | ||
| 
 | ||
| const astUtils = require("./utils/ast-utils");
 | ||
| 
 | ||
| //------------------------------------------------------------------------------
 | ||
| // Helpers
 | ||
| //------------------------------------------------------------------------------
 | ||
| 
 | ||
| /**
 | ||
|  * Checks whether the given node represents the body of a function.
 | ||
|  * @param {ASTNode} node the node to check.
 | ||
|  * @returns {boolean} `true` if the node is function body.
 | ||
|  */
 | ||
| function isFunctionBody(node) {
 | ||
|     const parent = node.parent;
 | ||
| 
 | ||
|     return (
 | ||
|         node.type === "BlockStatement" &&
 | ||
|         astUtils.isFunction(parent) &&
 | ||
|         parent.body === node
 | ||
|     );
 | ||
| }
 | ||
| 
 | ||
| //------------------------------------------------------------------------------
 | ||
| // Rule Definition
 | ||
| //------------------------------------------------------------------------------
 | ||
| 
 | ||
| /** @type {import('../shared/types').Rule} */
 | ||
| module.exports = {
 | ||
|     meta: {
 | ||
|         deprecated: true,
 | ||
|         replacedBy: [],
 | ||
|         type: "layout",
 | ||
| 
 | ||
|         docs: {
 | ||
|             description: "Enforce consistent spacing before blocks",
 | ||
|             recommended: false,
 | ||
|             url: "https://eslint.org/docs/latest/rules/space-before-blocks"
 | ||
|         },
 | ||
| 
 | ||
|         fixable: "whitespace",
 | ||
| 
 | ||
|         schema: [
 | ||
|             {
 | ||
|                 oneOf: [
 | ||
|                     {
 | ||
|                         enum: ["always", "never"]
 | ||
|                     },
 | ||
|                     {
 | ||
|                         type: "object",
 | ||
|                         properties: {
 | ||
|                             keywords: {
 | ||
|                                 enum: ["always", "never", "off"]
 | ||
|                             },
 | ||
|                             functions: {
 | ||
|                                 enum: ["always", "never", "off"]
 | ||
|                             },
 | ||
|                             classes: {
 | ||
|                                 enum: ["always", "never", "off"]
 | ||
|                             }
 | ||
|                         },
 | ||
|                         additionalProperties: false
 | ||
|                     }
 | ||
|                 ]
 | ||
|             }
 | ||
|         ],
 | ||
| 
 | ||
|         messages: {
 | ||
|             unexpectedSpace: "Unexpected space before opening brace.",
 | ||
|             missingSpace: "Missing space before opening brace."
 | ||
|         }
 | ||
|     },
 | ||
| 
 | ||
|     create(context) {
 | ||
|         const config = context.options[0],
 | ||
|             sourceCode = context.sourceCode;
 | ||
|         let alwaysFunctions = true,
 | ||
|             alwaysKeywords = true,
 | ||
|             alwaysClasses = true,
 | ||
|             neverFunctions = false,
 | ||
|             neverKeywords = false,
 | ||
|             neverClasses = false;
 | ||
| 
 | ||
|         if (typeof config === "object") {
 | ||
|             alwaysFunctions = config.functions === "always";
 | ||
|             alwaysKeywords = config.keywords === "always";
 | ||
|             alwaysClasses = config.classes === "always";
 | ||
|             neverFunctions = config.functions === "never";
 | ||
|             neverKeywords = config.keywords === "never";
 | ||
|             neverClasses = config.classes === "never";
 | ||
|         } else if (config === "never") {
 | ||
|             alwaysFunctions = false;
 | ||
|             alwaysKeywords = false;
 | ||
|             alwaysClasses = false;
 | ||
|             neverFunctions = true;
 | ||
|             neverKeywords = true;
 | ||
|             neverClasses = true;
 | ||
|         }
 | ||
| 
 | ||
|         /**
 | ||
|          * Checks whether the spacing before the given block is already controlled by another rule:
 | ||
|          * - `arrow-spacing` checks spaces after `=>`.
 | ||
|          * - `keyword-spacing` checks spaces after keywords in certain contexts.
 | ||
|          * - `switch-colon-spacing` checks spaces after `:` of switch cases.
 | ||
|          * @param {Token} precedingToken first token before the block.
 | ||
|          * @param {ASTNode|Token} node `BlockStatement` node or `{` token of a `SwitchStatement` node.
 | ||
|          * @returns {boolean} `true` if requiring or disallowing spaces before the given block could produce conflicts with other rules.
 | ||
|          */
 | ||
|         function isConflicted(precedingToken, node) {
 | ||
|             return (
 | ||
|                 astUtils.isArrowToken(precedingToken) ||
 | ||
|                 (
 | ||
|                     astUtils.isKeywordToken(precedingToken) &&
 | ||
|                     !isFunctionBody(node)
 | ||
|                 ) ||
 | ||
|                 (
 | ||
|                     astUtils.isColonToken(precedingToken) &&
 | ||
|                     node.parent &&
 | ||
|                     node.parent.type === "SwitchCase" &&
 | ||
|                     precedingToken === astUtils.getSwitchCaseColonToken(node.parent, sourceCode)
 | ||
|                 )
 | ||
|             );
 | ||
|         }
 | ||
| 
 | ||
|         /**
 | ||
|          * Checks the given BlockStatement node has a preceding space if it doesn’t start on a new line.
 | ||
|          * @param {ASTNode|Token} node The AST node of a BlockStatement.
 | ||
|          * @returns {void} undefined.
 | ||
|          */
 | ||
|         function checkPrecedingSpace(node) {
 | ||
|             const precedingToken = sourceCode.getTokenBefore(node);
 | ||
| 
 | ||
|             if (precedingToken && !isConflicted(precedingToken, node) && astUtils.isTokenOnSameLine(precedingToken, node)) {
 | ||
|                 const hasSpace = sourceCode.isSpaceBetweenTokens(precedingToken, node);
 | ||
|                 let requireSpace;
 | ||
|                 let requireNoSpace;
 | ||
| 
 | ||
|                 if (isFunctionBody(node)) {
 | ||
|                     requireSpace = alwaysFunctions;
 | ||
|                     requireNoSpace = neverFunctions;
 | ||
|                 } else if (node.type === "ClassBody") {
 | ||
|                     requireSpace = alwaysClasses;
 | ||
|                     requireNoSpace = neverClasses;
 | ||
|                 } else {
 | ||
|                     requireSpace = alwaysKeywords;
 | ||
|                     requireNoSpace = neverKeywords;
 | ||
|                 }
 | ||
| 
 | ||
|                 if (requireSpace && !hasSpace) {
 | ||
|                     context.report({
 | ||
|                         node,
 | ||
|                         messageId: "missingSpace",
 | ||
|                         fix(fixer) {
 | ||
|                             return fixer.insertTextBefore(node, " ");
 | ||
|                         }
 | ||
|                     });
 | ||
|                 } else if (requireNoSpace && hasSpace) {
 | ||
|                     context.report({
 | ||
|                         node,
 | ||
|                         messageId: "unexpectedSpace",
 | ||
|                         fix(fixer) {
 | ||
|                             return fixer.removeRange([precedingToken.range[1], node.range[0]]);
 | ||
|                         }
 | ||
|                     });
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         /**
 | ||
|          * Checks if the CaseBlock of an given SwitchStatement node has a preceding space.
 | ||
|          * @param {ASTNode} node The node of a SwitchStatement.
 | ||
|          * @returns {void} undefined.
 | ||
|          */
 | ||
|         function checkSpaceBeforeCaseBlock(node) {
 | ||
|             const cases = node.cases;
 | ||
|             let openingBrace;
 | ||
| 
 | ||
|             if (cases.length > 0) {
 | ||
|                 openingBrace = sourceCode.getTokenBefore(cases[0]);
 | ||
|             } else {
 | ||
|                 openingBrace = sourceCode.getLastToken(node, 1);
 | ||
|             }
 | ||
| 
 | ||
|             checkPrecedingSpace(openingBrace);
 | ||
|         }
 | ||
| 
 | ||
|         return {
 | ||
|             BlockStatement: checkPrecedingSpace,
 | ||
|             ClassBody: checkPrecedingSpace,
 | ||
|             SwitchStatement: checkSpaceBeforeCaseBlock
 | ||
|         };
 | ||
| 
 | ||
|     }
 | ||
| };
 |