From 12e6df6090abb7bac38e70dda5076713f3a45c36 Mon Sep 17 00:00:00 2001 From: walon Date: Tue, 13 Jul 2021 19:09:08 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91db=20typesc?= =?UTF-8?q?ript=20=E6=94=AF=E6=8C=81=EF=BC=88=E5=8F=AA=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E4=BA=86=E4=BD=BF=E7=94=A8=E6=8E=A5=E5=8F=A3=EF=BC=8C=E5=86=85?= =?UTF-8?q?=E9=83=A8=E6=9C=89=E5=BE=85=E5=AE=8C=E5=96=84=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Source/Defs/DefBeanBase.cs | 2 + .../Source/Defs/TTypeTemplateCommonExtends.cs | 2 +- .../Source/Defs/TTypeTemplateExtends.cs | 49 ++++ .../Source/Generate/TypescriptRender.cs | 242 +++++++++++++++++- src/Luban.Job.Db/Source/JobController.cs | 100 ++------ 5 files changed, 303 insertions(+), 92 deletions(-) diff --git a/src/Luban.Job.Common/Source/Defs/DefBeanBase.cs b/src/Luban.Job.Common/Source/Defs/DefBeanBase.cs index 3501a7e..11a9304 100644 --- a/src/Luban.Job.Common/Source/Defs/DefBeanBase.cs +++ b/src/Luban.Job.Common/Source/Defs/DefBeanBase.cs @@ -40,6 +40,8 @@ namespace Luban.Job.Common.Defs public string JavaMethodModifier => ParentDefType != null ? "override" : (IsAbstractType ? "virtual" : ""); + public string TsClassModifier => IsAbstractType ? "abstract" : ""; + public DefBeanBase(Bean b) { Name = b.Name; diff --git a/src/Luban.Job.Common/Source/Defs/TTypeTemplateCommonExtends.cs b/src/Luban.Job.Common/Source/Defs/TTypeTemplateCommonExtends.cs index d141f9c..09c2cad 100644 --- a/src/Luban.Job.Common/Source/Defs/TTypeTemplateCommonExtends.cs +++ b/src/Luban.Job.Common/Source/Defs/TTypeTemplateCommonExtends.cs @@ -130,7 +130,7 @@ namespace Luban.Job.Common.Defs public static string TsToString(string filedName, TType type) { - return $"{filedName}"; + return filedName; } public static string TsCtorDefaultValue(TType type) diff --git a/src/Luban.Job.Db/Source/Defs/TTypeTemplateExtends.cs b/src/Luban.Job.Db/Source/Defs/TTypeTemplateExtends.cs index 3b4dec0..976f7a3 100644 --- a/src/Luban.Job.Db/Source/Defs/TTypeTemplateExtends.cs +++ b/src/Luban.Job.Db/Source/Defs/TTypeTemplateExtends.cs @@ -1,5 +1,6 @@ using Luban.Job.Common.Defs; using Luban.Job.Common.Types; +using Luban.Job.Common.TypeVisitors; using Luban.Job.Db.TypeVisitors; using System.Text; @@ -78,5 +79,53 @@ namespace Luban.Job.Db.Defs //return type.Apply(DbWriteBlob.Ins, bufName, valueName); return DbCsCompatibleSerialize(bufName, fieldName, type); } + + public static string DbTsDefineType(TType type) + { + return type.Apply(TypescriptDefineTypeName.Ins); + } + + public static string DbTsInitField(string fieldName, string logType, TType type) + { + return "// ts init field";// type.Apply(DbCsInitFieldVisitor.Ins, fieldName, logType); + } + + public static string TsWriteBlob(string bufName, string fieldName, TType type) + { + //return type.Apply(DbWriteBlob.Ins, bufName, valueName); + return "// ts write blob"; // DbCsCompatibleSerialize(bufName, fieldName, type); + } + + public static string DbTsCompatibleSerialize(string bufName, string fieldName, TType type) + { + //if (type.Apply(CompatibleSerializeNeedEmbedVisitor.Ins)) + //{ + // var sb = new StringBuilder($"{bufName}.BeginWriteSegment(out var _state_);"); + // sb.Append(type.Apply(DbCsCompatibleSerializeVisitor.Ins, bufName, fieldName)); + // sb.Append("_buf.EndWriteSegment(_state_);"); + // return sb.ToString(); + //} + //else + //{ + // return type.Apply(DbCsCompatibleSerializeVisitor.Ins, bufName, fieldName); + //} + return "/* db ts compatible serialize */"; + } + + public static string DbTsCompatibleDeserialize(string bufName, string fieldName, TType type) + { + //if (type.Apply(CompatibleSerializeNeedEmbedVisitor.Ins)) + //{ + // var sb = new StringBuilder($"{bufName}.EnterSegment(out var _state_);"); + // sb.Append(type.Apply(DbCsCompatibleDeserializeVisitor.Ins, bufName, fieldName)); + // sb.Append("_buf.LeaveSegment(_state_);"); + // return sb.ToString(); + //} + //else + //{ + // return type.Apply(DbCsCompatibleDeserializeVisitor.Ins, bufName, fieldName); + //} + return "/* db ts compatible serialize */"; + } } } diff --git a/src/Luban.Job.Db/Source/Generate/TypescriptRender.cs b/src/Luban.Job.Db/Source/Generate/TypescriptRender.cs index 98cb362..fda69ca 100644 --- a/src/Luban.Job.Db/Source/Generate/TypescriptRender.cs +++ b/src/Luban.Job.Db/Source/Generate/TypescriptRender.cs @@ -1,6 +1,7 @@ using Luban.Job.Common.Defs; using Luban.Job.Common.Utils; using Luban.Job.Db.Defs; +using Scriban; using System; using System.Collections.Generic; using System.Linq; @@ -32,21 +33,248 @@ namespace Luban.Job.Db.Generate { return RenderUtil.RenderTypescriptEnumClass(e); } - - private string Render(DefBean b) + [ThreadStatic] + private static Template t_beanRender; + public string Render(DefBean b) { - return $"// {b.FullName}"; + var template = t_beanRender ??= Template.Parse(@" +{{ + name = x.name + full_name = x.full_name + parent_def_type = x.parent_def_type + fields = x.fields + hierarchy_fields = x.hierarchy_fields + is_abstract_type = x.is_abstract_type + readonly_name = ""IReadOnly"" + name +}} + + +{{x.typescript_namespace_begin}} +export {{x.ts_class_modifier}} class {{name}} extends {{if parent_def_type}} {{x.parent}} {{else}} TxnBeanBase {{end}}{ + {{~ for field in fields~}} + {{if is_abstract_type}}protected{{else}}private{{end}} {{field.internal_name}}: {{db_ts_define_type field.ctype}} + {{~end}} + + constructor() { + super() + {{~ for field in fields~}} + {{db_ts_init_field field.internal_name field.log_type field.ctype }} + {{~end~}} + } + + {{~ for field in fields~}} + {{ctype = field.ctype}} + {{~if has_setter field.ctype~}} + + private static {{field.log_type}} = class extends FieldLoggerGeneric2<{{name}}, {{db_ts_define_type field.ctype}}> + { + constructor(self:{{name}}, value: {{db_ts_define_type field.ctype}}) { super(self, value) } + + get fieldId(): number { return this.host.getObjectId() + {{field.id}} } + + commit() { this.host.{{field.internal_name}} = this.value } + + writeBlob(_buf: ByteBuf) { + _buf.WriteInt(FieldTag.{{tag_name field.ctype}}); + {{ts_write_blob '_buf' 'this.Value' field.ctype}} + } + } + + get {{field.ts_style_name}}(): {{db_ts_define_type field.ctype}} { + if (this.isManaged) { + var txn = TransactionContext.current + if (txn == null) return this.{{field.internal_name}} + let log: any = txn.getField(this.getObjectId() + {{field.id}}) + return log != null ? log.value : this.{{field.internal_name}} + } else { + return this.{{field.internal_name}}; + } + } + set {{field.ts_style_name}}(value: {{db_ts_define_type field.ctype}}) { + {{~if db_field_cannot_null~}} + if (value == null) throw new Error() + {{~end~}} + if (this.isManaged) { + let txn = TransactionContext.current + txn.putFieldLong(this.getObjectId() + {{field.id}}, new {{name}}.{{field.log_type}}(this, value)) + {{~if field.ctype.need_set_children_root}} + value?.initRoot(this.getRoot()) + {{end}} + } else { + this.{{field.internal_name}} = value + } + } + + {{~else~}} + {{~if field.ctype.is_collection~}} + // collection logger + {{~end~}} + + get {{field.ts_style_name}}(): {{db_ts_define_type field.ctype}} { return this.{{field.internal_name}} } + {{~end~}} + {{~end~}} + + {{~if is_abstract_type~}} + static serialize{{name}}Any(_buf: ByteBuf, x: {{name}}) { + if (x == null) { _buf.WriteInt(0); return } + _buf.WriteInt(x.getTypeId()) + x.serialize(_buf) + } + + deserialize{{name}}Any(_buf: ByteBuf): {{name}}{ + let x: {{name}} + switch (_buf.ReadInt()) { + {{~ for child in x.hierarchy_not_abstract_children~}} + case {{child.full_name}}.ID: x = new {{child.full_name}}(); break + {{~end~}} + default: throw new Error() + } + x.deserialize(_buf) + return x + } + {{~else~}} + serialize(_buf: ByteBuf) { + _buf.WriteNumberAsLong(this.getObjectId()) + {{~ for field in hierarchy_fields~}} + { _buf.WriteInt(FieldTag.{{tag_name field.ctype}} | ({{field.id}} << FieldTag.TAG_SHIFT)); {{db_ts_compatible_serialize '_buf' field.internal_name field.ctype}} } + {{~end}} + } + + deserialize(_buf: ByteBuf) { + this.setObjectId(_buf.ReadLongAsNumber()) + while(_buf.NotEmpty) { + let _tag_ = _buf.ReadInt() + switch (_tag_) { + {{~ for field in hierarchy_fields~}} + case FieldTag.{{tag_name field.ctype}} | ({{field.id}} << FieldTag.TAG_SHIFT) : { {{db_ts_compatible_deserialize '_buf' field.internal_name field.ctype}} break; } + {{~end~}} + default: { _buf.SkipUnknownField(_tag_); break; } + } + } + } + + static readonly ID = {{x.id}} + getTypeId(): number { return {{name}}.ID } + {{~end~}} + + initChildrenRoot(root: TKey) { + {{~ for field in hierarchy_fields~}} + {{if need_set_children_root field.ctype}}// this.{{field.internal_name}}?.initRoot(root);{{end}} + {{~end}} + } + + toString(): string { + return ""{{full_name}}{ "" + {{~ for field in hierarchy_fields~}} + + ""{{field.ts_style_name}}:"" + {{ts_to_string ('this.' + field.ts_style_name) field.ctype}} + "","" + {{~end~}} + + ""}"" + } +} + +{{x.typescript_namespace_end}} +"); + var result = template.RenderCode(b); + return result; } - public string Render(DefTable c) + [ThreadStatic] + private static Template t_tableRender; + public string Render(DefTable p) { - return $"// {c.FullName}"; + var template = t_tableRender ??= Template.Parse(@" +{{ + name = x.name + key_ttype = x.key_ttype + value_ttype = x.value_ttype + internal_table_type = x.internal_table_type +}} + +{{x.typescript_namespace_begin}} + + class {{internal_table_type}} extends TxnTableGeneric<{{db_ts_define_type key_ttype}},{{db_ts_define_type value_ttype}}> { + constructor() { + super({{x.table_uid}}, ""{{x.full_name}}"") + } + + serializeKey(buf: ByteBuf, key: {{db_ts_define_type key_ttype}}) { + throw new Error('Method not implemented.') + } + + serializeValue(buf: ByteBuf, value: {{db_ts_define_type value_ttype}}) { + throw new Error('Method not implemented.') + } + + deserializeKey(buf: ByteBuf): {{db_ts_define_type key_ttype}} { + throw new Error('Method not implemented.') + } + + deserializeValue(buf: ByteBuf): {{db_ts_define_type value_ttype}} { + throw new Error('Method not implemented.') + } +} + + +export class {{name}} { + static readonly _table = new {{internal_table_type}}(); + static get table(): TxnTableGeneric<{{db_ts_define_type key_ttype}},{{db_ts_define_type value_ttype}}> { return this._table } + + static getAsync(key: {{db_ts_define_type key_ttype}}): Promise<{{db_ts_define_type value_ttype}}> { + return {{name}}._table.getAsync(key); + } + + static createIfNotExistAsync(key: {{db_ts_define_type key_ttype}}): Promise<{{db_ts_define_type value_ttype}}> { + return {{name}}._table.createIfNotExistAsync(key); + } + + static insertAsync(key: {{db_ts_define_type key_ttype}}, value: {{db_ts_define_type value_ttype}}): Promise { + return {{name}}._table.insertAsync(key, value); + } + + static removeAsync(key: {{db_ts_define_type key_ttype}}): Promise { + return {{name}}._table.removeAsync(key); + } + + static put(key: {{db_ts_define_type key_ttype}}, value: {{db_ts_define_type value_ttype}}): Promise { + return {{name}}._table.putAsync(key, value); + } + + static selectAsync(key: {{db_ts_define_type key_ttype}}): Promise<{{db_ts_define_type value_ttype}}> { + return {{name}}._table.selectAsync(key); + } +} + +{{x.typescript_namespace_end}} + +"); + var result = template.RenderCode(p); + + return result; } - public string RenderService(string name, string module, List tables) + [ThreadStatic] + private static Template t_stubRender; + public string RenderTables(string name, string module, List tables) { + var template = t_stubRender ??= Template.Parse(@" - return "// services"; +export class {{name}} { + static readonly tableList: TxnTable[] = [ + {{~ for table in tables~}} + {{table.full_name}}.table, + {{~end}} + ] +} + +"); + var result = template.Render(new + { + Name = name, + Namespace = module, + Tables = tables, + }); + + return result; } } } diff --git a/src/Luban.Job.Db/Source/JobController.cs b/src/Luban.Job.Db/Source/JobController.cs index 9b8e5ee..043f42c 100644 --- a/src/Luban.Job.Db/Source/JobController.cs +++ b/src/Luban.Job.Db/Source/JobController.cs @@ -31,7 +31,7 @@ namespace Luban.Job.Db [Option('g', "gen_type", Required = true, HelpText = "cs,typescript . current only support cs")] public string GenType { get; set; } - [Option("typescript_bright_require_path", Required = false, HelpText = "bright require path in typescript")] + [Option("typescript_bright_require_path", Required = true, HelpText = "bright require path in typescript")] public string TypescriptBrightRequirePath { get; set; } } @@ -131,87 +131,24 @@ namespace Luban.Job.Db case "typescript": { var render = new TypescriptRender(); - var byteBufRequirePath = "";// args.TypescriptByteBufRequirePath ?? "csharp"; + var brightRequirePath = args.TypescriptBrightRequirePath; tasks.Add(Task.Run(() => { - var fileContent = new List - { - @$" -{ (string.IsNullOrEmpty(args.TypescriptBrightRequirePath) ? -@" -import {{Bright}} from 'cshar' -import ByteBuf = Bright.Serialization.ByteBuf + var fileContent = new List(); -export class Vector2 { - x: number - y: number - constructor(x: number, y: number) { - this.x = x - this.y = y - } + fileContent.Add(string.Format(TypescriptBrightTypeTemplates.BrightByteBufImportsFormat, brightRequirePath)); - static from(_buf_: Bright.Serialization.ByteBuf): Vector2 { - let x = _buf_.ReadFloat() - let y = _buf_.ReadFloat() - return new Vector2(x, y) - } - } - - - export class Vector3 { - x: number - y: number - z: number - constructor(x: number, y: number, z: number) { - this.x = x - this.y = y - this.z = z - } - - static from(_buf_: Bright.Serialization.ByteBuf): Vector3 { - let x = _buf_.ReadFloat() - let y = _buf_.ReadFloat() - let z = _buf_.ReadFloat() - return new Vector3(x, y, z) - } - } - - export class Vector4 { - x: number - y: number - z: number - w: number - constructor(x: number, y: number, z: number, w: number) { - this.x = x - this.y = y - this.z = z - this.w = w - } - - static from(_buf_: Bright.Serialization.ByteBuf): Vector4 { - let x = _buf_.ReadFloat() - let y = _buf_.ReadFloat() - let z = _buf_.ReadFloat() - let w = _buf_.ReadFloat() - return new Vector4(x, y, z, w) - } - } - -" : -@" - -import {{Bright}} from '{byteBufRequirePath}' -") } - -export namespace {ass.TopModule} {{ -", - - @" - - -" - }; + fileContent.Add(string.Format(TypescriptBrightTypeTemplates.SerializeImportsFormat, brightRequirePath)); + fileContent.Add(string.Format(TypescriptBrightTypeTemplates.ProtocolImportsFormat, brightRequirePath)); + fileContent.Add(string.Format(TypescriptBrightTypeTemplates.VectorImportsFormat, brightRequirePath)); + fileContent.Add($"import {{FieldLogger, FieldLoggerGeneric1, FieldLoggerGeneric2}} from '{brightRequirePath}/transaction/FieldLogger'"); + fileContent.Add($"import TxnBeanBase from '{brightRequirePath}/transaction/TxnBeanBase'"); + fileContent.Add($"import {{TxnTable, TxnTableGeneric}} from '{brightRequirePath}/transaction/TxnTable'"); + fileContent.Add($"import TransactionContext from '{brightRequirePath}/transaction/TransactionContext'"); + fileContent.Add($"import {{FieldTag}} from '{brightRequirePath}/serialization/FieldTag'"); + fileContent.Add($"import {{TKey}} from '{brightRequirePath}/storage/TKey'"); + fileContent.Add(@$"export namespace {ass.TopModule} {{"); foreach (var type in exportTypes) @@ -219,16 +156,15 @@ export namespace {ass.TopModule} {{ fileContent.Add(render.RenderAny(type)); } - var tables = ass.Types.Values.Where(t => t is DefTable).Select(t => (DefTable)t).ToList(); - fileContent.Add(render.RenderService("Tables", ass.TopModule, tables)); + fileContent.Add(render.RenderTables("Tables", ass.TopModule, tables)); fileContent.Add("}"); // end of topmodule var content = FileHeaderUtil.ConcatAutoGenerationHeader(string.Join('\n', fileContent), ELanguage.TYPESCRIPT); var file = "Types.ts"; var md5 = CacheFileUtil.GenMd5AndAddCache(file, content); - genScatteredFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + genCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); })); break; } @@ -242,10 +178,6 @@ export namespace {ass.TopModule} {{ await Task.WhenAll(tasks.ToArray()); res.FileGroups.Add(new FileGroup() { Dir = outputCodeDir, Files = genCodeFiles.ToList() }); - if (!genScatteredFiles.IsEmpty) - { - res.ScatteredFiles.AddRange(genScatteredFiles); - } } catch (Exception e) {