@@ -136,6 +136,29 @@ const PRECEDENCE: Record<string, number> = {
136136// 右结合运算符
137137const RIGHT_ASSOCIATIVE = new Set ( [ "**" ] ) ;
138138
139+ // 内置构造函数列表
140+ const BUILTIN_CONSTRUCTORS = new Set ( [
141+ "Date" ,
142+ "RegExp" ,
143+ "URL" ,
144+ "URLSearchParams" ,
145+ "Map" ,
146+ "Set" ,
147+ "Int8Array" ,
148+ "Uint8Array" ,
149+ "Uint8ClampedArray" ,
150+ "Int16Array" ,
151+ "Uint16Array" ,
152+ "Int32Array" ,
153+ "Uint32Array" ,
154+ "Float32Array" ,
155+ "Float64Array" ,
156+ "BigInt64Array" ,
157+ "BigUint64Array" ,
158+ "ArrayBuffer" ,
159+ "DataView" ,
160+ ] ) ;
161+
139162class Parser {
140163 private pos = 0 ;
141164 private source : string ;
@@ -824,53 +847,25 @@ export function generate(node: ASTNode): string {
824847 return generate ( node . argument ) + node . operator ;
825848
826849 case "ConditionalExpr" : {
827- const test = generate ( node . test ) ;
828- const consequent = generate ( node . consequent ) ;
829- const alternate = generate ( node . alternate ) ;
850+ const test = wrapIfNeeded ( node . test , node , "test" ) ;
851+ const consequent = wrapIfNeeded ( node . consequent , node , "consequent" ) ;
852+ const alternate = wrapIfNeeded ( node . alternate , node , "alternate" ) ;
830853 return `${ test } ?${ consequent } :${ alternate } ` ;
831854 }
832855
833856 case "MemberExpr" : {
834857 const object = wrapIfNeeded ( node . object , node , "object" ) ;
835- if ( node . computed ) {
836- const property = generate ( node . property ) ;
837- return node . optional ? `${ object } ?.[${ property } ]` : `${ object } [${ property } ]` ;
838- }
839858 const property = generate ( node . property ) ;
840- return node . optional ? `${ object } ?.${ property } ` : `${ object } .${ property } ` ;
859+ return node . computed
860+ ? `${ object } ${ node . optional ? "?." : "" } [${ property } ]`
861+ : `${ object } ${ node . optional ? "?." : "." } ${ property } ` ;
841862 }
842863
843864 case "CallExpr" : {
844865 const callee = wrapIfNeeded ( node . callee , node , "callee" ) ;
845866 const args = node . arguments . map ( generate ) . join ( "," ) ;
846- // 检测是否需要使用 new 关键字(构造函数)
847- const needsNew =
848- node . callee . type === "Identifier" &&
849- [
850- "Date" ,
851- "RegExp" ,
852- "URL" ,
853- "URLSearchParams" ,
854- "Map" ,
855- "Set" ,
856- "Int8Array" ,
857- "Uint8Array" ,
858- "Uint8ClampedArray" ,
859- "Int16Array" ,
860- "Uint16Array" ,
861- "Int32Array" ,
862- "Uint32Array" ,
863- "Float32Array" ,
864- "Float64Array" ,
865- "BigInt64Array" ,
866- "BigUint64Array" ,
867- "ArrayBuffer" ,
868- "DataView" ,
869- ] . includes ( node . callee . name ) ;
870- if ( needsNew ) {
871- return node . optional ? `new ${ callee } ?.(${ args } )` : `new ${ callee } (${ args } )` ;
872- }
873- return node . optional ? `${ callee } ?.(${ args } )` : `${ callee } (${ args } )` ;
867+ const isNew = node . callee . type === "Identifier" && BUILTIN_CONSTRUCTORS . has ( node . callee . name ) ;
868+ return `${ isNew ? "new " : "" } ${ callee } ${ node . optional ? "?." : "" } (${ args } )` ;
874869 }
875870
876871 case "ArrayExpr" :
@@ -889,15 +884,9 @@ export function generate(node: ASTNode): string {
889884
890885 case "ArrowFunctionExpr" : {
891886 const params = node . params . map ( ( p ) => p . name ) . join ( "," ) ;
892- let body = generate ( node . body ) ;
893- // 如果 body 是对象字面量,需要用括号包裹,否则会被解释为代码块
894- if ( node . body . type === "ObjectExpr" ) {
895- body = `(${ body } )` ;
896- }
897- if ( node . params . length === 1 ) {
898- return `${ params } =>${ body } ` ;
899- }
900- return `(${ params } )=>${ body } ` ;
887+ const body = node . body . type === "ObjectExpr" ? `(${ generate ( node . body ) } )` : generate ( node . body ) ;
888+ const paramsStr = node . params . length === 1 ? params : `(${ params } )` ;
889+ return `${ paramsStr } =>${ body } ` ;
901890 }
902891
903892 default : {
@@ -914,7 +903,7 @@ export function generate(node: ASTNode): string {
914903function wrapIfNeeded (
915904 child : ASTNode ,
916905 parent : ASTNode ,
917- position : "left" | "right" | "argument" | "object" | "callee"
906+ position : "left" | "right" | "argument" | "object" | "callee" | "test" | "consequent" | "alternate"
918907) : string {
919908 const code = generate ( child ) ;
920909
@@ -928,48 +917,40 @@ function wrapIfNeeded(
928917 * 判断子节点是否需要括号
929918 */
930919function needsParens ( child : ASTNode , parent : ASTNode , position : string ) : boolean {
931- // 条件表达式在二元表达式中需要括号
932- if ( child . type === "ConditionalExpr" && parent . type === "BinaryExpr" ) {
933- return true ;
934- }
935-
936- // 二元表达式嵌套时根据优先级判断
937- if ( child . type === "BinaryExpr" && parent . type === "BinaryExpr" ) {
938- const childPrec = PRECEDENCE [ child . operator ] || 0 ;
939- const parentPrec = PRECEDENCE [ parent . operator ] || 0 ;
940-
941- if ( childPrec < parentPrec ) {
942- return true ;
920+ switch ( parent . type ) {
921+ case "BinaryExpr" : {
922+ if ( child . type === "ConditionalExpr" || child . type === "UnaryExpr" ) return true ;
923+ if ( child . type === "BinaryExpr" ) {
924+ const childPrec = PRECEDENCE [ child . operator ] ?? 0 ;
925+ const parentPrec = PRECEDENCE [ parent . operator ] ?? 0 ;
926+ if ( childPrec < parentPrec ) return true ;
927+ if ( childPrec === parentPrec && position === "right" && ! RIGHT_ASSOCIATIVE . has ( parent . operator ) ) return true ;
928+ }
929+ return false ;
943930 }
944931
945- // 相同优先级时,右侧需要括号(除了右结合运算符)
946- if ( childPrec === parentPrec && position === "right" ) {
947- if ( ! RIGHT_ASSOCIATIVE . has ( parent . operator ) ) {
932+ case "UnaryExpr" :
933+ return position === "argument" && ( child . type === "BinaryExpr" || child . type === "ConditionalExpr" ) ;
934+
935+ case "MemberExpr" :
936+ case "CallExpr" : {
937+ if ( position !== "object" && position !== "callee" ) return false ;
938+ if ( [ "BinaryExpr" , "ConditionalExpr" , "UnaryExpr" , "ArrowFunctionExpr" , "ObjectExpr" ] . includes ( child . type ) ) {
948939 return true ;
949940 }
941+ // 处理 (42).toString() 这种整数紧跟点号的情况
942+ if ( child . type === "NumberLiteral" && parent . type === "MemberExpr" && ! parent . computed ) {
943+ return ! child . raw . includes ( "." ) && ! child . raw . includes ( "e" ) && ! child . raw . includes ( "x" ) ;
944+ }
945+ return false ;
950946 }
951- }
952947
953- // 二元表达式或条件表达式作为一元表达式的参数时需要括号
954- if (
955- ( child . type === "BinaryExpr" || child . type === "ConditionalExpr" ) &&
956- parent . type === "UnaryExpr" &&
957- position === "argument"
958- ) {
959- return true ;
960- }
948+ case "ConditionalExpr" :
949+ return position === "test" && child . type === "ConditionalExpr" ;
961950
962- // 一元表达式作为二元表达式的操作数时需要括号(为了保持原有的语义清晰)
963- if ( child . type === "UnaryExpr" && parent . type === "BinaryExpr" ) {
964- // ** 运算符左侧不能有一元表达式
965- if ( parent . operator === "**" && position === "left" ) {
966- return true ;
967- }
968- // 逻辑运算符、位运算符等需要明确一元表达式的边界
969- return true ;
951+ default :
952+ return false ;
970953 }
971-
972- return false ;
973954}
974955
975956/**
0 commit comments