@@ -2964,12 +2964,155 @@ func (p *Printer) emitExpressionNoASI(node *ast.Expression, precedence ast.Opera
2964
2964
// a;
2965
2965
// }
2966
2966
// Due to ASI, this would result in a `return` with no value followed by an unreachable expression statement.
2967
- if ! p .commentsDisabled && node .Kind == ast .KindPartiallyEmittedExpression && p .willEmitLeadingNewLine (node ) {
2968
- // !!! if there is an original parse tree node, restore it with location to preserve comments and source maps.
2969
- p .emitExpression (node , ast .OperatorPrecedenceParentheses )
2970
- } else {
2971
- p .emitExpression (node , precedence )
2967
+ p .emitExpression (p .parenthesizeExpressionForNoAsi (node ), precedence )
2968
+ }
2969
+
2970
+ // parenthesizeExpressionForNoAsi walks down the left side of expressions to check if any
2971
+ // PartiallyEmittedExpression might introduce ASI, and returns an expression that ensures
2972
+ // proper parenthesization to prevent ASI issues.
2973
+ func (p * Printer ) parenthesizeExpressionForNoAsi (node * ast.Expression ) * ast.Expression {
2974
+ if p .commentsDisabled {
2975
+ return node
2972
2976
}
2977
+
2978
+ switch node .Kind {
2979
+ case ast .KindPartiallyEmittedExpression :
2980
+ pee := node .AsPartiallyEmittedExpression ()
2981
+ if p .willEmitLeadingNewLine (node ) {
2982
+ // !!! if there is an original parse tree node, restore it with location to preserve comments and source maps.
2983
+ // Emit with parentheses precedence to force wrapping
2984
+ return p .createParenthesizedExpressionForNoAsi (node )
2985
+ }
2986
+ // Recursively check the inner expression
2987
+ innerParenthesized := p .parenthesizeExpressionForNoAsi (pee .Expression )
2988
+ if innerParenthesized != pee .Expression {
2989
+ // Need to create a new PartiallyEmittedExpression with the parenthesized inner expression
2990
+ return p .updatePartiallyEmittedExpression (pee , innerParenthesized )
2991
+ }
2992
+
2993
+ case ast .KindPropertyAccessExpression :
2994
+ pae := node .AsPropertyAccessExpression ()
2995
+ exprParenthesized := p .parenthesizeExpressionForNoAsi (pae .Expression )
2996
+ if exprParenthesized != pae .Expression {
2997
+ return p .updatePropertyAccessExpression (pae , exprParenthesized )
2998
+ }
2999
+
3000
+ case ast .KindElementAccessExpression :
3001
+ eae := node .AsElementAccessExpression ()
3002
+ exprParenthesized := p .parenthesizeExpressionForNoAsi (eae .Expression )
3003
+ if exprParenthesized != eae .Expression {
3004
+ return p .updateElementAccessExpression (eae , exprParenthesized )
3005
+ }
3006
+
3007
+ case ast .KindCallExpression :
3008
+ ce := node .AsCallExpression ()
3009
+ exprParenthesized := p .parenthesizeExpressionForNoAsi (ce .Expression )
3010
+ if exprParenthesized != ce .Expression {
3011
+ return p .updateCallExpression (ce , exprParenthesized )
3012
+ }
3013
+
3014
+ case ast .KindTaggedTemplateExpression :
3015
+ tte := node .AsTaggedTemplateExpression ()
3016
+ tagParenthesized := p .parenthesizeExpressionForNoAsi (tte .Tag )
3017
+ if tagParenthesized != tte .Tag {
3018
+ return p .updateTaggedTemplateExpression (tte , tagParenthesized )
3019
+ }
3020
+
3021
+ case ast .KindPostfixUnaryExpression :
3022
+ pue := node .AsPostfixUnaryExpression ()
3023
+ operandParenthesized := p .parenthesizeExpressionForNoAsi (pue .Operand )
3024
+ if operandParenthesized != pue .Operand {
3025
+ return p .updatePostfixUnaryExpression (pue , operandParenthesized )
3026
+ }
3027
+
3028
+ case ast .KindBinaryExpression :
3029
+ be := node .AsBinaryExpression ()
3030
+ leftParenthesized := p .parenthesizeExpressionForNoAsi (be .Left )
3031
+ if leftParenthesized != be .Left {
3032
+ return p .updateBinaryExpression (be , leftParenthesized )
3033
+ }
3034
+
3035
+ case ast .KindConditionalExpression :
3036
+ ce := node .AsConditionalExpression ()
3037
+ conditionParenthesized := p .parenthesizeExpressionForNoAsi (ce .Condition )
3038
+ if conditionParenthesized != ce .Condition {
3039
+ return p .updateConditionalExpression (ce , conditionParenthesized )
3040
+ }
3041
+
3042
+ case ast .KindAsExpression :
3043
+ ae := node .AsAsExpression ()
3044
+ exprParenthesized := p .parenthesizeExpressionForNoAsi (ae .Expression )
3045
+ if exprParenthesized != ae .Expression {
3046
+ return p .updateAsExpression (ae , exprParenthesized )
3047
+ }
3048
+
3049
+ case ast .KindSatisfiesExpression :
3050
+ se := node .AsSatisfiesExpression ()
3051
+ exprParenthesized := p .parenthesizeExpressionForNoAsi (se .Expression )
3052
+ if exprParenthesized != se .Expression {
3053
+ return p .updateSatisfiesExpression (se , exprParenthesized )
3054
+ }
3055
+
3056
+ case ast .KindNonNullExpression :
3057
+ nne := node .AsNonNullExpression ()
3058
+ exprParenthesized := p .parenthesizeExpressionForNoAsi (nne .Expression )
3059
+ if exprParenthesized != nne .Expression {
3060
+ return p .updateNonNullExpression (nne , exprParenthesized )
3061
+ }
3062
+ }
3063
+
3064
+ return node
3065
+ }
3066
+
3067
+ // Helper functions to create/update nodes with parenthesized sub-expressions
3068
+
3069
+ func (p * Printer ) createParenthesizedExpressionForNoAsi (node * ast.Expression ) * ast.Expression {
3070
+ // Create a parenthesized expression to force wrapping
3071
+ return p .emitContext .Factory .NewParenthesizedExpression (node )
3072
+ }
3073
+
3074
+ func (p * Printer ) updatePartiallyEmittedExpression (node * ast.PartiallyEmittedExpression , expression * ast.Expression ) * ast.Expression {
3075
+ return p .emitContext .Factory .UpdatePartiallyEmittedExpression (node , expression )
3076
+ }
3077
+
3078
+ func (p * Printer ) updatePropertyAccessExpression (node * ast.PropertyAccessExpression , expression * ast.Expression ) * ast.Expression {
3079
+ return p .emitContext .Factory .UpdatePropertyAccessExpression (node , expression , node .QuestionDotToken , node .Name ())
3080
+ }
3081
+
3082
+ func (p * Printer ) updateElementAccessExpression (node * ast.ElementAccessExpression , expression * ast.Expression ) * ast.Expression {
3083
+ return p .emitContext .Factory .UpdateElementAccessExpression (node , expression , node .QuestionDotToken , node .ArgumentExpression )
3084
+ }
3085
+
3086
+ func (p * Printer ) updateCallExpression (node * ast.CallExpression , expression * ast.Expression ) * ast.Expression {
3087
+ return p .emitContext .Factory .UpdateCallExpression (node , expression , node .QuestionDotToken , node .TypeArguments , node .Arguments )
3088
+ }
3089
+
3090
+ func (p * Printer ) updateTaggedTemplateExpression (node * ast.TaggedTemplateExpression , tag * ast.Expression ) * ast.Expression {
3091
+ return p .emitContext .Factory .UpdateTaggedTemplateExpression (node , tag , node .QuestionDotToken , node .TypeArguments , node .Template )
3092
+ }
3093
+
3094
+ func (p * Printer ) updatePostfixUnaryExpression (node * ast.PostfixUnaryExpression , operand * ast.Expression ) * ast.Expression {
3095
+ return p .emitContext .Factory .UpdatePostfixUnaryExpression (node , operand )
3096
+ }
3097
+
3098
+ func (p * Printer ) updateBinaryExpression (node * ast.BinaryExpression , left * ast.Expression ) * ast.Expression {
3099
+ return p .emitContext .Factory .UpdateBinaryExpression (node , node .Modifiers (), left , node .Type , node .OperatorToken , node .Right )
3100
+ }
3101
+
3102
+ func (p * Printer ) updateConditionalExpression (node * ast.ConditionalExpression , condition * ast.Expression ) * ast.Expression {
3103
+ return p .emitContext .Factory .UpdateConditionalExpression (node , condition , node .QuestionToken , node .WhenTrue , node .ColonToken , node .WhenFalse )
3104
+ }
3105
+
3106
+ func (p * Printer ) updateAsExpression (node * ast.AsExpression , expression * ast.Expression ) * ast.Expression {
3107
+ return p .emitContext .Factory .UpdateAsExpression (node , expression , node .Type )
3108
+ }
3109
+
3110
+ func (p * Printer ) updateSatisfiesExpression (node * ast.SatisfiesExpression , expression * ast.Expression ) * ast.Expression {
3111
+ return p .emitContext .Factory .UpdateSatisfiesExpression (node , expression , node .Type )
3112
+ }
3113
+
3114
+ func (p * Printer ) updateNonNullExpression (node * ast.NonNullExpression , expression * ast.Expression ) * ast.Expression {
3115
+ return p .emitContext .Factory .UpdateNonNullExpression (node , expression )
2973
3116
}
2974
3117
2975
3118
func (p * Printer ) emitExpression (node * ast.Expression , precedence ast.OperatorPrecedence ) {
0 commit comments