【特性】支持 enum 的external type映射。可以将定义中的某个枚举类映射到现成的另一个枚举类。暂时只支持cs语言。

main
walon 2021-12-02 13:43:33 +08:00
parent ff93a074c4
commit 7fc75871d4
21 changed files with 250 additions and 66 deletions

View File

@ -187,17 +187,19 @@ namespace Luban.Job.Cfg.Defs
return refTypes.Values.ToList();
}
public void Load(string outputService, Defines defines)
public void Load(Defines defines, RemoteAgent agent, GenArgs args)
{
LoadCommon(defines, agent, args);
OutputCompactJson = args.OutputCompactJson;
SupportDatetimeType = true;
TopModule = defines.TopModule;
CfgTargetService = defines.Services.Find(s => s.Name == outputService);
CfgTargetService = defines.Services.Find(s => s.Name == args.Service);
if (CfgTargetService == null)
{
throw new ArgumentException($"service:{outputService} not exists");
throw new ArgumentException($"service:{args.Service} not exists");
}
if (!string.IsNullOrWhiteSpace(_patchName))

View File

@ -145,19 +145,8 @@ namespace Luban.Job.Cfg
TimeZoneInfo timeZoneInfo = string.IsNullOrEmpty(args.L10nTimeZone) ? null : TimeZoneInfo.FindSystemTimeZoneById(args.L10nTimeZone);
var excludeTags = args.ExportExcludeTags.Split(',').Select(t => t.Trim().ToLowerInvariant()).Where(t => !string.IsNullOrEmpty(t)).ToList();
var ass = new DefAssembly(args.L10nPatchName, timeZoneInfo, excludeTags, agent)
{
CsUseUnityVectors = args.CsUseUnityVectors,
OutputCompactJson = args.OutputCompactJson,
NamingConventionModule = args.NamingConventionModule,
NamingConventionType = args.NamingConventionType,
NamingConventionBeanMember = args.NamingConventionBeanMember,
NamingConventionEnumMember = args.NamingConventionEnumMember,
};
ass.Load(args.Service, rawDefines);
DefAssemblyBase.LocalAssebmly = ass;
var ass = new DefAssembly(args.L10nPatchName, timeZoneInfo, excludeTags, agent);
ass.Load(rawDefines, agent, args);
List<DefTable> exportTables = ass.GetExportTables();
List<DefTypeBase> exportTypes = ass.GetExportTypes();

View File

@ -1,5 +1,6 @@
using Luban.Common.Utils;
using Luban.Job.Common.RawDefs;
using Luban.Job.Common.Utils;
using Luban.Server.Common;
using System;
using System.Collections.Generic;
@ -50,6 +51,7 @@ namespace Luban.Job.Common.Defs
protected readonly List<PEnum> _enums = new List<PEnum>();
protected readonly List<Bean> _beans = new List<Bean>();
protected readonly HashSet<string> _externalSelectors = new();
protected readonly Dictionary<string, ExternalType> _externalTypes = new();
protected CommonDefLoader(IAgent agent)
{
@ -61,6 +63,7 @@ namespace Luban.Job.Common.Defs
_moduleDefineHandlers.Add("module", AddModule);
_moduleDefineHandlers.Add("enum", AddEnum);
_moduleDefineHandlers.Add("bean", AddBean);
_moduleDefineHandlers.Add("externaltype", AddExternalType);
}
public string RootXml => _rootXml;
@ -111,6 +114,7 @@ namespace Luban.Job.Common.Defs
defines.Enums = _enums;
defines.Beans = _beans;
defines.ExternalSelectors = _externalSelectors;
defines.ExternalTypes = _externalTypes;
}
#region root handler
@ -302,11 +306,11 @@ namespace Luban.Job.Common.Defs
}
}
private static readonly List<string> _enumOptionalAttrs = new List<string> { "flags", "comment", "tags" };
private static readonly List<string> _enumOptionalAttrs = new List<string> { "flags", "comment", "tags", "unique", "externaltype" };
private static readonly List<string> _enumRequiredAttrs = new List<string> { "name" };
private static readonly List<string> _enumItemOptionalAttrs = new List<string> { "value", "alias", "comment", "tags", "unique" };
private static readonly List<string> _enumItemOptionalAttrs = new List<string> { "value", "alias", "comment", "tags" };
private static readonly List<string> _enumItemRequiredAttrs = new List<string> { "name" };
protected void AddEnum(string defineFile, XElement e)
@ -320,6 +324,7 @@ namespace Luban.Job.Common.Defs
IsFlags = XmlUtil.GetOptionBoolAttribute(e, "flags"),
Tags = XmlUtil.GetOptionalAttribute(e, "tags"),
IsUniqueItemId = XmlUtil.GetOptionBoolAttribute(e, "unique", true),
ExternalType = XmlUtil.GetOptionalAttribute(e, "externaltype"),
};
foreach (XElement item in e.Elements())
@ -347,7 +352,76 @@ namespace Luban.Job.Common.Defs
{
throw new LoadDefException($"定义文件:{_rootXml} externalselector name:{name} 重复");
}
s_logger.Info("add selector:{}", name);
s_logger.Trace("add selector:{}", name);
}
private static readonly List<string> _externalRequiredAttrs = new List<string> { "name" };
private void AddExternalType(string defineFile, XElement e)
{
ValidAttrKeys(_rootXml, e, null, _externalRequiredAttrs);
string name = XmlUtil.GetRequiredAttribute(e, "name");
if (_externalTypes.ContainsKey(name))
{
throw new LoadDefException($"定义文件:{_rootXml} externaltype:{name} 重复");
}
var et = new ExternalType()
{
Name = name,
};
var mappers = new Dictionary<string, ExternalTypeMapper>();
foreach (XElement mapperEle in e.Elements())
{
var tagName = mapperEle.Name.LocalName;
if (tagName == "mapper")
{
var mapper = CreateMapper(defineFile, name, mapperEle);
string uniqKey = $"{mapper.Lan}##{mapper.Selector}";
if (mappers.ContainsKey(uniqKey))
{
throw new LoadDefException($"定义文件:{_rootXml} externaltype name:{name} mapper(lan='{mapper.Lan}',selector='{mapper.Selector}') 重复");
}
mappers.Add(uniqKey, mapper);
et.Mappers.Add(mapper);
s_logger.Trace("add mapper. externaltype:{} mapper:{@}", name, mapper);
}
else
{
throw new LoadDefException($"定义文件:{defineFile} externaltype:{name} 非法 tag:'{tagName}'");
}
}
_externalTypes.Add(name, et);
}
private static readonly List<string> _mapperOptionalAttrs = new List<string> { };
private static readonly List<string> _mapperRequiredAttrs = new List<string> { "lan", "selector" };
private ExternalTypeMapper CreateMapper(string defineFile, string externalType, XElement e)
{
ValidAttrKeys(_rootXml, e, _mapperOptionalAttrs, _mapperRequiredAttrs);
var m = new ExternalTypeMapper()
{
Lan = DefUtil.ParseLanguage(XmlUtil.GetRequiredAttribute(e, "lan")),
Selector = XmlUtil.GetRequiredAttribute(e, "selector"),
};
foreach (XElement attrEle in e.Elements())
{
var tagName = attrEle.Name.LocalName;
switch (tagName)
{
case "typename":
{
m.TypeName = attrEle.Value;
break;
}
default: throw new LoadDefException($"定义文件:{defineFile} externaltype:{externalType} 非法 tag:{tagName}");
}
}
if (string.IsNullOrWhiteSpace(m.TypeName))
{
throw new LoadDefException($"定义文件:{defineFile} externaltype:{externalType} lan:{m.Lan} selector:{m.Selector} 没有定义 typename");
}
return m;
}
#endregion
}

