Skip to content

Commit ae80e25

Browse files
author
George Kinsman
committed
feat(api): add configuration to specify that fields may also be included as well as properties using WithTypeMembers
1 parent c31ec95 commit ae80e25

File tree

4 files changed

+74
-9
lines changed

4 files changed

+74
-9
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public static TypeScriptGenerator CreateDefault() => new TypeScriptGenerator()
6161
.WithPropertyTypeFormatter<DateTimeOffset>(t => "string")
6262
.WithEnumFormatter(EnumFormatter.ValueNamedEnumFormatter, EnumFormatter.UnionStringEnumPropertyTypeFormatter)
6363
.WithQuoteStyle(QuoteStyle.Single)
64+
.WithTypeMembers(MemberType.PropertiesOnly)
6465
.WithDictionaryPropertyFormatter(DictionaryPropertyFormatter.KeyValueFormatter)
6566
.WithCollectionPropertyFormatter(CollectionPropertyFormatter.Format)
6667
.WithNamespace("Api")

src/Typescript.Tests/Simple/SimpleGeneratorTests.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,5 +78,42 @@ public void Generator_TypeWithCustomValueTypeProp_ShouldRenderCustomTypeSeparate
7878

7979
this.Assent(generated.Types);
8080
}
81+
82+
83+
class TestTypeWithFields
84+
{
85+
#pragma warning disable 414
86+
public string StringField = "123";
87+
public int IntField = 4;
88+
#pragma warning restore 414
89+
}
90+
91+
[Fact]
92+
public void Generator_TypeWithFields_ShouldRenderFields()
93+
{
94+
var generator = TypeScriptGenerator.CreateDefault()
95+
.WithTypeMembers(MemberType.PropertiesAndFields);
96+
var generated = generator.Generate(new[] {typeof(TestTypeWithFields)});
97+
98+
this.Assent(generated.Types);
99+
}
100+
101+
class TestTypeWithFieldsAndProps
102+
{
103+
#pragma warning disable 414
104+
public string StringField = "123";
105+
public int IntField = 4;
106+
#pragma warning restore 414
107+
public string StringProp { get; set; }
108+
}
109+
110+
[Fact]
111+
public void Generator_TypeWithFieldsAndPropsButSetToPropsOnly_ShouldOnlyRenderProps()
112+
{
113+
var generator = TypeScriptGenerator.CreateDefault();
114+
var generated = generator.Generate(new[] {typeof(TestTypeWithFieldsAndProps)});
115+
116+
this.Assent(generated.Types);
117+
}
81118
}
82119
}

src/Typescriptr/MemberType.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace Typescriptr
2+
{
3+
public enum MemberType
4+
{
5+
PropertiesOnly,
6+
PropertiesAndFields
7+
}
8+
}

src/Typescriptr/TypeScriptGenerator.cs

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections;
33
using System.Collections.Generic;
44
using System.Linq;
5+
using System.Reflection;
56
using System.Security.Cryptography;
67
using System.Text;
78
using Typescriptr.Exceptions;
@@ -25,7 +26,9 @@ public class TypeScriptGenerator
2526
private FormatEnumProperty _enumPropertyFormatter;
2627
private FormatDictionaryProperty _dictionaryPropertyFormatter;
2728
private FormatCollectionProperty _collectionPropertyFormatter;
28-
29+
30+
private QuoteStyle _quoteStyle;
31+
private MemberType _memberTypes;
2932
private bool _useCamelCasePropertyNames;
3033

3134
private readonly Dictionary<Type, string> _propTypeMap = new Dictionary<Type, string>()
@@ -61,11 +64,18 @@ private TypeScriptGenerator()
6164
.WithEnumFormatter(EnumFormatter.ValueNamedEnumFormatter,
6265
EnumFormatter.UnionStringEnumPropertyTypeFormatter)
6366
.WithQuoteStyle(QuoteStyle.Single)
67+
.WithTypeMembers(MemberType.PropertiesOnly)
6468
.WithDictionaryPropertyFormatter(DictionaryPropertyFormatter.KeyValueFormatter)
6569
.WithCollectionPropertyFormatter(CollectionPropertyFormatter.Format)
6670
.WithNamespace("Api")
6771
.WithCamelCasedPropertyNames();
6872

73+
public TypeScriptGenerator WithTypeMembers(MemberType memberTypes)
74+
{
75+
_memberTypes = memberTypes;
76+
return this;
77+
}
78+
6979
public TypeScriptGenerator WithCamelCasedPropertyNames(bool useCamelCasedPropertyNames = true)
7080
{
7181
_useCamelCasePropertyNames = useCamelCasedPropertyNames;
@@ -118,7 +128,7 @@ public TypeScriptGenerator WithPropertyTypeFormatter<TType>(Func<Type, string> c
118128
private readonly HashSet<string> _enumNames = new HashSet<string>();
119129
private readonly Stack<Type> _typeStack = new Stack<Type>();
120130
private string _namespace;
121-
private QuoteStyle _quoteStyle;
131+
122132

123133
public GenerationResult Generate(IEnumerable<Type> types)
124134
{
@@ -159,18 +169,27 @@ private void RenderEnum(StringBuilder builder, Type enumType)
159169

160170
private void RenderType(StringBuilder builder, Type type)
161171
{
162-
var properties = type.GetProperties();
172+
var memberTypesToInclude = _memberTypes == MemberType.PropertiesOnly
173+
? MemberTypes.Property
174+
: MemberTypes.Property | MemberTypes.Field;
175+
176+
var members = type.GetMembers().Where(m => memberTypesToInclude.HasFlag(m.MemberType));
163177
builder.AppendLine($"interface {type.Name} {{");
164178

165-
foreach (var prop in properties)
179+
foreach (var memberInfo in members)
166180
{
167-
var propType = prop.PropertyType;
168-
var propName = prop.Name;
169-
181+
Type memberType = null;
182+
if (memberInfo is PropertyInfo p)
183+
memberType = p.PropertyType;
184+
else if (memberInfo is FieldInfo f)
185+
memberType = f.FieldType;
186+
if (memberType == null) throw new InvalidOperationException();
187+
188+
var memberName = memberInfo.Name;
170189
if (_useCamelCasePropertyNames)
171-
propName = propName.ToCamelCase();
190+
memberName = memberName.ToCamelCase();
172191

173-
RenderProperty(builder, propType, propName);
192+
RenderProperty(builder, memberType, memberName);
174193
}
175194

176195
builder.AppendLine("}");

0 commit comments

Comments
 (0)