Skip to content

Commit 11bdb2a

Browse files
author
mohammed belhaj
committed
Added Addtional properties feature.
u
1 parent ddd2b45 commit 11bdb2a

15 files changed

Lines changed: 286 additions & 84 deletions

src/TypeGen/TypeGen.Core/Generator/Generator.cs

Lines changed: 54 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.Collections;
32
using System.Collections.Generic;
43
using System.IO;
54
using System.Linq;
@@ -12,6 +11,7 @@
1211
using TypeGen.Core.Logging;
1312
using TypeGen.Core.Metadata;
1413
using TypeGen.Core.SpecGeneration;
14+
using TypeGen.Core.SpecGeneration.Builders.Traits;
1515
using TypeGen.Core.Storage;
1616
using TypeGen.Core.TypeAnnotations;
1717
using TypeGen.Core.Validation;
@@ -65,8 +65,8 @@ public Generator(GeneratorOptions options, ILogger logger = null)
6565
_typeService = new TypeService(_metadataReaderFactory, generatorOptionsProvider);
6666
_typeDependencyService = new TypeDependencyService(_typeService, _metadataReaderFactory, generatorOptionsProvider);
6767
_templateService = new TemplateService(internalStorage, generatorOptionsProvider);
68-
6968
_tsContentGenerator = new TsContentGenerator(_typeDependencyService,
69+
7070
_typeService,
7171
_templateService,
7272
new TsContentParser(_fileSystem),
@@ -140,6 +140,7 @@ public IEnumerable<string> Generate(IEnumerable<GenerationSpec> generationSpecs)
140140
Requires.NotNullOrEmpty(generationSpecs, nameof(generationSpecs));
141141

142142
generationSpecs = generationSpecs.ToList();
143+
143144
var files = new List<string>();
144145
_generationContext = new GenerationContext(_fileSystem);
145146

@@ -153,7 +154,7 @@ public IEnumerable<string> Generate(IEnumerable<GenerationSpec> generationSpecs)
153154
_metadataReaderFactory.GenerationSpec = generationSpec;
154155

155156
foreach (KeyValuePair<Type, TypeSpec> kvp in generationSpec.TypeSpecs)
156-
files.AddRange(GenerateMarkedType(kvp.Key));
157+
files.AddRange(GenerateMarkedType(kvp.Key, kvp.Value));
157158
}
158159

159160
files = files.Distinct().ToList();
@@ -326,15 +327,15 @@ private IEnumerable<string> GenerateIndexFile(IEnumerable<string> generatedFiles
326327
return new[] { filename };
327328
}
328329