View File

@ -1,5 +1,6 @@
using Luban.Common.Utils;
using Luban.Job.Common.RawDefs;
using Luban.Job.Common.Types;
using Luban.Job.Common.Utils;
using Luban.Server.Common;
@ -54,6 +55,55 @@ namespace Luban.Job.Common.Defs
public ELanguage CurrentLanguage { get; set; } = ELanguage.INVALID;
public HashSet<string> ExternalSelectors { get; private set; }
private Dictionary<string, ExternalType> ExternalTypes { get; set; }
public List<string> CurrentExternalSelectors { get; private set; }
private void SetCurrentExternalSelectors(string selectors)
{
if (string.IsNullOrEmpty(selectors))
{
CurrentExternalSelectors = new List<string>();
}
else
{
CurrentExternalSelectors = selectors.Split(',').Select(s => s.Trim()).ToList();
foreach (var selector in CurrentExternalSelectors)
{
if (!ExternalSelectors.Contains(selector))
{
throw new Exception($"未知 externalselector:{selector}, 有效值应该为 '{Bright.Common.StringUtil.CollectionToString(ExternalSelectors)}'");
}
}
}
}
public void LoadCommon(DefinesCommon defines, IAgent agent, GenArgsBase args)
{
LocalAssebmly = this;
this.Agent = agent;
this.TopModule = defines.TopModule;
this.ExternalSelectors = defines.ExternalSelectors;
this.ExternalTypes = defines.ExternalTypes;
SetCurrentExternalSelectors(args.ExternalSelectors);
CsUseUnityVectors = args.CsUseUnityVectors;
NamingConventionModule = args.NamingConventionModule;
NamingConventionType = args.NamingConventionType;
NamingConventionBeanMember = args.NamingConventionBeanMember;
NamingConventionEnumMember = args.NamingConventionEnumMember;
}
public bool TryGetExternalType(string typeName, out ExternalType type)
{
return ExternalTypes.TryGetValue(typeName, out type);
}
public void AddType(DefTypeBase type)
{
string fullName = type.FullName;
@ -175,11 +225,7 @@ namespace Luban.Job.Common.Defs
throw new Exception($"not support nullable type:'{module}.{type}'");
}
nullable = true;
#if !LUBAN_LITE
type = type[0..^1];
#else
type = type.Substring(0, type.Length - 1);
#endif
}
else
{

View File

@ -52,6 +52,7 @@ namespace Luban.Job.Common.Defs
IsValueType = b.IsValueType;
Comment = b.Comment;
Tags = DefUtil.ParseAttrs(b.Tags);
_externalTypeName = b.ExternalType;
foreach (var field in b.Fields)
{
Fields.Add(CreateField(field, 0));
@ -160,6 +161,8 @@ namespace Luban.Job.Common.Defs
public override void Compile()
{
base.Compile();
var cs = new List<DefBeanBase>();
if (Children != null)
{

View File

@ -54,7 +54,6 @@ namespace Luban.Job.Common.Defs
return _nameOrAlias2Value.TryGetValue(name, out value);
}
public int GetValueByNameOrAlias(string name)
{
// TODO flags ?
@ -98,7 +97,7 @@ namespace Luban.Job.Common.Defs
IsUniqueItemId = e.IsUniqueItemId;
Comment = e.Comment;
Tags = DefUtil.ParseAttrs(e.Tags);
_externalTypeName = e.ExternalType;
foreach (var item in e.Items)
{
Items.Add(new Item
@ -115,6 +114,7 @@ namespace Luban.Job.Common.Defs
public override void Compile()
{
base.Compile();
var fullName = FullName;
int lastEnumValue = -1;
@ -191,6 +191,8 @@ namespace Luban.Job.Common.Defs
_vaule2Name.Add(item.IntValue, item.Name);
}
}
}
}

View File

@ -42,7 +42,7 @@ namespace Luban.Job.Common.Defs
case ELanguage.GO: cn = TypeUtil.ToPascalCase(Name); break;
case ELanguage.CPP: cn = TypeUtil.ToCamelCase(Name); break;
case ELanguage.LUA: cn = TypeUtil.ToUnderScores(Name); break;
case ELanguage.JS: cn = TypeUtil.ToCamelCase(Name); break;
case ELanguage.JAVASCRIPT: cn = TypeUtil.ToCamelCase(Name); break;
case ELanguage.TYPESCRIPT: cn = TypeUtil.ToCamelCase(Name); break;
case ELanguage.PYTHON: cn = TypeUtil.ToUnderScores(Name); break;
case ELanguage.RUST: cn = TypeUtil.ToUnderScores(Name); break;

View File

@ -1,6 +1,8 @@
using Luban.Common.Utils;
using Luban.Job.Common.RawDefs;
using Luban.Job.Common.Utils;
using Luban.Server.Common;
using System;
using System.Collections.Generic;
namespace Luban.Job.Common.Defs
@ -19,6 +21,10 @@ namespace Luban.Job.Common.Defs
public string Namespace { get; set; }
protected string _externalTypeName;
public ExternalType ExternalType { get; private set; }
public string FullName => TypeUtil.MakeFullName(Namespace, Name);
public string NamespaceWithTopModule => TypeUtil.MakeNamespace(AssemblyBase.TopModule, Namespace);
@ -65,9 +71,34 @@ namespace Luban.Job.Common.Defs
return Tags != null && Tags.TryGetValue(attrName, out var value) ? value : null;
}
public ExternalTypeMapper CurrentExternalTypeMapper
{
get
{
if (ExternalType == null)
{
return null;
}
return ExternalType.Mappers.Find(m => m.Lan == DefAssemblyBase.LocalAssebmly.CurrentLanguage);
}
}
public virtual void PreCompile() { }
public abstract void Compile();
public virtual void Compile()
{
if (!string.IsNullOrEmpty(_externalTypeName))
{
if (AssemblyBase.TryGetExternalType(_externalTypeName, out var type))
{
this.ExternalType = type;
}
else
{
throw new Exception($"enum:'{FullName}' ¶ÔÓ¦µÄ externaltype:{_externalTypeName} ²»´æÔÚ");
}
}
}
public virtual void PostCompile() { }
}

View File

@ -8,7 +8,7 @@ namespace Luban.Job.Common
GO,
CPP,
LUA,
JS,
JAVASCRIPT,
TYPESCRIPT,
PYTHON,
ERLANG,

View File

@ -22,6 +22,8 @@ namespace Luban.Job.Common.RawDefs
public string Tags { get; set; }
public string ExternalType { get; set; }
public List<Field> Fields { get; set; } = new List<Field>();
}
}

