249 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			249 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/**
 | 
						|
 * @fileoverview Validates spacing before and after semicolon
 | 
						|
 * @author Mathias Schreck
 | 
						|
 * @deprecated in ESLint v8.53.0
 | 
						|
 */
 | 
						|
 | 
						|
"use strict";
 | 
						|
 | 
						|
const astUtils = require("./utils/ast-utils");
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
// Rule Definition
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
 | 
						|
/** @type {import('../shared/types').Rule} */
 | 
						|
module.exports = {
 | 
						|
    meta: {
 | 
						|
        deprecated: true,
 | 
						|
        replacedBy: [],
 | 
						|
        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
 | 
						|
        };
 | 
						|
    }
 | 
						|
};
 |