diff --git a/README.md b/README.md index 198d08c..e7e90e4 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,8 @@ ## 介绍 -目前主流的配置工具功能多为excel文件到json之类格式的转换工具及简单代码生成器,只能勉强满足中小类型项目的需求。 -在中大型游戏项目中,基本都会有技能、行为树之类的复杂功能。这些功能有非常复杂的数据结构,往往使用自定义编辑器制作,并以json、xml等文件格式保存。就算常规的excel表,也经常出现复杂的数据结构需求。这些简单工具面对此类需求要么无法支持,要么就强迫策划和程序使用拆表等奇技淫巧,严重影响设计和开发效率。 + +在中大型游戏项目中,就算常规的excel表也经常出现复杂的数据结构需求,常规的导表工具面对此类需求要么无法支持,要么就强迫策划和程序使用拆表等奇技淫巧,严重影响设计和开发效率。另外有复杂GamePlay的游戏,基本都会有技能、行为树、关卡之类的复杂功能,这些功能有非常复杂的数据结构,往往使用自定义编辑器制作,并以json、xml等文件格式保存,以excel为中心的导表工具无法处理这些数据,导致程序往往不得不手动解析它们,浪费了很多时间。 luban相较于常规的excel导表工具有以下核心优势: - 增强了excel格式。可以比较简洁地excel配置**任意复杂**的数据,像子结构、结构列表,以及更复杂的深层次的嵌套结构都能直接解析处理。 diff --git a/src/Luban.Job.Cfg/Source/DataCreators/ExcelNamedRowDataCreator.cs b/src/Luban.Job.Cfg/Source/DataCreators/ExcelNamedRowDataCreator.cs deleted file mode 100644 index 8330da9..0000000 --- a/src/Luban.Job.Cfg/Source/DataCreators/ExcelNamedRowDataCreator.cs +++ /dev/null @@ -1,350 +0,0 @@ -//using Luban.Common.Utils; -//using Luban.Job.Cfg.Datas; -//using Luban.Job.Cfg.DataSources.Excel; -//using Luban.Job.Cfg.Defs; -//using Luban.Job.Cfg.TypeVisitors; -//using Luban.Job.Common.Types; -//using Luban.Job.Common.TypeVisitors; -//using System; -//using System.Collections.Generic; - -//namespace Luban.Job.Cfg.DataCreators -//{ -// class ExcelNamedRowDataCreator : ITypeFuncVisitor -// { -// public static ExcelNamedRowDataCreator Ins { get; } = new ExcelNamedRowDataCreator(); - - -// public DType ReadExcel(TitleRow row, TBean btype) -// { -// return Accept(btype, row, false, false); -// } - -// public DType Accept(TBool type, TitleRow x, bool multirow, bool nullable) -// { -// throw new NotSupportedException(); -// } - -// public DType Accept(TByte type, TitleRow x, bool multirow, bool nullable) -// { -// throw new NotSupportedException(); -// } - -// public DType Accept(TShort type, TitleRow x, bool multirow, bool nullable) -// { -// throw new NotSupportedException(); -// } - -// public DType Accept(TFshort type, TitleRow x, bool multirow, bool nullable) -// { -// throw new NotSupportedException(); -// } - -// public DType Accept(TInt type, TitleRow x, bool multirow, bool nullable) -// { -// throw new NotSupportedException(); -// } - -// public DType Accept(TFint type, TitleRow x, bool multirow, bool nullable) -// { -// throw new NotSupportedException(); -// } - -// public DType Accept(TLong type, TitleRow x, bool multirow, bool nullable) -// { -// throw new NotSupportedException(); -// } - -// public DType Accept(TFlong type, TitleRow x, bool multirow, bool nullable) -// { -// throw new NotSupportedException(); -// } - -// public DType Accept(TFloat type, TitleRow x, bool multirow, bool nullable) -// { -// throw new NotSupportedException(); -// } - -// public DType Accept(TDouble type, TitleRow x, bool multirow, bool nullable) -// { -// throw new NotSupportedException(); -// } - -// public DType Accept(TEnum type, TitleRow x, bool multirow, bool nullable) -// { -// throw new NotSupportedException(); -// } - -// public DType Accept(TString type, TitleRow x, bool multirow, bool nullable) -// { -// throw new NotSupportedException(); -// } - -// public DType Accept(TBytes type, TitleRow x, bool multirow, bool nullable) -// { -// throw new NotSupportedException(); -// } - -// public DType Accept(TText type, TitleRow x, bool multirow, bool nullable) -// { -// throw new NotSupportedException(); -// } - -// private static bool IsContainerAndElementNotSepType(TType type) -// { -// switch (type) -// { -// case TArray ta: return ta.ElementType.Apply(IsNotSepTypeVisitor.Ins); -// case TList tl: return tl.ElementType.Apply(IsNotSepTypeVisitor.Ins); -// case TSet ts: return ts.ElementType.Apply(IsNotSepTypeVisitor.Ins); -// case TMap tm: return tm.KeyType.Apply(IsNotSepTypeVisitor.Ins) && tm.ValueType.Apply(IsNotSepTypeVisitor.Ins); -// default: return false; -// } -// throw new NotImplementedException(); -// } - -// private List CreateBeanFields(DefBean bean, TitleRow row) -// { -// var list = new List(); -// foreach (DefField f in bean.HierarchyFields) -// { -// string fname = f.Name; -// Title title = row.GetTitle(fname); -// if (title == null) -// { -// throw new Exception($"bean:'{bean.FullName}' 缺失 列:'{fname}',请检查是否写错或者遗漏"); -// } -// // 多级标题 -// if (title.SubTitles.Count > 0) -// { -// try -// { -// list.Add(f.CType.Apply(this, row.GetSubTitleNamedRow(fname), f.IsMultiRow, f.IsNullable)); -// } -// catch (DataCreateException dce) -// { -// dce.Push(bean, f); -// throw; -// } -// catch (Exception e) -// { -// var dce = new DataCreateException(e, $"列:{fname}"); -// dce.Push(bean, f); -// throw dce; -// } -// } -// else -// { -// string sep = ""; -// if (string.IsNullOrWhiteSpace(sep) && IsContainerAndElementNotSepType(f.CType)) -// { -// sep = ";,"; -// } - -// if (f.IsMultiRow) -// { -// try -// { -// if (f.CType.IsCollection) -// { -// list.Add(f.CType.Apply(MultiRowExcelDataCreator.Ins, row.GetColumnOfMultiRows(f.Name, sep), f.IsNullable, (DefAssembly)bean.AssemblyBase)); -// } -// else -// { -// list.Add(f.CType.Apply(ExcelDataCreator.Ins, f, row.GetMultiRowStream(f.Name, sep), (DefAssembly)bean.AssemblyBase)); -// } -// } -// catch (DataCreateException dce) -// { -// dce.Push(bean, f); -// throw; -// } -// catch (Exception e) -// { -// var dce = new DataCreateException(e, ""); -// dce.Push(bean, f); -// throw dce; -// } -// } -// else -// { -// //ExcelStream stream = row.GetColumn(f.Name, sep, !f.CType.Apply(IsMultiData.Ins)); -// ExcelStream stream = row.GetColumn(f.Name); -// try -// { -// list.Add(f.CType.Apply(ExcelDataCreator.Ins, f, stream, (DefAssembly)bean.AssemblyBase)); -// } -// catch (DataCreateException dce) -// { -// dce.Push(bean, f); -// throw; -// } -// catch (Exception e) -// { -// var dce = new DataCreateException(e, stream.LastReadDataInfo); -// dce.Push(bean, f); -// throw dce; -// } -// } -// } -// } -// return list; -// } - - -// public DType Accept(TBean type, TitleRow row, bool multirow, bool nullable) -// { -// var originBean = (DefBean)type.Bean; -// if (originBean.IsAbstractType) -// { -// string subType = row.GetColumn(DefBean.TYPE_NAME_KEY).Read().ToString().Trim(); -// if (subType.ToLower() == DefBean.BEAN_NULL_STR) -// { -// if (!type.IsNullable) -// { -// throw new Exception($"type:'{type}' 不是可空类型 '{type.Bean.FullName}?' , 不能为空"); -// } -// return null; -// } -// string fullType = TypeUtil.MakeFullName(originBean.Namespace, subType); -// DefBean implType = (DefBean)originBean.GetNotAbstractChildType(subType); -// if (implType == null) -// { -// throw new Exception($"type:'{fullType}' 不是 bean 类型"); -// } -// return new DBean(originBean, implType, CreateBeanFields(implType, row)); -// } -// else -// { -// if (type.IsNullable) -// { -// string subType = row.GetColumn(DefBean.TYPE_NAME_KEY).Read().ToString().Trim(); -// if (subType == DefBean.BEAN_NULL_STR) -// { -// return null; -// } -// else if (subType != DefBean.BEAN_NOT_NULL_STR && subType != originBean.Name) -// { -// throw new Exception($"type:'{type.Bean.FullName}' 可空标识:'{subType}' 不合法(只能为{DefBean.BEAN_NOT_NULL_STR}或{DefBean.BEAN_NULL_STR}或{originBean.Name})"); -// } -// } - -// return new DBean(originBean, originBean, CreateBeanFields(originBean, row)); -// } -// } - - -// private List ReadList(TBean elementType, TitleRow row, bool multirow) -// { -// var list = new List(); -// // 如果是多行数据,以当前title为title,每行读入一个element -// if (multirow) -// { -// //foreach (var sub in row.GenerateSubNameRows(elementType)) -// foreach (var sub in row.Elements) -// { -// list.Add(this.Accept(elementType, sub, false, false)); -// } -// } -// else -// { -// // 如果不是多行,并且定义了子标题的话。以一个子标题所占的列,读入一个数据 - -// //foreach (var sub in row.SelfTitle.SubTitleList) -// //{ -// // list.Add(this.Accept(elementType, new TitleRow(sub, row.Rows), false, false)); -// //} -// throw new NotSupportedException("只有multi_rows=1的list,bean类型才允许有子title"); -// } -// return list; -// } - -// public DType Accept(TArray type, TitleRow x, bool multirow, bool nullable) -// { -// if (type.ElementType is not TBean bean) -// { -// throw new Exception($"NamedRow 只支持 bean 类型的容器"); -// } -// else -// { -// return new DArray(type, ReadList(bean, x, multirow)); -// } -// } - -// public DType Accept(TList type, TitleRow x, bool multirow, bool nullable) -// { -// if (type.ElementType is not TBean bean) -// { -// throw new Exception($"NamedRow 只支持 bean 类型的容器"); -// } -// else -// { -// return new DList(type, ReadList(bean, x, multirow)); -// } -// } - -// public DType Accept(TSet type, TitleRow x, bool multirow, bool nullable) -// { -// throw new NotSupportedException(); -// } - - -// private bool TryCreateColumnStream(TitleRow x, Title title, out ExcelStream stream) -// { -// var cells = new List(); -// for (int i = title.FromIndex; i <= title.ToIndex; i++) -// { -// foreach (var row in x.Rows) -// { -// if (row.Count > i) -// { -// var value = row[i].Value; -// if (!(value == null || (value is string s && string.IsNullOrEmpty(s)))) -// { -// cells.Add(row[i]); -// } -// } -// } -// } -// if (cells.Count > 0) -// { -// stream = new ExcelStream(cells, 0, cells.Count - 1, "", false); -// return true; -// } -// stream = null; -// return false; -// } - -// public DType Accept(TMap type, TitleRow x, bool multirow, bool nullable) -// { -// var map = new Dictionary(); -// foreach (var e in x.Fields) -// { -// var keyData = type.KeyType.Apply(StringDataCreator.Ins, e.Key); -// var valueData = type.ValueType.Apply(ExcelDataCreator.Ins, null, e.Value.AsStream, DefAssembly.LocalAssebmly); -// map.Add(keyData, valueData); -// } -// return new DMap(type, map); -// } - -// public DType Accept(TVector2 type, TitleRow x, bool multirow, bool nullable) -// { -// throw new NotSupportedException(); -// } - -// public DType Accept(TVector3 type, TitleRow x, bool multirow, bool nullable) -// { -// throw new NotSupportedException(); -// } - -// public DType Accept(TVector4 type, TitleRow x, bool multirow, bool nullable) -// { -// throw new NotSupportedException(); -// } - -// public DType Accept(TDateTime type, TitleRow x, bool multirow, bool nullable) -// { -// throw new NotSupportedException(); -// } -// } -//} diff --git a/src/Luban.Job.Cfg/Source/DataCreators/SheetDataCreator.cs b/src/Luban.Job.Cfg/Source/DataCreators/SheetDataCreator.cs index b9f4edf..5d59368 100644 --- a/src/Luban.Job.Cfg/Source/DataCreators/SheetDataCreator.cs +++ b/src/Luban.Job.Cfg/Source/DataCreators/SheetDataCreator.cs @@ -224,19 +224,27 @@ namespace Luban.Job.Cfg.DataCreators public DType Accept(TText type, Sheet sheet, TitleRow row) { - if (row.CellCount != 2) + if (string.IsNullOrEmpty(row.SelfTitle.Sep)) { - throw new Exception($"text 要求两个字段"); + if (row.CellCount != 2) + { + throw new Exception($"text 要求两个字段"); + } + int startIndex = row.SelfTitle.FromIndex; + var key = ParseString(row.Row[startIndex].Value); + var text = ParseString(row.Row[startIndex + 1].Value); + if (type.IsNullable && key == null && text == null) + { + return null; + } + DataUtil.ValidateText(key, text); + return new DText(key, text); } - int startIndex = row.SelfTitle.FromIndex; - var key = ParseString(row.Row[startIndex].Value); - var text = ParseString(row.Row[startIndex + 1].Value); - if (type.IsNullable && key == null && text == null) + else { - return null; + var s = row.AsStream(""); + return type.Apply(ExcelStreamDataCreator.Ins, s); } - DataUtil.ValidateText(key, text); - return new DText(key, text); } private List CreateBeanFields(DefBean bean, Sheet sheet, TitleRow row) diff --git a/src/Luban.Job.Cfg/Source/DataSources/Excel/ExcelDataSource.cs b/src/Luban.Job.Cfg/Source/DataSources/Excel/ExcelDataSource.cs index 3c223a6..eeb5ea6 100644 --- a/src/Luban.Job.Cfg/Source/DataSources/Excel/ExcelDataSource.cs +++ b/src/Luban.Job.Cfg/Source/DataSources/Excel/ExcelDataSource.cs @@ -36,6 +36,16 @@ namespace Luban.Job.Cfg.DataSources.Excel } } + public void Load(params RawSheet[] rawSheets) + { + foreach (RawSheet rawSheet in rawSheets) + { + var sheet = new Sheet("__intern__", rawSheet.TableName); + sheet.Load(rawSheet); + _sheets.Add(sheet); + } + } + public RawSheetTableDefInfo LoadTableDefInfo(string rawUrl, string sheetName, Stream stream) { return SheetLoadUtil.LoadSheetTableDefInfo(rawUrl, sheetName, stream); diff --git a/src/Luban.Job.Cfg/Source/DataSources/Excel/RawSheet.cs b/src/Luban.Job.Cfg/Source/DataSources/Excel/RawSheet.cs index 09616eb..1d772a5 100644 --- a/src/Luban.Job.Cfg/Source/DataSources/Excel/RawSheet.cs +++ b/src/Luban.Job.Cfg/Source/DataSources/Excel/RawSheet.cs @@ -10,8 +10,12 @@ namespace Luban.Job.Cfg.DataSources.Excel class RawSheet { - public Title Title { get; init; } + public Title Title { get; set; } - public List> Cells { get; init; } + public string TableName { get; set; } + + public int TitleRowCount { get; set; } + + public List> Cells { get; set; } } } diff --git a/src/Luban.Job.Cfg/Source/DataSources/Excel/RawSheetTableDefInfo.cs b/src/Luban.Job.Cfg/Source/DataSources/Excel/RawSheetTableDefInfo.cs index 1537b5e..fc84db8 100644 --- a/src/Luban.Job.Cfg/Source/DataSources/Excel/RawSheetTableDefInfo.cs +++ b/src/Luban.Job.Cfg/Source/DataSources/Excel/RawSheetTableDefInfo.cs @@ -8,19 +8,19 @@ namespace Luban.Job.Cfg.DataSources.Excel { class FieldInfo { - public string Name { get; init; } + public string Name { get; set; } - public Dictionary Tags { get; init; } + public Dictionary Tags { get; set; } - public string Type { get; init; } + public string Type { get; set; } - public string BriefDesc { get; init; } + public string BriefDesc { get; set; } - public string DetailDesc { get; init; } + public string DetailDesc { get; set; } } class RawSheetTableDefInfo { - public Dictionary FieldInfos { get; init; } + public Dictionary FieldInfos { get; set; } } } diff --git a/src/Luban.Job.Cfg/Source/DataSources/Excel/SheetLoadUtil.cs b/src/Luban.Job.Cfg/Source/DataSources/Excel/SheetLoadUtil.cs index 11fe735..ab13cf2 100644 --- a/src/Luban.Job.Cfg/Source/DataSources/Excel/SheetLoadUtil.cs +++ b/src/Luban.Job.Cfg/Source/DataSources/Excel/SheetLoadUtil.cs @@ -67,14 +67,14 @@ namespace Luban.Job.Cfg.DataSources.Excel bool orientRow; int titleRowNum; - if (!TryParseMeta(reader, out orientRow, out titleRowNum, out var _)) + if (!TryParseMeta(reader, out orientRow, out titleRowNum, out var tableName)) { return null; } var cells = ParseRawSheetContent(reader, orientRow); var title = ParseTitle(cells, reader.MergeCells, orientRow, out _); cells.RemoveRange(0, Math.Min(titleRowNum, cells.Count)); - return new RawSheet() { Title = title, Cells = cells }; + return new RawSheet() { Title = title, TitleRowCount = titleRowNum, TableName = tableName, Cells = cells }; } private static int GetTitleRowNum(CellRange[] mergeCells, bool orientRow) @@ -108,8 +108,10 @@ namespace Luban.Job.Cfg.DataSources.Excel public static Title ParseTitle(List> cells, CellRange[] mergeCells, bool orientRow, out int titleRowNum) { - var rootTitle = new Title() { - Root = true, Name = "__root__", + var rootTitle = new Title() + { + Root = true, + Name = "__root__", Tags = new Dictionary(), FromIndex = 0, ToIndex = cells.Select(r => r.Count).Max() - 1 @@ -130,10 +132,14 @@ namespace Luban.Job.Cfg.DataSources.Excel private static bool IsIgnoreTitle(string title) { +#if !LUBAN_LITE return string.IsNullOrEmpty(title) || title.StartsWith('#'); +#else + return string.IsNullOrEmpty(title) || title.StartsWith("#"); +#endif } - private static (string Name, Dictionary Tags) ParseNameAndMetaAttrs(string nameAndAttrs) + public static (string Name, Dictionary Tags) ParseNameAndMetaAttrs(string nameAndAttrs) { var attrs = nameAndAttrs.Split('&'); @@ -227,24 +233,20 @@ namespace Luban.Job.Cfg.DataSources.Excel } } - public static bool TryParseMeta(IExcelDataReader reader, out bool orientRow, out int titleRows, out string tableName) + public static bool TryParseMeta(List cells, out bool orientRow, out int titleRows, out string tableName) { orientRow = true; titleRows = TITLE_DEFAULT_ROW_NUM; tableName = ""; - if (!reader.Read() || reader.FieldCount == 0) - { - return false; - } + // meta 行 必须以 ##为第一个单元格内容,紧接着 key:value 形式 表达meta属性 - if (reader.GetString(0) != "##") + if (cells.Count == 0 || cells[0] != "##") { return false; } - for (int i = 1, n = reader.FieldCount; i < n; i++) + foreach (var attr in cells.Skip(1)) { - var attr = reader.GetString(i)?.Trim(); if (string.IsNullOrWhiteSpace(attr)) { continue; @@ -255,8 +257,8 @@ namespace Luban.Job.Cfg.DataSources.Excel { throw new Exception($"单元薄 meta 定义出错. attribute:{attr}"); } - string key = ss[0].Trim().ToLower(); - string value = ss[1].Trim().ToLower(); + string key = ss[0].Trim(); + string value = ss[1].Trim(); switch (key) { case "orientation": @@ -291,6 +293,23 @@ namespace Luban.Job.Cfg.DataSources.Excel return true; } + public static bool TryParseMeta(IExcelDataReader reader, out bool orientRow, out int titleRows, out string tableName) + { + if (!reader.Read() || reader.FieldCount == 0) + { + orientRow = true; + titleRows = TITLE_DEFAULT_ROW_NUM; + tableName = ""; + return false; + } + var cells = new List(); + for (int i = 0, n = reader.FieldCount; i < n; i++) + { + cells.Add(reader.GetString(i)?.Trim()); + } + return TryParseMeta(cells, out orientRow, out titleRows, out tableName); + } + private static List> ParseRawSheetContent(IExcelDataReader reader, bool orientRow, int? maxParseRow = null) { // TODO 优化性能 diff --git a/src/Luban.Job.Cfg/Source/Defs/CfgDefLoader.cs b/src/Luban.Job.Cfg/Source/Defs/CfgDefLoader.cs index e82f432..4ea731e 100644 --- a/src/Luban.Job.Cfg/Source/Defs/CfgDefLoader.cs +++ b/src/Luban.Job.Cfg/Source/Defs/CfgDefLoader.cs @@ -301,8 +301,15 @@ namespace Luban.Job.Cfg.Defs //var titleRow = sheet.RowColumns[sheet.AttrRowCount]; //// 有可能没有注释行,此时使用标题行,这个是必须有的 //var descRow = sheet.HeaderRowCount >= sheet.AttrRowCount + 2 ? sheet.RowColumns[sheet.AttrRowCount + 1] : titleRow; +#if !LUBAN_LITE foreach (var (name, f) in tableDefInfo.FieldInfos) { +#else + foreach (var e in tableDefInfo.FieldInfos) + { + var name = e.Key; + var f = e.Value; +#endif var cf = new CfgField() { Name = name, Id = 0 }; string[] attrs = f.Type.Trim().Split('&').Select(s => s.Trim()).ToArray(); diff --git a/src/Luban.Job.Cfg/Source/Defs/DefAssembly.cs b/src/Luban.Job.Cfg/Source/Defs/DefAssembly.cs index 7c40ff4..f7d3a94 100644 --- a/src/Luban.Job.Cfg/Source/Defs/DefAssembly.cs +++ b/src/Luban.Job.Cfg/Source/Defs/DefAssembly.cs @@ -1,6 +1,8 @@ using Bright.Collections; using Luban.Job.Cfg.Datas; +#if !LUBAN_LITE using Luban.Job.Cfg.l10n; +#endif using Luban.Job.Cfg.RawDefs; using Luban.Job.Cfg.TypeVisitors; using Luban.Job.Common.Defs; @@ -14,6 +16,8 @@ namespace Luban.Job.Cfg.Defs { public class TableDataInfo { + public DefTable Table { get; } + public List MainRecords { get; } public List PatchRecords { get; } @@ -22,8 +26,9 @@ namespace Luban.Job.Cfg.Defs public Dictionary FinalRecordMap { get; set; } - public TableDataInfo(List mainRecords, List patchRecords) + public TableDataInfo(DefTable table, List mainRecords, List patchRecords) { + Table = table; MainRecords = mainRecords; PatchRecords = patchRecords; } @@ -69,6 +74,7 @@ namespace Luban.Job.Cfg.Defs public Dictionary CfgTables { get; } = new Dictionary(); +#if !LUBAN_LITE public RawTextTable RawTextTable { get; } = new RawTextTable(); public TextTable ExportTextTable { get; private set; } @@ -83,6 +89,8 @@ namespace Luban.Job.Cfg.Defs NotConvertTextSet = new NotConvertTextSet(); } +#endif + public Patch GetPatch(string name) { return _patches.Find(b => b.Name == name); @@ -103,7 +111,7 @@ namespace Luban.Job.Cfg.Defs public void AddDataTable(DefTable table, List mainRecords, List patchRecords) { - _recordsByTables[table.FullName] = new TableDataInfo(mainRecords, patchRecords); + _recordsByTables[table.FullName] = new TableDataInfo(table, mainRecords, patchRecords); } public List GetTableAllDataList(DefTable table) diff --git a/src/Luban.Job.Cfg/Source/Defs/DefField.cs b/src/Luban.Job.Cfg/Source/Defs/DefField.cs index 5a0bdb8..dfa8392 100644 --- a/src/Luban.Job.Cfg/Source/Defs/DefField.cs +++ b/src/Luban.Job.Cfg/Source/Defs/DefField.cs @@ -42,6 +42,7 @@ namespace Luban.Job.Cfg.Defs || (CType is TList tl && tl.ElementType.IsBean) || (CType is TMap tm && tm.ValueType.IsBean); +#if !LUBAN_LITE public string CsRefTypeName { get @@ -95,6 +96,7 @@ namespace Luban.Job.Cfg.Defs return $"{TsRefVarName} : {table.ValueTType.Apply(TypescriptDefineTypeNameVisitor.Ins)}{(IsNullable ? "" : " = undefined!")}"; } } +#endif public string CsRefVarName => $"{CsStyleName}_Ref"; diff --git a/src/Luban.Job.Cfg/Source/ValidatorContext.cs b/src/Luban.Job.Cfg/Source/ValidatorContext.cs index a9bd996..c7c39c1 100644 --- a/src/Luban.Job.Cfg/Source/ValidatorContext.cs +++ b/src/Luban.Job.Cfg/Source/ValidatorContext.cs @@ -1,3 +1,4 @@ +using Bright.Collections; using Luban.Common.Utils; using Luban.Job.Cfg.Datas; using Luban.Job.Cfg.DataVisitors; @@ -86,10 +87,12 @@ namespace Luban.Job.Cfg { CurrentVisitor = visitor; visitor.ValidateTable(t, records); +#if !LUBAN_LITE if (this.Assembly.NeedL10nTextTranslate) { ValidateText(t, records); } +#endif } finally { @@ -106,6 +109,7 @@ namespace Luban.Job.Cfg } } +#if !LUBAN_LITE private void ValidateText(DefTable table, List records) { foreach (var r in records) @@ -115,6 +119,7 @@ namespace Luban.Job.Cfg } CurrentVisitor.CurrentValidateRecord = null; } +#endif private async Task ValidatePaths() { @@ -165,7 +170,11 @@ namespace Luban.Job.Cfg { if (ls.All(f => fileNotExistsSet.Contains(f))) { +#if !LUBAN_LITE agent.Error("记录 {0} = {1} (来自文件:{2}) 所引用文件:{3} 不存在", q.DataPath, q.Value, q.Source, string.Join(',', ls)); +#else + agent.Error("记录 {0} = {1} (来自文件:{2}) 所引用文件:{3} 不存在", q.DataPath, q.Value, q.Source, string.Join(",", ls)); +#endif } break; } @@ -252,8 +261,10 @@ namespace Luban.Job.Cfg break; } } +#if !LUBAN_LITE tableDataInfo.FinalRecords = mainRecords; tableDataInfo.FinalRecordMap = mainRecordMap; +#endif } } } diff --git a/src/Luban.Job.Cfg/Source/Validators/PathValidator.cs b/src/Luban.Job.Cfg/Source/Validators/PathValidator.cs index b36ef20..2a1f67c 100644 --- a/src/Luban.Job.Cfg/Source/Validators/PathValidator.cs +++ b/src/Luban.Job.Cfg/Source/Validators/PathValidator.cs @@ -109,7 +109,11 @@ namespace Luban.Job.Cfg.Validators string suffix = groups[2].Value.Substring(1); if (suffix.EndsWith("_C")) { +#if !LUBAN_LITE suffix = suffix[0..^2]; +#else + suffix = suffix.Substring(0, suffix.Length - 2); +#endif } return path.EndsWith(suffix); } @@ -212,9 +216,17 @@ namespace Luban.Job.Cfg.Validators string patType = ss[0]; bool emptyAble = false; +#if !LUBAN_LITE if (patType.EndsWith('?')) +#else + if (patType.EndsWith("?")) +#endif { +#if !LUBAN_LITE patType = patType[0..^1]; +#else + patType = patType.Substring(0, patType.Length - 1); +#endif emptyAble = true; } diff --git a/src/Luban.Job.Cfg/Source/Validators/RangeValidator.cs b/src/Luban.Job.Cfg/Source/Validators/RangeValidator.cs index 59e7de7..2888cf9 100644 --- a/src/Luban.Job.Cfg/Source/Validators/RangeValidator.cs +++ b/src/Luban.Job.Cfg/Source/Validators/RangeValidator.cs @@ -82,14 +82,22 @@ namespace Luban.Job.Cfg.Validators case '(': _includeMinBound = false; break; default: ThrowError(); break; } +#if !LUBAN_LITE switch (_str[^1]) +#else + switch (_str[_str.Length - 1]) +#endif { case ']': _includeMaxBound = true; break; case ')': _includeMaxBound = false; break; default: ThrowError(); break; } +#if !LUBAN_LITE var pars = _str[1..^1].Split(','); +#else + var pars = _str.Substring(1, _str.Length - 1).Split(','); +#endif if (pars.Length != 2) { ThrowError(); diff --git a/src/Luban.Job.Cfg/Source/Validators/RefValidator.cs b/src/Luban.Job.Cfg/Source/Validators/RefValidator.cs index efbf561..b11b920 100644 --- a/src/Luban.Job.Cfg/Source/Validators/RefValidator.cs +++ b/src/Luban.Job.Cfg/Source/Validators/RefValidator.cs @@ -60,11 +60,13 @@ namespace Luban.Job.Cfg.Validators return; } DefTable ct = assembly.GetCfgTable(actualTable); +#if !LUBAN_LITE var recordMap = assembly.GetTableDataInfo(ct).FinalRecordMap; if (/*recordMap != null &&*/ recordMap.ContainsKey(key)) { return; } +#endif } foreach (var table in Tables) diff --git a/src/LubanAssistant/AssistantTab.cs b/src/LubanAssistant/AssistantTab.cs index 4dde56b..6a11464 100644 --- a/src/LubanAssistant/AssistantTab.cs +++ b/src/LubanAssistant/AssistantTab.cs @@ -98,11 +98,10 @@ namespace LubanAssistant private void LoadDataToCurrentDoc() { - Worksheet sheet = Globals.LubanAssistant.Application.ActiveSheet; - var metaAttrs = ExcelUtil.ParseMetaAttrs(sheet); - if (!metaAttrs.TryGetValue("table", out var tableName)) + var rawSheet = ExcelUtil.ParseRawSheetTitleOnly(sheet); + if (string.IsNullOrWhiteSpace(rawSheet.TableName)) { MessageBox.Show($"meta行未指定table名"); return; @@ -112,9 +111,9 @@ namespace LubanAssistant { try { - var tableDataInfo = LastLoadTableData = await DataLoaderUtil.LoadTableDataAsync(RootDefineFile, InputDataDir, tableName); + var tableDataInfo = LastLoadTableData = await DataLoaderUtil.LoadTableDataAsync(RootDefineFile, InputDataDir, rawSheet.TableName); var title = ExcelUtil.ParseTitles(sheet); - ExcelUtil.FillRecords(sheet, metaAttrs, title, tableDataInfo); + ExcelUtil.FillRecords(sheet, rawSheet.TitleRowCount, title, tableDataInfo); } catch (Exception e) { @@ -159,12 +158,13 @@ namespace LubanAssistant } } - private void SaveRecords(Action, TableDataInfo, DefTable, TitleInfo> saveTask) + private void SaveRecords(Action saveTask) { Worksheet sheet = Globals.LubanAssistant.Application.ActiveSheet; - var metaAttrs = ExcelUtil.ParseMetaAttrs(sheet); - if (!metaAttrs.TryGetValue("table", out var tableName)) + var rawSheet = ExcelUtil.ParseRawSheetTitleOnly(sheet); + string tableName = rawSheet.TableName; + if (string.IsNullOrWhiteSpace(tableName)) { MessageBox.Show($"meta行未指定table名"); return; @@ -181,7 +181,7 @@ namespace LubanAssistant var tableDef = await DataLoaderUtil.LoadTableDefAsync(RootDefineFile, InputDataDir, tableName); var title = ExcelUtil.ParseTitles(sheet); - saveTask(sheet, metaAttrs, LastLoadTableData, tableDef, title); + saveTask(sheet, rawSheet.TitleRowCount, LastLoadTableData, tableDef, title); } catch (Exception e) { @@ -192,13 +192,13 @@ namespace LubanAssistant private void BtnSaveAllClick(object sender, RibbonControlEventArgs e) { - SaveRecords((Worksheet sheet, Dictionary metaAttrs, TableDataInfo tableDataInfo, DefTable defTable, TitleInfo title) => + SaveRecords((Worksheet sheet, int titleRowNum, TableDataInfo tableDataInfo, DefTable defTable, Title title) => { int usedRowNum = sheet.UsedRange.Rows.Count; - int firstDataRowNum = int.Parse(metaAttrs["title_rows"]) + 2; + int firstDataRowNum = titleRowNum + 2; if (firstDataRowNum <= usedRowNum) { - var newRecords = ExcelUtil.LoadRecordsInRange(defTable, sheet, title.RootTitle, (sheet.Range[$"A{firstDataRowNum}:A{usedRowNum}"]).EntireRow); + var newRecords = ExcelUtil.LoadRecordsInRange(defTable, sheet, title, (sheet.Range[$"A{firstDataRowNum}:A{usedRowNum}"]).EntireRow); ExcelUtil.SaveRecords(InputDataDir, defTable, newRecords); CleanRemovedRecordFiles(LastLoadTableData, newRecords); } @@ -241,12 +241,12 @@ namespace LubanAssistant MessageBox.Show("没有选中的行"); return; } - SaveRecords((Worksheet sheet, Dictionary metaAttrs, TableDataInfo tableDataInfo, DefTable defTable, TitleInfo title) => + SaveRecords((Worksheet sheet, int titleRowNum, TableDataInfo tableDataInfo, DefTable defTable, Title title) => { int usedRowNum = sheet.UsedRange.Rows.Count; - if (title.RowNum + 1 < usedRowNum) + if (titleRowNum + 1 < usedRowNum) { - var newRecords = ExcelUtil.LoadRecordsInRange(defTable, sheet, title.RootTitle, selectRange.EntireRow); + var newRecords = ExcelUtil.LoadRecordsInRange(defTable, sheet, title, selectRange.EntireRow); ExcelUtil.SaveRecords(InputDataDir, defTable, newRecords); } else diff --git a/src/LubanAssistant/ExcelUtil.cs b/src/LubanAssistant/ExcelUtil.cs index 595961b..c8d2c03 100644 --- a/src/LubanAssistant/ExcelUtil.cs +++ b/src/LubanAssistant/ExcelUtil.cs @@ -17,51 +17,81 @@ namespace LubanAssistant { static class ExcelUtil { - public static Dictionary ParseMetaAttrs(Worksheet sheet) + public static RawSheet ParseRawSheet(Worksheet sheet, Range toSaveRecordRows) { - Range metaRow = sheet.Rows[1]; - if (metaRow.Cells[1, 1].Text.ToString() != "##") + if (!ParseMetaAttrs(sheet, out var orientRow, out var titleRows, out var tableName)) { - throw new Exception("A1 should be ##"); + throw new Exception($"meta行不合法"); } - var metaAttrs = new Dictionary(); - for (int i = 2, n = sheet.UsedRange.Columns.Count; i <= n; i++) + + if (!orientRow) { - Range cell = metaRow.Cells[1, i]; - string value = cell.Value?.ToString(); - if (!string.IsNullOrWhiteSpace(value)) + throw new Exception($"目前只支持行表"); + } + + Title title = ParseTitles(sheet); + var cells = new List>(); + + foreach (Range row in toSaveRecordRows) + { + var rowCell = new List(); + for (int i = title.FromIndex; i <= title.ToIndex; i++) { - var attrs = value.Split('='); - if (attrs.Length != 2) - { - throw new Exception($"invalid meta attr:{value}"); - } - metaAttrs.Add(attrs[0], attrs[1]); + rowCell.Add(new Cell(row.Row - 1, i, (row.Cells[1, i + 1] as Range).Value)); } + cells.Add(rowCell); } - return metaAttrs; + return new RawSheet() { Title = title, TitleRowCount = titleRows, TableName = tableName, Cells = cells }; } - public static TitleInfo ParseTitles(Worksheet sheet) + public static RawSheet ParseRawSheetTitleOnly(Worksheet sheet) { + if (!ParseMetaAttrs(sheet, out var orientRow, out var titleRows, out var tableName)) + { + throw new Exception($"meta行不合法"); + } + if (!orientRow) + { + throw new Exception($"目前只支持行表"); + } + + Title title = ParseTitles(sheet); + var cells = new List>(); + return new RawSheet() { Title = title, TitleRowCount = titleRows, TableName = tableName, Cells = cells }; + } + + public static bool ParseMetaAttrs(Worksheet sheet, out bool orientRow, out int titleRows, out string tableName) + { + Range metaRow = sheet.Rows[1]; + + var cells = new List(); + for (int i = 1, n = sheet.UsedRange.Columns.Count; i <= n; i++) + { + cells.Add(((Range)metaRow.Cells[1, i]).Value?.ToString()); + } + return SheetLoadUtil.TryParseMeta(cells, out orientRow, out titleRows, out tableName); + } + + public static Title ParseTitles(Worksheet sheet) + { int titleRows = 1; Range c1 = sheet.Cells[2, 1]; if (c1.MergeCells) { titleRows = c1.MergeArea.Count; } - - var rootTile = new Title() { - FromIndex = 2, - ToIndex = sheet.UsedRange.Columns.Count, + FromIndex = 0, + ToIndex = sheet.UsedRange.Columns.Count - 1, Name = "__root__", Root = true, + Tags = new Dictionary(), }; ParseSubTitle(sheet, 2, titleRows + 1, rootTile); - return new TitleInfo(rootTile, titleRows); + rootTile.Init(); + return rootTile; } private static void ParseSubTitle(Worksheet sheet, int rowIndex, int maxRowIndex, Title title) @@ -69,51 +99,23 @@ namespace LubanAssistant Range row = sheet.Rows[rowIndex]; for (int i = title.FromIndex; i <= title.ToIndex; i++) { - Range subTitleRange = row.Cells[1, i]; + Range subTitleRange = row.Cells[1, i + 1]; string subTitleValue = subTitleRange.Value?.ToString(); if (string.IsNullOrWhiteSpace(subTitleValue)) { continue; } - var attrs = subTitleValue.Split('&'); - string subTitleName = attrs[0]; - string sep = ""; - foreach (var attrPair in attrs.Skip(1)) - { - var pairs = attrPair.Split('='); - if (pairs.Length != 2) - { - throw new Exception($"invalid title: {subTitleValue}"); - } - switch (pairs[0]) - { - case "sep": - { - sep = pairs[1]; - break; - } - default: - { - throw new Exception($"invalid title: {subTitleValue}"); - } - } - } + var (subTitleName, tags) = SheetLoadUtil.ParseNameAndMetaAttrs(subTitleValue); + - if (title.SubTitles.ContainsKey(subTitleName)) - { - throw new Exception($"title:{subTitleName} 重复"); - } var newSubTitle = new Title() { Name = subTitleName, FromIndex = i, - ToIndex = i, + Tags = tags, }; - if (!string.IsNullOrWhiteSpace(sep)) - { - newSubTitle.Sep = sep; - } + if (subTitleRange.MergeCells) { newSubTitle.ToIndex = i + subTitleRange.MergeArea.Count - 1; @@ -122,9 +124,8 @@ namespace LubanAssistant { newSubTitle.ToIndex = i; } - title.SubTitles.Add(subTitleName, newSubTitle); + title.AddSubTitle(newSubTitle); } - title.SubTitleList.AddRange(title.SubTitles.Values); if (rowIndex < maxRowIndex) { foreach (var subTitle in title.SubTitleList) @@ -134,17 +135,8 @@ namespace LubanAssistant } } - public static void FillRecords(Worksheet sheet, Dictionary metaAttrs, TitleInfo title, TableDataInfo tableDataInfo) + public static void FillRecords(Worksheet sheet, int titleRowNum, Title title, TableDataInfo tableDataInfo) { - int titleRowNum = 3; - if (metaAttrs.TryGetValue("title_rows", out var titleRowsStr) && !int.TryParse(titleRowsStr, out titleRowNum)) - { - throw new Exception($"meta 属性 title_rows 不合法"); - } - if (titleRowNum < title.RowNum) - { - throw new Exception($"meta 属性title_rows不能比字段名行的行数小"); - } int usedRowNum = sheet.UsedRange.Rows.Count; if (usedRowNum > titleRowNum + 1) { @@ -158,35 +150,17 @@ namespace LubanAssistant { var fillVisitor = new FillSheetVisitor(sheet, nextRowIndex); //FillRecord(sheet, ref nextRowIndex, title.RootTitle, rec); - nextRowIndex += rec.Data.Apply(fillVisitor, title.RootTitle); + nextRowIndex += rec.Data.Apply(fillVisitor, title); } } public static List LoadRecordsInRange(DefTable table, Worksheet sheet, Title title, Range toSaveRecordRows) { - var recs = new List(); - foreach (Range row in toSaveRecordRows) - { - bool allEmpty = true; - for (int i = title.FromIndex; i <= title.ToIndex; i++) - { - if (!string.IsNullOrEmpty((row.Cells[1, i] as Range).Value?.ToString())) - { - allEmpty = false; - break; - } - } - if (allEmpty) - { - continue; - } - string tags = (row.Cells[1, 1] as Range).Value?.ToString(); - recs.Add(new Record( - (DBean)table.ValueTType.Apply(new SheetDataCreator(sheet, row.Row, table.Assembly), title, null), - "", - DataUtil.ParseTags(tags))); - } - return recs; + RawSheet rawSheet = ParseRawSheet(sheet, toSaveRecordRows); + var excelSource = new ExcelDataSource(); + excelSource.Load(rawSheet); + + return excelSource.ReadMulti(table.ValueTType); } public static void SaveRecords(string inputDataDir, DefTable table, List records) diff --git a/src/LubanAssistant/FillSheetVisitor.cs b/src/LubanAssistant/FillSheetVisitor.cs index 8b26fa0..f2b0f62 100644 --- a/src/LubanAssistant/FillSheetVisitor.cs +++ b/src/LubanAssistant/FillSheetVisitor.cs @@ -26,75 +26,77 @@ namespace LubanAssistant _startRowIndex = startRowIndex; } + Range Current(Title title) => _cells[_startRowIndex, title.FromIndex + 1] as Range; + public int Accept(DBool type, Title x) { - (_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Value; + Current(x).Value = type.Value; return 1; } public int Accept(DByte type, Title x) { - (_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Value; + Current(x).Value = type.Value; return 1; } public int Accept(DShort type, Title x) { - (_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Value; + Current(x).Value = type.Value; return 1; } public int Accept(DFshort type, Title x) { - (_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Value; + Current(x).Value = type.Value; return 1; } public int Accept(DInt type, Title x) { - (_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Value; + Current(x).Value = type.Value; return 1; } public int Accept(DFint type, Title x) { - (_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Value; + Current(x).Value = type.Value; return 1; } public int Accept(DLong type, Title x) { - (_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Value; + Current(x).Value = type.Value; return 1; } public int Accept(DFlong type, Title x) { - (_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Value; + Current(x).Value = type.Value; return 1; } public int Accept(DFloat type, Title x) { - (_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Value; + Current(x).Value = type.Value; return 1; } public int Accept(DDouble type, Title x) { - (_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Value; + Current(x).Value = type.Value; return 1; } public int Accept(DEnum type, Title x) { - (_cells[_startRowIndex, x.FromIndex] as Range).Value = type.StrValue; + Current(x).Value = type.StrValue; return 1; } public int Accept(DString type, Title x) { - (_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Value; + Current(x).Value = type.Value; return 1; } @@ -109,7 +111,7 @@ namespace LubanAssistant //{ // throw new Exception($"title:{x.Name}为text类型,至少要占两列"); //} - (_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep); + Current(x).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep); //(_cells[_startRowIndex, x.FromIndex + 1] as Range).Value = type.RawValue; return 1; } @@ -126,11 +128,11 @@ namespace LubanAssistant } if (type.ImplType != null) { - (_cells[_startRowIndex, typeTitle.FromIndex] as Range).Value = type.ImplType.Name; + Current(typeTitle).Value = type.ImplType.Name; } else { - (_cells[_startRowIndex, typeTitle.FromIndex] as Range).Value = DefBean.BEAN_NULL_STR; + Current(typeTitle).Value = DefBean.BEAN_NULL_STR; } } else @@ -141,7 +143,7 @@ namespace LubanAssistant } else { - //(_cells[_startRowIndex, x.FromIndex] as Range).Value = "null"; + //Current(x).Value = "null"; throw new Exception($"title:{x.Name} 不支持 值为null的普通bean"); } } @@ -173,59 +175,59 @@ namespace LubanAssistant } else { - (_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep); + Current(x).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep); } return 1; } public int Accept(DArray type, Title x) { - (_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep); + Current(x).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep); return 1; } public int Accept(DList type, Title x) { - (_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep); + Current(x).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep); return 1; } public int Accept(DSet type, Title x) { - (_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep); + Current(x).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep); return 1; } public int Accept(DMap type, Title x) { - (_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep); + Current(x).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep); return 1; } public int Accept(DVector2 type, Title x) { var v = type.Value; - (_cells[_startRowIndex, x.FromIndex] as Range).Value = $"{v.X},{v.Y}"; + Current(x).Value = $"{v.X},{v.Y}"; return 1; } public int Accept(DVector3 type, Title x) { var v = type.Value; - (_cells[_startRowIndex, x.FromIndex] as Range).Value = $"{v.X},{v.Y},{v.Z}"; + Current(x).Value = $"{v.X},{v.Y},{v.Z}"; return 1; } public int Accept(DVector4 type, Title x) { var v = type.Value; - (_cells[_startRowIndex, x.FromIndex] as Range).Value = $"{v.X},{v.Y},{v.Z},{v.W}"; + Current(x).Value = $"{v.X},{v.Y},{v.Z},{v.W}"; return 1; } public int Accept(DDateTime type, Title x) { - (_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Time; + Current(x).Value = type.Time; return 1; } } diff --git a/src/LubanAssistant/LubanAssistant.csproj b/src/LubanAssistant/LubanAssistant.csproj index 50886c5..87b94f1 100644 --- a/src/LubanAssistant/LubanAssistant.csproj +++ b/src/LubanAssistant/LubanAssistant.csproj @@ -229,11 +229,8 @@ Source\DataCreators\DataCreateException.cs - - Source\DataCreators\ExcelDataCreator.cs - - - Source\DataCreators\ExcelNamedRowDataCreator.cs + + Source\DataCreators\ExcelStreamDataCreator.cs Source\DataCreators\JsonDataCreator.cs @@ -244,6 +241,9 @@ Source\DataCreators\MultiRowExcelDataCreator.cs + + Source\DataCreators\SheetDataCreator.cs + Source\DataCreators\StringDataCreator.cs @@ -271,12 +271,24 @@ Source\DataSources\Excel\ExcelStream.cs + + Source\DataSources\Excel\RawSheet.cs + + + Source\DataCreators\RawSheetTableDefInfo.cs + Source\DataSources\Excel\Sheet.cs + + Source\DataSources\Excel\SheetLoadUtil.cs + Source\DataSources\Excel\Title.cs + + Source\DataSources\Excel\TitleRow.cs + Source\DataSources\Json\JsonDataSource.cs @@ -364,18 +376,33 @@ Source\DataVisitors\IDataFuncVisitor.cs + + Source\DataVisitors\IsDefaultValue.cs + Source\DataVisitors\ToLiteralVisitorBase.cs Source\DataVisitors\ToStringVisitor.cs + + Source\DataVisitors\ValidatorVisitor.cs + + + Source\Defs\CfgDefLoader.cs + Source\Defs\CfgDefTypeBase.cs + + Source\Defs\DefAssembly.cs + Source\Defs\DefBean.cs + + Source\Defs\DefField.cs + Source\Defs\DefTable.cs @@ -418,6 +445,24 @@ Source\Utils\DataUtil.cs + + Source\ValidatorContext.cs + + + Source\Validators\IValidator.cs + + + Source\Validators\PathValidator.cs + + + Source\Validators\RangeValidator.cs + + + Source\Validators\RefValidator.cs + + + Source\Validators\ValidatorFactory.cs + Source\Defs\CommonDefLoader.cs @@ -433,6 +478,9 @@ Source\Defs\DefFieldBase.cs + + Source\Defs\DefTypeBase.cs + Source\ELanguage.cs @@ -550,7 +598,6 @@ Code - @@ -577,7 +624,6 @@ Settings.settings True - @@ -590,10 +636,6 @@ - - - - diff --git a/src/LubanAssistant/SheetDataCreator.cs b/src/LubanAssistant/SheetDataCreator.cs deleted file mode 100644 index 7d02cc1..0000000 --- a/src/LubanAssistant/SheetDataCreator.cs +++ /dev/null @@ -1,201 +0,0 @@ -using Luban.Common.Utils; -using Luban.Job.Cfg.DataCreators; -using Luban.Job.Cfg.Datas; -using Luban.Job.Cfg.DataSources.Excel; -using Luban.Job.Cfg.Defs; -using Luban.Job.Common.Types; -using Luban.Job.Common.TypeVisitors; -using Microsoft.Office.Interop.Excel; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LubanAssistant -{ - class SheetDataCreator : ITypeFuncVisitor - { - private readonly Worksheet _sheet; - private readonly int _rowIndex; - private readonly DefAssembly _defAss; - - public SheetDataCreator(Worksheet sheet, int rowIndex, DefAssembly ass) - { - _sheet = sheet; - _rowIndex = rowIndex; - _defAss = ass; - } - - - private ExcelStream CreateStream(Title title, bool nameMode = true) - { - return new ExcelStream(new Cell(title.FromIndex, title.ToIndex, _sheet.Cells[_rowIndex, title.FromIndex].Value), title.Sep, nameMode); - } - - public DType Accept(TBool type, Title x, DefField y) - { - return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss); - } - - public DType Accept(TByte type, Title x, DefField y) - { - return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss); - } - - public DType Accept(TShort type, Title x, DefField y) - { - return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss); - } - - public DType Accept(TFshort type, Title x, DefField y) - { - return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss); - } - - public DType Accept(TInt type, Title x, DefField y) - { - return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss); - } - - public DType Accept(TFint type, Title x, DefField y) - { - return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss); - } - - public DType Accept(TLong type, Title x, DefField y) - { - return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss); - } - - public DType Accept(TFlong type, Title x, DefField y) - { - return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss); - } - - public DType Accept(TFloat type, Title x, DefField y) - { - return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss); - } - - public DType Accept(TDouble type, Title x, DefField y) - { - return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss); - } - - public DType Accept(TEnum type, Title x, DefField y) - { - return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss); - } - - public DType Accept(TString type, Title x, DefField y) - { - return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss); - } - - public DType Accept(TBytes type, Title x, DefField y) - { - throw new NotSupportedException(); - } - - public DType Accept(TText type, Title x, DefField y) - { - return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss); - } - - public DType Accept(TBean type, Title title, DefField defField) - { - if (title.HasSubTitle) - { - var originBean = (DefBean)type.Bean; - DefBean implType; - if (originBean.IsAbstractType) - { - if (!title.SubTitles.TryGetValue(DefBean.TYPE_NAME_KEY, out var typeTitle)) - { - throw new Exception($"title:{title.Name} 缺失 子title:{DefBean.TYPE_NAME_KEY}"); - } - - string subType = (_sheet.Cells[_rowIndex, typeTitle.FromIndex] as Range).Value.ToString().Trim(); - if (subType.ToLower() == DefBean.BEAN_NULL_STR) - { - if (!type.IsNullable) - { - throw new Exception($"type:'{type}' 不是可空类型 '{type.Bean.FullName}?' , 不能为空"); - } - return null; - } - string fullType = TypeUtil.MakeFullName(originBean.Namespace, subType); - implType = (DefBean)originBean.GetNotAbstractChildType(subType); - if (implType == null) - { - throw new Exception($"type:'{fullType}' 不是 bean 类型"); - } - - - } - else - { - implType = originBean; - } - var fields = new List(); - foreach (var f in implType.HierarchyFields) - { - if (!title.SubTitles.TryGetValue(f.Name, out var subTitle)) - { - throw new Exception($"title:{title.Name} 缺失子title:{f.Name}"); - } - fields.Add(f.CType.Apply(this, subTitle, (DefField)f)); - } - - return new DBean(originBean, implType, fields); - } - else - { - return type.Apply(ExcelDataCreator.Ins, defField, CreateStream(title, false), _defAss); - } - } - - public DType Accept(TArray type, Title x, DefField y) - { - return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss); - } - - public DType Accept(TList type, Title x, DefField y) - { - return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss); - } - - public DType Accept(TSet type, Title x, DefField y) - { - return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss); - } - - public DType Accept(TMap type, Title x, DefField y) - { - return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss); - } - - public DType Accept(TVector2 type, Title x, DefField y) - { - return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss); - } - - public DType Accept(TVector3 type, Title x, DefField y) - { - return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss); - } - - public DType Accept(TVector4 type, Title x, DefField y) - { - return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss); - } - - public DType Accept(TDateTime type, Title x, DefField y) - { - return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss); - } - - - } -} diff --git a/src/LubanAssistant/Source/DataSources/Excel/TitleInfo.cs b/src/LubanAssistant/Source/DataSources/Excel/TitleInfo.cs deleted file mode 100644 index 9456852..0000000 --- a/src/LubanAssistant/Source/DataSources/Excel/TitleInfo.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Luban.Job.Cfg.DataSources.Excel -{ - class TitleInfo - { - public Title RootTitle { get; } - - public int RowNum { get; } - - public TitleInfo(Title rootTitle, int rowNum) - { - RootTitle = rootTitle; - RowNum = rowNum; - } - } -} diff --git a/src/LubanAssistant/Source/Defs/CfgDefLoader.cs b/src/LubanAssistant/Source/Defs/CfgDefLoader.cs deleted file mode 100644 index ae03b55..0000000 --- a/src/LubanAssistant/Source/Defs/CfgDefLoader.cs +++ /dev/null @@ -1,893 +0,0 @@ -using Bright.Collections; -using Luban.Common.Utils; -using Luban.Job.Cfg.Datas; -using Luban.Job.Cfg.DataSources.Excel; -using Luban.Job.Cfg.RawDefs; -using Luban.Job.Cfg.Utils; -using Luban.Job.Common.Defs; -using Luban.Job.Common.RawDefs; -using Luban.Job.Common.Types; -using Luban.Job.Common.Utils; -using Luban.Server.Common; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using System.Xml.Linq; - -namespace Luban.Job.Cfg.Defs -{ - public class CfgDefLoader : CommonDefLoader - { - private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger(); - - private readonly List _importExcelTableFiles = new(); - private readonly List _importExcelEnumFiles = new(); - private readonly List _importExcelBeanFiles = new(); - - - private readonly List _patches = new(); - - private readonly List _cfgTables = new List
(); - - private readonly List _cfgServices = new List(); - - private readonly List _cfgGroups = new List(); - - private readonly List _defaultGroups = new List(); - - public CfgDefLoader(IAgent agent) : base(agent) - { - RegisterRootDefineHandler("importexcel", AddImportExcel); - RegisterRootDefineHandler("patch", AddPatch); - RegisterRootDefineHandler("service", AddService); - RegisterRootDefineHandler("group", AddGroup); - - RegisterModuleDefineHandler("table", AddTable); - - - IsBeanFieldMustDefineId = false; - } - - public Defines BuildDefines() - { - return new Defines() - { - TopModule = TopModule, - Patches = _patches, - Enums = _enums, - Beans = _beans, - Tables = _cfgTables, - Services = _cfgServices, - Groups = _cfgGroups, - }; - } - - private static readonly List _excelImportRequireAttrs = new List { "name", "type" }; - private void AddImportExcel(XElement e) - { - ValidAttrKeys(RootXml, e, null, _excelImportRequireAttrs); - var importName = XmlUtil.GetRequiredAttribute(e, "name"); - if (string.IsNullOrWhiteSpace(importName)) - { - throw new Exception("importexcel 属性name不能为空"); - } - var type = XmlUtil.GetRequiredAttribute(e, "type"); - if (string.IsNullOrWhiteSpace(type)) - { - throw new Exception($"importexcel name:'{importName}' type属性不能为空"); - } - switch (type) - { - case "table": this._importExcelTableFiles.Add(importName); break; - case "enum": this._importExcelEnumFiles.Add(importName); break; - case "bean": this._importExcelBeanFiles.Add(importName); break; - default: throw new Exception($"importexcel name:'{importName}' type:'{type}' 不合法. 有效值为 table|enum|bean"); - } - } - - private static readonly List _patchRequireAttrs = new List { "name" }; - private void AddPatch(XElement e) - { - ValidAttrKeys(RootXml, e, null, _patchRequireAttrs); - var patchName = e.Attribute("name").Value; - if (string.IsNullOrWhiteSpace(patchName)) - { - throw new Exception("patch 属性name不能为空"); - } - if (this._patches.Any(b => b.Name == patchName)) - { - throw new Exception($"patch '{patchName}' 重复"); - } - _patches.Add(new Patch(patchName)); - } - - private static readonly List _groupOptionalAttrs = new List { "default" }; - private static readonly List _groupRequireAttrs = new List { "name" }; - - private void AddGroup(XElement e) - { - ValidAttrKeys(RootXml, e, _groupOptionalAttrs, _groupRequireAttrs); - List groupNames = CreateGroups(e.Attribute("name").Value); - - foreach (var g in groupNames) - { - if (_cfgGroups.Any(cg => cg.Names.Contains(g))) - { - throw new Exception($"group名:'{g}' 重复"); - } - } - - if (XmlUtil.GetOptionBoolAttribute(e, "default")) - { - this._defaultGroups.AddRange(groupNames); - } - _cfgGroups.Add(new Group() { Names = groupNames }); - } - - private void FillValueValidator(CfgField f, string attrValue, string validatorName) - { - if (!string.IsNullOrWhiteSpace(attrValue)) - { - var validator = new Validator() { Type = validatorName, Rule = attrValue }; - f.Validators.Add(validator); - f.ValueValidators.Add(validator); - } - } - - private void FillValidators(string defineFile, string key, string attr, List result) - { - if (!string.IsNullOrWhiteSpace(attr)) - { -#if !LUBAN_LITE - foreach (var validatorStr in attr.Split('#', StringSplitOptions.RemoveEmptyEntries)) -#else - foreach (var validatorStr in attr.Split('#')) -#endif - { - var sepIndex = validatorStr.IndexOf(':'); - if (sepIndex <= 0) - { - throw new Exception($"定义文件:{defineFile} key:'{key}' attr:'{attr}' 不是合法的 validator 定义 (key1:value1#key2:value2 ...)"); - } -#if !LUBAN_LITE - result.Add(new Validator() { Type = validatorStr[..sepIndex], Rule = validatorStr[(sepIndex + 1)..] }); -#else - result.Add(new Validator() { Type = validatorStr.Substring(0, sepIndex), Rule = validatorStr.Substring(sepIndex + 1, validatorStr.Length - sepIndex - 1) }); -#endif - } - } - } - - private readonly List _serviceAttrs = new List { "name", "manager", "group" }; - - private void AddService(XElement e) - { - var name = XmlUtil.GetRequiredAttribute(e, "name"); - var manager = XmlUtil.GetRequiredAttribute(e, "manager"); - List groups = CreateGroups(XmlUtil.GetOptionalAttribute(e, "group")); - var refs = new List(); - - s_logger.Trace("service name:{name} manager:{manager}", name, manager); - ValidAttrKeys(RootXml, e, _serviceAttrs, _serviceAttrs); - foreach (XElement ele in e.Elements()) - { - string tagName = ele.Name.LocalName; - s_logger.Trace("service {service_name} tag: {name} {value}", name, tagName, ele); - switch (tagName) - { - case "ref": - { - refs.Add(XmlUtil.GetRequiredAttribute(ele, "name")); - break; - } - default: - { - throw new Exception($"service:'{name}' tag:'{tagName}' 非法"); - } - } - } - if (!ValidGroup(groups, out var invalidGroup)) - { - throw new Exception($"service:'{name}' group:'{invalidGroup}' 不存在"); - } - _cfgServices.Add(new Service() { Name = name, Manager = manager, Groups = groups, Refs = refs }); - } - - - private readonly Dictionary _name2CfgTable = new Dictionary(); - - private static List CreateGroups(string s) - { - return s.Split(',', ';').Select(x => x.Trim()).Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); - } - - private bool ValidGroup(List groups, out string invalidGroup) - { - foreach (var g in groups) - { - if (!this._cfgGroups.Any(cg => cg.Names.Contains(g))) - { - invalidGroup = g; - return false; - } - } - invalidGroup = null; - return true; - } - - private ETableMode ConvertMode(string defineFile, string tableName, string modeStr, string indexStr) - { - ETableMode mode; - switch (modeStr) - { - case "one": - { - if (!string.IsNullOrWhiteSpace(indexStr)) - { - throw new Exception($"定义文件:{defineFile} table:'{tableName}' mode=one 是单例表,不支持定义index属性"); - } - mode = ETableMode.ONE; - break; - } - case "map": - { - //if ((string.IsNullOrWhiteSpace(indexStr) || indexStr.Split(',').Length != 1)) - //{ - // throw new Exception($"定义文件:{CurImportFile} table:{tableName} 是单键表,必须在index属性里指定1个key"); - //} - mode = ETableMode.MAP; - break; - } - case "": - { - mode = ETableMode.MAP; - break; - } - default: - { - throw new ArgumentException($"不支持的 mode:{modeStr}"); - } - } - return mode; - } - - private readonly List _tableOptionalAttrs = new List { "index", "mode", "group", "patch_input", "comment", "define_from_file" }; - private readonly List _tableRequireAttrs = new List { "name", "value", "input" }; - - private void AddTable(string defineFile, XElement e) - { - ValidAttrKeys(defineFile, e, _tableOptionalAttrs, _tableRequireAttrs); - string name = XmlUtil.GetRequiredAttribute(e, "name"); - string module = CurNamespace; - string valueType = XmlUtil.GetRequiredAttribute(e, "value"); - bool defineFromFile = XmlUtil.GetOptionBoolAttribute(e, "define_from_file"); - string index = XmlUtil.GetOptionalAttribute(e, "index"); - string group = XmlUtil.GetOptionalAttribute(e, "group"); - string comment = XmlUtil.GetOptionalAttribute(e, "comment"); - string input = XmlUtil.GetRequiredAttribute(e, "input"); - string patchInput = XmlUtil.GetOptionalAttribute(e, "patch_input"); - string mode = XmlUtil.GetOptionalAttribute(e, "mode"); - string tags = XmlUtil.GetOptionalAttribute(e, "tags"); - AddTable(defineFile, name, module, valueType, index, mode, group, comment, defineFromFile, input, patchInput, tags); - } - - private void AddTable(string defineFile, string name, string module, string valueType, string index, string mode, string group, - string comment, bool defineFromExcel, string input, string patchInput, string tags) - { - var p = new Table() - { - Name = name, - Namespace = module, - ValueType = valueType, - LoadDefineFromFile = defineFromExcel, - Index = index, - Groups = CreateGroups(group), - Comment = comment, - Mode = ConvertMode(defineFile, name, mode, index), - Tags = tags, - }; - - if (p.Groups.Count == 0) - { - p.Groups = this._defaultGroups; - } - else if (!ValidGroup(p.Groups, out var invalidGroup)) - { - throw new Exception($"定义文件:{defineFile} table:'{p.Name}' group:'{invalidGroup}' 不存在"); - } - p.InputFiles.AddRange(input.Split(',').Select(s => s.Trim()).Where(s => !string.IsNullOrWhiteSpace(s))); - - if (!string.IsNullOrWhiteSpace(patchInput)) - { - foreach (var subPatchStr in patchInput.Split('|').Select(s => s.Trim()).Where(s => !string.IsNullOrWhiteSpace(s))) - { - var nameAndDirs = subPatchStr.Split(':'); - if (nameAndDirs.Length != 2) - { - throw new Exception($"定义文件:{defineFile} table:'{p.Name}' patch_input:'{subPatchStr}' 定义不合法"); - } - var patchDirs = nameAndDirs[1].Split(',', ';').ToList(); - if (!p.PatchInputFiles.TryAdd(nameAndDirs[0], patchDirs)) - { - throw new Exception($"定义文件:{defineFile} table:'{p.Name}' patch_input:'{subPatchStr}' 子patch:'{nameAndDirs[0]}' 重复"); - } - } - } - - _cfgTables.Add(p); - } - - private async Task LoadTableValueTypeDefineFromFileAsync(Table table, string dataDir) - { - var inputFileInfos = await DataLoaderUtil.CollectInputFilesAsync(this.Agent, table.InputFiles, dataDir); - var file = inputFileInfos[0]; - var source = new ExcelDataSource(); - var stream = new MemoryStream(await this.Agent.GetFromCacheOrReadAllBytesAsync(file.ActualFile, file.MD5)); - var sheet = source.LoadFirstSheet(file.OriginFile, file.SheetName, stream); - - var cb = new CfgBean() { Namespace = table.Namespace, Name = table.ValueType, }; - - var rc = sheet.RowColumns; - var attrRow = sheet.RowColumns[0]; - if (rc.Count < sheet.AttrRowCount + 1) - { - throw new Exception($"table:'{table.Name}' file:{file.OriginFile} 至少包含 属性行和标题行"); - } - var titleRow = sheet.RowColumns[sheet.AttrRowCount]; - // 有可能没有注释行,此时使用标题行,这个是必须有的 - var descRow = sheet.HeaderRowCount >= sheet.AttrRowCount + 2 ? sheet.RowColumns[sheet.AttrRowCount + 1] : titleRow; - foreach (var f in sheet.RootFields) - { - var cf = new CfgField() { Name = f.Name, Id = 0 }; - - string[] attrs = (attrRow[f.FromIndex].Value?.ToString() ?? "").Trim().Split('&').Select(s => s.Trim()).ToArray(); - - if (attrs.Length == 0 || string.IsNullOrWhiteSpace(attrs[0])) - { - throw new Exception($"table:'{table.Name}' file:{file.OriginFile} title:'{f.Name}' type missing!"); - } - - // 优先取desc行,如果为空,则取title行 - - cf.Comment = descRow[f.FromIndex].Value?.ToString(); - if (string.IsNullOrWhiteSpace(cf.Comment)) - { - cf.Comment = titleRow[f.FromIndex].Value?.ToString(); - } - if (string.IsNullOrWhiteSpace(cf.Comment)) - { - cf.Comment = ""; - } - - cf.Type = attrs[0]; - - for (int i = 1; i < attrs.Length; i++) - { -#if !LUBAN_LITE - var pair = attrs[i].Split('=', 2); -#else - var pair = attrs[i].Split(new char[] { '=' }, 2); -#endif - if (pair.Length != 2) - { - throw new Exception($"table:'{table.Name}' file:{file.OriginFile} title:'{f.Name}' attr:'{attrs[i]}' is invalid!"); - } - var attrName = pair[0].Trim(); - var attrValue = pair[1].Trim(); - switch (attrName) - { - case "index": - { - cf.Index = attrValue; - break; - } - case "sep": - { - cf.Sep = attrValue; - break; - } - case "ref": - case "path": - case "range": - { - var validator = new Validator() { Type = attrName, Rule = attrValue }; - cf.Validators.Add(validator); - cf.ValueValidators.Add(validator); - break; - } - case "multi_rows": - { - cf.IsMultiRow = attrValue == "1" || attrValue.Equals("true", StringComparison.OrdinalIgnoreCase); - break; - } - case "group": - { - cf.Groups = attrValue.Split(',').Select(s => s.Trim()).Where(s => !string.IsNullOrWhiteSpace(s)).ToList(); - break; - } - case "comment": - { - cf.Comment = attrValue; - break; - } - case "convert": - { - cf.Converter = attrValue; - break; - } - case "default": - { - cf.DefaultValue = attrValue; - break; - } - case "tags": - { - cf.Tags = attrValue; - break; - } - case "orientation": - { - cf.IsRowOrient = DefUtil.ParseOrientation(attrValue); - break; - } - default: - { - throw new Exception($"table:'{table.Name}' file:{file.OriginFile} title:'{f.Name}' attr:'{attrs[i]}' is invalid!"); - } - } - } - - cb.Fields.Add(cf); - } - return cb; - } - - private async Task LoadTableValueTypeDefinesFromFileAsync(string dataDir) - { - var loadTasks = new List>(); - foreach (var table in this._cfgTables.Where(t => t.LoadDefineFromFile)) - { - loadTasks.Add(Task.Run(async () => await this.LoadTableValueTypeDefineFromFileAsync(table, dataDir))); - } - - foreach (var task in loadTasks) - { - this._beans.Add(await task); - } - } - - private async Task LoadTableListFromFileAsync(string dataDir) - { - if (this._importExcelTableFiles.Count == 0) - { - return; - } - var inputFileInfos = await DataLoaderUtil.CollectInputFilesAsync(this.Agent, this._importExcelTableFiles, dataDir); - - var defTableRecordType = new DefBean(new CfgBean() - { - Namespace = "__intern__", - Name = "__TableRecord__", - Parent = "", - Alias = "", - IsValueType = false, - Sep = "", - TypeId = 0, - IsSerializeCompatible = false, - Fields = new List - { - new CfgField() { Name = "full_name", Type = "string" }, - new CfgField() { Name = "value_type", Type = "string" }, - new CfgField() { Name = "index", Type = "string" }, - new CfgField() { Name = "mode", Type = "string" }, - new CfgField() { Name = "group", Type = "string" }, - new CfgField() { Name = "comment", Type = "string" }, - new CfgField() { Name = "define_from_excel", Type = "bool" }, - new CfgField() { Name = "input", Type = "string" }, - new CfgField() { Name = "patch_input", Type = "string" }, - new CfgField() { Name = "tags", Type = "string" }, - } - }) - { - AssemblyBase = new DefAssembly("", null, new List(), Agent), - }; - defTableRecordType.PreCompile(); - defTableRecordType.Compile(); - defTableRecordType.PostCompile(); - var tableRecordType = TBean.Create(false, defTableRecordType); - - foreach (var file in inputFileInfos) - { - var source = new ExcelDataSource(); - var bytes = await this.Agent.GetFromCacheOrReadAllBytesAsync(file.ActualFile, file.MD5); - var records = DataLoaderUtil.LoadCfgRecords(tableRecordType, file.OriginFile, null, bytes, true); - foreach (var r in records) - { - DBean data = r.Data; - //s_logger.Info("== read text:{}", r.Data); - string fullName = (data.GetField("full_name") as DString).Value.Trim(); - string name = TypeUtil.GetName(fullName); - if (string.IsNullOrWhiteSpace(fullName) || string.IsNullOrWhiteSpace(name)) - { - throw new Exception($"file:{file.ActualFile} 定义了一个空的table类名"); - } - string module = TypeUtil.GetNamespace(fullName); - string valueType = (data.GetField("value_type") as DString).Value.Trim(); - string index = (data.GetField("index") as DString).Value.Trim(); - string mode = (data.GetField("mode") as DString).Value.Trim(); - string group = (data.GetField("group") as DString).Value.Trim(); - string comment = (data.GetField("comment") as DString).Value.Trim(); - bool isDefineFromExcel = (data.GetField("define_from_excel") as DBool).Value; - string inputFile = (data.GetField("input") as DString).Value.Trim(); - string patchInput = (data.GetField("patch_input") as DString).Value.Trim(); - string tags = (data.GetField("tags") as DString).Value.Trim(); - AddTable(file.OriginFile, name, module, valueType, index, mode, group, comment, isDefineFromExcel, inputFile, patchInput, tags); - }; - } - } - - private async Task LoadEnumListFromFileAsync(string dataDir) - { - if (this._importExcelEnumFiles.Count == 0) - { - return; - } - var inputFileInfos = await DataLoaderUtil.CollectInputFilesAsync(this.Agent, this._importExcelEnumFiles, dataDir); - - var defTableRecordType = new DefBean(new CfgBean() - { - Namespace = "__intern__", - Name = "__EnumInfo__", - Parent = "", - Alias = "", - IsValueType = false, - Sep = "", - TypeId = 0, - IsSerializeCompatible = false, - Fields = new List - { - new CfgField() { Name = "full_name", Type = "string" }, - new CfgField() { Name = "item", Type = "string" }, - new CfgField() { Name = "alias", Type = "string" }, - new CfgField() { Name = "value", Type = "int" }, - new CfgField() { Name = "comment", Type = "string" }, - new CfgField() { Name = "tags", Type = "string" }, - } - }) - { - AssemblyBase = new DefAssembly("", null, new List(), Agent), - }; - defTableRecordType.PreCompile(); - defTableRecordType.Compile(); - defTableRecordType.PostCompile(); - var tableRecordType = TBean.Create(false, defTableRecordType); - - foreach (var file in inputFileInfos) - { - var source = new ExcelDataSource(); - var bytes = await this.Agent.GetFromCacheOrReadAllBytesAsync(file.ActualFile, file.MD5); - var records = DataLoaderUtil.LoadCfgRecords(tableRecordType, file.OriginFile, null, bytes, true); - - PEnum curEnum = null; - foreach (var r in records) - { - DBean data = r.Data; - //s_logger.Info("== read text:{}", r.Data); - string fullName = (data.GetField("full_name") as DString).Value.Trim(); - string name = TypeUtil.GetName(fullName); - if (string.IsNullOrWhiteSpace(fullName) || string.IsNullOrWhiteSpace(name)) - { - throw new Exception($"file:{file.ActualFile} 定义了一个空的enum类名"); - } - string module = TypeUtil.GetNamespace(fullName); - - if (curEnum == null || curEnum.Name != name || curEnum.Namespace != module) - { - curEnum = new PEnum() { Name = name, Namespace = module, IsFlags = false, Comment = "", IsUniqueItemId = true }; - this._enums.Add(curEnum); - } - - string item = (data.GetField("item") as DString).Value.Trim(); - if (string.IsNullOrWhiteSpace(item)) - { - throw new Exception($"file:{file.ActualFile} module:'{module}' name:'{name}' 定义了一个空枚举项"); - } - string alias = (data.GetField("alias") as DString).Value.Trim(); - string value = (data.GetField("value") as DInt).Value.ToString(); - string comment = (data.GetField("comment") as DString).Value.Trim(); - string tags = (data.GetField("tags") as DString).Value.Trim(); - curEnum.Items.Add(new EnumItem() { Name = item, Alias = alias, Value = value, Comment = comment, Tags = tags }); - }; - } - } - - private async Task LoadBeanListFromFileAsync(string dataDir) - { - if (this._importExcelBeanFiles.Count == 0) - { - return; - } - var inputFileInfos = await DataLoaderUtil.CollectInputFilesAsync(this.Agent, this._importExcelBeanFiles, dataDir); - - - var ass = new DefAssembly("", null, new List(), Agent); - - var defBeanFieldType = new DefBean(new CfgBean() - { - Namespace = "__intern__", - Name = "__FieldInfo__", - Parent = "", - Alias = "", - IsValueType = false, - Sep = "", - TypeId = 0, - IsSerializeCompatible = false, - Fields = new List - { - new CfgField() { Name = "name", Type = "string" }, - new CfgField() { Name = "type", Type = "string" }, - new CfgField() { Name = "sep", Type = "string" }, - new CfgField() { Name = "is_multi_rows", Type = "bool" }, - new CfgField() { Name = "index", Type = "string" }, - new CfgField() { Name = "group", Type = "string" }, - new CfgField() { Name = "ref", Type = "string", IgnoreNameValidation = true }, - new CfgField() { Name = "path", Type = "string" }, - new CfgField() { Name = "comment", Type = "string" }, - new CfgField() { Name = "tags", Type = "string" }, - new CfgField() { Name = "orientation", Type = "string" }, - } - }) - { - AssemblyBase = ass, - }; - - defBeanFieldType.PreCompile(); - defBeanFieldType.Compile(); - defBeanFieldType.PostCompile(); - - ass.AddType(defBeanFieldType); - - var defTableRecordType = new DefBean(new CfgBean() - { - Namespace = "__intern__", - Name = "__BeanInfo__", - Parent = "", - Alias = "", - IsValueType = false, - Sep = "", - TypeId = 0, - IsSerializeCompatible = false, - Fields = new List - { - new CfgField() { Name = "full_name", Type = "string" }, - new CfgField() { Name = "sep", Type = "string" }, - new CfgField() { Name = "comment", Type = "string" }, - new CfgField() { Name = "tags", Type = "string" }, - new CfgField() { Name = "fields", Type = "list,__FieldInfo__", IsMultiRow = true }, - } - }) - { - AssemblyBase = ass, - }; - ass.AddType(defTableRecordType); - defTableRecordType.PreCompile(); - defTableRecordType.Compile(); - defTableRecordType.PostCompile(); - ass.MarkMultiRows(); - var tableRecordType = TBean.Create(false, defTableRecordType); - - foreach (var file in inputFileInfos) - { - var source = new ExcelDataSource(); - var bytes = await this.Agent.GetFromCacheOrReadAllBytesAsync(file.ActualFile, file.MD5); - var records = DataLoaderUtil.LoadCfgRecords(tableRecordType, file.OriginFile, null, bytes, true); - - foreach (var r in records) - { - DBean data = r.Data; - //s_logger.Info("== read text:{}", r.Data); - string fullName = (data.GetField("full_name") as DString).Value.Trim(); - string name = TypeUtil.GetName(fullName); - if (string.IsNullOrWhiteSpace(fullName) || string.IsNullOrWhiteSpace(name)) - { - throw new Exception($"file:{file.ActualFile} 定义了一个空bean类名"); - } - string module = TypeUtil.GetNamespace(fullName); - - - string sep = (data.GetField("sep") as DString).Value.Trim(); - string comment = (data.GetField("comment") as DString).Value.Trim(); - string tags = (data.GetField("tags") as DString).Value.Trim(); - DList fields = data.GetField("fields") as DList; - var curBean = new CfgBean() - { - Name = name, - Namespace = module, - Sep = sep, - Comment = comment, - Tags = tags, - Parent = "", - Fields = fields.Datas.Select(d => (DBean)d).Select(b => this.CreateField( - file.ActualFile, - (b.GetField("name") as DString).Value.Trim(), - (b.GetField("type") as DString).Value.Trim(), - (b.GetField("index") as DString).Value.Trim(), - (b.GetField("sep") as DString).Value.Trim(), - (b.GetField("is_multi_rows") as DBool).Value, - (b.GetField("group") as DString).Value, - "", - "", - (b.GetField("comment") as DString).Value.Trim(), - (b.GetField("ref") as DString).Value.Trim(), - (b.GetField("path") as DString).Value.Trim(), - "", - "", - "", - "", - (b.GetField("tags") as DString).Value.Trim(), - false, - DefUtil.ParseOrientation((b.GetField("orientation") as DString).Value) - )).ToList(), - }; - this._beans.Add(curBean); - }; - } - } - - public async Task LoadDefinesFromFileAsync(string dataDir) - { - await Task.WhenAll(LoadTableListFromFileAsync(dataDir), LoadEnumListFromFileAsync(dataDir), LoadBeanListFromFileAsync(dataDir)); - await LoadTableValueTypeDefinesFromFileAsync(dataDir); - } - - private static readonly List _fieldOptionalAttrs = new() - { - "index", - "sep", - "validator", - "key_validator", - "value_validator", - "ref", - "path", - "range", - "multi_rows", - "group", - "res", - "convert", - "comment", - "tags", - "default", - "orientation", - }; - - private static readonly List _fieldRequireAttrs = new List { "name", "type" }; - - protected override Field CreateField(string defineFile, XElement e) - { - ValidAttrKeys(defineFile, e, _fieldOptionalAttrs, _fieldRequireAttrs); - - return CreateField(defineFile, XmlUtil.GetRequiredAttribute(e, "name"), - XmlUtil.GetRequiredAttribute(e, "type"), - XmlUtil.GetOptionalAttribute(e, "index"), - XmlUtil.GetOptionalAttribute(e, "sep"), - XmlUtil.GetOptionBoolAttribute(e, "multi_rows"), - XmlUtil.GetOptionalAttribute(e, "group"), - XmlUtil.GetOptionalAttribute(e, "res"), - XmlUtil.GetOptionalAttribute(e, "convert"), - XmlUtil.GetOptionalAttribute(e, "comment"), - XmlUtil.GetOptionalAttribute(e, "ref"), - XmlUtil.GetOptionalAttribute(e, "path"), - XmlUtil.GetOptionalAttribute(e, "range"), - XmlUtil.GetOptionalAttribute(e, "key_validator"), - XmlUtil.GetOptionalAttribute(e, "value_validator"), - XmlUtil.GetOptionalAttribute(e, "validator"), - XmlUtil.GetOptionalAttribute(e, "tags"), - false, - DefUtil.ParseOrientation(XmlUtil.GetOptionalAttribute(e, "orientation")) - ); - } - - private Field CreateField(string defileFile, string name, string type, string index, string sep, bool isMultiRow, string group, string resource, string converter, - string comment, string refs, string path, string range, string keyValidator, string valueValidator, string validator, string tags, - bool ignoreNameValidation, bool isRowOrient) - { - var f = new CfgField() - { - Name = name, - Index = index, - Sep = sep, - IsMultiRow = isMultiRow, - Groups = CreateGroups(group), - Resource = resource, - Converter = converter, - Comment = comment, - Tags = tags, - IgnoreNameValidation = ignoreNameValidation, - IsRowOrient = isRowOrient, - }; - - // 字段与table的默认组不一样。 - // table 默认只属于default=1的组 - // 字段默认属于所有组 - if (f.Groups.Count == 0) - { - - } - else if (!ValidGroup(f.Groups, out var invalidGroup)) - { - throw new Exception($"定义文件:{defileFile} field:'{name}' group:'{invalidGroup}' 不存在"); - } - f.Type = type; - - - FillValueValidator(f, refs, "ref"); - FillValueValidator(f, path, "path"); // (ue4|unity|normal|regex);xxx;xxx - FillValueValidator(f, range, "range"); - - FillValidators(defileFile, "key_validator", keyValidator, f.KeyValidators); - FillValidators(defileFile, "value_validator", valueValidator, f.ValueValidators); - FillValidators(defileFile, "validator", validator, f.Validators); - return f; - } - - private static readonly List _beanOptinsAttrs = new List { "value_type", "alias", "sep", "comment", "tags" }; - private static readonly List _beanRequireAttrs = new List { "name" }; - - protected override void AddBean(string defineFile, XElement e, string parent) - { - ValidAttrKeys(defineFile, e, _beanOptinsAttrs, _beanRequireAttrs); - - var b = new CfgBean() - { - Name = XmlUtil.GetRequiredAttribute(e, "name"), - Namespace = CurNamespace, - Parent = parent.Length > 0 ? parent : "", - TypeId = 0, - IsSerializeCompatible = true, - IsValueType = XmlUtil.GetOptionBoolAttribute(e, "value_type"), - Alias = XmlUtil.GetOptionalAttribute(e, "alias"), - Sep = XmlUtil.GetOptionalAttribute(e, "sep"), - Comment = XmlUtil.GetOptionalAttribute(e, "comment"), - Tags = XmlUtil.GetOptionalAttribute(e, "tags"), - }; - var childBeans = new List(); - - bool defineAnyChildBean = false; - foreach (XElement fe in e.Elements()) - { - switch (fe.Name.LocalName) - { - case "var": - { - if (defineAnyChildBean) - { - throw new LoadDefException($"定义文件:{defineFile} 类型:{b.FullName} 的多态子bean必须在所有成员字段 之前定义"); - } - b.Fields.Add(CreateField(defineFile, fe)); ; - break; - } - case "bean": - { - defineAnyChildBean = true; - childBeans.Add(fe); - break; - } - default: - { - throw new LoadDefException($"定义文件:{defineFile} 类型:{b.FullName} 不支持 tag:{fe.Name}"); - } - } - } - s_logger.Trace("add bean:{@bean}", b); - _beans.Add(b); - - var fullname = b.FullName; - foreach (var cb in childBeans) - { - AddBean(defineFile, cb, fullname); - } - } - } -} diff --git a/src/LubanAssistant/Source/Defs/DefAssembly.cs b/src/LubanAssistant/Source/Defs/DefAssembly.cs deleted file mode 100644 index 7cfad64..0000000 --- a/src/LubanAssistant/Source/Defs/DefAssembly.cs +++ /dev/null @@ -1,276 +0,0 @@ -using Bright.Collections; -using Luban.Job.Cfg.Datas; -using Luban.Job.Cfg.RawDefs; -using Luban.Job.Cfg.TypeVisitors; -using Luban.Job.Common.Defs; -using Luban.Server.Common; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; - -namespace Luban.Job.Cfg.Defs -{ - public class TableDataInfo - { - public DefTable Table { get; } - - public List MainRecords { get; } - - public List PatchRecords { get; } - - //public List FinalRecords { get; set; } - - //public Dictionary FinalRecordMap { get; set; } - - public TableDataInfo(DefTable table, List mainRecords, List patchRecords) - { - Table = table; - MainRecords = mainRecords; - PatchRecords = patchRecords; - } - } - - public class DefAssembly : DefAssemblyBase - { - private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger(); - - public new static DefAssembly LocalAssebmly { get => (DefAssembly)DefAssemblyBase.LocalAssebmly; set => DefAssemblyBase.LocalAssebmly = value; } - - public Service CfgTargetService { get; private set; } - - private readonly string _patchName; - private readonly List _excludeTags; - - public Patch TargetPatch { get; private set; } - - public TimeZoneInfo TimeZone { get; } - - public DefAssembly(string patchName, TimeZoneInfo timezone, List excludeTags, IAgent agent) - { - this._patchName = patchName; - this.TimeZone = timezone; - this._excludeTags = excludeTags; - this.Agent = agent; - } - - public bool NeedExport(List groups) - { - if (groups.Count == 0) - { - return true; - } - return groups.Any(g => CfgTargetService.Groups.Contains(g)); - } - - private readonly List _patches = new List(); - - private readonly List _cfgServices = new List(); - - private readonly ConcurrentDictionary _recordsByTables = new(); - - public Dictionary CfgTables { get; } = new Dictionary(); - - - public Patch GetPatch(string name) - { - return _patches.Find(b => b.Name == name); - } - - public void AddCfgTable(DefTable table) - { - if (!CfgTables.TryAdd(table.FullName, table)) - { - throw new Exception($"table:'{table.FullName}' duplicated"); - } - } - - public DefTable GetCfgTable(string name) - { - return CfgTables.TryGetValue(name, out var t) ? t : null; - } - - public void AddDataTable(DefTable table, List mainRecords, List patchRecords) - { - _recordsByTables[table.FullName] = new TableDataInfo(table, mainRecords, patchRecords); - } - - public List GetTableAllDataList(DefTable table) - { - return _recordsByTables[table.FullName].MainRecords; - } - - public TableDataInfo GetTableDataInfo(DefTable table) - { - return _recordsByTables[table.FullName]; - } - - public List GetExportTables() - { - return Types.Values.Where(t => t is DefTable ct && ct.NeedExport).Select(t => (DefTable)t).ToList(); - } - - public List GetExportTypes() - { - var refTypes = new Dictionary(); - var targetService = CfgTargetService; - foreach (var refType in targetService.Refs) - { - if (!this.Types.ContainsKey(refType)) - { - throw new Exception($"service:'{targetService.Name}' ref:'{refType}' 类型不存在"); - } - if (!refTypes.TryAdd(refType, this.Types[refType])) - { - throw new Exception($"service:'{targetService.Name}' ref:'{refType}' 重复引用"); - } - } - foreach (var e in this.Types) - { - if (!refTypes.ContainsKey(e.Key) && (e.Value is DefEnum)) - { - refTypes.Add(e.Key, e.Value); - } - } - - foreach (var table in GetExportTables()) - { - refTypes[table.FullName] = table; - table.ValueTType.Apply(RefTypeVisitor.Ins, refTypes); - } - - return refTypes.Values.ToList(); - } - - public void Load(string outputService, Defines defines) - { - SupportDatetimeType = true; - - TopModule = defines.TopModule; - - CfgTargetService = defines.Services.Find(s => s.Name == outputService); - - if (CfgTargetService == null) - { - throw new ArgumentException($"service:{outputService} not exists"); - } - - if (!string.IsNullOrWhiteSpace(_patchName)) - { - TargetPatch = defines.Patches.Find(b => b.Name == _patchName); - if (TargetPatch == null) - { - throw new Exception($"patch '{_patchName}' not in valid patch set"); - } - } - - this._patches.AddRange(defines.Patches); - - foreach (var e in defines.Enums) - { - AddType(new DefEnum(e)); - } - - foreach (var b in defines.Beans) - { - AddType(new DefBean((CfgBean)b)); - } - - foreach (var p in defines.Tables) - { - var table = new DefTable(p); - AddType(table); - AddCfgTable(table); - } - - _cfgServices.AddRange(defines.Services); - - foreach (var type in Types.Values) - { - type.AssemblyBase = this; - } - - foreach (var type in Types.Values) - { - try - { - s_logger.Trace("precompile type:{0} begin", type.FullName); - type.PreCompile(); - s_logger.Trace("precompile type:{0} end", type.FullName); - } - catch (Exception) - { - this.Agent.Error("precompile type:{0} error", type.FullName); - throw; - } - } - foreach (var type in Types.Values) - { - try - { - s_logger.Trace("compile type:{0} begin", type.FullName); - type.Compile(); - s_logger.Trace("compile type:{0} end", type.FullName); - } - catch (Exception) - { - this.Agent.Error("compile type:{0} error", type.FullName); - s_logger.Error("compile type:{0} error", type.FullName); - throw; - } - } - foreach (var type in Types.Values) - { - try - { - s_logger.Trace("post compile type:{0} begin", type.FullName); - type.PostCompile(); - s_logger.Trace("post compile type:{0} end", type.FullName); - } - catch (Exception) - { - this.Agent.Error("post compile type:{0} error", type.FullName); - s_logger.Error("post compile type:{0} error", type.FullName); - throw; - } - } - - // 丑陋. 怎么写更好? - - // 递归 设置DefBean及DefField 的 IsMultiRow - - MarkMultiRows(); - } - - public void MarkMultiRows() - { - var multiRowBeans = new HashSet(); - for (bool anyMark = true; anyMark;) - { - anyMark = false; - foreach (var type in this.Types.Values) - { - if (type is DefBean beanType && !beanType.IsMultiRow) - { - bool isMultiRows; - if (beanType.IsNotAbstractType) - { - isMultiRows = beanType.HierarchyFields.Any(f => ((DefField)f).ComputeIsMultiRow()); - } - else - { - isMultiRows = beanType.HierarchyNotAbstractChildren.Any(c => ((DefBean)c).IsMultiRow); - } - if (isMultiRows) - { - beanType.IsMultiRow = true; - //s_logger.Info("bean:{bean} is multi row", beanType.FullName); - anyMark = true; - } - } - } - - } - } - } -} diff --git a/src/LubanAssistant/Source/Defs/DefField.cs b/src/LubanAssistant/Source/Defs/DefField.cs deleted file mode 100644 index cccacb5..0000000 --- a/src/LubanAssistant/Source/Defs/DefField.cs +++ /dev/null @@ -1,181 +0,0 @@ -using Luban.Common.Utils; -using Luban.Job.Cfg.DataCreators; -using Luban.Job.Cfg.Datas; -using Luban.Job.Cfg.RawDefs; -using Luban.Job.Common.Defs; -using Luban.Job.Common.Types; -using Luban.Job.Common.TypeVisitors; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Luban.Job.Cfg.Defs -{ - public class DefField : DefFieldBase - { - public DefAssembly Assembly => (DefAssembly)HostType.AssemblyBase; - - - public bool RawIsMultiRow { get; } - - public bool IsMultiRow { get; private set; } - - public bool ComputeIsMultiRow() - { - if (IsMultiRow) - { - return true; - } - - switch (CType) - { - case TBean b: { return IsMultiRow = ((DefBean)b.Bean).IsMultiRow; } - case TList b: { return IsMultiRow = b.ElementType is TBean b2 && ((DefBean)b2.Bean).IsMultiRow; } - case TArray b: { return IsMultiRow = b.ElementType is TBean b2 && ((DefBean)b2.Bean).IsMultiRow; } - case TMap b: { return IsMultiRow = b.ValueType is TBean b2 && ((DefBean)b2.Bean).IsMultiRow; } - default: return false; - } - } - - - public string Index { get; } - - public List Groups { get; } - - public DefField IndexField { get; private set; } - - - public string Sep { get; set; } - - // 如果没有指定sep - // 如果是bean,且指定了sep,则使用此值 - // 如果是vectorN,使用 , - public string ActualSep => string.IsNullOrWhiteSpace(Sep) ? (CType is TBean bean ? ((DefBean)bean.Bean).Sep : "") : Sep; - - public bool NeedExport => Assembly.NeedExport(this.Groups); - - public TEnum Remapper { get; private set; } - - public CfgField RawDefine { get; } - - public string GetTextKeyName(string name) => name + TText.L10N_FIELD_SUFFIX; - - public bool GenTextKey => this.CType is TText; - - - public string DefaultValue { get; } - - public DType DefalutDtypeValue { get; private set; } - - public bool IsRowOrient { get; } - - public DefField(DefTypeBase host, CfgField f, int idOffset) : base(host, f, idOffset) - { - Index = f.Index; - Sep = f.Sep; - this.IsMultiRow = this.RawIsMultiRow = f.IsMultiRow; - this.Groups = f.Groups; - this.RawDefine = f; - this.DefaultValue = f.DefaultValue; - this.IsRowOrient = f.IsRowOrient; - } - - public override void Compile() - { - base.Compile(); - - if (!string.IsNullOrWhiteSpace(this.DefaultValue)) - { - this.DefalutDtypeValue = CType.Apply(StringDataCreator.Ins, this.DefaultValue); - } - - switch (CType) - { - case TArray t: - { - if (t.ElementType is TBean e && !e.IsDynamic && e.Bean.HierarchyFields.Count == 0) - { - throw new Exception($"container element type:'{e.Bean.FullName}' can't be empty bean"); - } - if (t.ElementType is TText) - { - throw new Exception($"bean:{HostType.FullName} field:{Name} container element type can't text"); - } - break; - } - case TList t: - { - if (t.ElementType is TBean e && !e.IsDynamic && e.Bean.HierarchyFields.Count == 0) - { - throw new Exception($"container element type:'{e.Bean.FullName}' can't be empty bean"); - } - if (t.ElementType is TText) - { - throw new Exception($"bean:{HostType.FullName} field:{Name} container element type can't text"); - } - break; - } - case TSet t: - { - if (t.ElementType is TText) - { - throw new Exception($"bean:{HostType.FullName} field:{Name} container element type can't text"); - } - break; - } - case TMap t: - { - if (t.KeyType is TText) - { - throw new Exception($"bean:{HostType.FullName} field:{Name} container key type can't text"); - } - if (t.ValueType is TText) - { - throw new Exception($"bean:{HostType.FullName} field:{Name} container value type can't text"); - } - break; - } - } - - if (IsMultiRow && !CType.IsCollection && !CType.IsBean) - { - throw new Exception($"只有容器类型才支持 multi_line 属性"); - } - - if (string.IsNullOrEmpty(Sep) && CType is TBean bean) - { - Sep = bean.GetBeanAs().Sep; - } - if (!string.IsNullOrEmpty(Index)) - { - if ((CType is TArray tarray) && (tarray.ElementType is TBean b)) - { - if ((IndexField = b.GetBeanAs().GetField(Index)) == null) - { - throw new Exception($"type:'{HostType.FullName}' field:'{Name}' index:'{Index}'. index not exist"); - } - } - else if ((CType is TList tlist) && (tlist.ElementType is TBean tb)) - { - if ((IndexField = tb.GetBeanAs().GetField(Index)) == null) - { - throw new Exception($"type:'{HostType.FullName}' field:'{Name}' index:'{Index}'. index not exist"); - } - } - else - { - throw new Exception($"type:'{HostType.FullName}' field:'{Name}' index:'{Index}'. only array:bean or list:bean support index"); - } - } - - if (!string.IsNullOrEmpty(this.RawDefine.Converter)) - { - this.Remapper = AssemblyBase.GetDefTType(HostType.Namespace, this.RawDefine.Converter, this.IsNullable) as TEnum; - if (this.Remapper == null) - { - throw new Exception($"type:'{HostType.FullName}' field:'{Name}' converter:'{this.RawDefine.Converter}' not exists"); - } - } - } - } -} diff --git a/src/LubanAssistant/Source/Defs/DefTypeBase.cs b/src/LubanAssistant/Source/Defs/DefTypeBase.cs deleted file mode 100644 index 51d7bcf..0000000 --- a/src/LubanAssistant/Source/Defs/DefTypeBase.cs +++ /dev/null @@ -1,69 +0,0 @@ -using Luban.Common.Utils; -using Luban.Server.Common; -using System.Collections.Generic; - -namespace Luban.Job.Common.Defs -{ - public abstract class DefTypeBase - { - public DefAssemblyBase AssemblyBase { get; set; } - - public int Id { get; protected set; } - - public string TopModule => AssemblyBase.TopModule; - - public IAgent Agent => AssemblyBase.Agent; - - public string Name { get; set; } - - public string Namespace { get; set; } - - public string FullName => TypeUtil.MakeFullName(Namespace, Name); - - public string NamespaceWithTopModule => TypeUtil.MakeNamespace(AssemblyBase.TopModule, Namespace); - - public string FullNameWithTopModule => TypeUtil.MakeFullName(AssemblyBase.TopModule, FullName); - - public string JavaFullName => TypeUtil.MakeFullName(Namespace, Name); - - public string GoFullName => TypeUtil.MakeGoFullName(Namespace, Name); - - public string GoPkgName => TypeUtil.MakeGoPkgName(Namespace); - - public string CppNamespaceBegin => TypeUtil.MakeCppNamespaceBegin(Namespace); - - public string CppNamespaceEnd => TypeUtil.MakeCppNamespaceEnd(Namespace); - - public string CppFullNameWithTopModule => TypeUtil.MakeCppFullName(AssemblyBase.TopModule, FullName); - - public string TypescriptNamespaceBegin => TypeUtil.MakeTypescriptNamespaceBegin(Namespace); - - public string TypescriptNamespaceEnd => TypeUtil.MakeTypescriptNamespaceEnd(Namespace); - - public string CppFullName => TypeUtil.MakeCppFullName(Namespace, Name); - - public string PyFullName => TypeUtil.MakePyFullName(Namespace, Name); - - public string RustFullName => TypeUtil.MakeRustFullName(Namespace, Name); - - public string Comment { get; protected set; } - - public Dictionary Tags { get; protected set; } - - public bool HasTag(string attrName) - { - return Tags != null && Tags.ContainsKey(attrName); - } - - public string GetTag(string attrName) - { - return Tags != null && Tags.TryGetValue(attrName, out var value) ? value : null; - } - - public virtual void PreCompile() { } - - public abstract void Compile(); - - public virtual void PostCompile() { } - } -}