View File

@ -10,10 +10,12 @@ namespace Luban.Job.Common.RawDefs
{
public string TopModule { get; set; } = "";
public HashSet<string> ExternalSelectors { get; set; } = new HashSet<string>();
public HashSet<string> ExternalSelectors { get; set; } = new();
public List<Bean> Beans { get; set; } = new List<Bean>();
public Dictionary<string, ExternalType> ExternalTypes { get; set; } = new();
public List<PEnum> Enums { get; set; } = new List<PEnum>();
public List<Bean> Beans { get; set; } = new();
public List<PEnum> Enums { get; set; } = new();
}
}

View File

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Luban.Job.Common.RawDefs
{
public class ExternalTypeMapper
{
public string Selector { get; set; }
public ELanguage Lan { get; set; }
public string TypeName { get; set; }
}
public class ExternalType
{
public string Name { get; set; }
public List<ExternalTypeMapper> Mappers { get; set; } = new List<ExternalTypeMapper>();
}
}

View File

@ -30,6 +30,8 @@ namespace Luban.Job.Common.RawDefs
public string Tags { get; set; }
public string ExternalType { get; set; }
public List<EnumItem> Items { get; set; } = new List<EnumItem>();
}
}

View File

@ -59,7 +59,8 @@ namespace Luban.Job.Common.TypeVisitors
public string Accept(TEnum type)
{
return type.DefineEnum.FullName;
var mapper = type.DefineEnum.CurrentExternalTypeMapper;
return mapper != null ? mapper.TypeName : type.DefineEnum.FullName;
}
public string Accept(TString type)

