@@ -40,8 +40,28 @@ private string GetEnumValue<T>(string name, T value) where T : Enum
4040 return map [ value ] ;
4141 }
4242
43+ private readonly List < Node > _parentStack = new List < Node > ( ) ;
44+ protected IReadOnlyList < Node > ParentStack => _parentStack ;
45+
46+ /// <summary>
47+ /// Returns parent node at specified position.
48+ /// </summary>
49+ /// <param name="offset">Zero index value returns current node; one corresponds to direct
50+ /// parent of current node.</param>
51+ protected Node ? TryGetParentAt ( int offset )
52+ {
53+ if ( _parentStack . Count < offset + 1 )
54+ {
55+ return null ;
56+ }
57+
58+ return _parentStack [ _parentStack . Count - 1 - offset ] ;
59+ }
60+
4361 public virtual void Visit ( Node node )
4462 {
63+ _parentStack . Add ( node ) ;
64+
4565 switch ( node . Type )
4666 {
4767 case Nodes . AssignmentExpression :
@@ -252,6 +272,7 @@ public virtual void Visit(Node node)
252272 VisitUnknownNode ( node ) ;
253273 break ;
254274 }
275+ _parentStack . RemoveAt ( _parentStack . Count - 1 ) ;
255276 }
256277
257278 protected virtual void VisitProgram ( Program program )
@@ -266,15 +287,20 @@ protected virtual void VisitUnknownNode(Node node)
266287
267288 protected virtual void VisitCatchClause ( CatchClause catchClause )
268289 {
290+ _sb . Append ( "(" ) ;
269291 Visit ( catchClause . Param ) ;
292+ _sb . Append ( ")" ) ;
270293 Visit ( catchClause . Body ) ;
271294 }
272295
273296 protected virtual void VisitFunctionDeclaration ( FunctionDeclaration functionDeclaration )
274297 {
275- _sb . Append ( "function " ) ;
298+ _sb . Append ( "function" ) ;
299+ if ( functionDeclaration . Generator )
300+ _sb . Append ( "*" ) ;
276301 if ( functionDeclaration . Id != null )
277302 {
303+ _sb . Append ( " " ) ;
278304 Visit ( functionDeclaration . Id ) ;
279305 }
280306 _sb . Append ( "(" ) ;
@@ -285,20 +311,24 @@ protected virtual void VisitFunctionDeclaration(FunctionDeclaration functionDecl
285311
286312 protected virtual void VisitWithStatement ( WithStatement withStatement )
287313 {
314+ _sb . Append ( "with(" ) ;
288315 Visit ( withStatement . Object ) ;
316+ _sb . Append ( ")" ) ;
289317 Visit ( withStatement . Body ) ;
290318 }
291319
292320 protected virtual void VisitWhileStatement ( WhileStatement whileStatement )
293321 {
322+ _sb . Append ( "while(" ) ;
294323 Visit ( whileStatement . Test ) ;
324+ _sb . Append ( ")" ) ;
295325 Visit ( whileStatement . Body ) ;
296326 }
297327
298328 protected virtual void VisitVariableDeclaration ( VariableDeclaration variableDeclaration )
299329 {
300330 _sb . Append ( variableDeclaration . Kind . ToString ( ) . ToLower ( ) + " " ) ;
301- VisitNodeList ( variableDeclaration . Declarations ) ;
331+ VisitNodeList ( variableDeclaration . Declarations , appendSeperatorString : "," ) ;
302332 }
303333
304334 protected virtual void VisitTryStatement ( TryStatement tryStatement )
@@ -307,13 +337,12 @@ protected virtual void VisitTryStatement(TryStatement tryStatement)
307337 Visit ( tryStatement . Block ) ;
308338 if ( tryStatement . Handler != null )
309339 {
310- _sb . Append ( " catch " ) ;
340+ _sb . Append ( " catch" ) ;
311341 Visit ( tryStatement . Handler ) ;
312342 }
313-
314343 if ( tryStatement . Finalizer != null )
315344 {
316- _sb . Append ( " finally " ) ;
345+ _sb . Append ( " finally" ) ;
317346 Visit ( tryStatement . Finalizer ) ;
318347 }
319348 }
@@ -322,6 +351,7 @@ protected virtual void VisitThrowStatement(ThrowStatement throwStatement)
322351 {
323352 _sb . Append ( "throw " ) ;
324353 Visit ( throwStatement . Argument ) ;
354+ _sb . Append ( ";" ) ;
325355 }
326356
327357 protected virtual void VisitSwitchStatement ( SwitchStatement switchStatement )
@@ -354,6 +384,7 @@ protected virtual void VisitReturnStatement(ReturnStatement returnStatement)
354384 {
355385 Visit ( returnStatement . Argument ) ;
356386 }
387+ _sb . Append ( ";" ) ;
357388 }
358389
359390 protected virtual void VisitLabeledStatement ( LabeledStatement labeledStatement )
@@ -369,9 +400,14 @@ protected virtual void VisitIfStatement(IfStatement ifStatement)
369400 Visit ( ifStatement . Test ) ;
370401 WriteEndLineToSb ( ")" ) ;
371402 Visit ( ifStatement . Consequent ) ;
403+ if ( NodeNeedsSemicolon ( ifStatement . Consequent ) )
404+ _sb . Append ( ";" ) ;
372405 if ( ifStatement . Alternate != null )
373406 {
407+ _sb . Append ( " else " ) ;
374408 Visit ( ifStatement . Alternate ) ;
409+ if ( NodeNeedsSemicolon ( ifStatement . Alternate ) )
410+ _sb . Append ( ";" ) ;
375411 }
376412 }
377413
@@ -387,7 +423,23 @@ protected virtual void VisitDebuggerStatement(DebuggerStatement debuggerStatemen
387423
388424 protected virtual void VisitExpressionStatement ( ExpressionStatement expressionStatement )
389425 {
390- Visit ( expressionStatement . Expression ) ;
426+ if ( expressionStatement . Expression is CallExpression callExpression && ! ( callExpression . Callee is Identifier ) )
427+ {
428+ _sb . Append ( "(" ) ;
429+ Visit ( callExpression . Callee ) ;
430+ _sb . Append ( ")" ) ;
431+ _sb . Append ( "(" ) ;
432+ VisitNodeList ( callExpression . Arguments , appendSeperatorString : "," ) ;
433+ _sb . Append ( ")" ) ;
434+ }
435+ else if ( expressionStatement . Expression is ClassExpression )
436+ {
437+ _sb . Append ( "(" ) ;
438+ Visit ( expressionStatement . Expression ) ;
439+ _sb . Append ( ")" ) ;
440+ }
441+ else
442+ Visit ( expressionStatement . Expression ) ;
391443 }
392444
393445 protected virtual void VisitForStatement ( ForStatement forStatement )
@@ -409,6 +461,8 @@ protected virtual void VisitForStatement(ForStatement forStatement)
409461 }
410462 _sb . Append ( ")" ) ;
411463 Visit ( forStatement . Body ) ;
464+ if ( NodeNeedsSemicolon ( forStatement . Body ) )
465+ _sb . Append ( ";" ) ;
412466 }
413467
414468 protected virtual void VisitForInStatement ( ForInStatement forInStatement )
@@ -419,6 +473,8 @@ protected virtual void VisitForInStatement(ForInStatement forInStatement)
419473 Visit ( forInStatement . Right ) ;
420474 _sb . Append ( ")" ) ;
421475 Visit ( forInStatement . Body ) ;
476+ if ( NodeNeedsSemicolon ( forInStatement . Body ) )
477+ _sb . Append ( ";" ) ;
422478 }
423479
424480 protected virtual void VisitDoWhileStatement ( DoWhileStatement doWhileStatement )
@@ -453,11 +509,20 @@ protected virtual void VisitArrowFunctionExpression(ArrowFunctionExpression arro
453509
454510 protected virtual void VisitUnaryExpression ( UnaryExpression unaryExpression )
455511 {
512+ var op = GetEnumValue ( "unaryoperator" , unaryExpression . Operator ) ;
456513 if ( unaryExpression . Prefix )
457- _sb . Append ( GetEnumValue ( "unaryoperator" , unaryExpression . Operator ) ) ;
514+ {
515+ _sb . Append ( op ) ;
516+ if ( char . IsLetter ( op [ 0 ] ) )
517+ _sb . Append ( " " ) ;
518+ }
519+ if ( ! ( unaryExpression . Argument is Literal ) && ! ( unaryExpression . Argument is UnaryExpression ) )
520+ _sb . Append ( "(" ) ;
458521 Visit ( unaryExpression . Argument ) ;
522+ if ( ! ( unaryExpression . Argument is Literal ) && ! ( unaryExpression . Argument is UnaryExpression ) )
523+ _sb . Append ( ")" ) ;
459524 if ( ! unaryExpression . Prefix )
460- _sb . Append ( GetEnumValue ( "unaryoperator" , unaryExpression . Operator ) ) ;
525+ _sb . Append ( op ) ;
461526 }
462527
463528 protected virtual void VisitUpdateExpression ( UpdateExpression updateExpression )
@@ -498,8 +563,13 @@ protected virtual void VisitNewExpression(NewExpression newExpression)
498563 protected virtual void VisitMemberExpression ( MemberExpression memberExpression )
499564 {
500565 Visit ( memberExpression . Object ) ;
501- _sb . Append ( "." ) ;
566+ if ( memberExpression . Computed )
567+ _sb . Append ( "[" ) ;
568+ else
569+ _sb . Append ( "." ) ;
502570 Visit ( memberExpression . Property ) ;
571+ if ( memberExpression . Computed )
572+ _sb . Append ( "]" ) ;
503573 }
504574
505575 protected virtual void VisitLiteral ( Literal literal )
@@ -514,8 +584,13 @@ protected virtual void VisitIdentifier(Identifier identifier)
514584
515585 protected virtual void VisitFunctionExpression ( IFunction function )
516586 {
587+ if ( ! ( TryGetParentAt ( 1 ) is MethodDefinition ) )
588+ _sb . Append ( "function" ) ;
589+ if ( function . Generator )
590+ _sb . Append ( "*" ) ;
517591 if ( function . Id != null )
518592 {
593+ _sb . Append ( " " ) ;
519594 Visit ( function . Id ) ;
520595 }
521596 _sb . Append ( "(" ) ;
@@ -526,17 +601,20 @@ protected virtual void VisitFunctionExpression(IFunction function)
526601
527602 protected virtual void VisitClassExpression ( ClassExpression classExpression )
528603 {
604+ _sb . Append ( "class " ) ;
529605 if ( classExpression . Id != null )
530606 {
531607 Visit ( classExpression . Id ) ;
532608 }
533609
534610 if ( classExpression . SuperClass != null )
535611 {
612+ _sb . Append ( " extends " ) ;
536613 Visit ( classExpression . SuperClass ) ;
537614 }
538-
615+ _sb . Append ( "{" ) ;
539616 Visit ( classExpression . Body ) ;
617+ _sb . Append ( "}" ) ;
540618 }
541619
542620 protected virtual void VisitExportDefaultDeclaration ( ExportDefaultDeclaration exportDefaultDeclaration )
@@ -658,6 +736,8 @@ protected virtual void VisitForOfStatement(ForOfStatement forOfStatement)
658736 Visit ( forOfStatement . Right ) ;
659737 _sb . Append ( ")" ) ;
660738 Visit ( forOfStatement . Body ) ;
739+ if ( NodeNeedsSemicolon ( forOfStatement . Body ) )
740+ _sb . Append ( ";" ) ;
661741 }
662742
663743 protected virtual void VisitClassDeclaration ( ClassDeclaration classDeclaration )
@@ -792,9 +872,17 @@ protected virtual void VisitConditionalExpression(ConditionalExpression conditio
792872 {
793873 Visit ( conditionalExpression . Test ) ;
794874 _sb . Append ( "?" ) ;
875+ if ( ExpressionNeedsBrackets ( conditionalExpression . Consequent ) )
876+ _sb . Append ( "(" ) ;
795877 Visit ( conditionalExpression . Consequent ) ;
878+ if ( ExpressionNeedsBrackets ( conditionalExpression . Consequent ) )
879+ _sb . Append ( ")" ) ;
796880 _sb . Append ( ":" ) ;
881+ if ( ExpressionNeedsBrackets ( conditionalExpression . Alternate ) )
882+ _sb . Append ( "(" ) ;
797883 Visit ( conditionalExpression . Alternate ) ;
884+ if ( ExpressionNeedsBrackets ( conditionalExpression . Alternate ) )
885+ _sb . Append ( ")" ) ;
798886 }
799887
800888 protected virtual void VisitCallExpression ( CallExpression callExpression )
@@ -807,9 +895,22 @@ protected virtual void VisitCallExpression(CallExpression callExpression)
807895
808896 protected virtual void VisitBinaryExpression ( BinaryExpression binaryExpression )
809897 {
898+ if ( ExpressionNeedsBrackets ( binaryExpression . Left ) )
899+ _sb . Append ( "(" ) ;
810900 Visit ( binaryExpression . Left ) ;
811- _sb . Append ( GetEnumValue ( "operator" , binaryExpression . Operator ) ) ;
901+ if ( ExpressionNeedsBrackets ( binaryExpression . Left ) )
902+ _sb . Append ( ")" ) ;
903+ var op = GetEnumValue ( "operator" , binaryExpression . Operator ) ;
904+ if ( char . IsLetter ( op [ 0 ] ) )
905+ _sb . Append ( " " ) ;
906+ _sb . Append ( op ) ;
907+ if ( char . IsLetter ( op [ 0 ] ) )
908+ _sb . Append ( " " ) ;
909+ if ( ExpressionNeedsBrackets ( binaryExpression . Right ) )
910+ _sb . Append ( "(" ) ;
812911 Visit ( binaryExpression . Right ) ;
912+ if ( ExpressionNeedsBrackets ( binaryExpression . Right ) )
913+ _sb . Append ( ")" ) ;
813914 }
814915
815916 protected virtual void VisitArrayExpression ( ArrayExpression arrayExpression )
@@ -821,9 +922,14 @@ protected virtual void VisitArrayExpression(ArrayExpression arrayExpression)
821922
822923 protected virtual void VisitAssignmentExpression ( AssignmentExpression assignmentExpression )
823924 {
925+ var op = GetEnumValue ( "assignmentoperator" , assignmentExpression . Operator ) ;
824926 Visit ( assignmentExpression . Left ) ;
825- _sb . Append ( "=" ) ;
927+ _sb . Append ( op ) ;
928+ if ( ExpressionNeedsBrackets ( assignmentExpression . Right ) && ! ( assignmentExpression . Right is AssignmentExpression ) )
929+ _sb . Append ( "(" ) ;
826930 Visit ( assignmentExpression . Right ) ;
931+ if ( ExpressionNeedsBrackets ( assignmentExpression . Right ) && ! ( assignmentExpression . Right is AssignmentExpression ) )
932+ _sb . Append ( ")" ) ;
827933 }
828934
829935 protected virtual void VisitContinueStatement ( ContinueStatement continueStatement )
@@ -917,12 +1023,25 @@ node is ForInStatement ||
9171023 node is ForOfStatement ||
9181024 node is ForStatement ||
9191025 node is FunctionDeclaration ||
1026+ node is ReturnStatement ||
1027+ node is ThrowStatement ||
9201028 node is ClassDeclaration )
9211029 return false ;
9221030 if ( node is ExportNamedDeclaration end )
9231031 return NodeNeedsSemicolon ( end . Declaration ) ;
9241032 return true ;
9251033 }
1034+
1035+ public bool ExpressionNeedsBrackets ( Node ? node )
1036+ {
1037+ if ( node is AssignmentExpression )
1038+ return true ;
1039+ if ( node is SequenceExpression )
1040+ return true ;
1041+ if ( node is ConditionalExpression )
1042+ return true ;
1043+ return false ;
1044+ }
9261045 }
9271046 }
9281047}
0 commit comments