Skip to content
This repository was archived by the owner on Aug 24, 2026. It is now read-only.

Commit d0d1b41

Browse files
committed
improve public API
1 parent 844fad6 commit d0d1b41

9 files changed

Lines changed: 196 additions & 189 deletions

src/Esprima/Utils/AstToJavascript.cs

Lines changed: 34 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,77 +2,71 @@
22

33
namespace Esprima.Utils;
44

5+
public record class AstToJavascriptOptions
6+
{
7+
public static readonly AstToJavascriptOptions Default = new();
8+
9+
protected internal virtual AstToJavascriptConverter CreateConverter(JavascriptTextWriter writer) => new AstToJavascriptConverter(writer, this);
10+
}
11+
512
public static class AstToJavascript
613
{
7-
public record class Options
14+
public static string ToJavascriptString(this Node node)
815
{
9-
public static readonly Options Default = new();
16+
return ToJavascriptString(node, JavascriptTextWriterOptions.Default, AstToJavascriptOptions.Default);
1017
}
1118

12-
public static string ToJavascriptString(this Node node, AstToJavascriptConverter.Factory? converterFactory = null)
19+
public static string ToJavascriptString(this Node node, KnRJavascriptTextWriterOptions formattingOptions)
1320
{
14-
JavascriptTextWriter.Factory writerFactory = static (writer, formattingOptions) => new JavascriptTextWriter(writer, formattingOptions);
15-
return ToJavascriptString(node, writerFactory, JavascriptTextWriter.Options.Default, Options.Default, converterFactory);
21+
return ToJavascriptString(node, formattingOptions, AstToJavascriptOptions.Default);
1622
}
1723

18-
public static string ToJavascriptString(this Node node, KnRJavascriptTextWriter.Options formattingOptions, AstToJavascriptConverter.Factory? converterFactory = null)
24+
public static string ToJavascriptString(this Node node, bool beautify)
1925
{
20-
JavascriptTextWriter.Factory writerFactory = static (writer, formattingOptions) => new KnRJavascriptTextWriter(writer, formattingOptions);
21-
return ToJavascriptString(node, writerFactory, formattingOptions, Options.Default, converterFactory);
26+
return ToJavascriptString(node, beautify ? KnRJavascriptTextWriterOptions.Default : JavascriptTextWriterOptions.Default, AstToJavascriptOptions.Default);
2227
}
2328

24-
public static string ToJavascriptString(this Node node, bool beautify, AstToJavascriptConverter.Factory? converterFactory = null)
29+
public static string ToJavascriptString(this Node node, JavascriptTextWriterOptions writerOptions, AstToJavascriptOptions options)
2530
{
26-
if (beautify)
27-
{
28-
return ToJavascriptString(node, KnRJavascriptTextWriter.Options.Default, converterFactory);
29-
}
30-
else
31+
using (var writer = new StringWriter())
3132
{
32-
return ToJavascriptString(node, converterFactory);
33+
WriteJavascript(node, writer, writerOptions, options);
34+
return writer.ToString();
3335
}
3436
}
3537

36-
public static string ToJavascriptString(this Node node, JavascriptTextWriter.Factory writerFactory, JavascriptTextWriter.Options formattingOptions, Options options, AstToJavascriptConverter.Factory? converterFactory = null)
38+
public static void WriteJavascript(this Node node, TextWriter writer)
3739
{
38-
if (writerFactory is null)
39-
{
40-
throw new ArgumentNullException(nameof(writerFactory));
41-
}
42-
43-
using (var writer = new StringWriter())
44-
{
45-
WriteJavascript(node, writerFactory(writer, formattingOptions), options, converterFactory);
46-
return writer.ToString();
47-
}
40+
WriteJavascript(node, writer, JavascriptTextWriterOptions.Default, AstToJavascriptOptions.Default);
4841
}
4942

50-
public static void WriteJavascript(this Node node, TextWriter writer, AstToJavascriptConverter.Factory? converterFactory = null)
43+
public static void WriteJavascript(this Node node, TextWriter writer, KnRJavascriptTextWriterOptions formattingOptions)
5144
{
52-
WriteJavascript(node, new JavascriptTextWriter(writer, JavascriptTextWriter.Options.Default), Options.Default, converterFactory);
45+
WriteJavascript(node, writer, formattingOptions, AstToJavascriptOptions.Default);
5346
}
5447

55-
public static void WriteJavascript(this Node node, TextWriter writer, KnRJavascriptTextWriter.Options formattingOptions, AstToJavascriptConverter.Factory? converterFactory = null)
48+
public static void WriteJavascript(this Node node, TextWriter writer, bool beautify)
5649
{
57-
WriteJavascript(node, new KnRJavascriptTextWriter(writer, formattingOptions), Options.Default, converterFactory);
50+
WriteJavascript(node, writer, beautify ? KnRJavascriptTextWriterOptions.Default : JavascriptTextWriterOptions.Default, AstToJavascriptOptions.Default);
5851
}
5952

60-
public static void WriteJavascript(this Node node, TextWriter writer, bool beautify, AstToJavascriptConverter.Factory? converterFactory = null)
53+
public static void WriteJavascript(this Node node, TextWriter writer, JavascriptTextWriterOptions writerOptions, AstToJavascriptOptions options)
6154
{
62-
if (beautify)
55+
if (writerOptions is null)
6356
{
64-
WriteJavascript(node, writer, KnRJavascriptTextWriter.Options.Default, converterFactory);
65-
}
66-
else
67-
{
68-
WriteJavascript(node, writer, converterFactory);
57+
throw new ArgumentNullException(nameof(writerOptions));
6958
}
59+
60+
WriteJavascript(node, writerOptions.CreateWriter(writer), options);
7061
}
7162

72-
public static void WriteJavascript(this Node node, JavascriptTextWriter writer, Options options, AstToJavascriptConverter.Factory? converterFactory = null)
63+
public static void WriteJavascript(this Node node, JavascriptTextWriter writer, AstToJavascriptOptions options)
7364
{
74-
converterFactory ??= static (writer, options) => new AstToJavascriptConverter(writer, options);
65+
if (options is null)
66+
{
67+
throw new ArgumentNullException(nameof(options));
68+
}
7569

76-
converterFactory(writer, options).Convert(node);
70+
options.CreateConverter(writer).Convert(node);
7771
}
7872
}