View File

@ -59,7 +59,7 @@ namespace Luban.Job.Common.TypeVisitors
public string Accept(TEnum type, string bufName, string fieldName)
{
return $"{fieldName} = ({type.DefineEnum.FullName}){bufName}.ReadInt();";
return $"{fieldName} = ({ type.Apply(CsUnderingDefineTypeName.Ins)}){bufName}.ReadInt();";
}
public string Accept(TString type, string bufName, string fieldName)

View File

@ -169,7 +169,7 @@ namespace Luban.Job.Common.Utils
case ELanguage.GO:
case ELanguage.CPP:
case ELanguage.LUA:
case ELanguage.JS:
case ELanguage.JAVASCRIPT:
case ELanguage.TYPESCRIPT:
case ELanguage.PYTHON:
case ELanguage.RUST:
@ -182,5 +182,30 @@ namespace Luban.Job.Common.Utils
default: throw new Exception($"unknown language:{curLan}");
}
}
public static ELanguage ParseLanguage(string lan)
{
switch (lan.ToLower())
{
case "cs":
case "c#":
case "csharp": return ELanguage.CS;
case "java": return ELanguage.JAVA;
case "go":
case "golang": return ELanguage.GO;
case "cpp":
case "c++": return ELanguage.CPP;
case "lua": return ELanguage.LUA;
case "js":
case "javascript": return ELanguage.JAVASCRIPT;
case "ts":
case "typescript": return ELanguage.TYPESCRIPT;
case "python": return ELanguage.PYTHON;
case "rust": return ELanguage.RUST;
case "pb":
case "protobuf": return ELanguage.PROTOBUF;
default: throw new ArgumentException($"parse lan:'{lan}' fail");
}
}
}
}

