Permalink
Cannot retrieve contributors at this time
201 lines (177 sloc)
7.06 KB
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
codeql-action/node_modules/eslint/lib/rules/space-before-blocks.js
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @fileoverview A rule to ensure whitespace before blocks. | |
* @author Mathias Schreck <https://github.com/lo1tuma> | |
*/ | |
"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: { | |
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 | |
}; | |
} | |
}; |