[new] 支持proto java代码生成

main
walon 2022-11-28 20:17:12 +08:00
parent 88ab94e836
commit 9b97f5d0bd
15 changed files with 542 additions and 14 deletions

View File

@ -67,33 +67,33 @@ namespace Luban.Job.Cfg
}
if (genTypes.Contains("data_resources") && string.IsNullOrWhiteSpace(options.OutputDataResourceListFile))
{
errMsg = "--output_data_resource_list_file missing";
errMsg = "--output:data:resource_list_file missing";
return false;
}
if (genTypes.Contains("output_data_json_monolithic_file") && string.IsNullOrWhiteSpace(options.OutputDataJsonMonolithicFile))
if (genTypes.Contains("data_json_monolithic") && string.IsNullOrWhiteSpace(options.OutputDataJsonMonolithicFile))
{
errMsg = "--output_data_json_monolithic_file missing";
errMsg = "--output:data:json_monolithic_file missing";
return false;
}
if (string.IsNullOrWhiteSpace(options.L10nInputTextTableFiles) ^ string.IsNullOrWhiteSpace(options.L10nOutputNotTranslatedTextFile))
{
errMsg = "--input_l10n_text_files must be provided with --output_l10n_not_translated_text_file";
errMsg = "--l10n:input_text_files should be used with --l10n:output_not_translated_text_file";
return false;
}
if (genTypes.Contains("data_template") ^ !string.IsNullOrWhiteSpace(options.TemplateDataFile))
{
errMsg = "gen_types data_template should use with --template:data:file";
errMsg = "gen_types data_template should be used with --template:data:file";
return false;
}
if (genTypes.Contains("convert_template") ^ !string.IsNullOrWhiteSpace(options.TemplateConvertFile))
{
errMsg = "gen_types convert_template should use with --template:convert:file";
errMsg = "gen_types convert_template should be used with --template:convert:file";
return false;
}
if (genTypes.Contains("code_template") ^ !string.IsNullOrWhiteSpace(options.TemplateCodeDir))
{
errMsg = "gen_types code_template should use with --template:code:dir";
errMsg = "gen_types code_template should be used with --template:code:dir";
return false;
}
}

View File

