Permalink
Cannot retrieve contributors at this time
245 lines (212 sloc)
8.63 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/semi-spacing.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 Validates spacing before and after semicolon | |
* @author Mathias Schreck | |
*/ | |
"use strict"; | |
const astUtils = require("./utils/ast-utils"); | |
//------------------------------------------------------------------------------ | |
// Rule Definition | |
//------------------------------------------------------------------------------ | |
/** @type {import('../shared/types').Rule} */ | |
module.exports = { | |
meta: { | |
type: "layout", | |
docs: { | |
description: "Enforce consistent spacing before and after semicolons", | |
recommended: false, | |
url: "https://eslint.org/docs/latest/rules/semi-spacing" | |
}, | |
fixable: "whitespace", | |
schema: [ | |
{ | |
type: "object", | |
properties: { | |
before: { | |
type: "boolean", | |
default: false | |
}, | |
after: { | |
type: "boolean", | |
default: true | |
} | |
}, | |
additionalProperties: false | |
} | |
], | |
messages: { | |
unexpectedWhitespaceBefore: "Unexpected whitespace before semicolon.", | |
unexpectedWhitespaceAfter: "Unexpected whitespace after semicolon.", | |
missingWhitespaceBefore: "Missing whitespace before semicolon.", | |
missingWhitespaceAfter: "Missing whitespace after semicolon." | |
} | |
}, | |
create(context) { | |
const config = context.options[0], | |
sourceCode = context.sourceCode; | |
let requireSpaceBefore = false, | |
requireSpaceAfter = true; | |
if (typeof config === "object") { | |
requireSpaceBefore = config.before; | |
requireSpaceAfter = config.after; | |
} | |
/** | |
* Checks if a given token has leading whitespace. | |
* @param {Object} token The token to check. | |
* @returns {boolean} True if the given token has leading space, false if not. | |
*/ | |
function hasLeadingSpace(token) { | |
const tokenBefore = sourceCode.getTokenBefore(token); | |
return tokenBefore && astUtils.isTokenOnSameLine(tokenBefore, token) && sourceCode.isSpaceBetweenTokens(tokenBefore, token); | |
} | |
/** | |
* Checks if a given token has trailing whitespace. | |
* @param {Object} token The token to check. | |
* @returns {boolean} True if the given token has trailing space, false if not. | |
*/ | |
function hasTrailingSpace(token) { | |
const tokenAfter = sourceCode.getTokenAfter(token); | |
return tokenAfter && astUtils.isTokenOnSameLine(token, tokenAfter) && sourceCode.isSpaceBetweenTokens(token, tokenAfter); | |
} | |
/** | |
* Checks if the given token is the last token in its line. | |
* @param {Token} token The token to check. | |
* @returns {boolean} Whether or not the token is the last in its line. | |
*/ | |
function isLastTokenInCurrentLine(token) { | |
const tokenAfter = sourceCode.getTokenAfter(token); | |
return !(tokenAfter && astUtils.isTokenOnSameLine(token, tokenAfter)); | |
} | |
/** | |
* Checks if the given token is the first token in its line | |
* @param {Token} token The token to check. | |
* @returns {boolean} Whether or not the token is the first in its line. | |
*/ | |
function isFirstTokenInCurrentLine(token) { | |
const tokenBefore = sourceCode.getTokenBefore(token); | |
return !(tokenBefore && astUtils.isTokenOnSameLine(token, tokenBefore)); | |
} | |
/** | |
* Checks if the next token of a given token is a closing parenthesis. | |
* @param {Token} token The token to check. | |
* @returns {boolean} Whether or not the next token of a given token is a closing parenthesis. | |
*/ | |
function isBeforeClosingParen(token) { | |
const nextToken = sourceCode.getTokenAfter(token); | |
return (nextToken && astUtils.isClosingBraceToken(nextToken) || astUtils.isClosingParenToken(nextToken)); | |
} | |
/** | |
* Report location example : | |
* | |
* for unexpected space `before` | |
* | |
* var a = 'b' ; | |
* ^^^ | |
* | |
* for unexpected space `after` | |
* | |
* var a = 'b'; c = 10; | |
* ^^ | |
* | |
* Reports if the given token has invalid spacing. | |
* @param {Token} token The semicolon token to check. | |
* @param {ASTNode} node The corresponding node of the token. | |
* @returns {void} | |
*/ | |
function checkSemicolonSpacing(token, node) { | |
if (astUtils.isSemicolonToken(token)) { | |
if (hasLeadingSpace(token)) { | |
if (!requireSpaceBefore) { | |
const tokenBefore = sourceCode.getTokenBefore(token); | |
const loc = { | |
start: tokenBefore.loc.end, | |
end: token.loc.start | |
}; | |
context.report({ | |
node, | |
loc, | |
messageId: "unexpectedWhitespaceBefore", | |
fix(fixer) { | |
return fixer.removeRange([tokenBefore.range[1], token.range[0]]); | |
} | |
}); | |
} | |
} else { | |
if (requireSpaceBefore) { | |
const loc = token.loc; | |
context.report({ | |
node, | |
loc, | |
messageId: "missingWhitespaceBefore", | |
fix(fixer) { | |
return fixer.insertTextBefore(token, " "); | |
} | |
}); | |
} | |
} | |
if (!isFirstTokenInCurrentLine(token) && !isLastTokenInCurrentLine(token) && !isBeforeClosingParen(token)) { | |
if (hasTrailingSpace(token)) { | |
if (!requireSpaceAfter) { | |
const tokenAfter = sourceCode.getTokenAfter(token); | |
const loc = { | |
start: token.loc.end, | |
end: tokenAfter.loc.start | |
}; | |
context.report({ | |
node, | |
loc, | |
messageId: "unexpectedWhitespaceAfter", | |
fix(fixer) { | |
return fixer.removeRange([token.range[1], tokenAfter.range[0]]); | |
} | |
}); | |
} | |
} else { | |
if (requireSpaceAfter) { | |
const loc = token.loc; | |
context.report({ | |
node, | |
loc, | |
messageId: "missingWhitespaceAfter", | |
fix(fixer) { | |
return fixer.insertTextAfter(token, " "); | |
} | |
}); | |
} | |
} | |
} | |
} | |
} | |
/** | |
* Checks the spacing of the semicolon with the assumption that the last token is the semicolon. | |
* @param {ASTNode} node The node to check. | |
* @returns {void} | |
*/ | |
function checkNode(node) { | |
const token = sourceCode.getLastToken(node); | |
checkSemicolonSpacing(token, node); | |
} | |
return { | |
VariableDeclaration: checkNode, | |
ExpressionStatement: checkNode, | |
BreakStatement: checkNode, | |
ContinueStatement: checkNode, | |
DebuggerStatement: checkNode, | |
DoWhileStatement: checkNode, | |
ReturnStatement: checkNode, | |
ThrowStatement: checkNode, | |
ImportDeclaration: checkNode, | |
ExportNamedDeclaration: checkNode, | |
ExportAllDeclaration: checkNode, | |
ExportDefaultDeclaration: checkNode, | |
ForStatement(node) { | |
if (node.init) { | |
checkSemicolonSpacing(sourceCode.getTokenAfter(node.init), node); | |
} | |
if (node.test) { | |
checkSemicolonSpacing(sourceCode.getTokenAfter(node.test), node); | |
} | |
}, | |
PropertyDefinition: checkNode | |
}; | |
} | |
}; |