millermedeiros / esformatter

ECMAScript code beautifier/formatter
MIT License
970 stars 91 forks source link

Spacing in `new` statement #434

Closed abelnation closed 8 years ago

abelnation commented 8 years ago

I can't figure out how to preserve my paren spacing inside this call to new when the constructor is in parentheses. Note how the space after webkitAudioContext is removed. The goal is to keep it.

~$ echo "context = new ( window.AudioContext || window.webkitAudioContext )();" | ./node_modules/.bin/esformatter
# output
context = new ( window.AudioContext || window.webkitAudioContext)();

Note these two more condensed examples:

# Correct
~$ echo "(1,2,3 || a.b)" | ./node_modules/.bin/esformatter
( 1, 2, 3 || a.b );

~$ echo "foo (a)" | ./node_modules/.bin/esformatter
foo( a );

~$ echo "foo (a.b)" | ./node_modules/.bin/esformatter
foo( a.b );

# Incorrect
~$ echo "new (a)" | ./node_modules/.bin/esformatter
new (a);

~$ echo "new (a.b)" | ./node_modules/.bin/esformatter
new ( a.b);

~$ echo "new (1,2,3 || a.b)" | ./node_modules/.bin/esformatter
new ( 1, 2, 3 || a.b);

Here is my config:

{
    "root": true,
        "LimitLineBreaks": 2,

        "indent" : {
            "value": "\t",
            "alignComments": true,

            "ArrayExpression": 1,
            "ArrayPattern": 1,
            "ArrowFunctionExpression": 1,
            "AssignmentExpression": 1,
            "AssignmentExpression.BinaryExpression": 1,
            "AssignmentExpression.LogicalExpression": 1,
            "AssignmentExpression.UnaryExpression": 1,
            "CallExpression": 1,
            "CallExpression.BinaryExpression": 1,
            "CallExpression.LogicalExpression": 1,
            "CallExpression.UnaryExpression": 1,
            "CatchClause": 1,
            "ConditionalExpression": 1,
            "CommentInsideEmptyBlock": 1,
            "ClassDeclaration": 1,
            "ClassExpression": 1,
            "DoWhileStatement": 1,
            "ForInStatement": 1,
            "ForOfStatement": 1,
            "ForStatement": 1,
            "FunctionDeclaration": 1,
            "FunctionExpression": 1,
            "IfStatement": 1,
            "MemberExpression": 1,
            "MultipleVariableDeclaration": 1,
            "NewExpression": 1,
            "ObjectExpression": 1,
            "ObjectExpression.BinaryExpression": 1,
            "ObjectExpression.LogicalExpression": 1,
            "ObjectExpression.UnaryExpression": 1,
            "ObjectPattern": 1,
            "ParameterList": 1,
            "ReturnStatement": 1,
            "SingleVariableDeclaration": 0,
            "SwitchCase": 1,
            "SwitchStatement": 1,
            "TopLevelFunctionBlock": 1,
            "TryStatement": 1,
            "VariableDeclaration.BinaryExpression": 1,
            "VariableDeclaration.LogicalExpression": 1,
            "VariableDeclaration.UnaryExpression": 1,
            "WhileStatement": 1
        },

        "lineBreak" : {
            "value" : "\n",

            "before" : {
                "AssignmentExpression" : ">=1",
                "AssignmentOperator": 0,
                "AssignmentPattern" : 0,
                "ArrayPatternOpening": 0,
                "ArrayPatternClosing": 0,
                "ArrayPatternComma": 0,
                "ArrowFunctionExpressionArrow": 0,
                "ArrowFunctionExpressionOpeningBrace": 0,
                "ArrowFunctionExpressionClosingBrace": ">=1",
                "BlockStatement" : 0,
                "BreakKeyword": ">=1",
                "CallExpression" : -1,
                "CallExpressionOpeningParentheses" : 0,
                "CallExpressionClosingParentheses" : -1,
                "ClassDeclaration" : ">=1",
                "ClassExpression" : ">=1",
                "ClassOpeningBrace" : 0,
                "ClassClosingBrace" : ">=1",
                "ConditionalExpression" : ">=1",
                "CatchOpeningBrace" : 0,
                "CatchClosingBrace" : ">=1",
                "CatchKeyword": 0,
                "DeleteOperator" : ">=1",
                "DoWhileStatement" : ">=1",
                "DoWhileStatementOpeningBrace" : 0,
                "DoWhileStatementClosingBrace" : ">=1",
                "EndOfFile" : -1,
                "EmptyStatement" : -1,
                "ExportAllDeclaration": ">=1",
                "ExportDefaultDeclaration": ">=1",
                "ExportNamedDeclaration": ">=1",
                "FinallyKeyword" : -1,
                "FinallyOpeningBrace" : 0,
                "FinallyClosingBrace" : ">=1",
                "ForInStatement" : ">=1",
                "ForInStatementExpressionOpening" : 0,
                "ForInStatementExpressionClosing" : 0,
                "ForInStatementOpeningBrace" : 0,
                "ForInStatementClosingBrace" : ">=1",
                "ForOfStatement" : ">=1",
                "ForOfStatementExpressionOpening" : 0,
                "ForOfStatementExpressionClosing" : 0,
                "ForOfStatementOpeningBrace" : 0,
                "ForOfStatementClosingBrace" : ">=1",
                "ForStatement" : ">=1",
                "ForStatementExpressionOpening" : 0,
                "ForStatementExpressionClosing" : "<2",
                "ForStatementOpeningBrace" : 0,
                "ForStatementClosingBrace" : ">=1",
                "FunctionExpression" : -1,
                "FunctionExpressionOpeningBrace" : 0,
                "FunctionExpressionClosingBrace" : ">=1",
                "FunctionDeclaration" : ">=1",
                "FunctionDeclarationOpeningBrace" : 0,
                "FunctionDeclarationClosingBrace" : ">=1",
                "IIFEClosingParentheses" : 0,
                "IfStatement" : ">=1",
                "IfStatementOpeningBrace" : 0,
                "IfStatementClosingBrace" : ">=1",
                "ElseIfStatement" : 0,
                "ElseIfStatementOpeningBrace" : 0,
                "ElseIfStatementClosingBrace" : ">=1",
                "ElseStatement" : 0,
                "ElseStatementOpeningBrace" : 0,
                "ElseStatementClosingBrace" : ">=1",
                "LogicalExpression" : -1,
                "MethodDefinition": ">=1",
                "MemberExpressionOpening": 0,
                "MemberExpressionClosing": "<2",
                "MemberExpressionPeriod": -1,
                "ObjectExpressionClosingBrace" : "<=1",
                "ObjectPatternOpeningBrace": 0,
                "ObjectPatternClosingBrace": 0,
                "ObjectPatternComma": 0,
                "Property" : "<=2",
                "PropertyValue" : 0,
                "ReturnStatement" : -1,
                "SwitchOpeningBrace" : 0,
                "SwitchClosingBrace" : ">=1",
                "SwitchCaseColon": 0,
                "ThisExpression" : -1,
                "ThrowStatement" : ">=1",
                "TryKeyword": -1,
                "TryOpeningBrace" : 0,
                "TryClosingBrace" : ">=1",
                "VariableName" : ">=1",
                "VariableValue" : 0,
                "VariableDeclaration" : ">=1",
                "VariableDeclarationSemiColon" : 0,
                "VariableDeclarationWithoutInit" : ">=1",
                "WhileStatement" : ">=1",
                "WhileStatementOpeningBrace" : 0,
                "WhileStatementClosingBrace" : ">=1"
            },

            "after" : {
                "AssignmentExpression" : ">=1",
                "AssignmentOperator" : 0,
                "AssignmentPattern" : 0,
                "ArrayPatternOpening": 0,
                "ArrayPatternClosing": 0,
                "ArrayPatternComma": 0,
                "ArrowFunctionExpressionArrow": 0,
                "ArrowFunctionExpressionOpeningBrace": ">=1",
                "ArrowFunctionExpressionClosingBrace": -1,
                "BlockStatement" : 0,
                "BreakKeyword": -1,
                "CallExpression" : -1,
                "CallExpressionOpeningParentheses" : -1,
                "CallExpressionClosingParentheses" : -1,
                "ClassDeclaration" : ">=1",
                "ClassExpression" : ">=1",
                "ClassOpeningBrace" : ">=1",
                "ClassClosingBrace" : ">=1",
                "CatchOpeningBrace" : ">=1",
                "CatchClosingBrace" : ">=0",
                "CatchKeyword": 0,
                "ConditionalExpression" : ">=1",
                "DeleteOperator" : ">=1",
                "DoWhileStatement" : ">=1",
                "DoWhileStatementOpeningBrace" : ">=1",
                "DoWhileStatementClosingBrace" : 0,
                "EmptyStatement" : -1,
                "FinallyKeyword" : -1,
                "FinallyOpeningBrace" : ">=1",
                "FinallyClosingBrace" : ">=1",
                "ForInStatement" : ">=1",
                "ForInStatementExpressionOpening" : "<2",
                "ForInStatementExpressionClosing" : -1,
                "ForInStatementOpeningBrace" : ">=1",
                "ForInStatementClosingBrace" : ">=1",
                "ForOfStatement" : ">=1",
                "ForOfStatementExpressionOpening" : "<2",
                "ForOfStatementExpressionClosing" : -1,
                "ForOfStatementOpeningBrace" : ">=1",
                "ForOfStatementClosingBrace" : ">=1",
                "ForStatement" : ">=1",
                "ForStatementExpressionOpening" : "<2",
                "ForStatementExpressionClosing" : -1,
                "ForStatementOpeningBrace" : ">=1",
                "ForStatementClosingBrace" : ">=1",
                "FunctionExpression" : ">=1",
                "FunctionExpressionOpeningBrace" : ">=1",
                "FunctionExpressionClosingBrace" : -1,
                "FunctionDeclaration" : ">=1",
                "FunctionDeclarationOpeningBrace" : ">=1",
                "FunctionDeclarationClosingBrace" : ">=1",
                "IIFEOpeningParentheses" : 0,
                "IfStatement" : ">=1",
                "IfStatementOpeningBrace" : ">=1",
                "IfStatementClosingBrace" : ">=1",
                "ElseIfStatement" : ">=1",
                "ElseIfStatementOpeningBrace" : ">=1",
                "ElseIfStatementClosingBrace" : ">=1",
                "ElseStatement" : ">=1",
                "ElseStatementOpeningBrace" : ">=1",
                "ElseStatementClosingBrace" : ">=1",
                "LogicalExpression" : -1,
                "MethodDefinition": ">=1",
                "MemberExpressionOpening": "<2",
                "MemberExpressionClosing": "<2",
                "MemberExpressionPeriod": 0,
                "ObjectExpressionOpeningBrace" : "<=1",
                "ObjectPatternOpeningBrace": 0,
                "ObjectPatternClosingBrace": 0,
                "ObjectPatternComma": 0,
                "Property" : 0,
                "PropertyName" : 0,
                "ReturnStatement" : -1,
                "SwitchOpeningBrace" : ">=1",
                "SwitchClosingBrace" : ">=1",
                "SwitchCaseColon": ">=1",
                "ThisExpression" : 0,
                "ThrowStatement" : ">=1",
                "TryKeyword": -1,
                "TryOpeningBrace" : ">=1",
                "TryClosingBrace" : 0,
                "VariableValue" : -1,
                "VariableDeclaration" : ">=1",
                "VariableDeclarationSemiColon" : ">=1",
                "WhileStatement" : ">=1",
                "WhileStatementOpeningBrace" : ">=1",
                "WhileStatementClosingBrace" : ">=1"
            }
        },

        "whiteSpace" : {
            "value" : " ",
            "removeTrailing" : 1,

            "before" : {
                "AssignmentPattern" : 1,
                "ArrayExpressionOpening" : 0,
                "ArrayExpressionClosing" : 1,
                "ArrayExpressionComma" : 0,
                "ArrayPatternOpening": 1,
                "ArrayPatternClosing": 1,
                "ArrayPatternComma": 0,
                "ArrowFunctionExpressionArrow": 1,
                "ArrowFunctionExpressionOpeningBrace": 1,
                "ArrowFunctionExpressionClosingBrace": 0,
                "ArgumentComma" : 0,
                "ArgumentList" : 1,
                "AssignmentOperator" : 1,
                "BinaryExpression": 1,
                "BinaryExpressionOperator" : 1,
                "BlockComment" : 1,
                "CallExpression" : -1,
                "CallExpressionOpeningParentheses" : 0,
                "CallExpressionClosingParentheses" : 1,
                "CatchParameterList" : 1,
                "CatchOpeningBrace" : 1,
                "CatchClosingBrace" : 1,
                "CatchKeyword" : 1,
                "CommaOperator" : 0,
                "ClassOpeningBrace" : 1,
                "ClassClosingBrace" : 1,
                "ConditionalExpressionConsequent" : 1,
                "ConditionalExpressionAlternate" : 1,
                "DoWhileStatementOpeningBrace" : 1,
                "DoWhileStatementClosingBrace" : 1,
                "DoWhileStatementConditional" : 1,
                "EmptyStatement" : 0,
                "ExpressionClosingParentheses" : 1,
                "FinallyKeyword" : -1,
                "FinallyOpeningBrace" : 1,
                "FinallyClosingBrace" : 1,
                "ForInStatement" : 1,
                "ForInStatementExpressionOpening" : 1,
                "ForInStatementExpressionClosing" : 1,
                "ForInStatementOpeningBrace" : 1,
                "ForInStatementClosingBrace" : 1,
                "ForOfStatement" : 1,
                "ForOfStatementExpressionOpening" : 1,
                "ForOfStatementExpressionClosing" : 1,
                "ForOfStatementOpeningBrace" : 1,
                "ForOfStatementClosingBrace" : 1,
                "ForStatement" : 1,
                "ForStatementExpressionOpening" : 1,
                "ForStatementExpressionClosing" : 1,
                "ForStatementOpeningBrace" : 1,
                "ForStatementClosingBrace" : 1,
                "ForStatementSemicolon" : 0,
                "FunctionDeclarationOpeningBrace" : 1,
                "FunctionDeclarationClosingBrace" : 1,
                "FunctionExpressionOpeningBrace" : 1,
                "FunctionExpressionClosingBrace" : 1,
                "FunctionGeneratorAsterisk": 0,
                "FunctionName" : 1,
                "IIFEClosingParentheses" : 0,
                "IfStatementConditionalOpening" : 1,
                "IfStatementConditionalClosing" : 1,
                "IfStatementOpeningBrace" : 1,
                "IfStatementClosingBrace" : 1,
                "ModuleSpecifierClosingBrace": 1,
                "ElseStatementOpeningBrace" : 1,
                "ElseStatementClosingBrace" : 1,
                "ElseIfStatementOpeningBrace" : 1,
                "ElseIfStatementClosingBrace" : 1,
                "LineComment" : 1,
                "LogicalExpression": 1,
                "LogicalExpressionOperator" : 1,
                "MemberExpressionOpening": 0,
                "MemberExpressionClosing": 1,
                "MemberExpressionPeriod": 0,
                "NewExpressionOpeningBrace": 1,
                "ObjectExpressionOpeningBrace": 1,
                "ObjectExpressionClosingBrace": 1,
                "ObjectPatternOpeningBrace": 1,
                "ObjectPatternClosingBrace": 1,
                "ObjectPatternComma": 0,
                "Property": -1,
                "PropertyName": -1,
                "PropertyValue" : 1,
                "ParameterComma" : 0,
                "ParameterList" : 1,
                "SwitchDiscriminantOpening" : 1,
                "SwitchDiscriminantClosing" : 1,
                "SwitchCaseColon": 0,
                "ThrowKeyword": 1,
                "TryKeyword": -1,
                "TryOpeningBrace" : 1,
                "TryClosingBrace" : 1,
                "UpdateExpression" : 1,
                "UnaryExpressionOperator": 1,
                "VariableName" : 1,
                "VariableValue" : 1,
                "VariableDeclarationSemiColon" : 0,
                "WhileStatementConditionalOpening" : 1,
                "WhileStatementConditionalClosing" : 1,
                "WhileStatementOpeningBrace" : 1,
                "WhileStatementClosingBrace" : 1
            },

            "after" : {
                "AssignmentPattern" : 1,
                "ArrayExpressionOpening" : 1,
                "ArrayExpressionClosing" : 0,
                "ArrayExpressionComma" : 1,
                "ArrayPatternOpening": 1,
                "ArrayPatternClosing": 1,
                "ArrayPatternComma": 1,
                "ArrowFunctionExpressionArrow": 1,
                "ArrowFunctionExpressionOpeningBrace": 0,
                "ArrowFunctionExpressionClosingBrace": 0,
                "ArgumentComma" : -1,
                "ArgumentList" : 1,
                "AssignmentOperator" : 1,
                "BinaryExpression": 1,
                "BinaryExpressionOperator" : 1,
                "BlockComment" : 1,
                "CallExpression" : -1,
                "CallExpressionOpeningParentheses" : 1,
                "CallExpressionClosingParentheses" : -1,
                "CatchParameterList" : 1,
                "CatchOpeningBrace" : 1,
                "CatchClosingBrace" : 1,
                "CatchKeyword" : 1,
                "ClassOpeningBrace" : 1,
                "ClassClosingBrace" : 1,
                "CommaOperator" : 1,
                "ConditionalExpressionConsequent" : 1,
                "ConditionalExpressionTest" : 1,
                "DoWhileStatementOpeningBrace" : 1,
                "DoWhileStatementClosingBrace" : 1,
                "DoWhileStatementBody" : 1,
                "EmptyStatement" : 0,
                "ExpressionOpeningParentheses" : 1,
                "FinallyKeyword" : -1,
                "FinallyOpeningBrace" : 1,
                "FinallyClosingBrace" : 1,
                "ForInStatement" : 1,
                "ForInStatementExpressionOpening" : 1,
                "ForInStatementExpressionClosing" : 1,
                "ForInStatementOpeningBrace" : 1,
                "ForInStatementClosingBrace" : 1,
                "ForOfStatement" : 1,
                "ForOfStatementExpressionOpening" : 1,
                "ForOfStatementExpressionClosing" : 1,
                "ForOfStatementOpeningBrace" : 1,
                "ForOfStatementClosingBrace" : 1,
                "ForStatement" : 1,
                "ForStatementExpressionOpening" : 1,
                "ForStatementExpressionClosing" : 1,
                "ForStatementClosingBrace" : 1,
                "ForStatementOpeningBrace" : 1,
                "ForStatementSemicolon" : 1,
                "FunctionReservedWord": 1,
                "FunctionName" : 0,
                "FunctionExpressionOpeningBrace" : 1,
                "FunctionExpressionClosingBrace" : 0,
                "FunctionDeclarationOpeningBrace" : 1,
                "FunctionDeclarationClosingBrace" : 1,
                "IIFEOpeningParentheses" : 0,
                "IfStatementConditionalOpening" : 1,
                "IfStatementConditionalClosing" : 1,
                "IfStatementOpeningBrace" : 1,
                "IfStatementClosingBrace" : 1,
                "ModuleSpecifierOpeningBrace": 1,
                "ElseStatementOpeningBrace" : 1,
                "ElseStatementClosingBrace" : 1,
                "ElseIfStatementOpeningBrace" : 1,
                "ElseIfStatementClosingBrace" : 1,
                "MemberExpression": -1,
                "MemberExpressionClosing": 0,
                "MemberExpressionOpening": 1,
                "MemberExpressionPeriod": 0,
                "MethodDefinitionName": 0,
                "NewExpressionOpeningBrace": 1,
                "LineComment": 1,
                "LogicalExpression": 1,
                "LogicalExpressionOperator" : 1,
                "ObjectExpressionOpeningBrace": 1,
                "ObjectExpressionClosingBrace": 0,
                "ObjectExpressionComma": -1,
                "ObjectPatternOpeningBrace": 1,
                "ObjectPatternClosingBrace": 0,
                "ObjectPatternComma": -1,
                "Property": -1,
                "PropertyName" : 0,
                "PropertyValue" : 0,
                "ParameterComma" : 1,
                "ParameterList" : 1,
                "SwitchDiscriminantOpening" : 1,
                "SwitchDiscriminantClosing" : 1,
                "ThrowKeyword": 1,
                "TryKeyword": 1,
                "TryOpeningBrace" : 1,
                "TryClosingBrace" : 1,
                "UnaryExpressionOperator": 0,
                "VariableName" : 1,
                "VariableValue" : 0,
                "VariableDeclarationSemiColon" : 0,
                "WhileStatementConditionalOpening" : 1,
                "WhileStatementConditionalClosing" : 1,
                "WhileStatementOpeningBrace" : 1,
                "WhileStatementClosingBrace" : 1
            }
        }
}
millermedeiros commented 8 years ago

I did not try it yet but this is probably need to be handled similar to https://github.com/millermedeiros/esformatter/blob/master/lib/hooks/CallExpression.js#L50-L59

PS: NewExpression is also handled by this file

millermedeiros commented 8 years ago

WOW, this was harder than expected.. ended up introducing 2 new settings (CalleeOpeningParentheses and CalleeClosingParentheses) to handle these cases:

new ( foo );
new ( foo.bar );
new ( foo || bar )();
( foo || bar )();

there was some conflicts with the ExpressionOpeningParentheses and ExpressionClosingParentheses which was triggered automatically for cases like ( foo || bar )();

@abelnation thanks for the feature request/bug-report! please keep them coming!