src/Esprima/Utils/AstToJavascriptConverter.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ public partial class AstToJavascriptConverter : AstVisitor
1414
// * Visit identifiers using VisitAuxiliaryNode when they are binding identifiers (declarations) and visit them using VisitRootExpression when they are identifier references (actual expressions).
1515
// * Visit any other nodes using VisitAuxiliaryNode / VisitAuxiliaryNodeList.
1616

17-
public delegate AstToJavascriptConverter Factory(JavascriptTextWriter writer, AstToJavascript.Options options);
18-
1917
private static readonly object s_lastSwitchCaseFlag = new();
2018
private static readonly object s_forLoopInitDeclarationFlag = new();
2119

@@ -24,7 +22,7 @@ public partial class AstToJavascriptConverter : AstVisitor
2422
private ExpressionFlags _currentExpressionFlags;
2523
private object? _currentAuxiliaryNodeContext;
2624

27-
public AstToJavascriptConverter(JavascriptTextWriter writer, AstToJavascript.Options options)
25+
public AstToJavascriptConverter(JavascriptTextWriter writer, AstToJavascriptOptions options)
2826
{
2927
Writer = writer ?? throw new ArgumentNullException(nameof(writer));
3028

src/Esprima/Utils/AstToJson.cs

Lines changed: 43 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -8,76 +8,81 @@ public enum LocationMembersPlacement
88
Start
99
}
1010

11-
public static class AstToJson
11+
internal enum AstToJsonTestCompatibilityMode
1212
{
13-
public record class Options
14-
{
15-
public static readonly Options Default = new();
16-
17-
public bool IncludingLineColumn { get; init; }
18-
public bool IncludingRange { get; init; }
19-
public LocationMembersPlacement LocationMembersPlacement { get; init; }
20-
/// <summary>
21-
/// This switch is intended for enabling a compatibility mode for <see cref="AstToJsonConverter"/> to build a JSON output
22-
/// which matches the format of the test fixtures of the original Esprima project.
23-
/// </summary>
24-
internal TestCompatibilityMode TestCompatibilityMode { get; init; }
25-
}
13+
None,
14+
EsprimaOrg,
15+
}
2616

