Search code examples
eslinteslintrctypescript-eslint

eslint enforce space after the single-line-if parentheses


I'm quite new to ESLint and I couldn't find a rule that does what I want. Consider the following code:

if(someCondition)i++;

I want to enforce a single space after the parentheses, so that we should have the following instead:

if(someCondition) i++;

However I simply couldn't find such a rule; it's not space-before-function-paren (obviously), keyword-spacing (which only affects the spacing after if) or space-before-blocks (since this is a single-line-if, there's no block). Please help. Thanks!

P.S. Same rule should apply to single-line-while as well.


Solution

  • As ESLint doesn't have such a rule and the policy says that they will no longer consider such proposals, I ended up writing my own rules as follows:

    module.exports = {
        "single-line-control-statement-spacing": {
            meta: {
                type: "layout",
                docs: {
                    description: "Enforces consistent spacing in single-line control statements.",
                },
                fixable: "whitespace",
            },
            create(context) {
                const sourceCode = context.getSourceCode();
    
                function checkSpaceAfter(node) {
                    if(!node) return;
                    if(node.loc.start.line !== node.loc.end.line) return; // Not single-line
                    const body = node.consequent || node.body;
                    const token = sourceCode.getFirstToken(body);
                    const prev = sourceCode.getTokenBefore(token);
                    const start = prev.range[1];
                    const end = token.range[0];
                    if(start === end) {
                        context.report({
                            loc: {
                                start: sourceCode.getLocFromIndex(start),
                                end: sourceCode.getLocFromIndex(end),
                            },
                            message: "There should be a single space after control statements.",
                            fix(fixer) {
                                return fixer.replaceTextRange([start, end], " ");
                            },
                        });
                    }
                }
    
                return {
                    IfStatement: checkSpaceAfter,
                    DoWhileStatement: checkSpaceAfter,
                    ForInStatement: checkSpaceAfter,
                    ForOfStatement: checkSpaceAfter,
                    ForStatement: checkSpaceAfter,
                    WhileStatement: checkSpaceAfter,
                };
            },
        },
    };
    

    I then use eslint-plugin-local-rules to enable this rule in my project.