@ -5,6 +5,7 @@ using Luban.Job.Common.Types;
using Luban.Job.Common.TypeVisitors;
using System;
using System.Linq;
using JavaDeserializeVisitor = Luban.Job.Cfg.TypeVisitors.JavaDeserializeVisitor;
namespace Luban.Job.Cfg.Utils
{

View File

@ -0,0 +1,22 @@
using Luban.Job.Common.Types;
using Luban.Job.Common.TypeVisitors;
namespace Luban.Job.Common.TypeVisitors
{
public class JavaDeserializeVisitor : DecoratorFuncVisitor<string, string, string>
{
public static JavaDeserializeVisitor Ins { get; } = new JavaDeserializeVisitor();
public override string DoAccept(TType type, string bufName, string fieldName)
{
if (type.IsNullable)
{
return $"if({bufName}.readBool()){{ {type.Apply(JavaUnderingDeserializeVisitor.Ins, bufName, fieldName)} }} else {{ {fieldName} = null; }}";
}
else
{
return type.Apply(JavaUnderingDeserializeVisitor.Ins, bufName, fieldName);
}
}
}
}

View File

@ -0,0 +1,21 @@
using Luban.Job.Common.Types;
namespace Luban.Job.Common.TypeVisitors
{
public class JavaSerializeVisitor : DecoratorFuncVisitor<string, string, string>
{
public static JavaSerializeVisitor Ins { get; } = new JavaSerializeVisitor();
public override string DoAccept(TType type, string bufName, string fieldName)
{
if (type.IsNullable)
{
return $"{{ if ({fieldName} != null){{ {bufName}.writeBool(true); {type.Apply(JavaUnderingSerializeVisitor.Ins, bufName, fieldName)} }} else {{ {bufName}.writeBool(false); }} }}";
}
else
{
return type.Apply(JavaUnderingSerializeVisitor.Ins, bufName, fieldName);
}
}
}
}

View File

@ -0,0 +1,126 @@
using Luban.Job.Common.Types;
using Luban.Job.Common.TypeVisitors;
namespace Luban.Job.Common.TypeVisitors
{
class JavaUnderingDeserializeVisitor : ITypeFuncVisitor<string, string, string>
{
public static JavaUnderingDeserializeVisitor Ins { get; } = new JavaUnderingDeserializeVisitor();
public string Accept(TBool type, string bufName, string fieldName)
{
return $"{fieldName} = {bufName}.readBool();";
}
public string Accept(TByte type, string bufName, string fieldName)
{
return $"{fieldName} = {bufName}.readByte();";
}
public string Accept(TShort type, string bufName, string fieldName)
{
return $"{fieldName} = {bufName}.readShort();";
}
public string Accept(TFshort type, string bufName, string fieldName)
{
return $"{fieldName} = {bufName}.readFshort();";
}
public string Accept(TInt type, string bufName, string fieldName)
{
return $"{fieldName} = {bufName}.readInt();";
}
public string Accept(TFint type, string bufName, string fieldName)
{
return $"{fieldName} = {bufName}.readFint();";
}
public string Accept(TLong type, string bufName, string fieldName)
{
return $"{fieldName} = {bufName}.readLong();";
}
public string Accept(TFlong type, string bufName, string fieldName)
{
return $"{fieldName} = {bufName}.readFlong();";
}
public string Accept(TFloat type, string bufName, string fieldName)
{
return $"{fieldName} = {bufName}.readFloat();";
}
public string Accept(TDouble type, string bufName, string fieldName)
{
return $"{fieldName} = {bufName}.readDouble();";
}
public string Accept(TEnum type, string bufName, string fieldName)
{
return $"{fieldName} = {bufName}.readInt();";
}
public string Accept(TString type, string bufName, string fieldName)
{
return $"{fieldName} = {bufName}.readString();";
}
public string Accept(TBytes type, string bufName, string fieldName)
{
return $"{fieldName} = {bufName}.readBytes();";
}
public string Accept(TText type, string bufName, string fieldName)
{
return $"{bufName}.readString(); {fieldName} = {bufName}.readString();";
}
public string Accept(TBean type, string bufName, string fieldName)
{
return $"{fieldName} = {type.Bean.FullNameWithTopModule}.deserialize{type.Bean.Name}({bufName});";
}
public string Accept(TArray type, string bufName, string fieldName)
{
return $"{{int n = Math.min({bufName}.readSize(), {bufName}.size());{fieldName} = new {type.ElementType.Apply(JavaDefineTypeName.Ins)}[n];for(int i = 0 ; i < n ; i++) {{ {type.ElementType.Apply(JavaDefineTypeName.Ins)} _e;{type.ElementType.Apply(this, bufName, "_e")} {fieldName}[i] = _e;}}}}";
}
public string Accept(TList type, string bufName, string fieldName)
{
return $"{{int n = Math.min({bufName}.readSize(), {bufName}.size());{fieldName} = new {type.Apply(JavaDefineTypeName.Ins)}(n);for(int i = 0 ; i < n ; i++) {{ {type.ElementType.Apply(JavaBoxDefineTypeName.Ins)} _e; {type.ElementType.Apply(this, bufName, "_e")} {fieldName}.add(_e);}}}}";
}
public string Accept(TSet type, string bufName, string fieldName)
{
return $"{{int n = Math.min({bufName}.readSize(), {bufName}.size());{fieldName} = new {type.Apply(JavaDefineTypeName.Ins)}(n * 3 / 2);for(int i = 0 ; i < n ; i++) {{ {type.ElementType.Apply(JavaBoxDefineTypeName.Ins)} _e; {type.ElementType.Apply(this, bufName, "_e")} {fieldName}.add(_e);}}}}";
}
public string Accept(TMap type, string bufName, string fieldName)
{
return $"{{int n = Math.min({bufName}.readSize(), {bufName}.size());{fieldName} = new {type.Apply(JavaDefineTypeName.Ins)}(n * 3 / 2);for(int i = 0 ; i < n ; i++) {{ {type.KeyType.Apply(JavaBoxDefineTypeName.Ins)} _k; {type.KeyType.Apply(this, bufName, "_k")} {type.ValueType.Apply(JavaBoxDefineTypeName.Ins)} _v; {type.ValueType.Apply(this, bufName, "_v")} {fieldName}.put(_k, _v);}}}}";
}
public string Accept(TVector2 type, string bufName, string fieldName)
{
return $"{fieldName} = {bufName}.readVector2();";
}
public string Accept(TVector3 type, string bufName, string fieldName)
{
return $"{fieldName} = {bufName}.readVector3();";
}
public string Accept(TVector4 type, string bufName, string fieldName)
{
return $"{fieldName} = {bufName}.readVector4();";
}
public string Accept(TDateTime type, string bufName, string fieldName)
{
return $"{fieldName} = {bufName}.readInt();";
}
}
}

View File

@ -0,0 +1,128 @@
using Luban.Job.Common.Defs;
using Luban.Job.Common.Types;
namespace Luban.Job.Common.TypeVisitors
{
class JavaUnderingSerializeVisitor : ITypeFuncVisitor<string, string, string>
{
public static JavaUnderingSerializeVisitor Ins { get; } = new JavaUnderingSerializeVisitor();
public string Accept(TBool type, string bufName, string fieldName)
{
return $"{bufName}.writeBool({fieldName});";
}
public string Accept(TByte type, string bufName, string fieldName)
{
return $"{bufName}.writeByte({fieldName});";
}
public string Accept(TShort type, string bufName, string fieldName)
{
return $"{bufName}.writeShort({fieldName});";
}
public string Accept(TFshort type, string bufName, string fieldName)
{
return $"{bufName}.writeFshort({fieldName});";
}
public string Accept(TInt type, string bufName, string fieldName)
{
return $"{bufName}.writeInt({fieldName});";
}
public string Accept(TFint type, string bufName, string fieldName)
{
return $"{bufName}.writeFint({fieldName});";
}
public string Accept(TLong type, string bufName, string fieldName)
{
return $"{bufName}.writeLong({fieldName});";
}
public string Accept(TFlong type, string bufName, string fieldName)
{
return $"{bufName}.writeFlong({fieldName});";
}
public string Accept(TFloat type, string bufName, string fieldName)
{
return $"{bufName}.writeFloat({fieldName});";
}
public string Accept(TDouble type, string bufName, string fieldName)
{
return $"{bufName}.writeDouble({fieldName});";
}
public string Accept(TEnum type, string bufName, string fieldName)
{
return $"{bufName}.writeInt((int){fieldName});";
}
public string Accept(TString type, string bufName, string fieldName)
{
return $"{bufName}.writeString({fieldName});";
}
public string Accept(TBytes type, string bufName, string fieldName)
{
return $"{bufName}.writeBytes({fieldName});";
}
public string Accept(TText type, string bufName, string fieldName)
{
return $"{bufName}.writeString({fieldName});";
}
public string Accept(TBean type, string bufName, string fieldName)
{
return $"{type.Bean.FullNameWithTopModule}.serialize{type.Bean.Name}({bufName}, {fieldName});";
}
public string Accept(TArray type, string bufName, string fieldName)
{
return $"{{ {bufName}.writeSize({fieldName}.length); for({type.ElementType.Apply(JavaBoxDefineTypeName.Ins)} _e : {fieldName}) {{ {type.ElementType.Apply(this, bufName, "_e")} }} }}";
}
public string Accept(TList type, string bufName, string fieldName)
{
return $"{{ {bufName}.writeSize({fieldName}.size()); for({type.ElementType.Apply(JavaBoxDefineTypeName.Ins)} _e : {fieldName}) {{ {type.ElementType.Apply(this, bufName, "_e")} }} }}";
}
public string Accept(TSet type, string bufName, string fieldName)
{
return $"{{ {bufName}.writeSize({fieldName}.size()); for({type.ElementType.Apply(JavaBoxDefineTypeName.Ins)} _e : {fieldName}) {{ {type.ElementType.Apply(this, bufName, "_e")} }} }}";
}
public string Accept(TMap type, string bufName, string fieldName)
{
return $"{{ {bufName}.writeSize({fieldName}.size()); for(java.util.Map.Entry<{type.KeyType.Apply(JavaBoxDefineTypeName.Ins)},{type.ValueType.Apply(JavaBoxDefineTypeName.Ins)}> _e : {fieldName}.entrySet()) {{ {type.KeyType.Apply(this, bufName, "_e.getKey()")} {type.ValueType.Apply(this, bufName, "_e.getValue()")} }} }}";
}
public static string VectorName => "Vector";
public string Accept(TVector2 type, string bufName, string fieldName)
{
return $"{bufName}.write{VectorName}2({fieldName});";
}
public string Accept(TVector3 type, string bufName, string fieldName)
{
return $"{bufName}.write{VectorName}3({fieldName});";
}
public string Accept(TVector4 type, string bufName, string fieldName)
{
return $"{bufName}.write{VectorName}4({fieldName});";
}
public string Accept(TDateTime type, string bufName, string fieldName)
{
return $"{bufName}.writeInt({fieldName});";
}
}
}

View File

@ -8,12 +8,6 @@
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Source\TypeVisitors\**" />
<EmbeddedResource Remove="Source\TypeVisitors\**" />
<None Remove="Source\TypeVisitors\**" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\README.md">
<Pack>True</Pack>

View File

@ -1,8 +1,20 @@
using Luban.Job.Common.Defs;
using Luban.Job.Common.Types;
using Luban.Job.Common.TypeVisitors;
namespace Luban.Job.Proto.Defs
{
class TTypeTemplateExtends : TTypeTemplateCommonExtends
{
public static string JavaSerialize(string bufName, string fieldName, TType type)
{
return type.Apply(JavaSerializeVisitor.Ins, bufName, fieldName);
}
public static string JavaDeserialize(string bufName, string fieldName, TType type)
{
return type.Apply(JavaDeserializeVisitor.Ins, bufName, fieldName);
}
}
}

View File

@ -5,7 +5,7 @@ namespace Luban.Job.Proto
{
public class GenArgs : GenArgsBase
{
[Option('g', "gen_type", Required = true, HelpText = "cs,lua,java,cpp,typescript")]
[Option('g', "gen_type", Required = true, HelpText = "cs,lua,java,typescript")]
public string GenType { get; set; }
[Option('s', "service", Required = true, HelpText = "service")]

View File

@ -0,0 +1,14 @@
using Luban.Job.Common.Defs;
using Luban.Job.Common.Generate;
using Luban.Job.Common.Utils;
using Luban.Job.Proto.Defs;
using System;
using System.Collections.Generic;
namespace Luban.Job.Proto.Generate
{
[Render("java")]
class JavaRender : TemplateRenderBase
{
}
}

View File

@ -331,6 +331,18 @@
<None Update="Templates\db\typescript\tables.tpl">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Templates\proto\java\bean.tpl">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Templates\proto\java\proto.tpl">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Templates\proto\java\rpc.tpl">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Templates\proto\java\stub.tpl">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Templates\proto\cs\bean.tpl">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>

View File

@ -0,0 +1,91 @@
package {{x.namespace_with_top_module}};
import bright.serialization.*;
{{
name = x.name
parent_def_type = x.parent_def_type
fields = x.fields
hierarchy_fields = x.hierarchy_fields
is_abstract_type = x.is_abstract_type
}}
{{~if x.comment != '' ~}}
/**
* {{x.escape_comment}}
*/
{{~end~}}
public {{x.java_class_modifier}} class {{name}} extends {{if parent_def_type}}{{parent_def_type.full_name_with_top_module}}{{else}}bright.serialization.AbstractBean{{end}} {
{{~ for field in fields ~}}
{{~if field.comment != '' ~}}
/**
* {{field.escape_comment}}
*/
{{~end~}}
public {{java_define_type field.ctype}} {{field.convention_name}};
{{~end~}}
{{~if !is_abstract_type~}}
public static final int __ID__ = {{x.id}};
@Override
public int getTypeId() { return __ID__; }
{{~else~}}
public abstract int getTypeId();
{{~end~}}
@Override
public void serialize(ByteBuf _buf) {
{{~if parent_def_type~}}
super.serialize(_buf);
{{~end~}}
{{~ for field in fields ~}}
{{java_serialize '_buf' field.convention_name field.ctype}}
{{~end~}}
}
@Override
public void deserialize(ByteBuf _buf)
{
{{~if parent_def_type~}}
super.deserialize(_buf);
{{~end~}}
{{~ for field in fields ~}}
{{java_deserialize '_buf' field.convention_name field.ctype}}
{{~end~}}
}
public static void serialize{{name}}(ByteBuf _buf, {{name}} v) {
{{~if is_abstract_type~}}
_buf.writeInt(v.getTypeId());
{{~end~}}
v.serialize(_buf);
}
public static {{name}} deserialize{{name}}(ByteBuf _buf) {
{{~if is_abstract_type~}}
{{name}} v;
switch (_buf.readInt()) {
{{~for child in x.hierarchy_not_abstract_children~}}
case {{child.full_name_with_top_module}}.__ID__: v = new {{child.full_name_with_top_module}}(); break;
{{~end~}}
default: throw new SerializationException();
}
{{~else~}}
{{name}} v = new {{name}}();
{{~end~}}
v.deserialize(_buf);
return v;
}
@Override
public String toString() {
return "{{full_name}}{ "
{{~for field in hierarchy_fields ~}}
+ "{{field.convention_name}}:" + {{java_to_string field.convention_name field.ctype}} + ","
{{~end~}}
+ "}";
}
}

View File

@ -0,0 +1,56 @@
package {{x.namespace_with_top_module}};
import bright.serialization.*;
{{
name = x.name
parent_def_type = x.parent_def_type
fields = x.fields
}}
{{~if x.comment != '' ~}}
/**
* {{x.escape_comment}}
*/
{{~end~}}
public final class {{name}} extends bright.net.Protocol
{
{{~ for field in fields ~}}
{{~if field.comment != '' ~}}
/**
* {{field.escape_comment}}
*/
{{~end~}}
public {{java_define_type field.ctype}} {{field.convention_name}};
{{~end~}}
public static final int __ID__ = {{x.id}};
@Override
public int getTypeId() { return __ID__; }
@Override
public void serialize(ByteBuf _buf)
{
{{~ for field in fields ~}}
{{java_serialize '_buf' field.convention_name field.ctype}}
{{~end~}}
}
@Override
public void deserialize(ByteBuf _buf)
{
{{~ for field in fields ~}}
{{java_deserialize '_buf' field.convention_name field.ctype}}
{{~end~}}
}
@Override
public String toString() {
return "{{full_name}}{ "
{{~for field in fields ~}}
+ "{{field.convention_name}}:" + {{java_to_string field.convention_name field.ctype}} + ","
{{~end~}}
+ "}";
}
}

View File

@ -0,0 +1,29 @@
{{
name = x.name
full_name = x.full_name
parent = x.parent
fields = x.fields
targ_type = x.targ_type
tres_type = x.tres_type
}}
package {{x.namespace_with_top_module}};
import bright.serialization.*;
public final class {{name}} extends bright.net.Rpc<{{java_define_type targ_type}}, {{java_define_type tres_type}}> {
public static final int __ID__ = {{x.id}};
@Override
public int getTypeId() { return __ID__; }
@Override
public void serialize(ByteBuf _buf) {
throw new UnsupportedOperationException();
}
@Override
public void deserialize(ByteBuf _buf) {
throw new UnsupportedOperationException();
}
}

View File

@ -0,0 +1,22 @@
package {{namespace}};
import java.util.*;
import bright.net.*;
public final class {{name}} {
static final Map<Integer, IProtocolCreator> _factories = new HashMap<>();
static {
{{~ for proto in protos ~}}
_factories.put({{proto.full_name_with_top_module}}.__ID__, {{proto.full_name_with_top_module}}::new);
{{~end~}}
{{~ for rpc in rpcs ~}}
_factories.put({{rpc.full_name_with_top_module}}.__ID__, {{rpc.full_name_with_top_module}}::new);
{{~end~}}
}
public static Map<Integer, IProtocolCreator> getFactories() {
return _factories;
}
}