27-
internal enum TestCompatibilityMode
28-
{
29-
None,
30-
EsprimaOrg,
31-
}
17+
public record class AstToJsonOptions
18+
{
19+
public static readonly AstToJsonOptions Default = new();
3220

33-
public static string ToJsonString(this Node node, AstToJsonConverter.Factory? converterFactory = null)
21+
public bool IncludingLineColumn { get; init; }
22+
public bool IncludingRange { get; init; }
23+
public LocationMembersPlacement LocationMembersPlacement { get; init; }
24+
/// <summary>
25+
/// This switch is intended for enabling a compatibility mode for <see cref="AstToJsonConverter"/> to build a JSON output
26+
/// which matches the format of the test fixtures of the original Esprima project.
27+
/// </summary>
28+
internal AstToJsonTestCompatibilityMode TestCompatibilityMode { get; init; }
29+
30+
protected internal virtual AstToJsonConverter CreateConverter(JsonWriter writer) => new AstToJsonConverter(writer, this);
31+
}
32+
33+
public static class AstToJson
34+
{
35+
public static string ToJsonString(this Node node)
3436
{
35-
return ToJsonString(node, indent: null, converterFactory);
37+
return ToJsonString(node, indent: null);
3638
}
3739

38-
public static string ToJsonString(this Node node, string? indent, AstToJsonConverter.Factory? converterFactory = null)
40+
public static string ToJsonString(this Node node, string? indent)
3941
{
40-
return ToJsonString(node, Options.Default, indent, converterFactory);
42+
return ToJsonString(node, AstToJsonOptions.Default, indent);
4143
}
4244

43-
public static string ToJsonString(this Node node, Options options, AstToJsonConverter.Factory? converterFactory = null)
45+
public static string ToJsonString(this Node node, AstToJsonOptions options)
4446
{
45-
return ToJsonString(node, options, indent: null, converterFactory);
47+
return ToJsonString(node, options, indent: null);
4648
}
4749

48-
public static string ToJsonString(this Node node, Options options, string? indent, AstToJsonConverter.Factory? converterFactory = null)
50+
public static string ToJsonString(this Node node, AstToJsonOptions options, string? indent)
4951
{
5052
using (var writer = new StringWriter())
5153
{
52-
WriteJson(node, writer, options, indent, converterFactory);
54+
WriteJson(node, writer, options, indent);
5355
return writer.ToString();
5456
}
5557
}
5658

57-
public static void WriteJson(this Node node, TextWriter writer, AstToJsonConverter.Factory? converterFactory = null)
59+
public static void WriteJson(this Node node, TextWriter writer)
5860
{
59-
WriteJson(node, writer, indent: null, converterFactory);
61+
WriteJson(node, writer, indent: null);
6062
}
6163

62-
public static void WriteJson(this Node node, TextWriter writer, string? indent, AstToJsonConverter.Factory? converterFactory = null)
64+
public static void WriteJson(this Node node, TextWriter writer, string? indent)
6365
{
64-
WriteJson(node, writer, Options.Default, indent, converterFactory);
66+
WriteJson(node, writer, AstToJsonOptions.Default, indent);
6567
}
6668

67-
public static void WriteJson(this Node node, TextWriter writer, Options options, AstToJsonConverter.Factory? converterFactory = null)
69+
public static void WriteJson(this Node node, TextWriter writer, AstToJsonOptions options)
6870
{
69-
WriteJson(node, writer, options, indent: null, converterFactory);
71+
WriteJson(node, writer, options, indent: null);
7072
}
7173

72-
public static void WriteJson(this Node node, TextWriter writer, Options options, string? indent, AstToJsonConverter.Factory? converterFactory = null)
74+
public static void WriteJson(this Node node, TextWriter writer, AstToJsonOptions options, string? indent)
7375
{
74-
WriteJson(node, new JsonTextWriter(writer, indent), options, converterFactory);
76+
WriteJson(node, new JsonTextWriter(writer, indent), options);
7577
}
7678

77-
public static void WriteJson(this Node node, JsonWriter writer, Options options, AstToJsonConverter.Factory? converterFactory = null)
79+
public static void WriteJson(this Node node, JsonWriter writer, AstToJsonOptions options)
7880
{
79-
converterFactory ??= static (writer, options) => new AstToJsonConverter(writer, options);
81+
if (options is null)
82+
{
83+
throw new ArgumentNullException(nameof(options));
84+
}
8085

81-
converterFactory(writer, options).Convert(node);
86+
options.CreateConverter(writer).Convert(node);
8287
}
8388
}