329-
private IEnumerable<string> GenerateMarkedType(Type type)
330+
private IEnumerable<string> GenerateMarkedType(Type type, TypeSpec typeSpec)
330331
{
331332
if (Options.IsTypeBlacklisted(type)) return Enumerable.Empty<string>();
332333

333334
IEnumerable<string> files = Enumerable.Empty<string>();
334335

335336
_generationContext.BeginTypeGeneration(type);
336337
_generationContext.AddGeneratedType(type);
337-
ExecuteWithTypeContextLogging(() => { files = GenerateType(type); });
338+
ExecuteWithTypeContextLogging(() => { files = GenerateType(type, typeSpec); });
338339
_generationContext.EndTypeGeneration();
339340

340341
return files.Distinct();
@@ -346,50 +347,51 @@ private IEnumerable<string> GenerateMarkedType(Type type)
346347
/// </summary>
347348
/// <param name="type"></param>
348349
/// <returns>Generated TypeScript file paths (relative to the Options.BaseOutputDirectory)</returns>
349-
private IEnumerable<string> GenerateType(Type type)
350+
private IEnumerable<string> GenerateType(Type type, TypeSpec typeSpec)
350351
{
351352
var classAttribute = _metadataReaderFactory.GetInstance().GetAttribute<ExportTsClassAttribute>(type);
352353
var interfaceAttribute = _metadataReaderFactory.GetInstance().GetAttribute<ExportTsInterfaceAttribute>(type);
353354
var enumAttribute = _metadataReaderFactory.GetInstance().GetAttribute<ExportTsEnumAttribute>(type);
354355

355356
if (classAttribute != null)
356357
{
357-
return GenerateClass(type, classAttribute);
358+
return GenerateClass(type, classAttribute, typeSpec);
358359
}
359360

360361
if (interfaceAttribute != null)
361362
{
362-
return GenerateInterface(type, interfaceAttribute);
363+
return GenerateInterface(type, interfaceAttribute, typeSpec);
363364
}
364365

365366
if (enumAttribute != null)
366367
{
367368
return GenerateEnum(type, enumAttribute);
368369
}
369370

370-
return GenerateNotMarkedType(type, Options.BaseOutputDirectory);
371+
return GenerateNotMarkedType(type, Options.BaseOutputDirectory, typeSpec);
371372
}
372-
373+
373374
/// <summary>
374375
/// Generates TypeScript files for types that are not marked with an ExportTs... attribute
375376
/// </summary>
376377
/// <param name="type"></param>
377378
/// <param name="outputDirectory"></param>
379+
/// <param name="typeSpec"></param>
378380
/// <returns>Generated TypeScript file paths (relative to the Options.BaseOutputDirectory)</returns>
379-
private IEnumerable<string> GenerateNotMarkedType(Type type, string outputDirectory)
381+
private IEnumerable<string> GenerateNotMarkedType(Type type, string outputDirectory, TypeSpec typeSpec)
380382
{
381383
if (Options.IsTypeBlacklisted(type)) return Enumerable.Empty<string>();
382384

383385
var typeInfo = type.GetTypeInfo();
384386
if (typeInfo.IsClass || typeInfo.IsStruct())
385387
{
386388
return Options.ExportTypesAsInterfacesByDefault
387-
? GenerateInterface(type, new ExportTsInterfaceAttribute { OutputDir = outputDirectory })
388-
: GenerateClass(type, new ExportTsClassAttribute { OutputDir = outputDirectory });
389+
? GenerateInterface(type, new ExportTsInterfaceAttribute { OutputDir = outputDirectory }, typeSpec)
390+
: GenerateClass(type, new ExportTsClassAttribute { OutputDir = outputDirectory }, typeSpec);
389391
}
390392

391393
if (typeInfo.IsInterface)
392-
return GenerateInterface(type, new ExportTsInterfaceAttribute { OutputDir = outputDirectory });
394+
return GenerateInterface(type, new ExportTsInterfaceAttribute { OutputDir = outputDirectory }, typeSpec);
393395

394396
if (typeInfo.IsEnum)
395397
return GenerateEnum(type, new ExportTsEnumAttribute { OutputDir = outputDirectory });
@@ -402,11 +404,12 @@ private IEnumerable<string> GenerateNotMarkedType(Type type, string outputDirect
402404
/// </summary>
403405
/// <param name="type"></param>
404406
/// <param name="classAttribute"></param>
407+
/// <param name="typeSpec"></param>
405408
/// <returns>Generated TypeScript file paths (relative to the Options.BaseOutputDirectory)</returns>
406-
private IEnumerable<string> GenerateClass(Type type, ExportTsClassAttribute classAttribute)
409+
private IEnumerable<string> GenerateClass(Type type, ExportTsClassAttribute classAttribute, TypeSpec typeSpec)
407410
{
408411
string outputDir = classAttribute.OutputDir;
409-
IEnumerable<string> dependenciesGenerationResult = GenerateTypeDependencies(type, outputDir);
412+
IEnumerable<string> dependenciesGenerationResult = GenerateTypeDependencies(type, outputDir, typeSpec);
410413

411414
// get text for sections
412415

@@ -428,7 +431,7 @@ private IEnumerable<string> GenerateClass(Type type, ExportTsClassAttribute clas
428431
}
429432

430433
string importsText = _tsContentGenerator.GetImportsText(type, outputDir);
431-
string propertiesText = GetClassPropertiesText(type);
434+
string propertiesText = GetClassPropertiesText(type, typeSpec.AdditionalClassProperties);
432435

433436
// generate the file content
434437

@@ -458,11 +461,12 @@ private IEnumerable<string> GenerateClass(Type type, ExportTsClassAttribute clas
458461
/// </summary>
459462
/// <param name="type"></param>
460463
/// <param name="interfaceAttribute"></param>
464+
/// <param name="typeSpec"></param>
461465
/// <returns>Generated TypeScript file paths (relative to the Options.BaseOutputDirectory)</returns>
462-
private IEnumerable<string> GenerateInterface(Type type, ExportTsInterfaceAttribute interfaceAttribute)
466+
private IEnumerable<string> GenerateInterface(Type type, ExportTsInterfaceAttribute interfaceAttribute, TypeSpec typeSpec)
463467
{
464468
string outputDir = interfaceAttribute.OutputDir;
465-
IEnumerable<string> dependenciesGenerationResult = GenerateTypeDependencies(type, outputDir);
469+
IEnumerable<string> dependenciesGenerationResult = GenerateTypeDependencies(type, outputDir, typeSpec);
466470

467471
// get text for sections
468472

@@ -648,20 +652,44 @@ private void LogClassPropertyWarnings(MemberInfo memberInfo)
648652
/// Gets TypeScript class properties definition source code
649653
/// </summary>
650654
/// <param name="type"></param>
655+
/// <param name="additionalProperties"></param>
651656
/// <returns></returns>
652-
private string GetClassPropertiesText(Type type)
657+
private string GetClassPropertiesText(Type type, IEnumerable<AdditionalClassProperty> additionalProperties)
653658
{
654659
var propertiesText = "";
655660
IEnumerable<MemberInfo> memberInfos = type.GetTsExportableMembers(_metadataReaderFactory.GetInstance());
656661

657-
// create TypeScript source code for properties' definition
658-
662+
// Generate TypeScript properties from C# members
659663
propertiesText += memberInfos
660-
.Aggregate(propertiesText, (current, memberInfo) => current + GetClassPropertyText(type, memberInfo));
664+
.Aggregate("", (current, memberInfo) => current + GetClassPropertyText(type, memberInfo));
665+
666+
propertiesText += GetAdditionalPropertiesText(additionalProperties);
661667

662668
return RemoveLastLineEnding(propertiesText);
663669
}
664670

671+
/// <summary>
672+
/// Gets TypeScript class additional properties if defined
673+
/// </summary>
674+
/// <param name="additionalProperties"></param>
675+
/// <returns></returns>
676+
private string GetAdditionalPropertiesText(IEnumerable<AdditionalClassProperty> additionalProperties)
677+
{
678+
if (!additionalProperties.Any())
679+
{
680+
return "";
681+
}
682+
683+
var additionalPropertiesText = _templateService.FillWithSingleLineComment("Additional properties");
684+
685+
foreach (var property in additionalProperties)
686+
{
687+
additionalPropertiesText += _templateService.FillClassPropertyTemplate(property.Name, property.Type, property.DefaultValue);
688+
}
689+
690+
return additionalPropertiesText;
691+
}
692+
665693
/// <summary>
666694
/// Gets TypeScript interface property definition source code
667695
/// </summary>
@@ -772,8 +800,9 @@ private string GetEnumMembersText(Type type, bool asUnionType)
772800
/// </summary>
773801
/// <param name="type"></param>
774802
/// <param name="outputDir"></param>
803+
/// <param name="typeSpec"></param>
775804
/// <returns>Generated TypeScript file paths (relative to the Options.BaseOutputDirectory)</returns>
776-
private IEnumerable<string> GenerateTypeDependencies(Type type, string outputDir)
805+
private IEnumerable<string> GenerateTypeDependencies(Type type, string outputDir, TypeSpec typeSpec)
777806
{
778807
var generatedFiles = new List<string>();
779808
var typeDependencies = _typeDependencyService.GetTypeDependencies(type);
@@ -793,7 +822,7 @@ private IEnumerable<string> GenerateTypeDependencies(Type type, string outputDir
793822

794823
try
795824
{
796-
generatedFiles.AddRange(GenerateNotMarkedType(typeDependency, defaultOutputDir));
825+
generatedFiles.AddRange(GenerateNotMarkedType(typeDependency, defaultOutputDir, typeSpec));
797826
}
798827
catch (Exception ex)
799828
{

src/TypeGen/TypeGen.Core/Generator/Services/ITemplateService.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ internal interface ITemplateService
77
string FillClassTemplate(string imports, string name, string extends, string implements, string properties, string tsDoc, string customHead, string customBody, string fileHeading = null);
88
string FillClassDefaultExportTemplate(string imports, string name, string exportName, string extends, string implements, string properties, string tsDoc, string customHead, string customBody, string fileHeading = null);
99
string FillClassPropertyTemplate(string modifiers, string name, string type, IEnumerable<string> typeUnions, bool isOptional, string tsDoc, string defaultValue = null);
10+
string FillClassPropertyTemplate(string name, string type, string defaultValue = null);
1011
string FillInterfaceTemplate(string imports, string name, string extends, string properties, string tsDoc, string customHead, string customBody, string fileHeading = null);
1112
string FillInterfaceDefaultExportTemplate(string imports, string name, string exportName, string extends, string properties, string tsDoc, string customHead, string customBody, string fileHeading = null);
1213
string FillInterfacePropertyTemplate(string modifiers, string name, string type, IEnumerable<string> typeUnions, bool isOptional, string tsDoc);
@@ -17,6 +18,7 @@ internal interface ITemplateService
1718
string FillImportTemplate(string name, string typeAlias, string path, bool useImportType);
1819
string FillImportDefaultExportTemplate(string name, string path, bool useImportType);
1920
string FillIndexTemplate(string exports);
21+
string FillWithSingleLineComment(string comment);
2022
string FillIndexExportTemplate(string filename);
2123
string GetExtendsText(string name);
2224
string GetExtendsText(IEnumerable<string> names);

src/TypeGen/TypeGen.Core/Generator/Services/TemplateService.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System.Collections;
22
using System.Collections.Generic;
3+
using System.IO;
34
using System.Linq;
5+
using System.Xml.Linq;
46
using TypeGen.Core.Storage;
57
using TypeGen.Core.Utils;
68

@@ -33,6 +35,8 @@ internal class TemplateService : ITemplateService
3335
private readonly string _indexTemplate;
3436
private readonly string _indexExportTemplate;
3537
private readonly string _headingTemplate;
38+
private readonly string _singleLineCommentTemplate;
39+
private readonly string _lineBreakTemplate;
3640

3741
private GeneratorOptions GeneratorOptions => _generatorOptionsProvider.GeneratorOptions;
3842

@@ -58,6 +62,8 @@ public TemplateService(IInternalStorage internalStorage, IGeneratorOptionsProvid
5862
_indexTemplate = _internalStorage.GetEmbeddedResource("TypeGen.Core.Templates.Index.tpl");
5963
_indexExportTemplate = _internalStorage.GetEmbeddedResource("TypeGen.Core.Templates.IndexExport.tpl");
6064
_headingTemplate = _internalStorage.GetEmbeddedResource("TypeGen.Core.Templates.Heading.tpl");
65+
_singleLineCommentTemplate = _internalStorage.GetEmbeddedResource("TypeGen.Core.Templates.SingleLineComment.tpl");
66+
_lineBreakTemplate = _internalStorage.GetEmbeddedResource("TypeGen.Core.Templates.LineBreak.tpl");
6167
}
6268

6369
public string FillClassTemplate(string imports, string name, string extends, string implements, string properties,
@@ -111,6 +117,20 @@ public string FillClassPropertyTemplate(string modifiers, string name, string ty
111117
.Replace(GetTag("defaultValue"), defaultValue);
112118
}
113119

120+
public string FillClassPropertyTemplate(string name, string type, string defaultValue = null)
121+
{
122+
type = $": {type}";
123+
124+
defaultValue = string.IsNullOrWhiteSpace(defaultValue) ? "" : $" = {defaultValue}";
125+
126+
return ReplaceSpecialChars(_classPropertyTemplate)
127+
.Replace(GetTag("modifiers"), "")
128+
.Replace(GetTag("name"), name)
129+
.Replace(GetTag("type"), type)
130+
.Replace(GetTag("tsDoc"), "")
131+
.Replace(GetTag("defaultValue"), defaultValue);
132+
}
133+
114134
public string FillInterfaceTemplate(string imports, string name, string extends, string properties, string tsDoc,
115135
string customHead,string customBody, string fileHeading = null)
116136
{
@@ -242,6 +262,14 @@ public string FillIndexExportTemplate(string filename)
242262

243263
public string GetImplementsText(IEnumerable<string> names) => $" implements {string.Join(", ", names)}";
244264

265+
public string FillWithSingleLineComment(string comment)
266+
{
267+
return
268+
ReplaceSpecialChars(_lineBreakTemplate) +
269+
ReplaceSpecialChars(_singleLineCommentTemplate)
270+
.Replace(GetTag("comment"), comment);
271+
}
272+
245273
private static string GetTag(string tagName) => $"$tg{{{tagName}}}";
246274

247275
private string ReplaceSpecialChars(string template)

0 commit comments

Comments
 (0)