View File

@ -15,7 +15,7 @@ namespace Luban.Job.Common.Utils
case ELanguage.CPP: return fullName + ".cpp";
case ELanguage.GO: return fullName + ".go";
case ELanguage.LUA: return fullName.Replace('.', '_') + ".lua";
case ELanguage.JS: return fullName + ".js";
case ELanguage.JAVASCRIPT: return fullName + ".js";
case ELanguage.TYPESCRIPT: return fullName.Replace('.', '/') + ".ts";
case ELanguage.RUST: return fullName.Replace('.', '_') + ".rs";
case ELanguage.PROTOBUF: return fullName.Replace('.', '_') + ".pb";
@ -69,7 +69,7 @@ namespace Luban.Job.Common.Utils
{ "lua", ELanguage.LUA },
{ "python", ELanguage.PYTHON },
{ "typescript", ELanguage.TYPESCRIPT },
{ "javascript", ELanguage.JS },
{ "javascript", ELanguage.JAVASCRIPT },
{ "erlang", ELanguage.ERLANG },
{ "rust", ELanguage.RUST },
{ "pb", ELanguage.PROTOBUF },

View File

@ -28,11 +28,10 @@ namespace Luban.Job.Db.Defs
}
public void Load(Defines defines, RemoteAgent agent)
public void Load(Defines defines, RemoteAgent agent, GenArgs args)
{
LoadCommon(defines, agent, args);
this.SupportNullable = false;
this.Agent = agent;
TopModule = defines.TopModule;
foreach (var e in defines.Enums)
{

View File

@ -83,15 +83,8 @@ namespace Luban.Job.Db
var rawDefines = loader.BuildDefines();
var ass = new DefAssembly()
{
NamingConventionModule = args.NamingConventionModule,
NamingConventionType = args.NamingConventionType,
NamingConventionBeanMember = args.NamingConventionBeanMember,
NamingConventionEnumMember = args.NamingConventionEnumMember,
};
DefAssemblyBase.LocalAssebmly = ass;
ass.Load(rawDefines, agent);
var ass = new DefAssembly();
ass.Load(rawDefines, agent, args);
List<DefTypeBase> exportTypes = ass.GetExportTypes();

View File

@ -27,11 +27,9 @@ namespace Luban.Job.Proto.Defs
}
}
public void Load(Defines defines, RemoteAgent agent)
public void Load(Defines defines, RemoteAgent agent, GenArgs args)
{
this.Agent = agent;
TopModule = defines.TopModule;
LoadCommon(defines, agent, args);
foreach (var e in defines.Enums)
{

View File

@ -87,19 +87,9 @@ namespace Luban.Job.Proto
var rawDefines = loader.BuildDefines();
var ass = new DefAssembly()
{
CsUseUnityVectors = args.CsUseUnityVectors,
var ass = new DefAssembly();
NamingConventionModule = args.NamingConventionModule,
NamingConventionType = args.NamingConventionType,
NamingConventionBeanMember = args.NamingConventionBeanMember,
NamingConventionEnumMember = args.NamingConventionEnumMember,
};
ass.Load(rawDefines, agent);
DefAssemblyBase.LocalAssebmly = ass;
ass.Load(rawDefines, agent, args);
var targetService = args.Service;