src/Esprima/Utils/AstToJsonConverter.cs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,13 @@ namespace Esprima.Utils;
1010

1111
public class AstToJsonConverter : AstVisitor
1212
{
13-
public delegate AstToJsonConverter Factory(JsonWriter writer, AstToJson.Options options);
14-
1513
private readonly JsonWriter _writer;
1614
private protected readonly bool _includeLineColumn;
1715
private protected readonly bool _includeRange;
1816
private protected readonly LocationMembersPlacement _locationMembersPlacement;
19-
private protected readonly AstToJson.TestCompatibilityMode _testCompatibilityMode;
17+
private protected readonly AstToJsonTestCompatibilityMode _testCompatibilityMode;
2018

21-
public AstToJsonConverter(JsonWriter writer, AstToJson.Options options)
19+
public AstToJsonConverter(JsonWriter writer, AstToJsonOptions options)
2220
{
2321
_writer = writer ?? throw new ArgumentNullException(nameof(writer));
2422

@@ -232,7 +230,7 @@ public void Convert(Node node)
232230
Member("generator", ((IFunction) arrowFunctionExpression).Generator);
233231
Member("expression", arrowFunctionExpression.Expression);
234232
// original Esprima doesn't include this information yet
235-
if (_testCompatibilityMode != AstToJson.TestCompatibilityMode.EsprimaOrg)
233+
if (_testCompatibilityMode != AstToJsonTestCompatibilityMode.EsprimaOrg)
236234
{
237235
Member("strict", arrowFunctionExpression.Strict);
238236
}
@@ -444,7 +442,7 @@ public void Convert(Node node)
444442
Member("source", exportAllDeclaration.Source);
445443

446444
// original Esprima doesn't include this information yet
447-
if (_testCompatibilityMode != AstToJson.TestCompatibilityMode.EsprimaOrg)
445+
if (_testCompatibilityMode != AstToJsonTestCompatibilityMode.EsprimaOrg)
448446
{
449447
Member("exported", exportAllDeclaration.Exported);
450448
if (exportAllDeclaration.Assertions.Count > 0)
@@ -475,7 +473,7 @@ public void Convert(Node node)
475473
Member("specifiers", exportNamedDeclaration.Specifiers);
476474
Member("source", exportNamedDeclaration.Source);
477475
// original Esprima doesn't include this information yet
478-
if (_testCompatibilityMode != AstToJson.TestCompatibilityMode.EsprimaOrg && exportNamedDeclaration.Assertions.Count > 0)
476+
if (_testCompatibilityMode != AstToJsonTestCompatibilityMode.EsprimaOrg && exportNamedDeclaration.Assertions.Count > 0)
479477
{
480478
Member("assertions", exportNamedDeclaration.Assertions);
481479
}
@@ -559,7 +557,7 @@ public void Convert(Node node)
559557
Member("generator", functionDeclaration.Generator);
560558
Member("expression", ((IFunction) functionDeclaration).Expression);
561559
// original Esprima doesn't include this information yet
562-
if (_testCompatibilityMode != AstToJson.TestCompatibilityMode.EsprimaOrg)
560+
if (_testCompatibilityMode != AstToJsonTestCompatibilityMode.EsprimaOrg)
563561
{
564562
Member("strict", functionDeclaration.Strict);
565563
}
@@ -579,7 +577,7 @@ public void Convert(Node node)
579577
Member("generator", functionExpression.Generator);
580578
Member("expression", ((IFunction) functionExpression).Expression);
581579
// original Esprima doesn't include this information yet
582-
if (_testCompatibilityMode != AstToJson.TestCompatibilityMode.EsprimaOrg)
580+
if (_testCompatibilityMode != AstToJsonTestCompatibilityMode.EsprimaOrg)
583581
{
584582
Member("strict", functionExpression.Strict);
585583
}
@@ -630,7 +628,7 @@ public ImportCompat() : base(Nodes.Import) { }
630628
{
631629
// original Esprima uses CallExpression to represent dynamic imports currently,
632630
// so we need to rewrite our representation to match this expectation
633-
if (_testCompatibilityMode == AstToJson.TestCompatibilityMode.EsprimaOrg)
631+
if (_testCompatibilityMode == AstToJsonTestCompatibilityMode.EsprimaOrg)
634632
{
635633
const string importToken = "import";
636634

@@ -651,7 +649,7 @@ public ImportCompat() : base(Nodes.Import) { }
651649

652650
using (StartNodeObject(import))
653651
{
654-
if (_testCompatibilityMode != AstToJson.TestCompatibilityMode.EsprimaOrg)
652+
if (_testCompatibilityMode != AstToJsonTestCompatibilityMode.EsprimaOrg)
655653
{
656654
Member("source", import.Source);
657655

@@ -744,7 +742,7 @@ public ImportCompat() : base(Nodes.Import) { }
744742
switch (value)
745743
{
746744
case null:
747-
if (_testCompatibilityMode != AstToJson.TestCompatibilityMode.EsprimaOrg && literal.TokenType == TokenType.RegularExpression)
745+
if (_testCompatibilityMode != AstToJsonTestCompatibilityMode.EsprimaOrg && literal.TokenType == TokenType.RegularExpression)
748746
{
749747
// This is how esprima.org actually renders regexes since it relies on Regex.toString
750748
_writer.String(literal.Raw);
@@ -880,7 +878,7 @@ public ImportCompat() : base(Nodes.Import) { }
880878
Member("sourceType", program.SourceType);
881879

882880
// original Esprima doesn't include this information yet
883-
if (_testCompatibilityMode != AstToJson.TestCompatibilityMode.EsprimaOrg && program is Script s)
881+
if (_testCompatibilityMode != AstToJsonTestCompatibilityMode.EsprimaOrg && program is Script s)
884882
{
885883
Member("strict", s.Strict);
886884
}

src/Esprima/Utils/JavascriptTextWriter.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,21 @@ namespace Esprima.Utils;
77

88
public delegate ref readonly NodeList<T> NodePropertyListValueAccessor<T>(Node node) where T : Node?;
99

10+
public record class JavascriptTextWriterOptions
11+
{
12+
public static readonly JavascriptTextWriterOptions Default = new();
13+
14+
protected internal virtual JavascriptTextWriter CreateWriter(TextWriter writer) => new JavascriptTextWriter(writer, this);
15+
}
16+
1017
/// <summary>
1118
/// Base Javascript text writer (code formatter) which uses the most compact possible (i.e. minimal) format.
1219
/// </summary>
1320
public partial class JavascriptTextWriter
1421
{
15-
public record class Options
16-
{
17-
public static readonly Options Default = new();
18-
}
19-
20-
public delegate JavascriptTextWriter Factory(TextWriter writer, Options options);
21-
2222
private readonly TextWriter _writer;
2323

24-
public JavascriptTextWriter(TextWriter writer, Options options)
24+
public JavascriptTextWriter(TextWriter writer, JavascriptTextWriterOptions options)
2525
{
2626
_writer = writer ?? throw new ArgumentNullException(nameof(writer));
2727

src/Esprima/Utils/Jsx/JsxAstToJsonConverter.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,16 @@
33

44
namespace Esprima.Utils.Jsx;
55

6+
public record class JsxAstToJsonOptions : AstToJsonOptions
7+
{
8+
public static new readonly JsxAstToJsonOptions Default = new();
9+
10+
protected internal override AstToJsonConverter CreateConverter(JsonWriter writer) => new JsxAstToJsonConverter(writer, this);
11+
}
12+
613
public class JsxAstToJsonConverter : AstToJsonConverter, IJsxAstVisitor
714
{
8-
public JsxAstToJsonConverter(JsonWriter writer, AstToJson.Options options)
15+
public JsxAstToJsonConverter(JsonWriter writer, JsxAstToJsonOptions options)
916
: base(writer, options)
1017
{
1118
}

0 commit comments

Comments
 (0)